Skip to content

Commit

Permalink
mac80211: use rate index in TX control
Browse files Browse the repository at this point in the history
This patch modifies struct ieee80211_tx_control to give band
info and the rate index (instead of rate pointers) to drivers.
This mostly serves to reduce the TX control structure size to
make it fit into skb->cb so that the fragmentation code can
put it there and we can think about passing it to drivers that
way in the future.

The rt2x00 driver update was done by Ivo, thanks.

Signed-off-by: Ivo van Doorn <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
  • Loading branch information
jmberg authored and linvjw committed May 22, 2008
1 parent 36d6825 commit 2e92e6f
Show file tree
Hide file tree
Showing 25 changed files with 205 additions and 151 deletions.
6 changes: 3 additions & 3 deletions drivers/net/wireless/adm8211.c
Original file line number Diff line number Diff line change
Expand Up @@ -1693,10 +1693,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
size_t payload_len, hdrlen;
int plcp, dur, len, plcp_signal, short_preamble;
struct ieee80211_hdr *hdr;
struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, control);

short_preamble = !!(control->tx_rate->flags &
IEEE80211_TXCTL_SHORT_PREAMBLE);
plcp_signal = control->tx_rate->bitrate;
short_preamble = !!(txrate->flags & IEEE80211_TXCTL_SHORT_PREAMBLE);
plcp_signal = txrate->bitrate;

hdr = (struct ieee80211_hdr *)skb->data;
fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED;
Expand Down
8 changes: 5 additions & 3 deletions drivers/net/wireless/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1323,7 +1323,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,

ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
(sc->power_level * 2), ctl->tx_rate->hw_value,
(sc->power_level * 2),
ieee80211_get_tx_rate(sc->hw, ctl)->hw_value,
ctl->retry_limit, keyidx, 0, flags, 0, 0);
if (ret)
goto err_unmap;
Expand Down Expand Up @@ -2046,7 +2047,8 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
ieee80211_get_hdrlen_from_skb(skb),
AR5K_PKT_TYPE_BEACON, (sc->power_level * 2),
ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID,
ieee80211_get_tx_rate(sc->hw, ctl)->hw_value,
1, AR5K_TXKEYIX_INVALID,
antenna, flags, 0, 0);
if (ret)
goto err_unmap;
Expand Down Expand Up @@ -2654,7 +2656,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
memmove(skb->data, skb->data+pad, hdrlen);
}

sc->led_txrate = ctl->tx_rate->hw_value;
sc->led_txrate = ieee80211_get_tx_rate(hw, ctl)->hw_value;

spin_lock_irqsave(&sc->txbuflock, flags);
if (list_empty(&sc->txbuf)) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
len = min((size_t) dev->wl->current_beacon->len,
0x200 - sizeof(struct b43_plcp_hdr6));
rate = dev->wl->beacon_txctl.tx_rate->hw_value;
rate = ieee80211_get_tx_rate(dev->wl->hw, &dev->wl->beacon_txctl)->hw_value;

b43_write_template_common(dev, (const u8 *)bcn,
len, ram_offset, shm_size_offset, rate);
Expand Down
13 changes: 8 additions & 5 deletions drivers/net/wireless/b43/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,14 @@ int b43_generate_txhdr(struct b43_wldev *dev,
u32 mac_ctl = 0;
u16 phy_ctl = 0;
u8 extra_ft = 0;
struct ieee80211_rate *txrate;

memset(txhdr, 0, sizeof(*txhdr));

WARN_ON(!txctl->tx_rate);
rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB;
txrate = ieee80211_get_tx_rate(dev->wl->hw, txctl);
rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
rate_ofdm = b43_is_ofdm_rate(rate);
fbrate = txctl->alt_retry_rate ? : txctl->tx_rate;
fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, txctl) ? : txrate;
rate_fb = fbrate->hw_value;
rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);

Expand Down Expand Up @@ -336,9 +337,11 @@ int b43_generate_txhdr(struct b43_wldev *dev,
int rts_rate, rts_rate_fb;
int rts_rate_ofdm, rts_rate_fb_ofdm;
struct b43_plcp_hdr6 *plcp;
struct ieee80211_rate *rts_cts_rate;

WARN_ON(!txctl->rts_cts_rate);
rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, txctl);

rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB;
rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
rts_rate_fb = b43_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/wireless/b43legacy/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,18 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
unsigned int plcp_fragment_len;
u32 mac_ctl = 0;
u16 phy_ctl = 0;
struct ieee80211_rate *tx_rate;

wlhdr = (const struct ieee80211_hdr *)fragment_data;
fctl = le16_to_cpu(wlhdr->frame_control);

memset(txhdr, 0, sizeof(*txhdr));

rate = txctl->tx_rate->hw_value;
tx_rate = ieee80211_get_tx_rate(dev->wl->hw, txctl);

rate = tx_rate->hw_value;
rate_ofdm = b43legacy_is_ofdm_rate(rate);
rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate;
rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, txctl) ? : tx_rate;
rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);

txhdr->mac_frame_ctl = wlhdr->frame_control;
Expand Down Expand Up @@ -312,7 +315,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
int rts_rate_ofdm;
int rts_rate_fb_ofdm;

rts_rate = txctl->rts_cts_rate->hw_value;
rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, txctl)->hw_value;
rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/wireless/iwlwifi/iwl-3945-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ static void rs_tx_status(void *priv_rate,


retries = tx_resp->retry_count;
first_index = tx_resp->control.tx_rate->hw_value;
first_index = sband->bitrates[tx_resp->control.tx_rate_idx].hw_value;
if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
return;
Expand Down Expand Up @@ -669,7 +669,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
sel->rate = rate_lowest(local, sband, sta);
sel->rate_idx = rate_lowest_index(local, sband, sta);
rcu_read_unlock();
return;
}
Expand Down Expand Up @@ -813,7 +813,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,

IWL_DEBUG_RATE("leave: %d\n", index);

sel->rate = &sband->bitrates[sta->txrate_idx];
sel->rate_idx = sta->txrate_idx;
}

static struct rate_control_ops rs_ops = {
Expand Down
7 changes: 5 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-3945.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
tx_resp->rate, tx_resp->failure_frame);

rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
tx_status->control.tx_rate = &priv->ieee_rates[rate_idx];
if (tx_status->control.band == IEEE80211_BAND_5GHZ)
rate_idx -= IWL_FIRST_OFDM_RATE;
tx_status->control.tx_rate_idx = rate_idx;
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
iwl3945_tx_queue_reclaim(priv, txq_id, index);

Expand Down Expand Up @@ -962,7 +964,8 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
struct ieee80211_hdr *hdr, int sta_id, int tx_id)
{
unsigned long flags;
u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
u16 hw_value = ieee80211_get_tx_rate(priv->hw, ctrl)->hw_value;
u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1);
u16 rate_mask;
int rate;
u8 rts_retry_limit;
Expand Down
12 changes: 7 additions & 5 deletions drivers/net/wireless/iwlwifi/iwl-4965-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
if (priv->band == IEEE80211_BAND_5GHZ)
rs_index -= IWL_FIRST_OFDM_RATE;

if ((tx_resp->control.tx_rate == NULL) ||
if ((tx_resp->control.tx_rate_idx < 0) ||
(tbl_type.is_SGI ^
!!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) ||
(tbl_type.is_fat ^
Expand All @@ -875,7 +875,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
(!!(tx_rate & RATE_MCS_GF_MSK) ^
!!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) ||
(hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
tx_resp->control.tx_rate->bitrate)) {
hw->wiphy->bands[tx_resp->control.band]->bitrates[tx_resp->control.tx_rate_idx].bitrate)) {
IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate);
goto out;
}
Expand Down Expand Up @@ -2154,7 +2154,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,
fc = le16_to_cpu(hdr->frame_control);
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
!sta || !sta->rate_ctrl_priv) {
sel->rate = rate_lowest(local, sband, sta);
sel->rate_idx = rate_lowest_index(local, sband, sta);
goto out;
}

Expand Down Expand Up @@ -2184,11 +2184,13 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev,

done:
if ((i < 0) || (i > IWL_RATE_COUNT)) {
sel->rate = rate_lowest(local, sband, sta);
sel->rate_idx = rate_lowest_index(local, sband, sta);
goto out;
}

sel->rate = &priv->ieee_rates[i];
if (sband->band == IEEE80211_BAND_5GHZ)
i -= IWL_FIRST_OFDM_RATE;
sel->rate_idx = i;
out:
rcu_read_unlock();
}
Expand Down
10 changes: 3 additions & 7 deletions drivers/net/wireless/iwlwifi/iwl-4965.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,10 @@ void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
control->flags |= IEEE80211_TXCTL_DUP_DATA;
if (rate_n_flags & RATE_MCS_SGI_MSK)
control->flags |= IEEE80211_TXCTL_SHORT_GI;
/* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use
* IEEE80211_BAND_2GHZ band as it contains all the rates */
rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
if (rate_index == -1)
control->tx_rate = NULL;
else
control->tx_rate =
&priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index];
if (control->band == IEEE80211_BAND_5GHZ)
rate_index -= IWL_FIRST_OFDM_RATE;
control->tx_rate_idx = rate_index;
}

int iwl4965_hw_rxq_stop(struct iwl_priv *priv)
Expand Down
8 changes: 6 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,10 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
u8 data_retry_limit = 0;
u8 rate_plcp;
u16 rate_flags = 0;
int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1);
int rate_idx;

rate_idx = min(ieee80211_get_tx_rate(priv->hw, ctrl)->hw_value & 0xffff,
IWL_RATE_COUNT - 1);

rate_plcp = iwl_rates[rate_idx].plcp;

Expand Down Expand Up @@ -723,7 +726,8 @@ int iwl_tx_skb(struct iwl_priv *priv,
goto drop_unlock;
}

if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
if ((ieee80211_get_tx_rate(priv->hw, ctl)->hw_value & 0xFF) ==
IWL_INVALID_RATE) {
IWL_ERROR("ERROR: No TX rate available.\n");
goto drop_unlock;
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl3945-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -2581,7 +2581,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
goto drop_unlock;
}

if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) {
if ((ieee80211_get_tx_rate(priv->hw, ctl)->hw_value & 0xFF) == IWL_INVALID_RATE) {
IWL_ERROR("ERROR: No TX rate available.\n");
goto drop_unlock;
}
Expand Down Expand Up @@ -6694,7 +6694,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
}

IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ctl->tx_rate->bitrate);
ieee80211_get_tx_rate(hw, ctl)->bitrate);

if (iwl3945_tx_skb(priv, skb, ctl))
dev_kfree_skb_any(skb);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/iwlwifi/iwl4965-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -4281,7 +4281,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
}

IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ctl->tx_rate->bitrate);
ieee80211_get_tx_rate(hw, ctl)->bitrate);

if (iwl_tx_skb(priv, skb, ctl))
dev_kfree_skb_any(skb);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/p54/p54common.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
txhdr->padding2 = 0;

/* TODO: add support for alternate retry TX rates */
rate = control->tx_rate->hw_value;
rate = ieee80211_get_tx_rate(dev, control)->hw_value;
if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
rate |= 0x10;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/wireless/rt2x00/rt2x00queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
struct txentry_desc *txdesc,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
struct ieee80211_rate *rate = control->tx_rate;
struct ieee80211_rate *rate =
ieee80211_get_tx_rate(rt2x00dev->hw, control);
const struct rt2x00_rate *hwrate;
unsigned int data_length;
unsigned int duration;
Expand Down Expand Up @@ -77,8 +79,9 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
__set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags);
__clear_bit(ENTRY_TXD_ACK, &txdesc->flags);
}
if (control->rts_cts_rate)
rate = control->rts_cts_rate;
if (control->rts_cts_rate_idx >= 0)
rate =
ieee80211_get_rts_cts_rate(rt2x00dev->hw, control);
}

/*
Expand Down
19 changes: 8 additions & 11 deletions drivers/net/wireless/rtl8180_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,24 +257,21 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
mapping = pci_map_single(priv->pdev, skb->data,
skb->len, PCI_DMA_TODEVICE);

BUG_ON(!control->tx_rate);

tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
RTL8180_TX_DESC_FLAG_LS |
(control->tx_rate->hw_value << 24) | skb->len;
(ieee80211_get_tx_rate(dev, control)->hw_value << 24) |
skb->len;

if (priv->r8185)
tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
RTL8180_TX_DESC_FLAG_NO_ENC;

if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
BUG_ON(!control->rts_cts_rate);
tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
tx_flags |= control->rts_cts_rate->hw_value << 19;
tx_flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
BUG_ON(!control->rts_cts_rate);
tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
tx_flags |= control->rts_cts_rate->hw_value << 19;
tx_flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
}

*((struct ieee80211_tx_control **) skb->cb) =
Expand All @@ -288,9 +285,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
unsigned int remainder;

plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
(control->tx_rate->bitrate * 2) / 10);
(ieee80211_get_tx_rate(dev, control)->bitrate * 2) / 10);
remainder = (16 * (skb->len + 4)) %
((control->tx_rate->bitrate * 2) / 10);
((ieee80211_get_tx_rate(dev, control)->bitrate * 2) / 10);
if (remainder > 0 && remainder <= 6)
plcp_len |= 1 << 15;
}
Expand All @@ -303,8 +300,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
entry->plcp_len = cpu_to_le16(plcp_len);
entry->tx_buf = cpu_to_le32(mapping);
entry->frame_len = cpu_to_le32(skb->len);
entry->flags2 = control->alt_retry_rate != NULL ?
control->alt_retry_rate->bitrate << 4 : 0;
entry->flags2 = control->alt_retry_rate_idx >= 0 ?
ieee80211_get_alt_retry_rate(dev, control)->bitrate << 4 : 0;
entry->retry_limit = control->retry_limit;
entry->flags = cpu_to_le32(tx_flags);
__skb_queue_tail(&ring->queue, skb);
Expand Down
10 changes: 3 additions & 7 deletions drivers/net/wireless/rtl8187_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,21 +179,17 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
flags = skb->len;
flags |= RTL8187_TX_FLAG_NO_ENCRYPT;

BUG_ON(!control->tx_rate);

flags |= control->tx_rate->hw_value << 24;
flags |= ieee80211_get_tx_rate(dev, control)->hw_value << 24;
if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data))
flags |= RTL8187_TX_FLAG_MORE_FRAG;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
BUG_ON(!control->rts_cts_rate);
flags |= RTL8187_TX_FLAG_RTS;
flags |= control->rts_cts_rate->hw_value << 19;
flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
rts_dur = ieee80211_rts_duration(dev, priv->vif,
skb->len, control);
} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
BUG_ON(!control->rts_cts_rate);
flags |= RTL8187_TX_FLAG_CTS;
flags |= control->rts_cts_rate->hw_value << 19;
flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
}

hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
Expand Down
Loading

0 comments on commit 2e92e6f

Please sign in to comment.