use wifi TX socket option
Subsystems (2)
Johannes Berg
maintainercover use wifi TX socket option
This makes nl80211 advertise and mac80211 support
the Wifi TX status socket option thing.
It depends on "net: add wireless TX status socket option" that Dave said we can pick up through the wireless tree.
johannes
Johannes Berg
maintainerPATCH 1/2 nl80211: advertise socket TX status capability
From: Johannes Berg <[email protected]>
The new wifi socket TX capability should be
supported by wifi drivers, let them advertise
whether they do or not.
Signed-off-by Johannes Berg <[email protected]>
--- include/linux/nl80211.h | 18 ++++++++++++++++++ include/net/cfg80211.h | 3 ++- net/wireless/nl80211.c | 2 ++ 3 files changed, 22 insertions(+), 1 deletion(-)
include/linux/nl80211.h +18 -0
@@ -695,6 +695,8 @@ enum nl80211_commands {#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS +/* source-level API compatibility */ #define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG#define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG
@@ -1156,6 +1158,9 @@ enum nl80211_commands {* it will also not give a status callback nor return a cookie. This is * mostly useful for probe responses to save airtime. * +* @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from +* &enum nl80211_feature_flags and is advertised in wiphy information. +* * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */
@@ -1388,6 +1393,8 @@ enum nl80211_attrs {NL80211_ATTR_DONT_WAIT_FOR_ACK , +NL80211_ATTR_FEATURE_FLAGS , +/* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST,
@@ -1422,6 +1429,7 @@ enum nl80211_attrs {#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES#define NL80211_ATTR_KEY NL80211_ATTR_KEY#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS#define NL80211_MAX_SUPP_RATES 32#define NL80211_MAX_SUPP_REG_RULES 32
@@ -2714,4 +2722,14 @@ enum nl80211_ap_sme_features { NL80211_AP_SME_WSC = 1 << 0, }; +/** +* enum nl80211_feature_flags - device/driver features +* @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back +* TX status to the socket error queue when requested with the +* socket option. +*/ +enum nl80211_feature_flags { +NL80211_FEATURE_SK_TX_STATUS =1 <<0 , +}; +#endif /* __LINUX_NL80211_H */
include/net/cfg80211.h +2 -1
@@ -1877,6 +1877,7 @@ struct wiphy_wowlan_support {* @software_iftypes: bitmask of software interface types, these are not * subject to any restrictions since they are purely managed in SW. * @flags: wiphy flags, see &enum wiphy_flags +* @features: features advertised to nl80211, see &enum nl80211_feature_flags. * @bss_priv_size: each BSS struct has private data allocated with it, * this variable determines its size * @max_scan_ssids: maximum number of SSIDs the device can scan for in
@@ -1938,7 +1939,7 @@ struct wiphy {/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ u16 interface_modes; -u32 flags; +u32 flags, features;u32 ap_sme_capa;
net/wireless/nl80211.c +2 -0
@@ -1017,6 +1017,8 @@ static int nl80211_send_wiphy(struct sk_NLA_PUT_U32 (msg,NL80211_ATTR_DEVICE_AP_SME , dev->wiphy.ap_sme_capa); +NLA_PUT_U32 (msg,NL80211_ATTR_FEATURE_FLAGS , dev->wiphy.features); +return genlmsg_end (msg, hdr); nla_put_failure:
Johannes Berg
maintainerPATCH 2/2 mac80211: implement wifi TX status
In reply to Johannes BergFrom: Johannes Berg <[email protected]>
Implement the socket wifi TX status error
queue reflection in mac80211.
Signed-off-by Johannes Berg <[email protected]>
--- include/net/mac80211.h | 5 +--- net/mac80211/ieee80211_i.h | 4 +++ net/mac80211/main.c | 18 ++++++++++++++ net/mac80211/status.c | 38 ++++++++++++++++++++++++++++++ net/mac80211/tx.c | 56 ++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 115 insertions(+), 6 deletions(-)
net/mac80211/status.c +38 -0
@@ -548,6 +548,24 @@ void ieee80211_tx_status(struct ieee8021 } } +if (unlikely (info->ack_frame_id)) { +struct sk_buff *ack_skb; +unsigned long flags; + +spin_lock_irqsave (&local->ack_status_lock, flags); + ack_skb =idr_find (&local->ack_status_frames, + info->ack_frame_id); +if (ack_skb) +idr_remove (&local->ack_status_frames, + info->ack_frame_id); +spin_unlock_irqrestore (&local->ack_status_lock, flags); + +/* consumes ack_skb */ +if (ack_skb) +skb_complete_wifi_ack (ack_skb, + info->flags &IEEE80211_TX_STAT_ACK ); + } +/* this was a transmitted frame, but now we want to reuse it */ skb_orphan (skb);
@@ -621,6 +639,26 @@ EXPORT_SYMBOL(ieee80211_report_low_ack);void ieee80211_free_txskb (struct ieee80211_hw *hw,struct sk_buff *skb) { +struct ieee80211_local *local =hw_to_local (hw); +struct ieee80211_tx_info *info =IEEE80211_SKB_CB (skb); + +if (unlikely (info->ack_frame_id)) { +struct sk_buff *ack_skb; +unsigned long flags; + +spin_lock_irqsave (&local->ack_status_lock, flags); + ack_skb =idr_find (&local->ack_status_frames, + info->ack_frame_id); +if (ack_skb) +idr_remove (&local->ack_status_frames, + info->ack_frame_id); +spin_unlock_irqrestore (&local->ack_status_lock, flags); + +/* consumes ack_skb */ +if (ack_skb) +dev_kfree_skb_any (ack_skb); + } +dev_kfree_skb_any (skb); }EXPORT_SYMBOL (ieee80211_free_txskb);
net/mac80211/tx.c +53 -3
85 lines not on this page · raw message
include/net/mac80211.h +2 -3
@@ -518,7 +518,7 @@ struct ieee80211_tx_rate {* @flags: transmit info flags, defined above * @band: the band to transmit on (use for checking for races) * @antenna_sel_tx: antenna to use, 0 for automatic diversity -* @pad: padding, ignore +* @ack_frame_id: internal frame ID for TX status, used internally * @control: union for control data * @status: union for status data * @driver_data: array of driver_data pointers
@@ -535,8 +535,7 @@ struct ieee80211_tx_info {u8 antenna_sel_tx; -/* 2 byte hole */ -u8 pad[2 ]; +u16 ack_frame_id; union { struct {
net/mac80211/ieee80211_i.h +4 -0
@@ -24,6 +24,7 @@#include <linux/spinlock.h> #include <linux/etherdevice.h> #include <linux/leds.h> +#include <linux/idr.h> #include <net/ieee80211_radiotap.h> #include <net/cfg80211.h> #include <net/mac80211.h>
@@ -1017,6 +1018,9 @@ struct ieee80211_local {u32 hw_roc_cookie;bool hw_roc_for_tx; +struct idr ack_status_frames; +spinlock_t ack_status_lock; +/* dummy netdev for use w/ NAPI */ struct net_device napi_dev;
net/mac80211/main.c +18 -0
@@ -598,6 +598,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(WIPHY_FLAG_4ADDR_STATION |WIPHY_FLAG_REPORTS_OBSS ; + wiphy->features =NL80211_FEATURE_SK_TX_STATUS ; +if (!ops->set_key) wiphy->flags |=WIPHY_FLAG_IBSS_RSN ;
@@ -671,6 +673,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(INIT_WORK (&local->sched_scan_stopped_work, ieee80211_sched_scan_stopped_work); +spin_lock_init (&local->ack_status_lock); +idr_init (&local->ack_status_frames); +/* preallocate at least one entry */ +idr_pre_get (&local->ack_status_frames,GFP_KERNEL ); +sta_info_init (local);for (i =0 ; i <IEEE80211_MAX_QUEUES ; i++) {
@@ -1046,6 +1053,13 @@ void ieee80211_unregister_hw(struct ieee }EXPORT_SYMBOL (ieee80211_unregister_hw); +static int ieee80211_free_ack_frame (int id,void *p,void *data) +{ +WARN_ONCE (1 ,"Have pending ack frames!\n" ); +kfree_skb (p); +return 0 ; +} +void ieee80211_free_hw (struct ieee80211_hw *hw) {struct ieee80211_local *local =hw_to_local (hw);
@@ -1056,6 +1070,10 @@ void ieee80211_free_hw(struct ieee80211_if (local->wiphy_ciphers_allocated)kfree (local->hw.wiphy->cipher_suites); +idr_for_each (&local->ack_status_frames, + ieee80211_free_ack_frame,NULL ); +idr_destroy (&local->ack_status_frames); +wiphy_free (local->hw.wiphy); }EXPORT_SYMBOL (ieee80211_free_hw);