Commit e7f33e0c authored by John Crispin's avatar John Crispin Committed by Kalle Valo
Browse files

ath11k: add tx hw 802.11 encapsulation offloading support



This patch adds support for ethernet rxtx mode to the driver. The feature
is enabled via a new module parameter. If enabled to driver will enable
the feature on a per vif basis if all other requirements were met.

Signed-off-by: default avatarShashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: default avatarJohn Crispin <john@phrozen.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200430152814.18481-1-john@phrozen.org
parent 52f274b5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -60,9 +60,14 @@ static inline enum wme_ac ath11k_tid_to_ac(u32 tid)
		WME_AC_VO);
}

enum ath11k_skb_flags {
	ATH11K_SKB_HW_80211_ENCAP = BIT(0),
};

struct ath11k_skb_cb {
	dma_addr_t paddr;
	u8 eid;
	u8 flags;
	struct ath11k *ar;
	struct ieee80211_vif *vif;
} __packed;
+14 −3
Original line number Diff line number Diff line
@@ -12,7 +12,11 @@
static enum hal_tcl_encap_type
ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb)
{
	/* TODO: Determine encap type based on vif_type and configuration */
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);

	if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
		return HAL_TCL_ENCAP_TYPE_ETHERNET;

	return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI;
}

@@ -36,8 +40,11 @@ static void ath11k_dp_tx_encap_nwifi(struct sk_buff *skb)
static u8 ath11k_dp_tx_get_tid(struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (void *)skb->data;
	struct ath11k_skb_cb *cb = ATH11K_SKB_CB(skb);

	if (!ieee80211_is_data_qos(hdr->frame_control))
	if (cb->flags & ATH11K_SKB_HW_80211_ENCAP)
		return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
	else if (!ieee80211_is_data_qos(hdr->frame_control))
		return HAL_DESC_REO_NON_QOS_TID;
	else
		return skb->priority & IEEE80211_QOS_CTL_TID_MASK;
@@ -86,7 +93,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
	if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags))
		return -ESHUTDOWN;

	if (!ieee80211_is_data(hdr->frame_control))
	if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) &&
	    !ieee80211_is_data(hdr->frame_control))
		return -ENOTSUPP;

	pool_id = skb_get_queue_mapping(skb) & (ATH11K_HW_MAX_QUEUES - 1);
@@ -166,7 +174,10 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
		 *	  skb_checksum_help() is needed
		 */
	case HAL_TCL_ENCAP_TYPE_ETHERNET:
		/* no need to encap */
		break;
	case HAL_TCL_ENCAP_TYPE_802_3:
	default:
		/* TODO: Take care of other encap modes as well */
		ret = -EINVAL;
		goto fail_remove_idr;
+38 −9
Original line number Diff line number Diff line
@@ -33,6 +33,12 @@
	.max_power              = 30, \
}

/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
static unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
MODULE_PARM_DESC(frame_mode,
		 "Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");

static const struct ieee80211_channel ath11k_2ghz_channels[] = {
	CHAN2G(1, 2412, 0),
	CHAN2G(2, 2417, 0),
@@ -3686,10 +3692,10 @@ static int __ath11k_set_antenna(struct ath11k *ar, u32 tx_ant, u32 rx_ant)

int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx)
{
	struct sk_buff *msdu = skb;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
	struct ath11k *ar = ctx;
	struct ath11k_base *ab = ar->ab;
	struct sk_buff *msdu = skb;
	struct ieee80211_tx_info *info;

	spin_lock_bh(&ar->txmgmt_idr_lock);
	idr_remove(&ar->txmgmt_idr, buf_id);
@@ -3729,6 +3735,7 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
{
	struct ath11k_base *ab = ar->ab;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct ieee80211_tx_info *info;
	dma_addr_t paddr;
	int buf_id;
	int ret;
@@ -3740,12 +3747,15 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
	if (buf_id < 0)
		return -ENOSPC;

	info = IEEE80211_SKB_CB(skb);
	if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)) {
		if ((ieee80211_is_action(hdr->frame_control) ||
		     ieee80211_is_deauth(hdr->frame_control) ||
		     ieee80211_is_disassoc(hdr->frame_control)) &&
		     ieee80211_has_protected(hdr->frame_control)) {
			skb_put(skb, IEEE80211_CCMP_MIC_LEN);
		}
	}

	paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE);
	if (dma_mapping_error(ab->dev, paddr)) {
@@ -3856,6 +3866,7 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
			     struct ieee80211_tx_control *control,
			     struct sk_buff *skb)
{
	struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
	struct ath11k *ar = hw->priv;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_vif *vif = info->control.vif;
@@ -3864,7 +3875,9 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
	bool is_prb_rsp;
	int ret;

	if (ieee80211_is_mgmt(hdr->frame_control)) {
	if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) {
		skb_cb->flags |= ATH11K_SKB_HW_80211_ENCAP;
	} else if (ieee80211_is_mgmt(hdr->frame_control)) {
		is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
		ret = ath11k_mac_mgmt_tx(ar, skb, is_prb_rsp);
		if (ret) {
@@ -4145,6 +4158,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
	struct vdev_create_params vdev_param = {0};
	struct peer_create_params peer_param;
	u32 param_id, param_value;
	int hw_encap = 0;
	u16 nss;
	int i;
	int ret;
@@ -4239,7 +4253,22 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
	spin_unlock_bh(&ar->data_lock);

	param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE;
	if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET)
		switch (vif->type) {
		case NL80211_IFTYPE_STATION:
		case NL80211_IFTYPE_AP_VLAN:
		case NL80211_IFTYPE_AP:
			hw_encap = 1;
			break;
		default:
			break;
		}

	if (ieee80211_set_hw_80211_encap(vif, hw_encap))
		param_value = ATH11K_HW_TXRX_ETHERNET;
	else
		param_value = ATH11K_HW_TXRX_NATIVE_WIFI;

	ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
					    param_id, param_value);
	if (ret) {
+3 −0
Original line number Diff line number Diff line
@@ -4568,6 +4568,9 @@ enum wmi_sta_ps_param_rx_wake_policy {
	WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD = 1,
};

/* Do not change existing values! Used by ath11k_frame_mode parameter
 * module parameter.
 */
enum ath11k_hw_txrx_mode {
	ATH11K_HW_TXRX_RAW = 0,
	ATH11K_HW_TXRX_NATIVE_WIFI = 1,