From: Ben Greear <greearb@xxxxxxxxxxxxxxx> Some drivers, like ath10k-ct support rxswcrypt, but the firmware needs to handle at least part of the blockack logic internally. Since firmware cannot decode the frame in rxswcrypt mode, this patch adds a way for the driver to request to be delivered the decrypted blockack action frames. The driver can then re-insert the decrypted frame for proper handling. Signed-off-by: Ben Greear <greearb@xxxxxxxxxxxxxxx> --- include/net/mac80211.h | 10 ++++++++++ net/mac80211/driver-ops.c | 9 +++++++++ net/mac80211/driver-ops.h | 3 +++ net/mac80211/iface.c | 7 +++++++ 4 files changed, 29 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 523c6a09e1c8..7ea9a17c8cb8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3752,6 +3752,14 @@ enum ieee80211_reconfig_type { * * @start_pmsr: start peer measurement (e.g. FTM) (this call can sleep) * @abort_pmsr: abort peer measurement (this call can sleep) + * @consume_block_ack: Offer block-ack management frames back to driver to see + * if it wishes to consume it. This can be useful for when firmware wants + * to handle block-ack logic itself, but PMF is used and the firmware + * cannot actually decode the block-ack frames itself. So, firmware can + * pass the encoded block-ack up the stack, and receive it through this + * callback. If return value is zero, the mac80211 stack will not further + * process the skb. skb will be freed by calling code, so driver must + * make a copy of anything it needs in the skb before returning. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, @@ -4043,6 +4051,8 @@ struct ieee80211_ops { void (*del_nan_func)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u8 instance_id); + int (*consume_block_ack)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, struct sk_buff* skb); bool (*can_aggregate_in_amsdu)(struct ieee80211_hw *hw, struct sk_buff *head, struct sk_buff *skb); diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index c9a8a2433e8a..aba803bd2718 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -49,6 +49,15 @@ void drv_stop(struct ieee80211_local *local) local->started = false; } +int drv_consume_block_ack(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) +{ + /*pr_warn("consume-block-ack: %p\n", local->ops->consume_block_ack);*/ + if (local->ops->consume_block_ack) + return local->ops->consume_block_ack(&local->hw, &sdata->vif, skb); + return -EINVAL; +} + int drv_add_interface(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) { diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index e734a85165ad..b3cf5d88f83e 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -148,6 +148,9 @@ static inline void drv_set_wakeup(struct ieee80211_local *local, } #endif +int drv_consume_block_ack(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); + int drv_add_interface(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index af8b09214786..f050410d0986 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1249,6 +1249,11 @@ static void ieee80211_iface_work(struct work_struct *work) if (ieee80211_is_action(mgmt->frame_control) && mgmt->u.action.category == WLAN_CATEGORY_BACK) { int len = skb->len; + int barv = drv_consume_block_ack(local, sdata, skb); + + /*pr_err("called drv_consume_blockack, rv: %d\n", barv);*/ + if (barv == 0) + goto done_skb_free; mutex_lock(&local->sta_mtx); sta = sta_info_get_bss(sdata, mgmt->sa); @@ -1349,6 +1354,8 @@ static void ieee80211_iface_work(struct work_struct *work) break; } + done_skb_free: + kfree_skb(skb); } -- 2.20.1