* [ath9k-devel] [PATCH] mac80211: Add transmit power control support (TPC)
@ 2012-07-08 17:02 Thomas Huehn
0 siblings, 0 replies; only message in thread
From: Thomas Huehn @ 2012-07-08 17:02 UTC (permalink / raw)
To: ath9k-devel
This patch creates an transmit power control (TPC) API within the mac80211
subsystem. It enables a per multi-rate-retry stage annotaion of a power-level
value in dBm for each data packet and a global power-level for acknowledgement
packets. Furthermore, necessary flags are defined to specify and map TPC
hardware capabilities of individual wireless cards. This TPC API is a
pre-requisite to implement any power control algorithm at mac80211. A new joint
rate and power control algorithm "Minstrel-Blues" is released soon.
This patch consists of the following 6 logical sections:
(1) structure ieee80211_tx_control is added to mac80211
It holds the STA structure to be able to remove info->control.sta from
struct ieee80211_tx_info (therefor out of the tx-path) and put it on the stack.
(2) restructuring of ieee80211_tx_info to add TPC annotation
Remove info->control.sta from struct ieee80211_tx_info to free up suitable
memory in SKB_CB. Make use of the freed space to extend the struct
ieee80211_tx_rate by u8 tpc[4]. This enables a per packet annotation of one
powerlevel in dBm per multi-rate-retry stage.
(3) add tpc hardware capability flags
To map different tpc hardware capabilities to mac80211, a new enum
ieee80211_tpc_support (type of transmit power control) support is added. Based
on these flags someone can specify transmit power control capabilities
to the stack.
@IEEE80211_TPC_NONE: No tpc beside a fixed global setting is available.
This setting is used as the default case. Extended tpc capabilities
need to be announced via flags within the individual hardware driver.
@IEEE80211_TPC_PER_DATA_PACKET: One power level per data packet can
be set. Each data packet is send out with its individual power level.
@IEEE80211_TPC_PER_DATA_MRR: Multiple individual power levels per
multi-rate-retry stage within a data packet are supported.
@IEEE80211_TPC_ACK_POWER_GLOBAL: One power level of ack packets is
globaly adjustable.
(4) add support to change power-level of acknowledgement packets.
Add flag IEEE80211_CONF_CHANGE_ACK_POWER to ieee80211_conf_flags. This enables
to specify ack_power as global power level in dBm to use for all mac80211
acknowledgement packets.
(5) brcmsmac: restructure info->control.sta handling as it is goning to be removed.
brcmsmac uses info->control.sta while doing ampdu aggregation. The usage of the
structure info->control.sta is changed, as it is going to be removed from
struct ieee80211_tx_info.
(6) restructure tx-path of all effected drivers
Restructure tx-path of all effected drivers to respect new TPC support in
mac80211. TPC support is added to mac80211 by restructuring of struct
ieee80211_tx_info. Therfore the tx-path of all effected drivers is modified
to receive struct sta from the stack and respect the new ieee80211_tx_info
struct. List of modified driver:
ath9k
ath5k
iwl3954
iwl4965
iwl-agn
mwl8k
carl9170
ath9k-htc
p54
rt2x00
rtl8180
rtl8087
hwsim
b43
b43legacy
brcmsmac
zd1211rw
Signed-off-by: Thomas Huehn <thomas@net.t-labs.tu-berlin.de>
Signed-off-by: Alina Friedrichsen <x-alina@gmx.net>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
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 | 3 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 +-
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 3 +-
drivers/net/wireless/ath/ath9k/main.c | 5 +-
drivers/net/wireless/ath/ath9k/xmit.c | 10 ++-
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 +
drivers/net/wireless/brcm80211/brcmsmac/ampdu.c | 10 +--
.../net/wireless/brcm80211/brcmsmac/mac80211_if.c | 6 +-
drivers/net/wireless/brcm80211/brcmsmac/main.c | 2 +-
drivers/net/wireless/iwlegacy/3945-mac.c | 12 ++-
drivers/net/wireless/iwlegacy/4965-mac.c | 25 ++++--
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 | 15 ++--
drivers/net/wireless/mac80211_hwsim.c | 14 ++--
drivers/net/wireless/mwl8k.c | 33 +++++---
drivers/net/wireless/p54/lmac.h | 4 +-
drivers/net/wireless/p54/main.c | 3 +-
drivers/net/wireless/p54/txrx.c | 17 ++--
drivers/net/wireless/rt2x00/rt2x00.h | 4 +-
drivers/net/wireless/rt2x00/rt2x00dev.c | 3 +-
drivers/net/wireless/rt2x00/rt2x00mac.c | 4 +-
drivers/net/wireless/rt2x00/rt2x00queue.c | 22 +++--
drivers/net/wireless/rtl818x/rtl8180/dev.c | 7 +-
drivers/net/wireless/rtl818x/rtl8187/dev.c | 7 +-
drivers/net/wireless/zd1211rw/zd_mac.c | 7 +-
include/net/mac80211.h | 87 +++++++++++++++-----
net/mac80211/driver-ops.h | 6 +-
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/tx.c | 13 +--
37 files changed, 258 insertions(+), 119 deletions(-)
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 22b80af..93a800f 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 79840d6..1de556c 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_tx_control control;
};
#define ATH_TX_ERROR 0x01
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 936e920..b0a6ad5 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_tx_control *control,
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 77d541f..5f07359 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -296,6 +296,7 @@ static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv,
struct ath_common *common = ath9k_hw_common(priv->ah);
struct ieee80211_vif *vif;
struct sk_buff *skb;
+ struct ieee80211_tx_control control;
struct ieee80211_hdr *hdr;
int padpos, padsize, ret, tx_slot;
@@ -326,7 +327,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, &control, 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 374c32e..295f89a 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, 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 47e61d0..948a060 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -333,12 +333,13 @@ static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv,
}
int ath9k_htc_tx_start(struct ath9k_htc_priv *priv,
+ struct ieee80211_tx_control *control,
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_sta *sta = 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 248e5b2..9673693c 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -680,7 +680,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);
@@ -740,6 +742,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)];
+ memcpy(&txctl.control, control, sizeof(struct ieee80211_tx_control));
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 cafb4a0..bf5d390 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1771,11 +1771,13 @@ 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_tx_control *control,
+ 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_sta *sta = 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;
@@ -1933,7 +1935,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->control.sta;
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
@@ -1977,7 +1979,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, &txctl->control, 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 0cea20e..5b48b43 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -566,7 +566,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 ede0b57..1aa9564 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -277,7 +277,7 @@ static void carl9170_tx_release(struct kref *ref)
return;
BUILD_BUG_ON(
- offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
+ offsetof(struct ieee80211_tx_info, status.ack_signal) != 24);
memset(&txinfo->status.ack_signal, 0,
sizeof(struct ieee80211_tx_info) -
@@ -826,7 +826,9 @@ 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_tx_control *control,
+ struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
struct _carl9170_tx_superframe *txc;
@@ -869,7 +871,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
else
cvif = NULL;
- sta = info->control.sta;
+ sta = control->sta;
txc = (void *)skb_push(skb, sizeof(*txc));
memset(txc, 0, sizeof(*txc));
@@ -1394,7 +1396,9 @@ 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;
@@ -1405,9 +1409,9 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
goto err_free;
info = IEEE80211_SKB_CB(skb);
- sta = info->control.sta;
+ sta = control->sta;
- if (unlikely(carl9170_tx_prepare(ar, skb)))
+ if (unlikely(carl9170_tx_prepare(ar, control, 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 1b988f2..b6fc409 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3409,7 +3409,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 8156135..74d4c20 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/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index 01b190a..d341c91 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -665,7 +665,7 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
u8 plcp0, plcp3, is40, sgi;
struct ieee80211_sta *sta;
- sta = tx_info->control.sta;
+ sta = tx_info->rate_driver_data[0];
if (rr) {
plcp0 = plcp[0];
@@ -1195,8 +1195,8 @@ static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
bool rc;
rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
- rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
- tx_info->control.sta == ampdu_pars->sta);
+ rc = rc && (tx_info->rate_driver_data[0] == NULL || ampdu_pars->sta == NULL ||
+ tx_info->rate_driver_data[0] == ampdu_pars->sta);
rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
return rc;
}
@@ -1210,8 +1210,8 @@ static void dma_cb_fn_ampdu(void *txi, void *arg_a)
struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
- (tx_info->control.sta == sta || sta == NULL))
- tx_info->control.sta = NULL;
+ (tx_info->rate_driver_data[0] == sta || sta == NULL))
+ tx_info->rate_driver_data[0] = NULL;
}
/*
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 2d5a404..d270c4f 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -264,9 +264,12 @@ 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);
spin_lock_bh(&wl->lock);
if (!wl->pub->up) {
@@ -275,6 +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] = control->sta;
done:
spin_unlock_bh(&wl->lock);
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 8776fbc..28dd37e3 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -879,7 +879,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
tx_info = IEEE80211_SKB_CB(p);
h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
- if (tx_info->control.sta)
+ if (tx_info->rate_driver_data[0])
scb = &wlc->pri_scb;
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
index faec404..7efec7c 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_tx_control *control,
+ 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, control->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, 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 34f61a0..95e3b34 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_tx_control *control,
+ __le16 fc)
{
const u8 rts_retry_limit = 60;
u32 rate_flags;
@@ -1563,7 +1566,7 @@ il4965_tx_cmd_build_rate(struct il_priv *il, struct il_tx_cmd *tx_cmd,
|| rate_idx > RATE_COUNT_LEGACY)
rate_idx =
rate_lowest_index(&il->bands[info->band],
- info->control.sta);
+ control->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 +1633,13 @@ 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_tx_control *control,
+ 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 = control->sta;
struct il_station_priv *sta_priv = NULL;
struct il_tx_queue *txq;
struct il_queue *q;
@@ -1680,7 +1685,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, control->sta);
if (sta_id == IL_INVALID_STATION) {
D_DROP("Dropping - INVALID STATION: %pM\n", hdr->addr1);
@@ -1786,7 +1791,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, control, fc);
il_update_stats(il, true, fc, len);
/*
@@ -5828,7 +5833,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 +5844,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, 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 1db6776..29e77bf 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_tx_control *control,
+ 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 9bb16bd..a02d843 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_tx_control *control,
+ 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 a5f7bce..6bc03a3 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, 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 5971a23..fc386dc 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_tx_control *control,
__le16 fc)
{
u32 rate_flags;
@@ -188,7 +189,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
rate_idx = rate_lowest_index(
&priv->eeprom_data->bands[info->band],
- info->control.sta);
+ control->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 +292,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_tx_control *control,
+ struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -345,7 +348,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, control->sta);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1);
@@ -355,8 +358,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 (control->sta)
+ sta_priv = (void *)control->sta->drv_priv;
if (sta_priv && sta_priv->asleep &&
(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)) {
@@ -397,7 +400,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, control, fc);
memset(&info->status, 0, sizeof(info->status));
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 3f38d84..a55c70b 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);
@@ -1495,6 +1497,8 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
struct hwsim_tx_rate *tx_attempts;
unsigned long ret_skb_ptr;
struct sk_buff *skb, *tmp;
+ struct ieee80211_tx_control control;
+ struct ieee80211_sta *sta = control.sta;
struct mac_address *src;
unsigned int hwsim_flags;
@@ -1542,8 +1546,8 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
if (txi->control.vif)
hwsim_check_magic(txi->control.vif);
- if (txi->control.sta)
- hwsim_check_sta_magic(txi->control.sta);
+ if (sta)
+ hwsim_check_sta_magic(sta);
ieee80211_tx_info_clear_status(txi);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 1404373..af669a2 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1610,7 +1610,9 @@ static int mwl8k_tid_queue_mapping(u8 tid)
#define RI_RATE_ID_MCS(a) ((a & 0x01f8) >> 3)
static int
-mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
+mwl8k_txq_reclaim(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control,
+ int index, int limit, int force)
{
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_tx_queue *txq = priv->txq + index;
@@ -1708,12 +1710,13 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
{
struct mwl8k_priv *priv = hw->priv;
+ struct ieee80211_tx_control control;
struct mwl8k_tx_queue *txq = priv->txq + index;
if (txq->txd == NULL)
return;
- mwl8k_txq_reclaim(hw, index, INT_MAX, 1);
+ mwl8k_txq_reclaim(hw, &control, index, INT_MAX, 1);
kfree(txq->skb);
txq->skb = NULL;
@@ -1828,7 +1831,10 @@ 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_tx_control *control,
+ struct sk_buff *skb)
{
struct mwl8k_priv *priv = hw->priv;
struct ieee80211_tx_info *tx_info;
@@ -1865,7 +1871,7 @@ 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;
+ sta = control->sta;
mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
@@ -2017,8 +2023,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 && control->sta != NULL)
+ tx->peer_id = MWL8K_STA(control->sta)->peer_id;
else
tx->peer_id = 0;
@@ -4315,6 +4321,7 @@ static void mwl8k_tx_poll(unsigned long data)
{
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
struct mwl8k_priv *priv = hw->priv;
+ struct ieee80211_tx_control control;
int limit;
int i;
@@ -4323,7 +4330,7 @@ static void mwl8k_tx_poll(unsigned long data)
spin_lock_bh(&priv->tx_lock);
for (i = 0; i < mwl8k_tx_queues(priv); i++)
- limit -= mwl8k_txq_reclaim(hw, i, limit, 0);
+ limit -= mwl8k_txq_reclaim(hw, &control, i, limit, 0);
if (!priv->pending_tx_pkts && priv->tx_wait != NULL) {
complete(priv->tx_wait);
@@ -4362,7 +4369,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);
@@ -4374,7 +4383,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, skb);
}
static int mwl8k_start(struct ieee80211_hw *hw)
@@ -4439,6 +4448,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
static void mwl8k_stop(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
+ struct ieee80211_tx_control control;
int i;
if (!priv->hw_restart_in_progress)
@@ -4465,7 +4475,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
/* Return all skbs to mac80211 */
for (i = 0; i < mwl8k_tx_queues(priv); i++)
- mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
+ mwl8k_txq_reclaim(hw, &control, i, INT_MAX, 1);
}
static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image);
@@ -5841,6 +5851,7 @@ static void __devexit mwl8k_shutdown(struct pci_dev *pdev)
static void __devexit mwl8k_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ieee80211_tx_control control;
struct mwl8k_priv *priv;
int i;
@@ -5868,7 +5879,7 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
/* Return all skbs to mac80211 */
for (i = 0; i < mwl8k_tx_queues(priv); i++)
- mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
+ mwl8k_txq_reclaim(hw, &control, i, INT_MAX, 1);
for (i = 0; i < mwl8k_tx_queues(priv); i++)
mwl8k_txq_deinit(hw, i);
diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h
index 3d8d622..de1d46b 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 7cffea7..9c8ce8e 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -140,6 +140,7 @@ static int p54_beacon_update(struct p54_common *priv,
struct ieee80211_vif *vif)
{
struct sk_buff *beacon;
+ struct ieee80211_tx_control control;
int ret;
beacon = ieee80211_beacon_get(priv->hw, vif);
@@ -158,7 +159,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, &control, 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 f38786e..edec732 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -426,7 +426,7 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb)
sizeof(struct ieee80211_tx_info) -
offsetof(struct ieee80211_tx_info, status.ack_signal));
BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
- status.ack_signal) != 20);
+ status.ack_signal) != 24);
if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
pad = entry_data->align[0];
@@ -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_tx_control *control,
+ 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 (control->sta)
+ *aid = control->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, &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 8afb546..f991e8b 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 a6b88bd..87e335a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -181,6 +181,7 @@ static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = data;
+ struct ieee80211_tx_control control;
struct sk_buff *skb;
/*
@@ -194,7 +195,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, &control, 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 4ff26c2..c3d0f2f 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 2fd8301..d80118d 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_tx_control *control,
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 (control->sta) {
txdesc->u.ht.mpdu_density =
- tx_info->control.sta->ht_cap.ampdu_density;
+ control->sta->ht_cap.ampdu_density;
- sta_priv = sta_to_rt2x00_sta(tx_info->control.sta);
+ sta_priv = sta_to_rt2x00_sta(control->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 (control->sta && txdesc->u.ht.mcs > 7 &&
+ ((control->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_tx_control *control)
{
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);
+ control, hwrate);
else
rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,
hwrate);
@@ -587,6 +589,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
struct queue_entry *entry;
struct txentry_desc txdesc;
struct skb_frame_desc *skbdesc;
+ struct ieee80211_tx_control control;
u8 rate_idx, rate_flags;
int ret = 0;
@@ -595,7 +598,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, &control);
/*
* All information is retrieved from the skb->cb array,
@@ -722,6 +725,7 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf = vif_to_intf(vif);
struct skb_frame_desc *skbdesc;
struct txentry_desc txdesc;
+ struct ieee80211_tx_control control;
if (unlikely(!intf->beacon))
return -ENOBUFS;
@@ -740,7 +744,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, &control);
/*
* Fill in skb descriptor
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 3b50539..69963f3 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;
@@ -689,6 +691,7 @@ static void rtl8180_beacon_work(struct work_struct *work)
container_of((void *)vif_priv, struct ieee80211_vif, drv_priv);
struct ieee80211_hw *dev = vif_priv->dev;
struct ieee80211_mgmt *mgmt;
+ struct ieee80211_tx_control control;
struct sk_buff *skb;
/* don't overflow the tx ring */
@@ -710,7 +713,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, &control, skb);
resched:
/*
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 4fb1ca1..5c4bd11 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);
@@ -1055,6 +1057,7 @@ static void rtl8187_beacon_work(struct work_struct *work)
container_of((void *)vif_priv, struct ieee80211_vif, drv_priv);
struct ieee80211_hw *dev = vif_priv->dev;
struct ieee80211_mgmt *mgmt;
+ struct ieee80211_tx_control control;
struct sk_buff *skb;
/* don't overflow the tx ring */
@@ -1076,7 +1079,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, &control, skb);
resched:
/*
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index c9e2660..4b05427 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);
@@ -1162,6 +1164,7 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
static void zd_beacon_done(struct zd_mac *mac)
{
+ struct ieee80211_tx_control control;
struct sk_buff *skb, *beacon;
if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
@@ -1176,7 +1179,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, &control, skb);
}
/*
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e3fa90c..a5b8ce5 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -483,32 +483,35 @@ enum mac80211_rate_control_flags {
* @idx: rate index to attempt to send with
* @flags: rate control flags (&enum mac80211_rate_control_flags)
* @count: number of tries in this rate before going to the next rate
+ * @tpc: transmit power level in dBm per packet multi-rate-retry (mrr) stage
*
* A value of -1 for @idx indicates an invalid rate and, if used
* in an array of retry rates, that no more rates should be tried.
*
* When used for transmit status reporting, the driver should
- * always report the rate along with the flags it used.
+ * always report the rate and power along with the flags it used.
*
* &struct ieee80211_tx_info contains an array of these structs
- * in the control information, and it will be filled by the rate
- * control algorithm according to what should be sent. For example,
- * if this array contains, in the format { <idx>, <count> } the
+ * in the control information, and it will be filled by the joint rate-
+ * power control algorithm according to what should be sent. For example,
+ * if this array contains, in the format { <idx>, <count>, <tpc> } the
* information
- * { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }
+ * { 3, 2, 16 }, { 2, 2, 10 }, { 1, 4, 5 }, { -1, 0, 0 }
* then this means that the frame should be transmitted
- * up to twice at rate 3, up to twice at rate 2, and up to four
- * times at rate 1 if it doesn't get acknowledged. Say it gets
- * acknowledged by the peer after the fifth attempt, the status
+ * up to twice at rate 3 with 16 dBm, up to twice at rate 2 with 10 dBm,
+ * and up to four times at rate 1 with 5 dBm if it doesn't get acknowledged.
+ * Say it gets acknowledged by the peer after the fifth attempt, the status
* information should then contain
- * { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...
- * since it was transmitted twice at rate 3, twice at rate 2
- * and once at rate 1 after which we received an acknowledgement.
+ * { 3, 2, 16 }, { 2, 2, 10 }, { 1, 1, 5 }, { -1, 0, 0 }
+ * since it was transmitted twice at rate 3 with 16 dBm, twice at rate 2 with
+ * 10 dBm and once at rate 1 with 5 dBm after which we received an
+ * acknowledgement.
*/
struct ieee80211_tx_rate {
s8 idx;
u8 count;
u8 flags;
+ u8 tpc;
} __packed;
/**
@@ -519,9 +522,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
@@ -529,11 +529,11 @@ struct ieee80211_tx_rate {
* @control: union for control data
* @status: union for status data
* @driver_data: array of driver_data pointers
+ * @ack_signal: signal strength of the ACK frame
* @ampdu_ack_len: number of acked aggregated frames.
* relevant only if IEEE80211_TX_STAT_AMPDU was set.
* @ampdu_len: number of aggregated frames.
* relevant only if IEEE80211_TX_STAT_AMPDU was set.
- * @ack_signal: signal strength of the ACK frame
*/
struct ieee80211_tx_info {
/* common information */
@@ -547,7 +547,7 @@ struct ieee80211_tx_info {
union {
struct {
union {
- /* rate control */
+ /* rate control and transmit power control */
struct {
struct ieee80211_tx_rate rates[
IEEE80211_TX_MAX_RATES];
@@ -559,7 +559,6 @@ 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;
} control;
struct {
struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
@@ -567,7 +566,7 @@ struct ieee80211_tx_info {
u8 ampdu_ack_len;
u8 ampdu_len;
u8 antenna;
- /* 21 bytes free */
+ /* 17 bytes free */
} status;
struct {
struct ieee80211_tx_rate driver_rates[
@@ -634,7 +633,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
info->status.rates[i].count = 0;
BUILD_BUG_ON(
- offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
+ offsetof(struct ieee80211_tx_info, status.ack_signal) != 24);
memset(&info->status.ampdu_ack_len, 0,
sizeof(struct ieee80211_tx_info) -
offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
@@ -760,6 +759,7 @@ enum ieee80211_conf_flags {
* @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
* @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
* @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
+ * @IEEE80211_CONF_CHANGE_ACK_POWER: Global ACK power level (in dBm) changed
*/
enum ieee80211_conf_changed {
IEEE80211_CONF_CHANGE_SMPS = BIT(1),
@@ -770,6 +770,7 @@ enum ieee80211_conf_changed {
IEEE80211_CONF_CHANGE_CHANNEL = BIT(6),
IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7),
IEEE80211_CONF_CHANGE_IDLE = BIT(8),
+ IEEE80211_CONF_CHANGE_ACK_POWER = BIT(9),
};
/**
@@ -826,6 +827,8 @@ enum ieee80211_smps_mode {
* @smps_mode: spatial multiplexing powersave mode; note that
* %IEEE80211_SMPS_STATIC is used when the device is not
* configured for an HT channel
+ * @ack_power: global power level in dBm to use for all
+ * mac80211 acknowledgement_packets
*/
struct ieee80211_conf {
u32 flags;
@@ -840,6 +843,8 @@ struct ieee80211_conf {
struct ieee80211_channel *channel;
enum nl80211_channel_type channel_type;
enum ieee80211_smps_mode smps_mode;
+
+ u8 ack_power;
};
/**
@@ -1068,6 +1073,15 @@ enum sta_notify_cmd {
};
/**
+ * struct ieee80211_tx_control - TX control data
+ *
+ * @sta: station table entry
+ */
+struct ieee80211_tx_control {
+ struct ieee80211_sta *sta;
+};
+
+/**
* enum ieee80211_hw_flags - hardware flags
*
* These flags are used to indicate hardware capabilities to
@@ -1227,6 +1241,35 @@ enum ieee80211_hw_flags {
};
/**
+ * enum ieee80211_tpc_support - type of transmit power control support
+ *
+ * These flags are used to indicate transmit power control capabilities
+ * to the stack. Generally, flags here should have their meaning
+ * done in a way that the simplest hardware doesn't need setting
+ * any particular flags. There are some exceptions to this rule,
+ * however, so you are advised to review these flags carefully.
+ *
+ * @IEEE80211_TPC_NONE: No tpc beside a fixed global setting is available.
+ * This setting is used as the default case. Extended tpc capabilities
+ * need to be announced via flags within the individual hardware driver.
+ *
+ * @IEEE80211_TPC_PER_DATA_PACKET: One power level per data packet can
+ * be set. Each data packet is send out with its individual power level.
+ *
+ * @IEEE80211_TPC_PER_DATA_MRR: Multiple individual power levels per
+ * multi-rate-retry stage within a data packet are supported.
+ *
+ * @IEEE80211_TPC_ACK_POWER_GLOBAL: One power level of ack packets is
+ * globaly adjustable.
+ */
+enum ieee80211_tpc_support {
+ IEEE80211_TPC_NONE =1<<0,
+ IEEE80211_TPC_PER_DATA_PACKET =1<<1,
+ IEEE80211_TPC_PER_DATA_MRR =1<<2,
+ IEEE80211_TPC_ACK_POWER_GLOBAL =1<<3,
+};
+
+/**
* struct ieee80211_hw - hardware information and state
*
* This structure contains the configuration and hardware
@@ -1274,6 +1317,7 @@ enum ieee80211_hw_flags {
* @max_report_rates: maximum number of alternate rate retry stages
* the hw can report back.
* @max_rate_tries: maximum number of tries for each stage
+ * @tpc_support: indicates the type of transmit power control support
*
* @napi_weight: weight used for NAPI polling. You must specify an
* appropriate value here if a napi_poll operation is provided
@@ -1319,6 +1363,7 @@ struct ieee80211_hw {
u8 max_rates;
u8 max_report_rates;
u8 max_rate_tries;
+ u8 tpc_support;
u8 max_rx_aggregation_subframes;
u8 max_tx_aggregation_subframes;
u8 offchannel_tx_hw_queue;
@@ -2258,7 +2303,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 df92031..a81117a 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/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e0423f8..d3c69db 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -194,6 +194,8 @@ struct ieee80211_tx_data {
struct ieee80211_channel *channel;
unsigned int flags;
+
+ struct ieee80211_tx_control control;
};
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c9d2175..94c362d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1194,6 +1194,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
static bool ieee80211_tx_frags(struct ieee80211_local *local,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
+ struct ieee80211_tx_control *control,
struct sk_buff_head *skbs,
bool txpending)
{
@@ -1233,10 +1234,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;
@@ -1246,6 +1247,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
* Returns false if the frame couldn't be transmitted but was queued instead.
*/
static bool __ieee80211_tx(struct ieee80211_local *local,
+ struct ieee80211_tx_control *control,
struct sk_buff_head *skbs, int led_len,
struct sta_info *sta, bool txpending)
{
@@ -1294,7 +1296,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
break;
}
- result = ieee80211_tx_frags(local, vif, pubsta, skbs,
+ result = ieee80211_tx_frags(local, vif, pubsta, control, skbs,
txpending);
ieee80211_tpt_led_trig_tx(local, fc, led_len);
@@ -1402,7 +1404,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
if (!invoke_tx_handlers(&tx))
- result = __ieee80211_tx(local, &tx.skbs, led_len,
+ result = __ieee80211_tx(local, &tx.control, &tx.skbs, led_len,
tx.sta, txpending);
out:
rcu_read_unlock();
@@ -2144,6 +2146,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata;
struct sta_info *sta;
struct ieee80211_hdr *hdr;
+ struct ieee80211_tx_control control;
bool result;
sdata = vif_to_sdata(info->control.vif);
@@ -2159,7 +2162,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
hdr = (struct ieee80211_hdr *)skb->data;
sta = sta_info_get(sdata, hdr->addr1);
- result = __ieee80211_tx(local, &skbs, skb->len, sta, true);
+ result = __ieee80211_tx(local, &control, &skbs, skb->len, sta, true);
}
return result;
--
1.7.10.4
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2012-07-08 17:02 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-08 17:02 [ath9k-devel] [PATCH] mac80211: Add transmit power control support (TPC) Thomas Huehn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).