iwlwifi: mvm: support offload of AMSDU rate control
Support the new APIs and activate AMSDU based on the offloaded TLC decisions. Signed-off-by: Sara Sharon <sara.sharon@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
		
							parent
							
								
									cf58c9e091
								
							
						
					
					
						commit
						84226ca1c5
					
				| @ -92,6 +92,11 @@ enum iwl_data_path_subcmd_ids { | ||||
| 	 */ | ||||
| 	TLC_MNG_NOTIF_REQ_CMD = 0x10, | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @TLC_MNG_AMSDU_ENABLE_NOTIF: &struct iwl_tlc_amsdu_notif | ||||
| 	 */ | ||||
| 	TLC_MNG_AMSDU_ENABLE_NOTIF = 0xF6, | ||||
| 
 | ||||
| 	/**
 | ||||
| 	 * @TLC_MNG_UPDATE_NOTIF: &struct iwl_tlc_update_notif | ||||
| 	 */ | ||||
|  | ||||
| @ -205,7 +205,7 @@ enum iwl_tlc_mng_ht_rates { | ||||
|  * @non_ht_supp_rates: bitmap of supported legacy rates | ||||
|  * @ht_supp_rates: bitmap of supported HT/VHT rates, valid bits are 0-9 | ||||
|  * @mode: &enum iwl_tlc_mng_cfg_mode | ||||
|  * @reserved2: reserved | ||||
|  * @amsdu: TX amsdu is supported | ||||
|  * @he_supp_rates: bitmap of supported HE rates | ||||
|  * @sgi_ch_width_supp: bitmap of SGI support per channel width | ||||
|  * @he_gi_support: 11ax HE guard interval | ||||
| @ -222,13 +222,27 @@ struct iwl_tlc_config_cmd { | ||||
| 	__le16 non_ht_supp_rates; | ||||
| 	__le16 ht_supp_rates[MAX_RS_ANT_NUM]; | ||||
| 	u8 mode; | ||||
| 	u8 reserved2; | ||||
| 	u8 amsdu; | ||||
| 	__le16 he_supp_rates; | ||||
| 	u8 sgi_ch_width_supp; | ||||
| 	u8 he_gi_support; | ||||
| 	__le32 max_ampdu_cnt; | ||||
| } __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_1 */ | ||||
| 
 | ||||
| /**
 | ||||
|  * struct iwl_tlc_amsdu_notif - TLC AMSDU configuration | ||||
|  * @sta_id: station id | ||||
|  * @reserved: reserved | ||||
|  * @amsdu_size: Max AMSDU size, in bytes | ||||
|  * @amsdu_enabled: bitmap for per-TID AMSDU enablement | ||||
|  */ | ||||
| struct iwl_tlc_amsdu_notif { | ||||
| 	u8 sta_id; | ||||
| 	u8 reserved[3]; | ||||
| 	__le16 amsdu_size; | ||||
| 	__le16 amsdu_enabled; | ||||
| } __packed; /* TLC_MNG_AMSDU_ENABLE_NTFY_API_S_VER_1 */ | ||||
| 
 | ||||
| #define IWL_TLC_NOTIF_INIT_RATE_POS 0 | ||||
| #define IWL_TLC_NOTIF_INIT_RATE_MSK BIT(IWL_TLC_NOTIF_INIT_RATE_POS) | ||||
| #define IWL_TLC_NOTIF_REQ_INTERVAL (500) | ||||
|  | ||||
| @ -250,6 +250,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | ||||
| 	RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, RX_HANDLER_SYNC), | ||||
| 	RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, RX_HANDLER_SYNC), | ||||
| 
 | ||||
| 	RX_HANDLER_GRP(DATA_PATH_GROUP, TLC_MNG_UPDATE_NOTIF, | ||||
| 		       iwl_mvm_tlc_update_notif, RX_HANDLER_SYNC), | ||||
| 
 | ||||
| 	RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, | ||||
| 		   RX_HANDLER_ASYNC_LOCKED), | ||||
| 	RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, | ||||
| @ -309,6 +312,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | ||||
| 		       iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC), | ||||
| 	RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF, | ||||
| 		       iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC), | ||||
| 	RX_HANDLER_GRP(DATA_PATH_GROUP, TLC_MNG_AMSDU_ENABLE_NOTIF, | ||||
| 		       iwl_mvm_tlc_amsdu_notif, RX_HANDLER_SYNC), | ||||
| }; | ||||
| #undef RX_HANDLER | ||||
| #undef RX_HANDLER_GRP | ||||
| @ -445,6 +450,7 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { | ||||
| 	HCMD_NAME(DQA_ENABLE_CMD), | ||||
| 	HCMD_NAME(UPDATE_MU_GROUPS_CMD), | ||||
| 	HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), | ||||
| 	HCMD_NAME(TLC_MNG_AMSDU_ENABLE_NOTIF), | ||||
| 	HCMD_NAME(STA_PM_NOTIF), | ||||
| 	HCMD_NAME(MU_GROUP_MGMT_NOTIF), | ||||
| 	HCMD_NAME(RX_QUEUES_NOTIFICATION), | ||||
| @ -1034,8 +1040,6 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, | ||||
| 		iwl_mvm_rx_queue_notif(mvm, rxb, 0); | ||||
| 	else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE)) | ||||
| 		iwl_mvm_rx_frame_release(mvm, napi, rxb, 0); | ||||
| 	else if (cmd == WIDE_ID(DATA_PATH_GROUP, TLC_MNG_UPDATE_NOTIF)) | ||||
| 		iwl_mvm_tlc_update_notif(mvm, pkt); | ||||
| 	else | ||||
| 		iwl_mvm_rx_common(mvm, rxb, pkt); | ||||
| } | ||||
|  | ||||
| @ -228,8 +228,47 @@ static void rs_fw_tlc_mng_notif_req_config(struct iwl_mvm *mvm, u8 sta_id) | ||||
| 		IWL_ERR(mvm, "Failed to send TLC notif request (%d)\n", ret); | ||||
| } | ||||
| 
 | ||||
| void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) | ||||
| void iwl_mvm_tlc_amsdu_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) | ||||
| { | ||||
| 	struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||||
| 	struct iwl_tlc_amsdu_notif *notif; | ||||
| 	struct ieee80211_sta *sta; | ||||
| 	struct iwl_mvm_sta *mvmsta; | ||||
| 	u16 size; | ||||
| 
 | ||||
| 	notif = (void *)pkt->data; | ||||
| 
 | ||||
| 	if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))) | ||||
| 		return; | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 
 | ||||
| 	sta = rcu_dereference(mvm->fw_id_to_mac_id[notif->sta_id]); | ||||
| 	if (IS_ERR_OR_NULL(sta)) { | ||||
| 		rcu_read_unlock(); | ||||
| 		IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n", | ||||
| 			notif->sta_id); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||||
| 
 | ||||
| 	size = min(le16_to_cpu(notif->amsdu_size), sta->max_amsdu_len); | ||||
| 	mvmsta->amsdu_enabled = le16_to_cpu(notif->amsdu_enabled); | ||||
| 	mvmsta->max_amsdu_len = size; | ||||
| 
 | ||||
| 	IWL_DEBUG_RATE(mvm, | ||||
| 		       "AMSDU notification. AMSDU size: %d, AMSDU selected size: %d, AMSDU TID bitmap 0x%X\n", | ||||
| 		       le16_to_cpu(notif->amsdu_size), size, | ||||
| 		       mvmsta->amsdu_enabled); | ||||
| 
 | ||||
| 	rcu_read_unlock(); | ||||
| }; | ||||
| 
 | ||||
| void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, | ||||
| 			      struct iwl_rx_cmd_buffer *rxb) | ||||
| { | ||||
| 	struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||||
| 	struct iwl_tlc_update_notif *notif; | ||||
| 	struct iwl_mvm_sta *mvmsta; | ||||
| 	struct iwl_lq_sta_rs_fw *lq_sta; | ||||
| @ -273,6 +312,7 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||||
| 		.max_supp_ss = sta->rx_nss, | ||||
| 		.max_ampdu_cnt = cpu_to_le32(mvmsta->max_agg_bufsize), | ||||
| 		.sgi_ch_width_supp = rs_fw_sgi_cw_support(sta), | ||||
| 		.amsdu = iwl_mvm_is_csum_supported(mvm), | ||||
| 	}; | ||||
| 	int ret; | ||||
| 
 | ||||
|  | ||||
| @ -1715,12 +1715,18 @@ static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||||
| { | ||||
| 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * In case TLC offload is not active amsdu_enabled is either 0xFFFF | ||||
| 	 * or 0, since there is no per-TID alg. | ||||
| 	 */ | ||||
| 	if ((!is_vht(&tbl->rate) && !is_ht(&tbl->rate)) || | ||||
| 	    tbl->rate.index < IWL_RATE_MCS_5_INDEX || | ||||
| 	    scale_action == RS_ACTION_DOWNSCALE) | ||||
| 		mvmsta->tlc_amsdu = false; | ||||
| 		mvmsta->amsdu_enabled = 0; | ||||
| 	else | ||||
| 		mvmsta->tlc_amsdu = true; | ||||
| 		mvmsta->amsdu_enabled = 0xFFFF; | ||||
| 
 | ||||
| 	mvmsta->max_amsdu_len = sta->max_amsdu_len; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -3134,7 +3140,8 @@ static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||||
| 	sband = hw->wiphy->bands[band]; | ||||
| 
 | ||||
| 	lq_sta->lq.sta_id = mvmsta->sta_id; | ||||
| 	mvmsta->tlc_amsdu = false; | ||||
| 	mvmsta->amsdu_enabled = 0; | ||||
| 	mvmsta->max_amsdu_len = sta->max_amsdu_len; | ||||
| 
 | ||||
| 	for (j = 0; j < LQ_SIZE; j++) | ||||
| 		rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); | ||||
| @ -3744,7 +3751,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | ||||
| 				(rate->sgi) ? "SGI" : "NGI", | ||||
| 				(rate->ldpc) ? "LDPC" : "BCC", | ||||
| 				(lq_sta->is_agg) ? "AGG on" : "", | ||||
| 				(mvmsta->tlc_amsdu) ? "AMSDU on" : ""); | ||||
| 				(mvmsta->amsdu_enabled) ? "AMSDU on" : ""); | ||||
| 	} | ||||
| 	desc += scnprintf(buff + desc, bufsz - desc, "last tx rate=0x%X\n", | ||||
| 			lq_sta->last_rate_n_flags); | ||||
|  | ||||
| @ -454,5 +454,8 @@ void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||||
| 		     enum nl80211_band band); | ||||
| int rs_fw_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | ||||
| 			bool enable); | ||||
| void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt); | ||||
| void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, | ||||
| 			      struct iwl_rx_cmd_buffer *rxb); | ||||
| void iwl_mvm_tlc_amsdu_notif(struct iwl_mvm *mvm, | ||||
| 			     struct iwl_rx_cmd_buffer *rxb); | ||||
| #endif /* __rs__ */ | ||||
|  | ||||
| @ -391,7 +391,9 @@ struct iwl_mvm_rxq_dup_data { | ||||
|  * @tx_protection: reference counter for controlling the Tx protection. | ||||
|  * @tt_tx_protection: is thermal throttling enable Tx protection? | ||||
|  * @disable_tx: is tx to this STA disabled? | ||||
|  * @tlc_amsdu: true if A-MSDU is allowed | ||||
|  * @amsdu_enabled: bitmap of TX AMSDU allowed TIDs. | ||||
|  *	In case TLC offload is not active it is either 0xFFFF or 0. | ||||
|  * @max_amsdu_len: max AMSDU length | ||||
|  * @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON) | ||||
|  * @sleep_tx_count: the number of frames that we told the firmware to let out | ||||
|  *	even when that station is asleep. This is useful in case the queue | ||||
| @ -436,7 +438,8 @@ struct iwl_mvm_sta { | ||||
| 	bool tt_tx_protection; | ||||
| 
 | ||||
| 	bool disable_tx; | ||||
| 	bool tlc_amsdu; | ||||
| 	u16 amsdu_enabled; | ||||
| 	u16 max_amsdu_len; | ||||
| 	bool sleeping; | ||||
| 	bool associated; | ||||
| 	u8 agg_tids; | ||||
|  | ||||
| @ -774,9 +774,9 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | ||||
| 
 | ||||
| 	dbg_max_amsdu_len = READ_ONCE(mvm->max_amsdu_len); | ||||
| 
 | ||||
| 	if (!sta->max_amsdu_len || | ||||
| 	if (!mvmsta->max_amsdu_len || | ||||
| 	    !ieee80211_is_data_qos(hdr->frame_control) || | ||||
| 	    (!mvmsta->tlc_amsdu && !dbg_max_amsdu_len)) | ||||
| 	    (!mvmsta->amsdu_enabled && !dbg_max_amsdu_len)) | ||||
| 		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); | ||||
| 
 | ||||
| 	/*
 | ||||
| @ -803,7 +803,12 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, | ||||
| 	    !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) | ||||
| 		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); | ||||
| 
 | ||||
| 	max_amsdu_len = sta->max_amsdu_len; | ||||
| 	if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(mvmsta->vif)) || | ||||
| 	    tid_to_mac80211_ac[tid] < IEEE80211_AC_BE || | ||||
| 	    !(mvmsta->amsdu_enabled & BIT(tid))) | ||||
| 		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); | ||||
| 
 | ||||
| 	max_amsdu_len = mvmsta->max_amsdu_len; | ||||
| 
 | ||||
| 	/* the Tx FIFO to which this A-MSDU will be routed */ | ||||
| 	txf = iwl_mvm_mac_ac_to_tx_fifo(mvm, tid_to_mac80211_ac[tid]); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user