From ab09587740fddf6b4116be7b6716ab47f34d2634 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 27 Jul 2012 12:33:22 +0300 Subject: mac80211: add PS flag to bss_conf Currently, ps mode is indicated per device (rather than per interface), which doesn't make a lot of sense. Moreover, there are subtle bugs caused by the inability to indicate ps change along with other changes (e.g. when the AP deauth us, we'd like to indicate CHANGED_PS | CHANGED_ASSOC, as changing PS before notifying about disassociation will result in null-packets being sent (if IEEE80211_HW_SUPPORTS_DYNAMIC_PS) while the sta is already disconnected.) Keep the current per-device notifications, and add parallel per-vif notifications. In order to keep it simple, the per-device ps and the per-vif ps are orthogonal - the per-vif ps configuration is determined only by the user configuration (enable/disable) and the connection state, and is not affected by other vifs state and (temporary) dynamic_ps/offchannel operations (unlike per-device ps). Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- include/net/mac80211.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index bb86aa6f98dd..d67d3bbe21c1 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -171,6 +171,7 @@ struct ieee80211_low_level_stats { * @BSS_CHANGED_IDLE: Idle changed for this BSS/interface. * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode) * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode) + * @BSS_CHANGED_PS: PS changed for this BSS (STA mode) */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -190,6 +191,7 @@ enum ieee80211_bss_change { BSS_CHANGED_IDLE = 1<<14, BSS_CHANGED_SSID = 1<<15, BSS_CHANGED_AP_PROBE_RESP = 1<<16, + BSS_CHANGED_PS = 1<<17, /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -266,6 +268,8 @@ enum ieee80211_rssi_event { * @idle: This interface is idle. There's also a global idle flag in the * hardware config which may be more appropriate depending on what * your driver/device needs to do. + * @ps: power-save mode (STA only). This flag is NOT affected by + * offchannel/dynamic_ps operations. * @ssid: The SSID of the current vif. Only valid in AP-mode. * @ssid_len: Length of SSID given in @ssid. * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode. @@ -296,6 +300,7 @@ struct ieee80211_bss_conf { bool arp_filter_enabled; bool qos; bool idle; + bool ps; u8 ssid[IEEE80211_MAX_SSID_LEN]; size_t ssid_len; bool hidden_ssid; -- cgit v1.2.3-71-gd317 From 36323f817af0376c78612cfdab714b0feb05fea5 Mon Sep 17 00:00:00 2001 From: Thomas Huehn Date: Mon, 23 Jul 2012 21:33:42 +0200 Subject: mac80211: move TX station pointer and restructure TX Remove the control.sta pointer from ieee80211_tx_info to free up sufficient space in the TX skb control buffer for the upcoming Transmit Power Control (TPC). Instead, the pointer is now on the stack in a new control struct that is passed as a function parameter to the drivers' tx method. Signed-off-by: Thomas Huehn Signed-off-by: Alina Friedrichsen Signed-off-by: Felix Fietkau [reworded commit message] Signed-off-by: Johannes Berg --- drivers/net/wireless/adm8211.c | 4 +++- drivers/net/wireless/at76c50x-usb.c | 4 +++- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 3 ++- drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/htc.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 +++-- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 5 ++++- drivers/net/wireless/ath/ath9k/xmit.c | 9 ++++---- drivers/net/wireless/ath/carl9170/carl9170.h | 4 +++- drivers/net/wireless/ath/carl9170/tx.c | 16 ++++++------- drivers/net/wireless/b43/main.c | 3 ++- drivers/net/wireless/b43legacy/main.c | 1 + .../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 6 +++-- drivers/net/wireless/iwlegacy/3945-mac.c | 12 ++++++---- drivers/net/wireless/iwlegacy/4965-mac.c | 26 +++++++++++++--------- drivers/net/wireless/iwlegacy/4965.h | 8 +++++-- drivers/net/wireless/iwlwifi/dvm/agn.h | 4 +++- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 6 +++-- drivers/net/wireless/iwlwifi/dvm/tx.c | 16 +++++++------ drivers/net/wireless/libertas_tf/main.c | 4 +++- drivers/net/wireless/mac80211_hwsim.c | 8 ++++--- drivers/net/wireless/mwl8k.c | 17 ++++++++------ drivers/net/wireless/p54/lmac.h | 4 +++- drivers/net/wireless/p54/main.c | 2 +- drivers/net/wireless/p54/txrx.c | 15 ++++++++----- drivers/net/wireless/rt2x00/rt2x00.h | 4 +++- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 4 +++- drivers/net/wireless/rt2x00/rt2x00queue.c | 20 +++++++++-------- drivers/net/wireless/rtl818x/rtl8180/dev.c | 6 +++-- drivers/net/wireless/rtl818x/rtl8187/dev.c | 6 +++-- drivers/net/wireless/rtlwifi/base.c | 3 +-- drivers/net/wireless/rtlwifi/core.c | 8 ++++--- drivers/net/wireless/rtlwifi/pci.c | 16 ++++++------- drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 5 +++-- drivers/net/wireless/rtlwifi/rtl8192ce/trx.h | 1 + drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 5 +++-- drivers/net/wireless/rtlwifi/rtl8192cu/trx.h | 4 +++- drivers/net/wireless/rtlwifi/rtl8192de/trx.c | 5 +++-- drivers/net/wireless/rtlwifi/rtl8192de/trx.h | 1 + drivers/net/wireless/rtlwifi/rtl8192se/trx.c | 5 +++-- drivers/net/wireless/rtlwifi/rtl8192se/trx.h | 1 + drivers/net/wireless/rtlwifi/usb.c | 15 ++++++++----- drivers/net/wireless/rtlwifi/wifi.h | 13 +++++++---- drivers/net/wireless/ti/wl1251/main.c | 4 +++- drivers/net/wireless/ti/wlcore/main.c | 6 +++-- drivers/net/wireless/zd1211rw/zd_mac.c | 6 +++-- drivers/staging/winbond/wbusb.c | 4 +++- include/net/mac80211.h | 20 ++++++++++++----- net/mac80211/driver-ops.h | 6 +++-- net/mac80211/tx.c | 5 +++-- 53 files changed, 232 insertions(+), 132 deletions(-) (limited to 'include') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 689a71c1af71..154a4965be4f 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1661,7 +1661,9 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, } /* Put adm8211_tx_hdr on skb and transmit */ -static void adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) +static void adm8211_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct adm8211_tx_hdr *txhdr; size_t payload_len, hdrlen; diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index efc162e0b511..abb520dec032 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1726,7 +1726,9 @@ static void at76_mac80211_tx_callback(struct urb *urb) ieee80211_wake_queues(priv->hw); } -static void at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void at76_mac80211_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct at76_priv *priv = hw->priv; struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer; diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 260e7dc7f751..934f04c1cb9d 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -55,7 +55,8 @@ \********************/ static void -ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +ath5k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct ath5k_hw *ah = hw->priv; u16 qnum = skb_get_queue_mapping(skb); diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b09285c36c4a..7373e4b92c92 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -280,6 +280,7 @@ struct ath_tx_control { struct ath_txq *txq; struct ath_node *an; u8 paprd; + struct ieee80211_sta *sta; }; #define ATH_TX_ERROR 0x01 diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 936e920fb88e..b30596fcf73a 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -542,6 +542,7 @@ void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); int ath9k_tx_init(struct ath9k_htc_priv *priv); int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, + struct ieee80211_sta *sta, struct sk_buff *skb, u8 slot, bool is_cab); void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 77d541feb910..f42d2eb6af99 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -326,7 +326,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, goto next; } - ret = ath9k_htc_tx_start(priv, skb, tx_slot, true); + ret = ath9k_htc_tx_start(priv, NULL, skb, tx_slot, true); if (ret != 0) { ath9k_htc_tx_clear_slot(priv, tx_slot); dev_kfree_skb_any(skb); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index c785129692ff..8a0ccf70aa14 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -856,7 +856,9 @@ set_timer: /* mac80211 Callbacks */ /**********************/ -static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void ath9k_htc_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct ath9k_htc_priv *priv = hw->priv; @@ -883,7 +885,7 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) goto fail_tx; } - ret = ath9k_htc_tx_start(priv, skb, slot, false); + ret = ath9k_htc_tx_start(priv, control->sta, skb, slot, false); if (ret != 0) { ath_dbg(common, XMIT, "Tx failed\n"); goto clear_slot; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 47e61d0da33b..06cdcb772d78 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -333,12 +333,12 @@ static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv, } int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, + struct ieee80211_sta *sta, struct sk_buff *skb, u8 slot, bool is_cab) { struct ieee80211_hdr *hdr; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_vif *vif = tx_info->control.vif; struct ath9k_htc_sta *ista; struct ath9k_htc_vif *avp = NULL; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6049d8b82855..4d8dc9ff5a75 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -694,7 +694,9 @@ mutex_unlock: return r; } -static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void ath9k_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -754,6 +756,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) memset(&txctl, 0, sizeof(struct ath_tx_control)); txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)]; + txctl.sta = control->sta; ath_dbg(common, XMIT, "transmitting packet, skb: %p\n", skb); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c9da6b2ecb1..ef91f6cc2d79 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1773,11 +1773,12 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, TX_STAT_INC(txq->axq_qnum, queued); } -static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, +static void setup_frame_info(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, int framelen) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; const struct ieee80211_rate *rate; @@ -1935,7 +1936,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; + struct ieee80211_sta *sta = txctl->sta; struct ieee80211_vif *vif = info->control.vif; struct ath_softc *sc = hw->priv; struct ath_txq *txq = txctl->txq; @@ -1979,7 +1980,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, !ieee80211_is_data(hdr->frame_control)) info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; - setup_frame_info(hw, skb, frmlen); + setup_frame_info(hw, sta, skb, frmlen); /* * At this point, the vif, hw_key and sta pointers in the tx control diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 376be11161c0..8f0cbc35816f 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -577,7 +577,9 @@ void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len); void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); /* TX */ -void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +void carl9170_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb); void carl9170_tx_janitor(struct work_struct *work); void carl9170_tx_process_status(struct ar9170 *ar, const struct carl9170_rsp *cmd); diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 6a8681407a1d..84377cf580e0 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -867,14 +867,15 @@ static bool carl9170_tx_cts_check(struct ar9170 *ar, return false; } -static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) +static int carl9170_tx_prepare(struct ar9170 *ar, + struct ieee80211_sta *sta, + struct sk_buff *skb) { struct ieee80211_hdr *hdr; struct _carl9170_tx_superframe *txc; struct carl9170_vif_info *cvif; struct ieee80211_tx_info *info; struct ieee80211_tx_rate *txrate; - struct ieee80211_sta *sta; struct carl9170_tx_info *arinfo; unsigned int hw_queue; int i; @@ -910,8 +911,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) else cvif = NULL; - sta = info->control.sta; - txc = (void *)skb_push(skb, sizeof(*txc)); memset(txc, 0, sizeof(*txc)); @@ -1457,20 +1456,21 @@ err_unlock_rcu: return false; } -void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +void carl9170_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct ar9170 *ar = hw->priv; struct ieee80211_tx_info *info; - struct ieee80211_sta *sta; + struct ieee80211_sta *sta = control->sta; bool run; if (unlikely(!IS_STARTED(ar))) goto err_free; info = IEEE80211_SKB_CB(skb); - sta = info->control.sta; - if (unlikely(carl9170_tx_prepare(ar, skb))) + if (unlikely(carl9170_tx_prepare(ar, sta, skb))) goto err_free; carl9170_tx_accounting(ar, skb); diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index b80352b308d5..2ca4e885f5ff 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3407,7 +3407,8 @@ static void b43_tx_work(struct work_struct *work) } static void b43_op_tx(struct ieee80211_hw *hw, - struct sk_buff *skb) + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct b43_wl *wl = hw_to_b43_wl(hw); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 8156135a0590..74d4c20cc31b 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2492,6 +2492,7 @@ static void b43legacy_tx_work(struct work_struct *work) } static void b43legacy_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, struct sk_buff *skb) { struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 9e79d47e077f..a7be68d2eaf7 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -264,7 +264,9 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) } } -static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void brcms_ops_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct brcms_info *wl = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@ -276,7 +278,7 @@ static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb) goto done; } brcms_c_sendpkt_mac80211(wl->wlc, skb, hw); - tx_info->rate_driver_data[0] = tx_info->control.sta; + tx_info->rate_driver_data[0] = control->sta; done: spin_unlock_bh(&wl->lock); } diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index faec40467208..e252acb9c862 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -460,7 +460,9 @@ il3945_build_tx_cmd_basic(struct il_priv *il, struct il_device_cmd *cmd, * start C_TX command process */ static int -il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) +il3945_tx_skb(struct il_priv *il, + struct ieee80211_sta *sta, + struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -512,7 +514,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); /* Find idx into station table for destination station */ - sta_id = il_sta_id_or_broadcast(il, info->control.sta); + sta_id = il_sta_id_or_broadcast(il, sta); if (sta_id == IL_INVALID_STATION) { D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); goto drop; @@ -2859,7 +2861,9 @@ il3945_mac_stop(struct ieee80211_hw *hw) } static void -il3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +il3945_mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct il_priv *il = hw->priv; @@ -2868,7 +2872,7 @@ il3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); - if (il3945_tx_skb(il, skb)) + if (il3945_tx_skb(il, control->sta, skb)) dev_kfree_skb_any(skb); D_MAC80211("leave\n"); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 34f61a0581a2..eac4dc8bc879 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -1526,8 +1526,11 @@ il4965_tx_cmd_build_basic(struct il_priv *il, struct sk_buff *skb, } static void -il4965_tx_cmd_build_rate(struct il_priv *il, struct il_tx_cmd *tx_cmd, - struct ieee80211_tx_info *info, __le16 fc) +il4965_tx_cmd_build_rate(struct il_priv *il, + struct il_tx_cmd *tx_cmd, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + __le16 fc) { const u8 rts_retry_limit = 60; u32 rate_flags; @@ -1561,9 +1564,7 @@ il4965_tx_cmd_build_rate(struct il_priv *il, struct il_tx_cmd *tx_cmd, rate_idx = info->control.rates[0].idx; if ((info->control.rates[0].flags & IEEE80211_TX_RC_MCS) || rate_idx < 0 || rate_idx > RATE_COUNT_LEGACY) - rate_idx = - rate_lowest_index(&il->bands[info->band], - info->control.sta); + rate_idx = rate_lowest_index(&il->bands[info->band], sta); /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ if (info->band == IEEE80211_BAND_5GHZ) rate_idx += IL_FIRST_OFDM_RATE; @@ -1630,11 +1631,12 @@ il4965_tx_cmd_build_hwcrypto(struct il_priv *il, struct ieee80211_tx_info *info, * start C_TX command process */ int -il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) +il4965_tx_skb(struct il_priv *il, + struct ieee80211_sta *sta, + struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; struct il_station_priv *sta_priv = NULL; struct il_tx_queue *txq; struct il_queue *q; @@ -1680,7 +1682,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) sta_id = il->hw_params.bcast_id; else { /* Find idx into station table for destination station */ - sta_id = il_sta_id_or_broadcast(il, info->control.sta); + sta_id = il_sta_id_or_broadcast(il, sta); if (sta_id == IL_INVALID_STATION) { D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -1786,7 +1788,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) /* TODO need this for burst mode later on */ il4965_tx_cmd_build_basic(il, skb, tx_cmd, info, hdr, sta_id); - il4965_tx_cmd_build_rate(il, tx_cmd, info, fc); + il4965_tx_cmd_build_rate(il, tx_cmd, info, sta, fc); il_update_stats(il, true, fc, len); /* @@ -5828,7 +5830,9 @@ il4965_mac_stop(struct ieee80211_hw *hw) } void -il4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +il4965_mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct il_priv *il = hw->priv; @@ -5837,7 +5841,7 @@ il4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) D_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); - if (il4965_tx_skb(il, skb)) + if (il4965_tx_skb(il, control->sta, skb)) dev_kfree_skb_any(skb); D_MACDUMP("leave\n"); diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 1db677689cfe..2d092f328547 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h @@ -78,7 +78,9 @@ int il4965_hw_txq_attach_buf_to_tfd(struct il_priv *il, struct il_tx_queue *txq, int il4965_hw_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq); void il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags, struct ieee80211_tx_info *info); -int il4965_tx_skb(struct il_priv *il, struct sk_buff *skb); +int il4965_tx_skb(struct il_priv *il, + struct ieee80211_sta *sta, + struct sk_buff *skb); int il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 * ssn); int il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif, @@ -163,7 +165,9 @@ void il4965_eeprom_release_semaphore(struct il_priv *il); int il4965_eeprom_check_version(struct il_priv *il); /* mac80211 handlers (for 4965) */ -void il4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +void il4965_mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb); int il4965_mac_start(struct ieee80211_hw *hw); void il4965_mac_stop(struct ieee80211_hw *hw); void il4965_configure_filter(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 9bb16bdf6d26..f0b8c1f7591c 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h @@ -201,7 +201,9 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success); /* tx */ -int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); +int iwlagn_tx_skb(struct iwl_priv *priv, + struct ieee80211_sta *sta, + struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index a5f7bce96325..e64af60a37c1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -511,14 +511,16 @@ static void iwlagn_mac_set_wakeup(struct ieee80211_hw *hw, bool enabled) } #endif -static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void iwlagn_mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); - if (iwlagn_tx_skb(priv, skb)) + if (iwlagn_tx_skb(priv, control->sta, skb)) dev_kfree_skb_any(skb); } diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index 5971a23aa47d..d17799b316d7 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -127,6 +127,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, struct iwl_tx_cmd *tx_cmd, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, __le16 fc) { u32 rate_flags; @@ -187,8 +188,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) rate_idx = rate_lowest_index( - &priv->eeprom_data->bands[info->band], - info->control.sta); + &priv->eeprom_data->bands[info->band], sta); /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ if (info->band == IEEE80211_BAND_5GHZ) rate_idx += IWL_FIRST_OFDM_RATE; @@ -291,7 +291,9 @@ static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context, /* * start REPLY_TX command process */ -int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) +int iwlagn_tx_skb(struct iwl_priv *priv, + struct ieee80211_sta *sta, + struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -345,7 +347,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) sta_id = ctx->bcast_sta_id; else { /* Find index into station table for destination station */ - sta_id = iwl_sta_id_or_broadcast(ctx, info->control.sta); + sta_id = iwl_sta_id_or_broadcast(ctx, sta); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -355,8 +357,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); - if (info->control.sta) - sta_priv = (void *)info->control.sta->drv_priv; + if (sta) + sta_priv = (void *)sta->drv_priv; if (sta_priv && sta_priv->asleep && (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)) { @@ -397,7 +399,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* TODO need this for burst mode later on */ iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id); - iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); + iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, sta, fc); memset(&info->status, 0, sizeof(info->status)); diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index a03457292c88..7001856241e6 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -227,7 +227,9 @@ static void lbtf_free_adapter(struct lbtf_private *priv) lbtf_deb_leave(LBTF_DEB_MAIN); } -static void lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void lbtf_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct lbtf_private *priv = hw->priv; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 643f968b05ee..ed1386aa3b17 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -709,7 +709,9 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, return ack; } -static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void mac80211_hwsim_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { bool ack; struct ieee80211_tx_info *txi; @@ -741,8 +743,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (txi->control.vif) hwsim_check_magic(txi->control.vif); - if (txi->control.sta) - hwsim_check_sta_magic(txi->control.sta); + if (control->sta) + hwsim_check_sta_magic(control->sta); ieee80211_tx_info_clear_status(txi); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 224e03ade145..5099e5375cb3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -1830,12 +1830,14 @@ static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid) } static void -mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) +mwl8k_txq_xmit(struct ieee80211_hw *hw, + int index, + struct ieee80211_sta *sta, + struct sk_buff *skb) { struct mwl8k_priv *priv = hw->priv; struct ieee80211_tx_info *tx_info; struct mwl8k_vif *mwl8k_vif; - struct ieee80211_sta *sta; struct ieee80211_hdr *wh; struct mwl8k_tx_queue *txq; struct mwl8k_tx_desc *tx; @@ -1867,7 +1869,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) wh = &((struct mwl8k_dma_data *)skb->data)->wh; tx_info = IEEE80211_SKB_CB(skb); - sta = tx_info->control.sta; mwl8k_vif = MWL8K_VIF(tx_info->control.vif); if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { @@ -2019,8 +2020,8 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) tx->pkt_phys_addr = cpu_to_le32(dma); tx->pkt_len = cpu_to_le16(skb->len); tx->rate_info = 0; - if (!priv->ap_fw && tx_info->control.sta != NULL) - tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id; + if (!priv->ap_fw && sta != NULL) + tx->peer_id = MWL8K_STA(sta)->peer_id; else tx->peer_id = 0; @@ -4364,7 +4365,9 @@ static void mwl8k_rx_poll(unsigned long data) /* * Core driver operations. */ -static void mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void mwl8k_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct mwl8k_priv *priv = hw->priv; int index = skb_get_queue_mapping(skb); @@ -4376,7 +4379,7 @@ static void mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return; } - mwl8k_txq_xmit(hw, index, skb); + mwl8k_txq_xmit(hw, index, control->sta, skb); } static int mwl8k_start(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h index 3d8d622bec55..de1d46bf97df 100644 --- a/drivers/net/wireless/p54/lmac.h +++ b/drivers/net/wireless/p54/lmac.h @@ -526,7 +526,9 @@ int p54_init_leds(struct p54_common *priv); void p54_unregister_leds(struct p54_common *priv); /* xmit functions */ -void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb); +void p54_tx_80211(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb); int p54_tx_cancel(struct p54_common *priv, __le32 req_id); void p54_tx(struct p54_common *priv, struct sk_buff *skb); diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 7cffea795ad2..5e91ad06dd5d 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -158,7 +158,7 @@ static int p54_beacon_update(struct p54_common *priv, * to cancel the old beacon template by hand, instead the firmware * will release the previous one through the feedback mechanism. */ - p54_tx_80211(priv->hw, beacon); + p54_tx_80211(priv->hw, NULL, beacon); priv->tsf_high32 = 0; priv->tsf_low32 = 0; diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index f38786e02623..5861e13a6fd8 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -676,8 +676,9 @@ int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) EXPORT_SYMBOL_GPL(p54_rx); static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, - struct ieee80211_tx_info *info, u8 *queue, - u32 *extra_len, u16 *flags, u16 *aid, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + u8 *queue, u32 *extra_len, u16 *flags, u16 *aid, bool *burst_possible) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -746,8 +747,8 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, } } - if (info->control.sta) - *aid = info->control.sta->aid; + if (sta) + *aid = sta->aid; break; } } @@ -767,7 +768,9 @@ static u8 p54_convert_algo(u32 cipher) } } -void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) +void p54_tx_80211(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct p54_common *priv = dev->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -784,7 +787,7 @@ void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) u8 nrates = 0, nremaining = 8; bool burst_allowed = false; - p54_tx_80211_header(priv, skb, info, &queue, &extra_len, + p54_tx_80211_header(priv, skb, info, control->sta, &queue, &extra_len, &hdr_flags, &aid, &burst_allowed); if (p54_tx_qos_accounting_alloc(priv, skb, queue)) { diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8afb546c2b2d..f991e8bedc70 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1287,7 +1287,9 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp); /* * mac80211 handlers. */ -void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +void rt2x00mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb); int rt2x00mac_start(struct ieee80211_hw *hw); void rt2x00mac_stop(struct ieee80211_hw *hw); int rt2x00mac_add_interface(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a6b88bd4a1a5..a59048ffa092 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -194,7 +194,7 @@ static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac, */ skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); while (skb) { - rt2x00mac_tx(rt2x00dev->hw, skb); + rt2x00mac_tx(rt2x00dev->hw, NULL, skb); skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif); } } diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 4ff26c2159bf..c3d0f2f87b69 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -99,7 +99,9 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, return retval; } -void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +void rt2x00mac_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index f7e74a0a7759..e488b944a034 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -315,6 +315,7 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct txentry_desc *txdesc, + struct ieee80211_sta *sta, const struct rt2x00_rate *hwrate) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@ -322,11 +323,11 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rt2x00_sta *sta_priv = NULL; - if (tx_info->control.sta) { + if (sta) { txdesc->u.ht.mpdu_density = - tx_info->control.sta->ht_cap.ampdu_density; + sta->ht_cap.ampdu_density; - sta_priv = sta_to_rt2x00_sta(tx_info->control.sta); + sta_priv = sta_to_rt2x00_sta(sta); txdesc->u.ht.wcid = sta_priv->wcid; } @@ -341,8 +342,8 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, * MIMO PS should be set to 1 for STA's using dynamic SM PS * when using more then one tx stream (>MCS7). */ - if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && - ((tx_info->control.sta->ht_cap.cap & + if (sta && txdesc->u.ht.mcs > 7 && + ((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> IEEE80211_HT_CAP_SM_PS_SHIFT) == WLAN_HT_CAP_SM_PS_DYNAMIC) @@ -409,7 +410,8 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txentry_desc *txdesc) + struct txentry_desc *txdesc, + struct ieee80211_sta *sta) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -503,7 +505,7 @@ static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc, - hwrate); + sta, hwrate); else rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc, hwrate); @@ -595,7 +597,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, * after that we are free to use the skb->cb array * for our information. */ - rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc); + rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, NULL); /* * All information is retrieved from the skb->cb array, @@ -740,7 +742,7 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev, * after that we are free to use the skb->cb array * for our information. */ - rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc); + rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc, NULL); /* * Fill in skb descriptor diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index aceaf689f737..021d83e1b1d3 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -244,7 +244,9 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) +static void rtl8180_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -710,7 +712,7 @@ static void rtl8180_beacon_work(struct work_struct *work) /* TODO: use actual beacon queue */ skb_set_queue_mapping(skb, 0); - rtl8180_tx(dev, skb); + rtl8180_tx(dev, NULL, skb); resched: /* diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index 71a30b026089..05d8ca045afd 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -228,7 +228,9 @@ static void rtl8187_tx_cb(struct urb *urb) } } -static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) +static void rtl8187_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct rtl8187_priv *priv = dev->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -1076,7 +1078,7 @@ static void rtl8187_beacon_work(struct work_struct *work) /* TODO: use actual beacon queue */ skb_set_queue_mapping(skb, 0); - rtl8187_tx(dev, skb); + rtl8187_tx(dev, NULL, skb); resched: /* diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 942e56b77b60..59381fe8ed06 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -1341,9 +1341,8 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0); info->control.rates[0].idx = 0; - info->control.sta = sta; info->band = hw->conf.channel->band; - rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); + rtlpriv->intf_ops->adapter_tx(hw, sta, skb, &tcb_desc); } err_free: return 0; diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index a18ad2a98938..a7c0e52869ba 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -124,7 +124,9 @@ static void rtl_op_stop(struct ieee80211_hw *hw) mutex_unlock(&rtlpriv->locks.conf_mutex); } -static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void rtl_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); @@ -138,8 +140,8 @@ static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (!test_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status)) goto err_free; - if (!rtlpriv->intf_ops->waitq_insert(hw, skb)) - rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); + if (!rtlpriv->intf_ops->waitq_insert(hw, control->sta, skb)) + rtlpriv->intf_ops->adapter_tx(hw, control->sta, skb, &tcb_desc); return; diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 80f75d3ba84a..aad9d44c0a51 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -504,7 +504,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) _rtl_update_earlymode_info(hw, skb, &tcb_desc, tid); - rtlpriv->intf_ops->adapter_tx(hw, skb, &tcb_desc); + rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, &tcb_desc); } } } @@ -929,7 +929,7 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) info = IEEE80211_SKB_CB(pskb); pdesc = &ring->desc[0]; rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *) pdesc, - info, pskb, BEACON_QUEUE, &tcb_desc); + info, NULL, pskb, BEACON_QUEUE, &tcb_desc); __skb_queue_tail(&ring->queue, pskb); @@ -1305,11 +1305,10 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) } static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; struct rtl_sta_info *sta_entry = NULL; u8 tid = rtl_get_tid(skb); @@ -1337,13 +1336,14 @@ static bool rtl_pci_tx_chk_waitq_insert(struct ieee80211_hw *hw, return true; } -static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, - struct rtl_tcb_desc *ptcb_desc) +static int rtl_pci_tx(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_sta_info *sta_entry = NULL; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_sta *sta = info->control.sta; struct rtl8192_tx_ring *ring; struct rtl_tx_desc *pdesc; u8 idx; @@ -1418,7 +1418,7 @@ static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb, rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, - info, skb, hw_queue, ptcb_desc); + info, sta, skb, hw_queue, ptcb_desc); __skb_queue_tail(&ring->queue, skb); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 52166640f167..390d6d4fcaa0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -596,7 +596,9 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *tcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -604,7 +606,6 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta; u8 *pdesc = pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index c4adb9777365..a7cdd514cb2e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -713,6 +713,7 @@ struct rx_desc_92c { void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 2e6eb356a93e..27863d773790 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -496,7 +496,9 @@ static void _rtl_tx_desc_checksum(u8 *txdesc) void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 queue_index, struct rtl_tcb_desc *tcb_desc) { @@ -504,7 +506,6 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool defaultadapter = true; - struct ieee80211_sta *sta = info->control.sta = info->control.sta; u8 *qc = ieee80211_get_qos_ctl(hdr); u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; u16 seq_number; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h index 332b06e78b00..725c53accc58 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h @@ -420,7 +420,9 @@ struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *, struct sk_buff_head *); void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 queue_index, struct rtl_tcb_desc *tcb_desc); void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc, diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index f80690d82c11..4686f340b9d6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -551,7 +551,9 @@ static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -559,7 +561,6 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); - struct ieee80211_sta *sta = info->control.sta; u8 *pdesc = pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h index 057a52431b00..c1b5dfb79d53 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h @@ -730,6 +730,7 @@ struct rx_desc_92d { void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 36d1cb3aef8a..28c53fb12aeb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -591,14 +591,15 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, - struct ieee80211_tx_info *info, struct sk_buff *skb, + struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, + struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct ieee80211_sta *sta = info->control.sta; u8 *pdesc = pdesc_tx; u16 seq_number; __le16 fc = hdr->frame_control; diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/rtlwifi/rtl8192se/trx.h index 011e7b0695f2..64dd66f287c1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.h @@ -31,6 +31,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index aa970fc18a21..914046903cfd 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -848,8 +848,10 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, _rtl_submit_tx_urb(hw, _urb); } -static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, - u16 hw_queue) +static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, + u16 hw_queue) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); @@ -891,7 +893,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, seq_number += 1; seq_number <<= 4; } - rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb, + rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, sta, skb, hw_queue, &tcb_desc); if (!ieee80211_has_morefrags(hdr->frame_control)) { if (qc) @@ -901,7 +903,9 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb, rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX); } -static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb, +static int rtl_usb_tx(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, struct rtl_tcb_desc *dummy) { struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); @@ -913,7 +917,7 @@ static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb, if (unlikely(is_hal_stop(rtlhal))) goto err_free; hw_queue = rtlusb->usb_mq_to_hwq(fc, skb_get_queue_mapping(skb)); - _rtl_usb_tx_preprocess(hw, skb, hw_queue); + _rtl_usb_tx_preprocess(hw, sta, skb, hw_queue); _rtl_usb_transmit(hw, skb, hw_queue); return NETDEV_TX_OK; @@ -923,6 +927,7 @@ err_free: } static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw, + struct ieee80211_sta *sta, struct sk_buff *skb) { return false; diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index cdaa21f29710..40153e7bf702 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -122,7 +122,7 @@ enum rt_eeprom_type { EEPROM_BOOT_EFUSE, }; -enum rtl_status { +enum ttl_status { RTL_STATUS_INTERFACE_START = 0, }; @@ -1418,6 +1418,7 @@ struct rtl_hal_ops { void (*fill_tx_desc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, u8 *pdesc_tx, struct ieee80211_tx_info *info, + struct ieee80211_sta *sta, struct sk_buff *skb, u8 hw_queue, struct rtl_tcb_desc *ptcb_desc); void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 *pDesc, @@ -1475,11 +1476,15 @@ struct rtl_intf_ops { int (*adapter_start) (struct ieee80211_hw *hw); void (*adapter_stop) (struct ieee80211_hw *hw); - int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb, - struct rtl_tcb_desc *ptcb_desc); + int (*adapter_tx) (struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb, + struct rtl_tcb_desc *ptcb_desc); void (*flush)(struct ieee80211_hw *hw, bool drop); int (*reset_trx_ring) (struct ieee80211_hw *hw); - bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb); + bool (*waitq_insert) (struct ieee80211_hw *hw, + struct ieee80211_sta *sta, + struct sk_buff *skb); /*pci */ void (*disable_aspm) (struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 3118c425bcf1..441cbccbd381 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c @@ -354,7 +354,9 @@ out: return ret; } -static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void wl1251_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct wl1251 *wl = hw->priv; unsigned long flags; diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 5efd5919db3b..ff830cf50c70 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1181,7 +1181,9 @@ out: return ret; } -static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void wl1271_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct wl1271 *wl = hw->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -1197,7 +1199,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) mapping = skb_get_queue_mapping(skb); q = wl1271_tx_get_queue(mapping); - hlid = wl12xx_tx_get_hlid(wl, wlvif, skb, info->control.sta); + hlid = wl12xx_tx_get_hlid(wl, wlvif, skb, control->sta); spin_lock_irqsave(&wl->wl_lock, flags); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index c9e2660e1263..459880104758 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -937,7 +937,9 @@ static int fill_ctrlset(struct zd_mac *mac, * control block of the skbuff will be initialized. If necessary the incoming * mac80211 queues will be stopped. */ -static void zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +static void zd_op_tx(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct zd_mac *mac = zd_hw_mac(hw); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -1176,7 +1178,7 @@ static void zd_beacon_done(struct zd_mac *mac) skb = ieee80211_get_buffered_bc(mac->hw, mac->vif); if (!skb) break; - zd_op_tx(mac->hw, skb); + zd_op_tx(mac->hw, NULL, skb); } /* diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index ef360547ecec..b76d95e180fa 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -119,7 +119,9 @@ static void wbsoft_configure_filter(struct ieee80211_hw *dev, *total_flags = new_flags; } -static void wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb) +static void wbsoft_tx(struct ieee80211_hw *dev, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { struct wbsoft_priv *priv = dev->priv; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d67d3bbe21c1..8114f590f715 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -527,9 +527,6 @@ struct ieee80211_tx_rate { * (2) driver internal use (if applicable) * (3) TX status information - driver tells mac80211 what happened * - * The TX control's sta pointer is only valid during the ->tx call, - * it may be NULL. - * * @flags: transmit info flags, defined above * @band: the band to transmit on (use for checking for races) * @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC @@ -560,6 +557,7 @@ struct ieee80211_tx_info { struct ieee80211_tx_rate rates[ IEEE80211_TX_MAX_RATES]; s8 rts_cts_rate_idx; + /* 3 bytes free */ }; /* only needed before rate control */ unsigned long jiffies; @@ -567,7 +565,7 @@ struct ieee80211_tx_info { /* NB: vif can be NULL for injected frames */ struct ieee80211_vif *vif; struct ieee80211_key_conf *hw_key; - struct ieee80211_sta *sta; + /* 8 bytes free */ } control; struct { struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; @@ -1078,6 +1076,16 @@ enum sta_notify_cmd { STA_NOTIFY_SLEEP, STA_NOTIFY_AWAKE, }; +/** + * struct ieee80211_tx_control - TX control data + * + * @sta: station table entry, this sta pointer may be NULL and + * it is not allowed to copy the pointer, due to RCU. + */ +struct ieee80211_tx_control { + struct ieee80211_sta *sta; +}; + /** * enum ieee80211_hw_flags - hardware flags * @@ -2269,7 +2277,9 @@ enum ieee80211_rate_control_changed { * The callback is optional and can (should!) sleep. */ struct ieee80211_ops { - void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); + void (*tx)(struct ieee80211_hw *hw, + struct ieee80211_tx_control *control, + struct sk_buff *skb); int (*start)(struct ieee80211_hw *hw); void (*stop)(struct ieee80211_hw *hw); #ifdef CONFIG_PM diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index df9203199102..a81117a83996 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -22,9 +22,11 @@ get_bss_sdata(struct ieee80211_sub_if_data *sdata) return sdata; } -static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) +static inline void drv_tx(struct ieee80211_local *local, + struct ieee80211_tx_control *control, + struct sk_buff *skb) { - local->ops->tx(&local->hw, skb); + local->ops->tx(&local->hw, control, skb); } static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index acf712ffb5e6..7558ba58ea23 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1204,6 +1204,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, struct sk_buff_head *skbs, bool txpending) { + struct ieee80211_tx_control control; struct sk_buff *skb, *tmp; unsigned long flags; @@ -1240,10 +1241,10 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); info->control.vif = vif; - info->control.sta = sta; + control.sta = sta; __skb_unlink(skb, skbs); - drv_tx(local, skb); + drv_tx(local, &control, skb); } return true; -- cgit v1.2.3-71-gd317 From e687f61eedab8895e5669cb82cebe0253631cd8c Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sun, 12 Aug 2012 18:24:55 +0200 Subject: mac80211: add supported rates change notification in IBSS In IBSS it is possible that the supported rates set for a station changes over time (e.g. it gets first initialised as an empty set because of no available information about rates and updated later). In this case the driver has to be notified about the change in order to update its internal table accordingly (if needed). This behaviour is needed by all those drivers that handle rc internally but leave stations management to mac80211 Reported-by: Gui Iribarren Signed-off-by: Antonio Quartulli [Johannes - add docs, validate IBSS mode only, fix compilation] Signed-off-by: Johannes Berg --- include/net/mac80211.h | 4 ++++ net/mac80211/driver-ops.h | 3 +++ net/mac80211/ibss.c | 5 ++++- 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8114f590f715..d9cef31f4cbf 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1897,10 +1897,14 @@ enum ieee80211_frame_release_type { * @IEEE80211_RC_BW_CHANGED: The bandwidth that can be used to transmit * to this station changed. * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed. + * @IEEE80211_RC_SUPP_RATES_CHANGED: The supported rate set of this peer + * changed (in IBSS mode) due to discovering more information about + * the peer. */ enum ieee80211_rate_control_changed { IEEE80211_RC_BW_CHANGED = BIT(0), IEEE80211_RC_SMPS_CHANGED = BIT(1), + IEEE80211_RC_SUPP_RATES_CHANGED = BIT(2), }; /** diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index a81117a83996..a81154d27291 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -528,6 +528,9 @@ static inline void drv_sta_rc_update(struct ieee80211_local *local, sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); + WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && + sdata->vif.type != NL80211_IFTYPE_ADHOC); + trace_drv_sta_rc_update(local, sdata, sta, changed); if (local->ops->sta_rc_update) local->ops->sta_rc_update(&local->hw, &sdata->vif, diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 1ebda2f9e57b..a9d93285dba7 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -459,8 +459,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, } } - if (sta && rates_updated) + if (sta && rates_updated) { + drv_sta_rc_update(local, sdata, &sta->sta, + IEEE80211_RC_SUPP_RATES_CHANGED); rate_control_rate_init(sta); + } rcu_read_unlock(); } -- cgit v1.2.3-71-gd317 From 48613ece3d6a2613caa376f51477435cc080f3cd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Jul 2012 11:32:16 +0200 Subject: wireless: add radiotap A-MPDU status field Define the A-MPDU status field in radiotap, also update the radiotap parser for it and the MCS field that was apparently missed last time. Signed-off-by: Johannes Berg --- include/net/ieee80211_radiotap.h | 11 +++++++++++ net/wireless/radiotap.c | 2 ++ 2 files changed, 13 insertions(+) (limited to 'include') diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 71392545d0a1..7f0df133d119 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h @@ -183,6 +183,9 @@ struct ieee80211_radiotap_header { * Contains a bitmap of known fields/flags, the flags, and * the MCS index. * + * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless + * + * Contains the AMPDU information for the subframe. */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, @@ -205,6 +208,7 @@ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_DATA_RETRIES = 17, IEEE80211_RADIOTAP_MCS = 19, + IEEE80211_RADIOTAP_AMPDU_STATUS = 20, /* valid in every it_present bitmap, even vendor namespaces */ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, @@ -270,6 +274,13 @@ enum ieee80211_radiotap_type { #define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 +/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ +#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 +#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 +#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 +#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 /* helpers */ static inline int ieee80211_get_radiotap_len(unsigned char *data) diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index c4ad7958af52..7d604c06c3dc 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -41,6 +41,8 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = { [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, }, [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, }, [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, }, + [IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, }, + [IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, }, /* * add more here as they are defined in radiotap.h */ -- cgit v1.2.3-71-gd317 From 4c29867790131c281ef96af507d85e3e5f829408 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 5 Jul 2012 11:34:31 +0200 Subject: mac80211: support A-MPDU status reporting Support getting A-MPDU status information from the drivers and reporting it to userspace via radiotap in the standard fields. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 53 +++++++++++++++++++++++++++++++++++++------------- net/mac80211/rx.c | 42 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d9cef31f4cbf..edc235c51a68 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -676,21 +676,41 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_HT_GF: This frame was received in a HT-greenfield transmission, if * the driver fills this value it should add %IEEE80211_RADIOTAP_MCS_HAVE_FMT * to hw.radiotap_mcs_details to advertise that fact + * @RX_FLAG_AMPDU_DETAILS: A-MPDU details are known, in particular the reference + * number (@ampdu_reference) must be populated and be a distinct number for + * each A-MPDU + * @RX_FLAG_AMPDU_REPORT_ZEROLEN: driver reports 0-length subframes + * @RX_FLAG_AMPDU_IS_ZEROLEN: This is a zero-length subframe, for + * monitoring purposes only + * @RX_FLAG_AMPDU_LAST_KNOWN: last subframe is known, should be set on all + * subframes of a single A-MPDU + * @RX_FLAG_AMPDU_IS_LAST: this subframe is the last subframe of the A-MPDU + * @RX_FLAG_AMPDU_DELIM_CRC_ERROR: A delimiter CRC error has been detected + * on this subframe + * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC + * is stored in the @ampdu_delimiter_crc field) */ enum mac80211_rx_flags { - RX_FLAG_MMIC_ERROR = 1<<0, - RX_FLAG_DECRYPTED = 1<<1, - RX_FLAG_MMIC_STRIPPED = 1<<3, - RX_FLAG_IV_STRIPPED = 1<<4, - RX_FLAG_FAILED_FCS_CRC = 1<<5, - RX_FLAG_FAILED_PLCP_CRC = 1<<6, - RX_FLAG_MACTIME_MPDU = 1<<7, - RX_FLAG_SHORTPRE = 1<<8, - RX_FLAG_HT = 1<<9, - RX_FLAG_40MHZ = 1<<10, - RX_FLAG_SHORT_GI = 1<<11, - RX_FLAG_NO_SIGNAL_VAL = 1<<12, - RX_FLAG_HT_GF = 1<<13, + RX_FLAG_MMIC_ERROR = BIT(0), + RX_FLAG_DECRYPTED = BIT(1), + RX_FLAG_MMIC_STRIPPED = BIT(3), + RX_FLAG_IV_STRIPPED = BIT(4), + RX_FLAG_FAILED_FCS_CRC = BIT(5), + RX_FLAG_FAILED_PLCP_CRC = BIT(6), + RX_FLAG_MACTIME_MPDU = BIT(7), + RX_FLAG_SHORTPRE = BIT(8), + RX_FLAG_HT = BIT(9), + RX_FLAG_40MHZ = BIT(10), + RX_FLAG_SHORT_GI = BIT(11), + RX_FLAG_NO_SIGNAL_VAL = BIT(12), + RX_FLAG_HT_GF = BIT(13), + RX_FLAG_AMPDU_DETAILS = BIT(14), + RX_FLAG_AMPDU_REPORT_ZEROLEN = BIT(15), + RX_FLAG_AMPDU_IS_ZEROLEN = BIT(16), + RX_FLAG_AMPDU_LAST_KNOWN = BIT(17), + RX_FLAG_AMPDU_IS_LAST = BIT(18), + RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19), + RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20), }; /** @@ -714,17 +734,22 @@ enum mac80211_rx_flags { * HT rates are use (RX_FLAG_HT) * @flag: %RX_FLAG_* * @rx_flags: internal RX flags for mac80211 + * @ampdu_reference: A-MPDU reference number, must be a different value for + * each A-MPDU but the same for each subframe within one A-MPDU + * @ampdu_delimiter_crc: A-MPDU delimiter CRC */ struct ieee80211_rx_status { u64 mactime; u32 device_timestamp; - u16 flag; + u32 ampdu_reference; + u32 flag; u16 freq; u8 rate_idx; u8 rx_flags; u8 band; u8 antenna; s8 signal; + u8 ampdu_delimiter_crc; }; /** diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0cb4edee6af5..78bf6c7e80c8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -60,7 +60,9 @@ static inline int should_drop_frame(struct sk_buff *skb, struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) + if (status->flag & (RX_FLAG_FAILED_FCS_CRC | + RX_FLAG_FAILED_PLCP_CRC | + RX_FLAG_AMPDU_IS_ZEROLEN)) return 1; if (unlikely(skb->len < 16 + present_fcs_len)) return 1; @@ -91,6 +93,13 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, if (status->flag & RX_FLAG_HT) /* HT info */ len += 3; + if (status->flag & RX_FLAG_AMPDU_DETAILS) { + /* padding */ + while (len & 3) + len++; + len += 8; + } + return len; } @@ -215,6 +224,37 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, pos++; *pos++ = status->rate_idx; } + + if (status->flag & RX_FLAG_AMPDU_DETAILS) { + u16 flags = 0; + + /* ensure 4 byte alignment */ + while ((pos - (u8 *)rthdr) & 3) + pos++; + rthdr->it_present |= + cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); + put_unaligned_le32(status->ampdu_reference, pos); + pos += 4; + if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN) + flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN; + if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN) + flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN; + if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN) + flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN; + if (status->flag & RX_FLAG_AMPDU_IS_LAST) + flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST; + if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR) + flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR; + if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) + flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN; + put_unaligned_le16(flags, pos); + pos += 2; + if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) + *pos++ = status->ampdu_delimiter_crc; + else + *pos++ = 0; + *pos++ = 0; + } } /* -- cgit v1.2.3-71-gd317 From 98104fdeda63d57631c9f89e90a7b83b58fcee40 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 16 Jun 2012 00:19:54 +0200 Subject: cfg80211: add P2P Device abstraction In order to support using a different MAC address for the P2P Device address we must first have a P2P Device abstraction that can be assigned a MAC address. This abstraction will also be useful to support offloading P2P operations to the device, e.g. periodic listen for discoverability. Currently, the driver is responsible for assigning a MAC address to the P2P Device, but this could be changed by allowing a MAC address to be given to the NEW_INTERFACE command. As it has no associated netdev, a P2P Device can only be identified by its wdev identifier but the previous patches allowed using the wdev identifier in various APIs, e.g. remain-on-channel. Signed-off-by: Johannes Berg --- include/linux/nl80211.h | 30 ++++++++++-- include/net/cfg80211.h | 40 +++++++++++++++- net/mac80211/iface.c | 3 ++ net/mac80211/util.c | 2 + net/wireless/chan.c | 7 ++- net/wireless/core.c | 53 ++++++++++++++++++++- net/wireless/mlme.c | 10 ++-- net/wireless/nl80211.c | 122 +++++++++++++++++++++++++++++++++++++++++++++--- net/wireless/util.c | 18 ++++++- 9 files changed, 265 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2f3878806403..458416279347 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -565,6 +565,14 @@ * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. * + * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. It must have been created with + * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the + * P2P Device can be used for P2P operations, e.g. remain-on-channel and + * public action frame TX. + * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -708,6 +716,9 @@ enum nl80211_commands { NL80211_CMD_CH_SWITCH_NOTIFY, + NL80211_CMD_START_P2P_DEVICE, + NL80211_CMD_STOP_P2P_DEVICE, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1575,6 +1586,10 @@ enum nl80211_attrs { * @NL80211_IFTYPE_MESH_POINT: mesh point * @NL80211_IFTYPE_P2P_CLIENT: P2P client * @NL80211_IFTYPE_P2P_GO: P2P group owner + * @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev + * and therefore can't be created in the normal ways, use the + * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE + * commands to create and destroy one * @NL80211_IFTYPE_MAX: highest interface type number currently defined * @NUM_NL80211_IFTYPES: number of defined interface types * @@ -1593,6 +1608,7 @@ enum nl80211_iftype { NL80211_IFTYPE_MESH_POINT, NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_P2P_GO, + NL80211_IFTYPE_P2P_DEVICE, /* keep last */ NUM_NL80211_IFTYPES, @@ -2994,12 +3010,18 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested * to work properly to suppport receiving regulatory hints from * cellular base stations. + * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: If this is set, an active + * P2P Device (%NL80211_IFTYPE_P2P_DEVICE) requires its own channel + * in the interface combinations, even when it's only used for scan + * and remain-on-channel. This could be due to, for example, the + * remain-on-channel implementation requiring a channel context. */ enum nl80211_feature_flags { - NL80211_FEATURE_SK_TX_STATUS = 1 << 0, - NL80211_FEATURE_HT_IBSS = 1 << 1, - NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, - NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, + NL80211_FEATURE_SK_TX_STATUS = 1 << 0, + NL80211_FEATURE_HT_IBSS = 1 << 1, + NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, + NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4, }; /** diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 493fa0c79005..4c518f1f1aca 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1437,7 +1437,8 @@ struct cfg80211_gtk_rekey_data { * @add_virtual_intf: create a new virtual interface with the given name, * must set the struct wireless_dev's iftype. Beware: You must create * the new netdev in the wiphy's network namespace! Returns the struct - * wireless_dev, or an ERR_PTR. + * wireless_dev, or an ERR_PTR. For P2P device wdevs, the driver must + * also set the address member in the wdev. * * @del_virtual_intf: remove the virtual interface * @@ -1616,6 +1617,9 @@ struct cfg80211_gtk_rekey_data { * @get_channel: Get the current operating channel for the virtual interface. * For monitor interfaces, it should return %NULL unless there's a single * current monitoring channel. + * + * @start_p2p_device: Start the given P2P device. + * @stop_p2p_device: Stop the given P2P device. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1832,6 +1836,11 @@ struct cfg80211_ops { (*get_channel)(struct wiphy *wiphy, struct wireless_dev *wdev, enum nl80211_channel_type *type); + + int (*start_p2p_device)(struct wiphy *wiphy, + struct wireless_dev *wdev); + void (*stop_p2p_device)(struct wiphy *wiphy, + struct wireless_dev *wdev); }; /* @@ -2395,6 +2404,8 @@ struct cfg80211_cached_keys; * @cleanup_work: work struct used for cleanup that can't be done directly * @beacon_interval: beacon interval used on this device for transmitting * beacons, 0 when not valid + * @address: The address for this device, valid only if @netdev is %NULL + * @p2p_started: true if this is a P2P Device that has been started */ struct wireless_dev { struct wiphy *wiphy; @@ -2413,7 +2424,9 @@ struct wireless_dev { struct work_struct cleanup_work; - bool use_4addr; + bool use_4addr, p2p_started; + + u8 address[ETH_ALEN] __aligned(sizeof(u16)); /* currently used for IBSS and SME - might be rearranged later */ u8 ssid[IEEE80211_MAX_SSID_LEN]; @@ -2461,6 +2474,13 @@ struct wireless_dev { #endif }; +static inline u8 *wdev_address(struct wireless_dev *wdev) +{ + if (wdev->netdev) + return wdev->netdev->dev_addr; + return wdev->address; +} + /** * wdev_priv - return wiphy priv from wireless_dev * @@ -3528,6 +3548,22 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, */ u32 cfg80211_calculate_bitrate(struct rate_info *rate); +/** + * cfg80211_unregister_wdev - remove the given wdev + * @wdev: struct wireless_dev to remove + * + * Call this function only for wdevs that have no netdev assigned, + * e.g. P2P Devices. It removes the device from the list so that + * it can no longer be used. It is necessary to call this function + * even when cfg80211 requests the removal of the interface by + * calling the del_virtual_intf() callback. The function must also + * be called when the driver wishes to unregister the wdev, e.g. + * when the device is unbound from the driver. + * + * Requires the RTNL to be held. + */ +void cfg80211_unregister_wdev(struct wireless_dev *wdev); + /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index fbab7a84ca21..366d9d3e84c4 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -449,6 +449,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) case NUM_NL80211_IFTYPES: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_P2P_DEVICE: /* cannot happen */ WARN_ON(1); break; @@ -1146,6 +1147,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_WDS: case NL80211_IFTYPE_AP_VLAN: break; + case NL80211_IFTYPE_P2P_DEVICE: + /* not yet supported */ case NL80211_IFTYPE_UNSPECIFIED: case NUM_NL80211_IFTYPES: BUG(); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 7dff94e43a0c..9a4e4e30ea6c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1390,6 +1390,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) case NL80211_IFTYPE_MONITOR: /* ignore virtual */ break; + case NL80211_IFTYPE_P2P_DEVICE: + /* not yet supported */ case NL80211_IFTYPE_UNSPECIFIED: case NUM_NL80211_IFTYPES: case NL80211_IFTYPE_P2P_CLIENT: diff --git a/net/wireless/chan.c b/net/wireless/chan.c index d355f67d0cdd..2f876b9ee344 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -105,7 +105,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, ASSERT_WDEV_LOCK(wdev); - if (!netif_running(wdev->netdev)) + if (wdev->netdev && !netif_running(wdev->netdev)) return; switch (wdev->iftype) { @@ -143,6 +143,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, case NL80211_IFTYPE_WDS: /* these interface types don't really have a channel */ return; + case NL80211_IFTYPE_P2P_DEVICE: + if (wdev->wiphy->features & + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL) + *chanmode = CHAN_MODE_EXCLUSIVE; + return; case NL80211_IFTYPE_UNSPECIFIED: case NUM_NL80211_IFTYPES: WARN_ON(1); diff --git a/net/wireless/core.c b/net/wireless/core.c index 31b40cc4a9c3..91b300443f4b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -230,9 +230,24 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) rtnl_lock(); mutex_lock(&rdev->devlist_mtx); - list_for_each_entry(wdev, &rdev->wdev_list, list) - if (wdev->netdev) + list_for_each_entry(wdev, &rdev->wdev_list, list) { + if (wdev->netdev) { dev_close(wdev->netdev); + continue; + } + /* otherwise, check iftype */ + switch (wdev->iftype) { + case NL80211_IFTYPE_P2P_DEVICE: + if (!wdev->p2p_started) + break; + rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); + wdev->p2p_started = false; + rdev->opencount--; + break; + default: + break; + } + } mutex_unlock(&rdev->devlist_mtx); rtnl_unlock(); @@ -407,6 +422,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) if (WARN_ON(wiphy->software_iftypes & types)) return -EINVAL; + /* Only a single P2P_DEVICE can be allowed */ + if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && + c->limits[j].max > 1)) + return -EINVAL; + cnt += c->limits[j].max; /* * Don't advertise an unsupported type @@ -734,6 +754,35 @@ static void wdev_cleanup_work(struct work_struct *work) dev_put(wdev->netdev); } +void cfg80211_unregister_wdev(struct wireless_dev *wdev) +{ + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + + ASSERT_RTNL(); + + if (WARN_ON(wdev->netdev)) + return; + + mutex_lock(&rdev->devlist_mtx); + list_del_rcu(&wdev->list); + rdev->devlist_generation++; + + switch (wdev->iftype) { + case NL80211_IFTYPE_P2P_DEVICE: + if (!wdev->p2p_started) + break; + rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); + wdev->p2p_started = false; + rdev->opencount--; + break; + default: + WARN_ON_ONCE(1); + break; + } + mutex_unlock(&rdev->devlist_mtx); +} +EXPORT_SYMBOL(cfg80211_unregister_wdev); + static struct device_type wiphy_type = { .name = "wlan", }; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1cdb1d5e6b0f..8fd0242ee169 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -736,7 +736,6 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, const u8 *buf, size_t len, bool no_cck, bool dont_wait_for_ack, u64 *cookie) { - struct net_device *dev = wdev->netdev; const struct ieee80211_mgmt *mgmt; u16 stype; @@ -796,7 +795,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: case NL80211_IFTYPE_AP_VLAN: - if (!ether_addr_equal(mgmt->bssid, dev->dev_addr)) + if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev))) err = -EINVAL; break; case NL80211_IFTYPE_MESH_POINT: @@ -809,6 +808,11 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, * cfg80211 doesn't track the stations */ break; + case NL80211_IFTYPE_P2P_DEVICE: + /* + * fall through, P2P device only supports + * public action frames + */ default: err = -EOPNOTSUPP; break; @@ -819,7 +823,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, return err; } - if (!ether_addr_equal(mgmt->sa, dev->dev_addr)) + if (!ether_addr_equal(mgmt->sa, wdev_address(wdev))) return -EINVAL; /* Transmit the Action frame as requested by user space */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 97026f3b215a..787aeaa902fe 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1100,6 +1100,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) goto nla_put_failure; } + CMD(start_p2p_device, START_P2P_DEVICE); #ifdef CONFIG_NL80211_TESTMODE CMD(testmode_cmd, TESTMODE); @@ -1748,13 +1749,13 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (dev && (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || - nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) || - nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dev->dev_addr))) + nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name))) goto nla_put_failure; if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) || nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) || nla_put_u32(msg, NL80211_ATTR_GENERATION, rdev->devlist_generation ^ (cfg80211_rdev_list_generation << 2))) @@ -2021,8 +2022,10 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) return PTR_ERR(wdev); } - if (type == NL80211_IFTYPE_MESH_POINT && - info->attrs[NL80211_ATTR_MESH_ID]) { + switch (type) { + case NL80211_IFTYPE_MESH_POINT: + if (!info->attrs[NL80211_ATTR_MESH_ID]) + break; wdev_lock(wdev); BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN); @@ -2031,6 +2034,26 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]), wdev->mesh_id_up_len); wdev_unlock(wdev); + break; + case NL80211_IFTYPE_P2P_DEVICE: + /* + * P2P Device doesn't have a netdev, so doesn't go + * through the netdev notifier and must be added here + */ + mutex_init(&wdev->mtx); + INIT_LIST_HEAD(&wdev->event_list); + spin_lock_init(&wdev->event_lock); + INIT_LIST_HEAD(&wdev->mgmt_registrations); + spin_lock_init(&wdev->mgmt_registrations_lock); + + mutex_lock(&rdev->devlist_mtx); + wdev->identifier = ++rdev->wdev_id; + list_add_rcu(&wdev->list, &rdev->wdev_list); + rdev->devlist_generation++; + mutex_unlock(&rdev->devlist_mtx); + break; + default: + break; } if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, @@ -6053,6 +6076,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_P2P_DEVICE: break; default: return -EOPNOTSUPP; @@ -6099,6 +6123,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_P2P_DEVICE: break; default: return -EOPNOTSUPP; @@ -6195,6 +6220,7 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_P2P_DEVICE: break; default: return -EOPNOTSUPP; @@ -6810,6 +6836,68 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) return 0; } +static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct wireless_dev *wdev = info->user_ptr[1]; + int err; + + if (!rdev->ops->start_p2p_device) + return -EOPNOTSUPP; + + if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) + return -EOPNOTSUPP; + + if (wdev->p2p_started) + return 0; + + mutex_lock(&rdev->devlist_mtx); + err = cfg80211_can_add_interface(rdev, wdev->iftype); + mutex_unlock(&rdev->devlist_mtx); + if (err) + return err; + + err = rdev->ops->start_p2p_device(&rdev->wiphy, wdev); + if (err) + return err; + + wdev->p2p_started = true; + mutex_lock(&rdev->devlist_mtx); + rdev->opencount++; + mutex_unlock(&rdev->devlist_mtx); + + return 0; +} + +static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct wireless_dev *wdev = info->user_ptr[1]; + + if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) + return -EOPNOTSUPP; + + if (!rdev->ops->stop_p2p_device) + return -EOPNOTSUPP; + + if (!wdev->p2p_started) + return 0; + + rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); + wdev->p2p_started = false; + + mutex_lock(&rdev->devlist_mtx); + rdev->opencount--; + mutex_unlock(&rdev->devlist_mtx); + + if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { + rdev->scan_req->aborted = true; + ___cfg80211_scan_done(rdev, true); + } + + return 0; +} + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -6817,7 +6905,7 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) #define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\ NL80211_FLAG_CHECK_NETDEV_UP) #define NL80211_FLAG_NEED_WDEV 0x10 -/* If a netdev is associated, it must be UP */ +/* If a netdev is associated, it must be UP, P2P must be started */ #define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\ NL80211_FLAG_CHECK_NETDEV_UP) @@ -6878,6 +6966,13 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, } dev_hold(dev); + } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { + if (!wdev->p2p_started) { + mutex_unlock(&cfg80211_mutex); + if (rtnl) + rtnl_unlock(); + return -ENETDOWN; + } } cfg80211_lock_rdev(rdev); @@ -7439,7 +7534,22 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, }, - + { + .cmd = NL80211_CMD_START_P2P_DEVICE, + .doit = nl80211_start_p2p_device, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_WDEV | + NL80211_FLAG_NEED_RTNL, + }, + { + .cmd = NL80211_CMD_STOP_P2P_DEVICE, + .doit = nl80211_stop_p2p_device, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_WDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, }; static struct genl_multicast_group nl80211_mlme_mcgrp = { diff --git a/net/wireless/util.c b/net/wireless/util.c index ce393dd8c928..d7b672262b5f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -800,6 +800,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, if (otype == NL80211_IFTYPE_AP_VLAN) return -EOPNOTSUPP; + /* cannot change into P2P device type */ + if (ntype == NL80211_IFTYPE_P2P_DEVICE) + return -EOPNOTSUPP; + if (!rdev->ops->change_virtual_intf || !(rdev->wiphy.interface_modes & (1 << ntype))) return -EOPNOTSUPP; @@ -877,6 +881,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, case NUM_NL80211_IFTYPES: /* not happening */ break; + case NL80211_IFTYPE_P2P_DEVICE: + WARN_ON(1); + break; } } @@ -1041,8 +1048,15 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { if (wdev_iter == wdev) continue; - if (!netif_running(wdev_iter->netdev)) - continue; + if (wdev_iter->netdev) { + if (!netif_running(wdev_iter->netdev)) + continue; + } else if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) { + if (!wdev_iter->p2p_started) + continue; + } else { + WARN_ON(1); + } if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) continue; -- cgit v1.2.3-71-gd317 From 6d71117a279aa30574a8af6c7348570c292285c2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 19 Jun 2012 17:19:44 +0200 Subject: mac80211: add IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF Some devices like the current iwlwifi implementation require that the P2P interface address match the P2P Device address (only one P2P interface is supported.) Add the HW flag IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF that allows drivers to request that P2P Interfaces added while a P2P Device is active get the same MAC address by default. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 5 +++++ net/mac80211/iface.c | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index edc235c51a68..71f8262fc1df 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1241,6 +1241,10 @@ struct ieee80211_tx_control { * queue mapping in order to use different queues (not just one per AC) * for different virtual interfaces. See the doc section on HW queue * control for more details. + * + * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any + * P2P Interface. This will be honoured even if more than one interface + * is supported. */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -1268,6 +1272,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_AP_LINK_PS = 1<<22, IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, + IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, }; /** diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 152aeea14c85..59f8adc2aa5f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1313,7 +1313,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, local->hw.wiphy->n_addresses <= 1) return; - mutex_lock(&local->iflist_mtx); switch (type) { @@ -1331,6 +1330,19 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, } /* keep default if no AP interface present */ break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: + if (local->hw.flags & IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF) { + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) + continue; + if (!ieee80211_sdata_running(sdata)) + continue; + memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); + goto out_unlock; + } + } + /* otherwise fall through */ default: /* assign a new address if possible -- try n_addresses first */ for (i = 0; i < local->hw.wiphy->n_addresses; i++) { @@ -1405,6 +1417,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, break; } + out_unlock: mutex_unlock(&local->iflist_mtx); } -- cgit v1.2.3-71-gd317