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 393501666820..0a49f683de57 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3631,6 +3631,14 @@ enum ieee80211_reconfig_type { * skb is always a real frame, head may or may not be an A-MSDU. * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available. * Statistics should be cumulative, currently no way to reset is provided. + * @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, @@ -3917,6 +3925,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 bb886e7db47f..0dc3b9606e01 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -52,6 +52,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 e019199f6f7b..de2ca3cd16e7 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -153,6 +153,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 03764e58db4c..0add6c47b8e3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1304,6 +1304,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); @@ -1404,6 +1409,8 @@ static void ieee80211_iface_work(struct work_struct *work) break; } + done_skb_free: + kfree_skb(skb); } -- 2.20.1