diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath12k/dp_tx.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/dp_tx.c | 169 | 
1 files changed, 108 insertions, 61 deletions
| diff --git a/drivers/net/wireless/ath/ath12k/dp_tx.c b/drivers/net/wireless/ath/ath12k/dp_tx.c index 9b6d7d72f57c..d08c04343e90 100644 --- a/drivers/net/wireless/ath/ath12k/dp_tx.c +++ b/drivers/net/wireless/ath/ath12k/dp_tx.c @@ -124,6 +124,44 @@ static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab,  						 HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE);  } +#define HTT_META_DATA_ALIGNMENT 0x8 + +static void *ath12k_dp_metadata_align_skb(struct sk_buff *skb, u8 tail_len) +{ +	struct sk_buff *tail; +	void *metadata; + +	if (unlikely(skb_cow_data(skb, tail_len, &tail) < 0)) +		return NULL; + +	metadata = pskb_put(skb, tail, tail_len); +	memset(metadata, 0, tail_len); +	return metadata; +} + +/* Preparing HTT Metadata when utilized with ext MSDU */ +static int ath12k_dp_prepare_htt_metadata(struct sk_buff *skb) +{ +	struct hal_tx_msdu_metadata *desc_ext; +	u8 htt_desc_size; +	/* Size rounded of multiple of 8 bytes */ +	u8 htt_desc_size_aligned; + +	htt_desc_size = sizeof(struct hal_tx_msdu_metadata); +	htt_desc_size_aligned = ALIGN(htt_desc_size, HTT_META_DATA_ALIGNMENT); + +	desc_ext = ath12k_dp_metadata_align_skb(skb, htt_desc_size_aligned); +	if (!desc_ext) +		return -ENOMEM; + +	desc_ext->info0 = le32_encode_bits(1, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_FLAG) | +			  le32_encode_bits(0, HAL_TX_MSDU_METADATA_INFO0_ENCRYPT_TYPE) | +			  le32_encode_bits(1, +					   HAL_TX_MSDU_METADATA_INFO0_HOST_TX_DESC_POOL); + +	return 0; +} +  int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,  		 struct sk_buff *skb)  { @@ -145,6 +183,7 @@ int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif,  	u8 ring_selector, ring_map = 0;  	bool tcl_ring_retry;  	bool msdu_ext_desc = false; +	bool add_htt_metadata = false;  	if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))  		return -ESHUTDOWN; @@ -248,6 +287,18 @@ tcl_ring_sel:  		goto fail_remove_tx_buf;  	} +	if (!test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags) && +	    !(skb_cb->flags & ATH12K_SKB_HW_80211_ENCAP) && +	    !(skb_cb->flags & ATH12K_SKB_CIPHER_SET) && +	    ieee80211_has_protected(hdr->frame_control)) { +		/* Add metadata for sw encrypted vlan group traffic */ +		add_htt_metadata = true; +		msdu_ext_desc = true; +		ti.flags0 |= u32_encode_bits(1, HAL_TCL_DATA_CMD_INFO2_TO_FW); +		ti.encap_type = HAL_TCL_ENCAP_TYPE_RAW; +		ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; +	} +  	tx_desc->skb = skb;  	tx_desc->mac_id = ar->pdev_idx;  	ti.desc_id = tx_desc->desc_id; @@ -269,6 +320,15 @@ tcl_ring_sel:  		msg = (struct hal_tx_msdu_ext_desc *)skb_ext_desc->data;  		ath12k_hal_tx_cmd_ext_desc_setup(ab, msg, &ti); +		if (add_htt_metadata) { +			ret = ath12k_dp_prepare_htt_metadata(skb_ext_desc); +			if (ret < 0) { +				ath12k_dbg(ab, ATH12K_DBG_DP_TX, +					   "Failed to add HTT meta data, dropping packet\n"); +				goto fail_unmap_dma; +			} +		} +  		ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data,  					  skb_ext_desc->len, DMA_TO_DEVICE);  		ret = dma_mapping_error(ab->dev, ti.paddr); @@ -352,15 +412,15 @@ static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab,  	u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(ab->hw_params, mac_id);  	skb_cb = ATH12K_SKB_CB(msdu); +	ar = ab->pdevs[pdev_id].ar;  	dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);  	if (skb_cb->paddr_ext_desc)  		dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc,  				 sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); -	dev_kfree_skb_any(msdu); +	ieee80211_free_txskb(ar->ah->hw, msdu); -	ar = ab->pdevs[pdev_id].ar;  	if (atomic_dec_and_test(&ar->dp.num_tx_pending))  		wake_up(&ar->dp.tx_empty_waitq);  } @@ -393,8 +453,12 @@ ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab,  	if (ts->acked) {  		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {  			info->flags |= IEEE80211_TX_STAT_ACK; -			info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR + -						  ts->ack_rssi; +			info->status.ack_signal = ts->ack_rssi; + +			if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT, +				      ab->wmi_ab.svc_map)) +				info->status.ack_signal += ATH12K_DEFAULT_NOISE_FLOOR; +  			info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID;  		} else {  			info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; @@ -448,6 +512,7 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,  				       struct hal_tx_status *ts)  {  	struct ath12k_base *ab = ar->ab; +	struct ath12k_hw *ah = ar->ah;  	struct ieee80211_tx_info *info;  	struct ath12k_skb_cb *skb_cb; @@ -466,12 +531,12 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,  	rcu_read_lock();  	if (!rcu_dereference(ab->pdevs_active[ar->pdev_idx])) { -		dev_kfree_skb_any(msdu); +		ieee80211_free_txskb(ah->hw, msdu);  		goto exit;  	}  	if (!skb_cb->vif) { -		dev_kfree_skb_any(msdu); +		ieee80211_free_txskb(ah->hw, msdu);  		goto exit;  	} @@ -481,17 +546,39 @@ static void ath12k_dp_tx_complete_msdu(struct ath12k *ar,  	/* skip tx rate update from ieee80211_status*/  	info->status.rates[0].idx = -1; -	if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED && -	    !(info->flags & IEEE80211_TX_CTL_NO_ACK)) { -		info->flags |= IEEE80211_TX_STAT_ACK; -		info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR + -					  ts->ack_rssi; -		info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; -	} +	switch (ts->status) { +	case HAL_WBM_TQM_REL_REASON_FRAME_ACKED: +		if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { +			info->flags |= IEEE80211_TX_STAT_ACK; +			info->status.ack_signal = ts->ack_rssi; -	if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && -	    (info->flags & IEEE80211_TX_CTL_NO_ACK)) -		info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; +			if (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT, +				      ab->wmi_ab.svc_map)) +				info->status.ack_signal += ATH12K_DEFAULT_NOISE_FLOOR; + +			info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; +		} +		break; +	case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX: +		if (info->flags & IEEE80211_TX_CTL_NO_ACK) { +			info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; +			break; +		} +		fallthrough; +	case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_MPDU: +	case HAL_WBM_TQM_REL_REASON_DROP_THRESHOLD: +	case HAL_WBM_TQM_REL_REASON_CMD_REMOVE_AGED_FRAMES: +		/* The failure status is due to internal firmware tx failure +		 * hence drop the frame; do not update the status of frame to +		 * the upper layer +		 */ +		ieee80211_free_txskb(ah->hw, msdu); +		goto exit; +	default: +		ath12k_dbg(ab, ATH12K_DBG_DP_TX, "tx frame is not acked status %d\n", +			   ts->status); +		break; +	}  	/* NOTE: Tx rate status reporting. Tx completion status does not have  	 * necessary information (for example nss) to build the tx rate. @@ -669,14 +756,6 @@ ath12k_dp_tx_get_ring_id_type(struct ath12k_base *ab,  		*htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;  		*htt_ring_type = HTT_SW_TO_HW_RING;  		break; -	case HAL_TX_MONITOR_BUF: -		*htt_ring_id = HTT_TX_MON_HOST2MON_BUF_RING; -		*htt_ring_type = HTT_SW_TO_HW_RING; -		break; -	case HAL_TX_MONITOR_DST: -		*htt_ring_id = HTT_TX_MON_MON2HOST_DEST_RING; -		*htt_ring_type = HTT_HW_TO_SW_RING; -		break;  	default:  		ath12k_warn(ab, "Unsupported ring type in DP :%d\n", ring_type);  		ret = -EINVAL; @@ -854,7 +933,7 @@ int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask)  	int ret;  	int i; -	for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++) { +	for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {  		skb = ath12k_htc_alloc_skb(ab, len);  		if (!skb)  			return -ENOMEM; @@ -1007,6 +1086,7 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,  	struct htt_ext_stats_cfg_cmd *cmd;  	int len = sizeof(*cmd);  	int ret; +	u32 pdev_id;  	skb = ath12k_htc_alloc_skb(ab, len);  	if (!skb) @@ -1018,7 +1098,8 @@ ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type,  	memset(cmd, 0, sizeof(*cmd));  	cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG; -	cmd->hdr.pdev_mask = 1 << ar->pdev->pdev_id; +	pdev_id = ath12k_mac_get_target_pdev_id(ar); +	cmd->hdr.pdev_mask = 1 << pdev_id;  	cmd->hdr.stats_type = type;  	cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0); @@ -1044,13 +1125,7 @@ int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset)  	struct ath12k_base *ab = ar->ab;  	int ret; -	ret = ath12k_dp_tx_htt_tx_monitor_mode_ring_config(ar, reset); -	if (ret) { -		ath12k_err(ab, "failed to setup tx monitor filter %d\n", ret); -		return ret; -	} - -	ret = ath12k_dp_tx_htt_tx_monitor_mode_ring_config(ar, reset); +	ret = ath12k_dp_tx_htt_rx_monitor_mode_ring_config(ar, reset);  	if (ret) {  		ath12k_err(ab, "failed to setup rx monitor filter %d\n", ret);  		return ret; @@ -1209,31 +1284,3 @@ err_free:  	dev_kfree_skb_any(skb);  	return ret;  } - -int ath12k_dp_tx_htt_tx_monitor_mode_ring_config(struct ath12k *ar, bool reset) -{ -	struct ath12k_base *ab = ar->ab; -	struct ath12k_dp *dp = &ab->dp; -	struct htt_tx_ring_tlv_filter tlv_filter = {0}; -	int ret, ring_id; - -	ring_id = dp->tx_mon_buf_ring.refill_buf_ring.ring_id; - -	/* TODO: Need to set upstream/downstream tlv filters -	 * here -	 */ - -	if (ab->hw_params->rxdma1_enable) { -		ret = ath12k_dp_tx_htt_tx_filter_setup(ar->ab, ring_id, 0, -						       HAL_TX_MONITOR_BUF, -						       DP_RXDMA_REFILL_RING_SIZE, -						       &tlv_filter); -		if (ret) { -			ath12k_err(ab, -				   "failed to setup filter for monitor buf %d\n", ret); -			return ret; -		} -	} - -	return 0; -} |