Skip to content

Commit

Permalink
ath11k: add tx hw 802.11 encapsulation offloading support
Browse files Browse the repository at this point in the history
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: Shashidhar Lakkavalli <slakkavalli@datto.com>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200430152814.18481-1-john@phrozen.org
  • Loading branch information
John Crispin authored and Kalle Valo committed May 6, 2020
1 parent 52f274b commit e7f33e0
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 12 deletions.
5 changes: 5 additions & 0 deletions drivers/net/wireless/ath/ath11k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
17 changes: 14 additions & 3 deletions drivers/net/wireless/ath/ath11k/dp_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
47 changes: 38 additions & 9 deletions drivers/net/wireless/ath/ath11k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -3740,11 +3747,14 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
if (buf_id < 0)
return -ENOSPC;

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);
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);
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
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) {
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath/ath11k/wmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit e7f33e0

Please sign in to comment.