forked from Minki/linux
mac80211: move TX info into skb->cb
This patch converts mac80211 and all drivers to have transmit information and status in skb->cb rather than allocating extra memory for it and copying all the data around. To make it fit, a union is used where only data that is necessary for all steps is kept outside of the union. A number of fixes were done by Ivo, as well as the rt2x00 part of this patch. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Acked-by: David S. Miller <davem@davemloft.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
e24549485f
commit
e039fa4a41
@ -324,7 +324,7 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
|
||||
for (dirty_tx = priv->dirty_tx; priv->cur_tx - dirty_tx; dirty_tx++) {
|
||||
unsigned int entry = dirty_tx % priv->tx_ring_size;
|
||||
u32 status = le32_to_cpu(priv->tx_ring[entry].status);
|
||||
struct ieee80211_tx_status tx_status;
|
||||
struct ieee80211_tx_info *txi;
|
||||
struct adm8211_tx_ring_info *info;
|
||||
struct sk_buff *skb;
|
||||
|
||||
@ -334,24 +334,23 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
|
||||
|
||||
info = &priv->tx_buffers[entry];
|
||||
skb = info->skb;
|
||||
txi = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/* TODO: check TDES0_STATUS_TUF and TDES0_STATUS_TRO */
|
||||
|
||||
pci_unmap_single(priv->pdev, info->mapping,
|
||||
info->skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
memset(&tx_status, 0, sizeof(tx_status));
|
||||
memset(&txi->status, 0, sizeof(txi->status));
|
||||
skb_pull(skb, sizeof(struct adm8211_tx_hdr));
|
||||
memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen);
|
||||
memcpy(&tx_status.control, &info->tx_control,
|
||||
sizeof(tx_status.control));
|
||||
if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
if (status & TDES0_STATUS_ES)
|
||||
tx_status.excessive_retries = 1;
|
||||
txi->status.excessive_retries = 1;
|
||||
else
|
||||
tx_status.flags |= IEEE80211_TX_STATUS_ACK;
|
||||
txi->flags |= IEEE80211_TX_STAT_ACK;
|
||||
}
|
||||
ieee80211_tx_status_irqsafe(dev, skb, &tx_status);
|
||||
ieee80211_tx_status_irqsafe(dev, skb);
|
||||
|
||||
info->skb = NULL;
|
||||
}
|
||||
@ -1638,7 +1637,6 @@ static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int
|
||||
/* Transmit skb w/adm8211_tx_hdr (802.11 header created by hardware) */
|
||||
static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
u16 plcp_signal,
|
||||
struct ieee80211_tx_control *control,
|
||||
size_t hdrlen)
|
||||
{
|
||||
struct adm8211_priv *priv = dev->priv;
|
||||
@ -1664,7 +1662,6 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
|
||||
priv->tx_buffers[entry].skb = skb;
|
||||
priv->tx_buffers[entry].mapping = mapping;
|
||||
memcpy(&priv->tx_buffers[entry].tx_control, control, sizeof(*control));
|
||||
priv->tx_buffers[entry].hdrlen = hdrlen;
|
||||
priv->tx_ring[entry].buffer1 = cpu_to_le32(mapping);
|
||||
|
||||
@ -1685,17 +1682,17 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
/* Put adm8211_tx_hdr on skb and transmit */
|
||||
static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct adm8211_tx_hdr *txhdr;
|
||||
u16 fc;
|
||||
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);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info);
|
||||
|
||||
short_preamble = !!(txrate->flags & IEEE80211_TXCTL_SHORT_PREAMBLE);
|
||||
short_preamble = !!(txrate->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE);
|
||||
plcp_signal = txrate->bitrate;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
@ -1730,15 +1727,15 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
if (short_preamble)
|
||||
txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE);
|
||||
|
||||
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS);
|
||||
|
||||
if (fc & IEEE80211_FCTL_PROTECTED)
|
||||
txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_WEP_ENGINE);
|
||||
|
||||
txhdr->retry_limit = control->retry_limit;
|
||||
txhdr->retry_limit = info->control.retry_limit;
|
||||
|
||||
adm8211_tx_raw(dev, skb, plcp_signal, control, hdrlen);
|
||||
adm8211_tx_raw(dev, skb, plcp_signal, hdrlen);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
@ -443,7 +443,6 @@ struct adm8211_rx_ring_info {
|
||||
struct adm8211_tx_ring_info {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t mapping;
|
||||
struct ieee80211_tx_control tx_control;
|
||||
size_t hdrlen;
|
||||
};
|
||||
|
||||
|
@ -167,8 +167,7 @@ static struct pci_driver ath5k_pci_driver = {
|
||||
/*
|
||||
* Prototypes - MAC 802.11 stack related functions
|
||||
*/
|
||||
static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl);
|
||||
static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
static int ath5k_reset(struct ieee80211_hw *hw);
|
||||
static int ath5k_start(struct ieee80211_hw *hw);
|
||||
static void ath5k_stop(struct ieee80211_hw *hw);
|
||||
@ -196,8 +195,7 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
|
||||
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
|
||||
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
|
||||
static int ath5k_beacon_update(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl);
|
||||
struct sk_buff *skb);
|
||||
|
||||
static struct ieee80211_ops ath5k_hw_ops = {
|
||||
.tx = ath5k_tx,
|
||||
@ -251,9 +249,7 @@ static void ath5k_desc_free(struct ath5k_softc *sc,
|
||||
static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
|
||||
struct ath5k_buf *bf);
|
||||
static int ath5k_txbuf_setup(struct ath5k_softc *sc,
|
||||
struct ath5k_buf *bf,
|
||||
struct ieee80211_tx_control *ctl);
|
||||
|
||||
struct ath5k_buf *bf);
|
||||
static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
|
||||
struct ath5k_buf *bf)
|
||||
{
|
||||
@ -289,8 +285,7 @@ static void ath5k_tx_processq(struct ath5k_softc *sc,
|
||||
static void ath5k_tasklet_tx(unsigned long data);
|
||||
/* Beacon handling */
|
||||
static int ath5k_beacon_setup(struct ath5k_softc *sc,
|
||||
struct ath5k_buf *bf,
|
||||
struct ieee80211_tx_control *ctl);
|
||||
struct ath5k_buf *bf);
|
||||
static void ath5k_beacon_send(struct ath5k_softc *sc);
|
||||
static void ath5k_beacon_config(struct ath5k_softc *sc);
|
||||
static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
|
||||
@ -1295,37 +1290,36 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
{
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath5k_txq *txq = sc->txq;
|
||||
struct ath5k_desc *ds = bf->desc;
|
||||
struct sk_buff *skb = bf->skb;
|
||||
struct ieee80211_tx_info *info = (void*) skb->cb;
|
||||
unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
|
||||
int ret;
|
||||
|
||||
flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
|
||||
bf->ctl = *ctl;
|
||||
|
||||
/* XXX endianness */
|
||||
bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
if (ctl->flags & IEEE80211_TXCTL_NO_ACK)
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
flags |= AR5K_TXDESC_NOACK;
|
||||
|
||||
pktlen = skb->len;
|
||||
|
||||
if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) {
|
||||
keyidx = ctl->hw_key->hw_key_idx;
|
||||
pktlen += ctl->icv_len;
|
||||
if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT)) {
|
||||
keyidx = info->control.hw_key->hw_key_idx;
|
||||
pktlen += info->control.icv_len;
|
||||
}
|
||||
|
||||
ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
|
||||
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
|
||||
(sc->power_level * 2),
|
||||
ieee80211_get_tx_rate(sc->hw, ctl)->hw_value,
|
||||
ctl->retry_limit, keyidx, 0, flags, 0, 0);
|
||||
ieee80211_get_tx_rate(sc->hw, info)->hw_value,
|
||||
info->control.retry_limit, keyidx, 0, flags, 0, 0);
|
||||
if (ret)
|
||||
goto err_unmap;
|
||||
|
||||
@ -1927,11 +1921,11 @@ next:
|
||||
static void
|
||||
ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
||||
{
|
||||
struct ieee80211_tx_status txs = {};
|
||||
struct ath5k_tx_status ts = {};
|
||||
struct ath5k_buf *bf, *bf0;
|
||||
struct ath5k_desc *ds;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *info;
|
||||
int ret;
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
@ -1951,24 +1945,25 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
|
||||
}
|
||||
|
||||
skb = bf->skb;
|
||||
info = (void*) skb->cb;
|
||||
bf->skb = NULL;
|
||||
|
||||
pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
|
||||
txs.control = bf->ctl;
|
||||
txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
|
||||
info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6;
|
||||
if (unlikely(ts.ts_status)) {
|
||||
sc->ll_stats.dot11ACKFailureCount++;
|
||||
if (ts.ts_status & AR5K_TXERR_XRETRY)
|
||||
txs.excessive_retries = 1;
|
||||
info->status.excessive_retries = 1;
|
||||
else if (ts.ts_status & AR5K_TXERR_FILT)
|
||||
txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
|
||||
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
|
||||
} else {
|
||||
txs.flags |= IEEE80211_TX_STATUS_ACK;
|
||||
txs.ack_signal = ts.ts_rssi;
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.ack_signal = ts.ts_rssi;
|
||||
}
|
||||
|
||||
ieee80211_tx_status(sc->hw, skb, &txs);
|
||||
ieee80211_tx_status(sc->hw, skb);
|
||||
sc->tx_stats[txq->qnum].count++;
|
||||
|
||||
spin_lock(&sc->txbuflock);
|
||||
@ -2005,10 +2000,10 @@ ath5k_tasklet_tx(unsigned long data)
|
||||
* Setup the beacon frame for transmit.
|
||||
*/
|
||||
static int
|
||||
ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
|
||||
{
|
||||
struct sk_buff *skb = bf->skb;
|
||||
struct ieee80211_tx_info *info = (void*) skb->cb;
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
struct ath5k_desc *ds;
|
||||
int ret, antenna = 0;
|
||||
@ -2047,7 +2042,7 @@ 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),
|
||||
ieee80211_get_tx_rate(sc->hw, ctl)->hw_value,
|
||||
ieee80211_get_tx_rate(sc->hw, info)->hw_value,
|
||||
1, AR5K_TXKEYIX_INVALID,
|
||||
antenna, flags, 0, 0);
|
||||
if (ret)
|
||||
@ -2626,11 +2621,11 @@ ath5k_led_event(struct ath5k_softc *sc, int event)
|
||||
\********************/
|
||||
|
||||
static int
|
||||
ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ath5k_buf *bf;
|
||||
struct ieee80211_tx_info *info = (void*) skb->cb;
|
||||
unsigned long flags;
|
||||
int hdrlen;
|
||||
int pad;
|
||||
@ -2656,13 +2651,13 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
memmove(skb->data, skb->data+pad, hdrlen);
|
||||
}
|
||||
|
||||
sc->led_txrate = ieee80211_get_tx_rate(hw, ctl)->hw_value;
|
||||
sc->led_txrate = ieee80211_get_tx_rate(hw, info)->hw_value;
|
||||
|
||||
spin_lock_irqsave(&sc->txbuflock, flags);
|
||||
if (list_empty(&sc->txbuf)) {
|
||||
ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
|
||||
spin_unlock_irqrestore(&sc->txbuflock, flags);
|
||||
ieee80211_stop_queue(hw, ctl->queue);
|
||||
ieee80211_stop_queue(hw, info->queue);
|
||||
return -1;
|
||||
}
|
||||
bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
|
||||
@ -2674,7 +2669,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
|
||||
bf->skb = skb;
|
||||
|
||||
if (ath5k_txbuf_setup(sc, bf, ctl)) {
|
||||
if (ath5k_txbuf_setup(sc, bf)) {
|
||||
bf->skb = NULL;
|
||||
spin_lock_irqsave(&sc->txbuflock, flags);
|
||||
list_add_tail(&bf->list, &sc->txbuf);
|
||||
@ -3052,8 +3047,7 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
static int
|
||||
ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
int ret;
|
||||
@ -3069,7 +3063,7 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
|
||||
ath5k_txbuf_free(sc, sc->bbuf);
|
||||
sc->bbuf->skb = skb;
|
||||
ret = ath5k_beacon_setup(sc, sc->bbuf, ctl);
|
||||
ret = ath5k_beacon_setup(sc, sc->bbuf);
|
||||
if (ret)
|
||||
sc->bbuf->skb = NULL;
|
||||
else
|
||||
|
@ -60,7 +60,6 @@ struct ath5k_buf {
|
||||
dma_addr_t daddr; /* physical addr of desc */
|
||||
struct sk_buff *skb; /* skbuff for buf */
|
||||
dma_addr_t skbaddr;/* physical addr of skb data */
|
||||
struct ieee80211_tx_control ctl;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -733,7 +733,6 @@ struct b43_wl {
|
||||
/* The beacon we are currently using (AP or IBSS mode).
|
||||
* This beacon stuff is protected by the irq_lock. */
|
||||
struct sk_buff *current_beacon;
|
||||
struct ieee80211_tx_control beacon_txctl;
|
||||
bool beacon0_uploaded;
|
||||
bool beacon1_uploaded;
|
||||
struct work_struct beacon_update_trigger;
|
||||
|
@ -1131,10 +1131,10 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
|
||||
}
|
||||
|
||||
static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct b43_dma_ops *ops = ring->ops;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
u8 *header;
|
||||
int slot, old_top_slot, old_used_slots;
|
||||
int err;
|
||||
@ -1158,7 +1158,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
header = &(ring->txhdr_cache[slot * hdrsize]);
|
||||
cookie = generate_cookie(ring, slot);
|
||||
err = b43_generate_txhdr(ring->dev, header,
|
||||
skb->data, skb->len, ctl, cookie);
|
||||
skb->data, skb->len, info, cookie);
|
||||
if (unlikely(err)) {
|
||||
ring->current_slot = old_top_slot;
|
||||
ring->used_slots = old_used_slots;
|
||||
@ -1180,7 +1180,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
desc = ops->idx2desc(ring, slot, &meta);
|
||||
memset(meta, 0, sizeof(*meta));
|
||||
|
||||
memcpy(&meta->txstat.control, ctl, sizeof(*ctl));
|
||||
meta->skb = skb;
|
||||
meta->is_last_fragment = 1;
|
||||
|
||||
@ -1210,7 +1209,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
|
||||
|
||||
ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1);
|
||||
|
||||
if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
|
||||
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
|
||||
/* Tell the firmware about the cookie of the last
|
||||
* mcast frame, so it can clear the more-data bit in it. */
|
||||
b43_shm_write16(ring->dev, B43_SHM_SHARED,
|
||||
@ -1281,16 +1280,16 @@ static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev,
|
||||
return ring;
|
||||
}
|
||||
|
||||
int b43_dma_tx(struct b43_wldev *dev,
|
||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
|
||||
int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct b43_dmaring *ring;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
|
||||
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
|
||||
/* The multicast ring will be sent after the DTIM */
|
||||
ring = dev->dma.tx_ring_mcast;
|
||||
/* Set the more-data bit. Ucode will clear it on
|
||||
@ -1298,7 +1297,7 @@ int b43_dma_tx(struct b43_wldev *dev,
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
} else {
|
||||
/* Decide by priority where to put this frame. */
|
||||
ring = select_ring_by_priority(dev, ctl->queue);
|
||||
ring = select_ring_by_priority(dev, info->queue);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
@ -1316,9 +1315,9 @@ int b43_dma_tx(struct b43_wldev *dev,
|
||||
/* Assign the queue number to the ring (if not already done before)
|
||||
* so TX status handling can use it. The queue to ring mapping is
|
||||
* static, so we don't need to store it per frame. */
|
||||
ring->queue_prio = ctl->queue;
|
||||
ring->queue_prio = info->queue;
|
||||
|
||||
err = dma_tx_fragment(ring, skb, ctl);
|
||||
err = dma_tx_fragment(ring, skb);
|
||||
if (unlikely(err == -ENOKEY)) {
|
||||
/* Drop this packet, as we don't have the encryption key
|
||||
* anymore and must not transmit it unencrypted. */
|
||||
@ -1334,7 +1333,7 @@ int b43_dma_tx(struct b43_wldev *dev,
|
||||
if ((free_slots(ring) < SLOTS_PER_PACKET) ||
|
||||
should_inject_overflow(ring)) {
|
||||
/* This TX ring is full. */
|
||||
ieee80211_stop_queue(dev->wl->hw, ctl->queue);
|
||||
ieee80211_stop_queue(dev->wl->hw, info->queue);
|
||||
ring->stopped = 1;
|
||||
if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
|
||||
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
|
||||
@ -1377,13 +1376,19 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||
b43_txhdr_size(dev), 1);
|
||||
|
||||
if (meta->is_last_fragment) {
|
||||
B43_WARN_ON(!meta->skb);
|
||||
/* Call back to inform the ieee80211 subsystem about the
|
||||
* status of the transmission.
|
||||
* Some fields of txstat are already filled in dma_tx().
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
BUG_ON(!meta->skb);
|
||||
|
||||
info = IEEE80211_SKB_CB(meta->skb);
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
/*
|
||||
* Call back to inform the ieee80211 subsystem about
|
||||
* the status of the transmission.
|
||||
*/
|
||||
frame_succeed = b43_fill_txstatus_report(
|
||||
&(meta->txstat), status);
|
||||
frame_succeed = b43_fill_txstatus_report(info, status);
|
||||
#ifdef CONFIG_B43_DEBUG
|
||||
if (frame_succeed)
|
||||
ring->nr_succeed_tx_packets++;
|
||||
@ -1391,8 +1396,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||
ring->nr_failed_tx_packets++;
|
||||
ring->nr_total_packet_tries += status->frame_count;
|
||||
#endif /* DEBUG */
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
|
||||
&(meta->txstat));
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
|
||||
|
||||
/* skb is freed by ieee80211_tx_status_irqsafe() */
|
||||
meta->skb = NULL;
|
||||
} else {
|
||||
|
@ -181,7 +181,6 @@ struct b43_dmadesc_meta {
|
||||
dma_addr_t dmaaddr;
|
||||
/* ieee80211 TX status. Only used once per 802.11 frag. */
|
||||
bool is_last_fragment;
|
||||
struct ieee80211_tx_status txstat;
|
||||
};
|
||||
|
||||
struct b43_dmaring;
|
||||
@ -285,7 +284,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev,
|
||||
struct ieee80211_tx_queue_stats *stats);
|
||||
|
||||
int b43_dma_tx(struct b43_wldev *dev,
|
||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl);
|
||||
struct sk_buff *skb);
|
||||
void b43_dma_handle_txstatus(struct b43_wldev *dev,
|
||||
const struct b43_txstatus *status);
|
||||
|
||||
|
@ -1368,18 +1368,18 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
|
||||
unsigned int rate;
|
||||
u16 ctl;
|
||||
int antenna;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon);
|
||||
|
||||
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 = ieee80211_get_tx_rate(dev->wl->hw, &dev->wl->beacon_txctl)->hw_value;
|
||||
rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
|
||||
|
||||
b43_write_template_common(dev, (const u8 *)bcn,
|
||||
len, ram_offset, shm_size_offset, rate);
|
||||
|
||||
/* Write the PHY TX control parameters. */
|
||||
antenna = b43_antenna_from_ieee80211(dev,
|
||||
dev->wl->beacon_txctl.antenna_sel_tx);
|
||||
antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx);
|
||||
antenna = b43_antenna_to_phyctl(antenna);
|
||||
ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
|
||||
/* We can't send beacons with short preamble. Would get PHY errors. */
|
||||
@ -1613,8 +1613,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
|
||||
|
||||
/* Asynchronously update the packet templates in template RAM.
|
||||
* Locking: Requires wl->irq_lock to be locked. */
|
||||
static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon,
|
||||
const struct ieee80211_tx_control *txctl)
|
||||
static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
|
||||
{
|
||||
/* This is the top half of the ansynchronous beacon update.
|
||||
* The bottom half is the beacon IRQ.
|
||||
@ -1625,7 +1624,6 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon,
|
||||
if (wl->current_beacon)
|
||||
dev_kfree_skb_any(wl->current_beacon);
|
||||
wl->current_beacon = beacon;
|
||||
memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl));
|
||||
wl->beacon0_uploaded = 0;
|
||||
wl->beacon1_uploaded = 0;
|
||||
queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
|
||||
@ -2813,8 +2811,7 @@ static int b43_rng_init(struct b43_wl *wl)
|
||||
}
|
||||
|
||||
static int b43_op_tx(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
@ -2836,9 +2833,9 @@ static int b43_op_tx(struct ieee80211_hw *hw,
|
||||
err = -ENODEV;
|
||||
if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
|
||||
if (b43_using_pio_transfers(dev))
|
||||
err = b43_pio_tx(dev, skb, ctl);
|
||||
err = b43_pio_tx(dev, skb);
|
||||
else
|
||||
err = b43_dma_tx(dev, skb, ctl);
|
||||
err = b43_dma_tx(dev, skb);
|
||||
}
|
||||
|
||||
read_unlock_irqrestore(&wl->tx_lock, flags);
|
||||
@ -3429,10 +3426,8 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
|
||||
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
|
||||
B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
|
||||
b43_set_ssid(dev, conf->ssid, conf->ssid_len);
|
||||
if (conf->beacon) {
|
||||
b43_update_templates(wl, conf->beacon,
|
||||
conf->beacon_control);
|
||||
}
|
||||
if (conf->beacon)
|
||||
b43_update_templates(wl, conf->beacon);
|
||||
}
|
||||
b43_write_mac_bssid_templates(dev);
|
||||
}
|
||||
@ -4118,31 +4113,29 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct sk_buff *beacon;
|
||||
unsigned long flags;
|
||||
struct ieee80211_tx_control txctl;
|
||||
|
||||
/* We could modify the existing beacon and set the aid bit in
|
||||
* the TIM field, but that would probably require resizing and
|
||||
* moving of data within the beacon template.
|
||||
* Simply request a new beacon and let mac80211 do the hard work. */
|
||||
beacon = ieee80211_beacon_get(hw, wl->vif, &txctl);
|
||||
beacon = ieee80211_beacon_get(hw, wl->vif);
|
||||
if (unlikely(!beacon))
|
||||
return -ENOMEM;
|
||||
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||
b43_update_templates(wl, beacon, &txctl);
|
||||
b43_update_templates(wl, beacon);
|
||||
spin_unlock_irqrestore(&wl->irq_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
|
||||
struct sk_buff *beacon,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *beacon)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||
b43_update_templates(wl, beacon, ctl);
|
||||
b43_update_templates(wl, beacon);
|
||||
spin_unlock_irqrestore(&wl->irq_lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -446,29 +446,27 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
|
||||
}
|
||||
|
||||
static int pio_tx_frame(struct b43_pio_txqueue *q,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct b43_pio_txpacket *pack;
|
||||
struct b43_txhdr txhdr;
|
||||
u16 cookie;
|
||||
int err;
|
||||
unsigned int hdrlen;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
B43_WARN_ON(list_empty(&q->packets_list));
|
||||
pack = list_entry(q->packets_list.next,
|
||||
struct b43_pio_txpacket, list);
|
||||
memset(&pack->txstat, 0, sizeof(pack->txstat));
|
||||
memcpy(&pack->txstat.control, ctl, sizeof(*ctl));
|
||||
|
||||
cookie = generate_cookie(q, pack);
|
||||
hdrlen = b43_txhdr_size(q->dev);
|
||||
err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data,
|
||||
skb->len, ctl, cookie);
|
||||
skb->len, info, cookie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
|
||||
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
|
||||
/* Tell the firmware about the cookie of the last
|
||||
* mcast frame, so it can clear the more-data bit in it. */
|
||||
b43_shm_write16(q->dev, B43_SHM_SHARED,
|
||||
@ -492,17 +490,18 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int b43_pio_tx(struct b43_wldev *dev,
|
||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
|
||||
int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct b43_pio_txqueue *q;
|
||||
struct ieee80211_hdr *hdr;
|
||||
unsigned long flags;
|
||||
unsigned int hdrlen, total_len;
|
||||
int err = 0;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
|
||||
/* The multicast queue will be sent after the DTIM. */
|
||||
q = dev->pio.tx_queue_mcast;
|
||||
/* Set the frame More-Data bit. Ucode will clear it
|
||||
@ -510,7 +509,7 @@ int b43_pio_tx(struct b43_wldev *dev,
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
} else {
|
||||
/* Decide by priority where to put this frame. */
|
||||
q = select_queue_by_priority(dev, ctl->queue);
|
||||
q = select_queue_by_priority(dev, info->queue);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&q->lock, flags);
|
||||
@ -533,7 +532,7 @@ int b43_pio_tx(struct b43_wldev *dev,
|
||||
if (total_len > (q->buffer_size - q->buffer_used)) {
|
||||
/* Not enough memory on the queue. */
|
||||
err = -EBUSY;
|
||||
ieee80211_stop_queue(dev->wl->hw, ctl->queue);
|
||||
ieee80211_stop_queue(dev->wl->hw, info->queue);
|
||||
q->stopped = 1;
|
||||
goto out_unlock;
|
||||
}
|
||||
@ -541,9 +540,9 @@ int b43_pio_tx(struct b43_wldev *dev,
|
||||
/* Assign the queue number to the ring (if not already done before)
|
||||
* so TX status handling can use it. The mac80211-queue to b43-queue
|
||||
* mapping is static, so we don't need to store it per frame. */
|
||||
q->queue_prio = ctl->queue;
|
||||
q->queue_prio = info->queue;
|
||||
|
||||
err = pio_tx_frame(q, skb, ctl);
|
||||
err = pio_tx_frame(q, skb);
|
||||
if (unlikely(err == -ENOKEY)) {
|
||||
/* Drop this packet, as we don't have the encryption key
|
||||
* anymore and must not transmit it unencrypted. */
|
||||
@ -561,7 +560,7 @@ int b43_pio_tx(struct b43_wldev *dev,
|
||||
if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
|
||||
(q->free_packet_slots == 0)) {
|
||||
/* The queue is full. */
|
||||
ieee80211_stop_queue(dev->wl->hw, ctl->queue);
|
||||
ieee80211_stop_queue(dev->wl->hw, info->queue);
|
||||
q->stopped = 1;
|
||||
}
|
||||
|
||||
@ -578,6 +577,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
|
||||
struct b43_pio_txqueue *q;
|
||||
struct b43_pio_txpacket *pack = NULL;
|
||||
unsigned int total_len;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
q = parse_cookie(dev, status->cookie, &pack);
|
||||
if (unlikely(!q))
|
||||
@ -586,15 +586,17 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
|
||||
|
||||
spin_lock(&q->lock); /* IRQs are already disabled. */
|
||||
|
||||
b43_fill_txstatus_report(&(pack->txstat), status);
|
||||
info = (void *)pack->skb;
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
b43_fill_txstatus_report(info, status);
|
||||
|
||||
total_len = pack->skb->len + b43_txhdr_size(dev);
|
||||
total_len = roundup(total_len, 4);
|
||||
q->buffer_used -= total_len;
|
||||
q->free_packet_slots += 1;
|
||||
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb,
|
||||
&(pack->txstat));
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb);
|
||||
pack->skb = NULL;
|
||||
list_add(&pack->list, &q->packets_list);
|
||||
|
||||
|
@ -62,8 +62,6 @@ struct b43_pio_txpacket {
|
||||
struct b43_pio_txqueue *queue;
|
||||
/* The TX data packet. */
|
||||
struct sk_buff *skb;
|
||||
/* The status meta data. */
|
||||
struct ieee80211_tx_status txstat;
|
||||
/* Index in the (struct b43_pio_txqueue)->packets array. */
|
||||
u8 index;
|
||||
|
||||
@ -167,8 +165,7 @@ int b43_pio_init(struct b43_wldev *dev);
|
||||
void b43_pio_stop(struct b43_wldev *dev);
|
||||
void b43_pio_free(struct b43_wldev *dev);
|
||||
|
||||
int b43_pio_tx(struct b43_wldev *dev,
|
||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl);
|
||||
int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb);
|
||||
void b43_pio_handle_txstatus(struct b43_wldev *dev,
|
||||
const struct b43_txstatus *status);
|
||||
void b43_pio_get_tx_stats(struct b43_wldev *dev,
|
||||
@ -193,8 +190,7 @@ static inline void b43_pio_stop(struct b43_wldev *dev)
|
||||
{
|
||||
}
|
||||
static inline int b43_pio_tx(struct b43_wldev *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -185,14 +185,14 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
u8 *_txhdr,
|
||||
const unsigned char *fragment_data,
|
||||
unsigned int fragment_len,
|
||||
const struct ieee80211_tx_control *txctl,
|
||||
const struct ieee80211_tx_info *info,
|
||||
u16 cookie)
|
||||
{
|
||||
struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
|
||||
const struct b43_phy *phy = &dev->phy;
|
||||
const struct ieee80211_hdr *wlhdr =
|
||||
(const struct ieee80211_hdr *)fragment_data;
|
||||
int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
|
||||
int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT));
|
||||
u16 fctl = le16_to_cpu(wlhdr->frame_control);
|
||||
struct ieee80211_rate *fbrate;
|
||||
u8 rate, rate_fb;
|
||||
@ -205,10 +205,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
|
||||
memset(txhdr, 0, sizeof(*txhdr));
|
||||
|
||||
txrate = ieee80211_get_tx_rate(dev->wl->hw, txctl);
|
||||
txrate = ieee80211_get_tx_rate(dev->wl->hw, info);
|
||||
rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB;
|
||||
rate_ofdm = b43_is_ofdm_rate(rate);
|
||||
fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, txctl) ? : txrate;
|
||||
fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate;
|
||||
rate_fb = fbrate->hw_value;
|
||||
rate_fb_ofdm = b43_is_ofdm_rate(rate_fb);
|
||||
|
||||
@ -228,15 +228,13 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
* use the original dur_id field. */
|
||||
txhdr->dur_fb = wlhdr->duration_id;
|
||||
} else {
|
||||
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
|
||||
txctl->vif,
|
||||
fragment_len,
|
||||
fbrate);
|
||||
txhdr->dur_fb = ieee80211_generic_frame_duration(
|
||||
dev->wl->hw, info->control.vif, fragment_len, fbrate);
|
||||
}
|
||||
|
||||
plcp_fragment_len = fragment_len + FCS_LEN;
|
||||
if (use_encryption) {
|
||||
u8 key_idx = txctl->hw_key->hw_key_idx;
|
||||
u8 key_idx = info->control.hw_key->hw_key_idx;
|
||||
struct b43_key *key;
|
||||
int wlhdr_len;
|
||||
size_t iv_len;
|
||||
@ -254,7 +252,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
}
|
||||
|
||||
/* Hardware appends ICV. */
|
||||
plcp_fragment_len += txctl->icv_len;
|
||||
plcp_fragment_len += info->control.icv_len;
|
||||
|
||||
key_idx = b43_kidx_to_fw(dev, key_idx);
|
||||
mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
|
||||
@ -262,7 +260,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
|
||||
B43_TXH_MAC_KEYALG;
|
||||
wlhdr_len = ieee80211_get_hdrlen(fctl);
|
||||
iv_len = min((size_t) txctl->iv_len,
|
||||
iv_len = min((size_t) info->control.iv_len,
|
||||
ARRAY_SIZE(txhdr->iv));
|
||||
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
|
||||
}
|
||||
@ -293,10 +291,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
phy_ctl |= B43_TXH_PHY_ENC_OFDM;
|
||||
else
|
||||
phy_ctl |= B43_TXH_PHY_ENC_CCK;
|
||||
if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
|
||||
if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
|
||||
phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
|
||||
|
||||
switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
|
||||
switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) {
|
||||
case 0: /* Default */
|
||||
phy_ctl |= B43_TXH_PHY_ANT01AUTO;
|
||||
break;
|
||||
@ -317,21 +315,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
}
|
||||
|
||||
/* MAC control */
|
||||
if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK))
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
mac_ctl |= B43_TXH_MAC_ACK;
|
||||
if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
|
||||
((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
|
||||
mac_ctl |= B43_TXH_MAC_HWSEQ;
|
||||
if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
|
||||
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
|
||||
mac_ctl |= B43_TXH_MAC_STMSDU;
|
||||
if (phy->type == B43_PHYTYPE_A)
|
||||
mac_ctl |= B43_TXH_MAC_5GHZ;
|
||||
if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
|
||||
if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
|
||||
mac_ctl |= B43_TXH_MAC_LONGFRAME;
|
||||
|
||||
/* Generate the RTS or CTS-to-self frame */
|
||||
if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
|
||||
(txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
|
||||
if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
|
||||
(info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
|
||||
unsigned int len;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int rts_rate, rts_rate_fb;
|
||||
@ -339,14 +337,14 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
struct b43_plcp_hdr6 *plcp;
|
||||
struct ieee80211_rate *rts_cts_rate;
|
||||
|
||||
rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, txctl);
|
||||
rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
|
||||
|
||||
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);
|
||||
|
||||
if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
|
||||
struct ieee80211_cts *cts;
|
||||
|
||||
if (b43_is_old_txhdr_format(dev)) {
|
||||
@ -356,9 +354,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
cts = (struct ieee80211_cts *)
|
||||
(txhdr->new_format.rts_frame);
|
||||
}
|
||||
ieee80211_ctstoself_get(dev->wl->hw, txctl->vif,
|
||||
ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
|
||||
fragment_data, fragment_len,
|
||||
txctl, cts);
|
||||
info, cts);
|
||||
mac_ctl |= B43_TXH_MAC_SENDCTS;
|
||||
len = sizeof(struct ieee80211_cts);
|
||||
} else {
|
||||
@ -371,9 +369,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
rts = (struct ieee80211_rts *)
|
||||
(txhdr->new_format.rts_frame);
|
||||
}
|
||||
ieee80211_rts_get(dev->wl->hw, txctl->vif,
|
||||
ieee80211_rts_get(dev->wl->hw, info->control.vif,
|
||||
fragment_data, fragment_len,
|
||||
txctl, rts);
|
||||
info, rts);
|
||||
mac_ctl |= B43_TXH_MAC_SENDRTS;
|
||||
len = sizeof(struct ieee80211_rts);
|
||||
}
|
||||
@ -687,27 +685,27 @@ void b43_handle_txstatus(struct b43_wldev *dev,
|
||||
/* Fill out the mac80211 TXstatus report based on the b43-specific
|
||||
* txstatus report data. This returns a boolean whether the frame was
|
||||
* successfully transmitted. */
|
||||
bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
|
||||
bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
|
||||
const struct b43_txstatus *status)
|
||||
{
|
||||
bool frame_success = 1;
|
||||
|
||||
if (status->acked) {
|
||||
/* The frame was ACKed. */
|
||||
report->flags |= IEEE80211_TX_STATUS_ACK;
|
||||
report->flags |= IEEE80211_TX_STAT_ACK;
|
||||
} else {
|
||||
/* The frame was not ACKed... */
|
||||
if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
/* ...but we expected an ACK. */
|
||||
frame_success = 0;
|
||||
report->excessive_retries = 1;
|
||||
report->status.excessive_retries = 1;
|
||||
}
|
||||
}
|
||||
if (status->frame_count == 0) {
|
||||
/* The frame was not transmitted at all. */
|
||||
report->retry_count = 0;
|
||||
report->status.retry_count = 0;
|
||||
} else
|
||||
report->retry_count = status->frame_count - 1;
|
||||
report->status.retry_count = status->frame_count - 1;
|
||||
|
||||
return frame_success;
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
|
||||
u8 * txhdr,
|
||||
const unsigned char *fragment_data,
|
||||
unsigned int fragment_len,
|
||||
const struct ieee80211_tx_control *txctl, u16 cookie);
|
||||
const struct ieee80211_tx_info *txctl, u16 cookie);
|
||||
|
||||
/* Transmit Status */
|
||||
struct b43_txstatus {
|
||||
@ -294,7 +294,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
|
||||
|
||||
void b43_handle_txstatus(struct b43_wldev *dev,
|
||||
const struct b43_txstatus *status);
|
||||
bool b43_fill_txstatus_report(struct ieee80211_tx_status *report,
|
||||
bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
|
||||
const struct b43_txstatus *status);
|
||||
|
||||
void b43_tx_suspend(struct b43_wldev *dev);
|
||||
|
@ -1205,10 +1205,10 @@ struct b43legacy_dmaring *parse_cookie(struct b43legacy_wldev *dev,
|
||||
}
|
||||
|
||||
static int dma_tx_fragment(struct b43legacy_dmaring *ring,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct b43legacy_dma_ops *ops = ring->ops;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
u8 *header;
|
||||
int slot, old_top_slot, old_used_slots;
|
||||
int err;
|
||||
@ -1231,7 +1231,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
|
||||
header = &(ring->txhdr_cache[slot * sizeof(
|
||||
struct b43legacy_txhdr_fw3)]);
|
||||
err = b43legacy_generate_txhdr(ring->dev, header,
|
||||
skb->data, skb->len, ctl,
|
||||
skb->data, skb->len, info,
|
||||
generate_cookie(ring, slot));
|
||||
if (unlikely(err)) {
|
||||
ring->current_slot = old_top_slot;
|
||||
@ -1255,7 +1255,6 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
|
||||
desc = ops->idx2desc(ring, slot, &meta);
|
||||
memset(meta, 0, sizeof(*meta));
|
||||
|
||||
memcpy(&meta->txstat.control, ctl, sizeof(*ctl));
|
||||
meta->skb = skb;
|
||||
meta->is_last_fragment = 1;
|
||||
|
||||
@ -1323,14 +1322,14 @@ int should_inject_overflow(struct b43legacy_dmaring *ring)
|
||||
}
|
||||
|
||||
int b43legacy_dma_tx(struct b43legacy_wldev *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct b43legacy_dmaring *ring;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
|
||||
ring = priority_to_txring(dev, ctl->queue);
|
||||
ring = priority_to_txring(dev, info->queue);
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
B43legacy_WARN_ON(!ring->tx);
|
||||
if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
|
||||
@ -1343,7 +1342,7 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
|
||||
* That would be a mac80211 bug. */
|
||||
B43legacy_BUG_ON(ring->stopped);
|
||||
|
||||
err = dma_tx_fragment(ring, skb, ctl);
|
||||
err = dma_tx_fragment(ring, skb);
|
||||
if (unlikely(err == -ENOKEY)) {
|
||||
/* Drop this packet, as we don't have the encryption key
|
||||
* anymore and must not transmit it unencrypted. */
|
||||
@ -1401,26 +1400,29 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
|
||||
1);
|
||||
|
||||
if (meta->is_last_fragment) {
|
||||
B43legacy_WARN_ON(!meta->skb);
|
||||
struct ieee80211_tx_info *info;
|
||||
BUG_ON(!meta->skb);
|
||||
info = IEEE80211_SKB_CB(meta->skb);
|
||||
/* Call back to inform the ieee80211 subsystem about the
|
||||
* status of the transmission.
|
||||
* Some fields of txstat are already filled in dma_tx().
|
||||
*/
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
if (status->acked) {
|
||||
meta->txstat.flags |= IEEE80211_TX_STATUS_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
} else {
|
||||
if (!(meta->txstat.control.flags
|
||||
& IEEE80211_TXCTL_NO_ACK))
|
||||
meta->txstat.excessive_retries = 1;
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
info->status.excessive_retries = 1;
|
||||
}
|
||||
if (status->frame_count == 0) {
|
||||
/* The frame was not transmitted at all. */
|
||||
meta->txstat.retry_count = 0;
|
||||
info->status.retry_count = 0;
|
||||
} else
|
||||
meta->txstat.retry_count = status->frame_count
|
||||
info->status.retry_count = status->frame_count
|
||||
- 1;
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
|
||||
&(meta->txstat));
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
|
||||
/* skb is freed by ieee80211_tx_status_irqsafe() */
|
||||
meta->skb = NULL;
|
||||
} else {
|
||||
|
@ -195,7 +195,6 @@ struct b43legacy_dmadesc_meta {
|
||||
dma_addr_t dmaaddr;
|
||||
/* ieee80211 TX status. Only used once per 802.11 frag. */
|
||||
bool is_last_fragment;
|
||||
struct ieee80211_tx_status txstat;
|
||||
};
|
||||
|
||||
struct b43legacy_dmaring;
|
||||
@ -297,8 +296,7 @@ void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev,
|
||||
struct ieee80211_tx_queue_stats *stats);
|
||||
|
||||
int b43legacy_dma_tx(struct b43legacy_wldev *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl);
|
||||
struct sk_buff *skb);
|
||||
void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
|
||||
const struct b43legacy_txstatus *status);
|
||||
|
||||
|
@ -2358,8 +2358,7 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
|
||||
}
|
||||
|
||||
static int b43legacy_op_tx(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
struct b43legacy_wldev *dev = wl->current_dev;
|
||||
@ -2373,10 +2372,10 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw,
|
||||
/* DMA-TX is done without a global lock. */
|
||||
if (b43legacy_using_pio(dev)) {
|
||||
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||
err = b43legacy_pio_tx(dev, skb, ctl);
|
||||
err = b43legacy_pio_tx(dev, skb);
|
||||
spin_unlock_irqrestore(&wl->irq_lock, flags);
|
||||
} else
|
||||
err = b43legacy_dma_tx(dev, skb, ctl);
|
||||
err = b43legacy_dma_tx(dev, skb);
|
||||
out:
|
||||
if (unlikely(err))
|
||||
return NETDEV_TX_BUSY;
|
||||
@ -3409,7 +3408,7 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
|
||||
* field, but that would probably require resizing and moving of data
|
||||
* within the beacon template. Simply request a new beacon and let
|
||||
* mac80211 do the hard work. */
|
||||
beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
|
||||
beacon = ieee80211_beacon_get(hw, wl->vif);
|
||||
if (unlikely(!beacon))
|
||||
return -ENOMEM;
|
||||
spin_lock_irqsave(&wl->irq_lock, flags);
|
||||
@ -3420,8 +3419,7 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
|
||||
struct sk_buff *beacon,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *beacon)
|
||||
{
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
unsigned long flags;
|
||||
|
@ -196,7 +196,7 @@ static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
|
||||
B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
|
||||
err = b43legacy_generate_txhdr(queue->dev,
|
||||
txhdr, skb->data, skb->len,
|
||||
&packet->txstat.control,
|
||||
IEEE80211_SKB_CB(skb),
|
||||
generate_cookie(queue, packet));
|
||||
if (err)
|
||||
return err;
|
||||
@ -463,8 +463,7 @@ err_destroy0:
|
||||
}
|
||||
|
||||
int b43legacy_pio_tx(struct b43legacy_wldev *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct b43legacy_pioqueue *queue = dev->pio.queue1;
|
||||
struct b43legacy_pio_txpacket *packet;
|
||||
@ -476,9 +475,6 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev,
|
||||
list);
|
||||
packet->skb = skb;
|
||||
|
||||
memset(&packet->txstat, 0, sizeof(packet->txstat));
|
||||
memcpy(&packet->txstat.control, ctl, sizeof(*ctl));
|
||||
|
||||
list_move_tail(&packet->list, &queue->txqueue);
|
||||
queue->nr_txfree--;
|
||||
queue->nr_tx_packets++;
|
||||
@ -494,6 +490,7 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
|
||||
{
|
||||
struct b43legacy_pioqueue *queue;
|
||||
struct b43legacy_pio_txpacket *packet;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
queue = parse_cookie(dev, status->cookie, &packet);
|
||||
B43legacy_WARN_ON(!queue);
|
||||
@ -505,11 +502,13 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
|
||||
queue->tx_devq_used -= (packet->skb->len +
|
||||
sizeof(struct b43legacy_txhdr_fw3));
|
||||
|
||||
info = IEEE80211_SKB_CB(packet->skb);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
if (status->acked)
|
||||
packet->txstat.flags |= IEEE80211_TX_STATUS_ACK;
|
||||
packet->txstat.retry_count = status->frame_count - 1;
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb,
|
||||
&(packet->txstat));
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->status.retry_count = status->frame_count - 1;
|
||||
ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb);
|
||||
packet->skb = NULL;
|
||||
|
||||
free_txpacket(packet, 1);
|
||||
|
@ -41,7 +41,6 @@ struct b43legacy_xmitstatus;
|
||||
struct b43legacy_pio_txpacket {
|
||||
struct b43legacy_pioqueue *queue;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_status txstat;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
@ -104,8 +103,7 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev);
|
||||
void b43legacy_pio_free(struct b43legacy_wldev *dev);
|
||||
|
||||
int b43legacy_pio_tx(struct b43legacy_wldev *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl);
|
||||
struct sk_buff *skb);
|
||||
void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
|
||||
const struct b43legacy_txstatus *status);
|
||||
void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev,
|
||||
|
@ -188,11 +188,11 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
struct b43legacy_txhdr_fw3 *txhdr,
|
||||
const unsigned char *fragment_data,
|
||||
unsigned int fragment_len,
|
||||
const struct ieee80211_tx_control *txctl,
|
||||
const struct ieee80211_tx_info *info,
|
||||
u16 cookie)
|
||||
{
|
||||
const struct ieee80211_hdr *wlhdr;
|
||||
int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
|
||||
int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT));
|
||||
u16 fctl;
|
||||
u8 rate;
|
||||
struct ieee80211_rate *rate_fb;
|
||||
@ -208,11 +208,11 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
|
||||
memset(txhdr, 0, sizeof(*txhdr));
|
||||
|
||||
tx_rate = ieee80211_get_tx_rate(dev->wl->hw, txctl);
|
||||
tx_rate = ieee80211_get_tx_rate(dev->wl->hw, info);
|
||||
|
||||
rate = tx_rate->hw_value;
|
||||
rate_ofdm = b43legacy_is_ofdm_rate(rate);
|
||||
rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, txctl) ? : tx_rate;
|
||||
rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate;
|
||||
rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
|
||||
|
||||
txhdr->mac_frame_ctl = wlhdr->frame_control;
|
||||
@ -228,14 +228,14 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
txhdr->dur_fb = wlhdr->duration_id;
|
||||
} else {
|
||||
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
|
||||
txctl->vif,
|
||||
info->control.vif,
|
||||
fragment_len,
|
||||
rate_fb);
|
||||
}
|
||||
|
||||
plcp_fragment_len = fragment_len + FCS_LEN;
|
||||
if (use_encryption) {
|
||||
u8 key_idx = txctl->hw_key->hw_key_idx;
|
||||
u8 key_idx = info->control.hw_key->hw_key_idx;
|
||||
struct b43legacy_key *key;
|
||||
int wlhdr_len;
|
||||
size_t iv_len;
|
||||
@ -245,7 +245,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
|
||||
if (key->enabled) {
|
||||
/* Hardware appends ICV. */
|
||||
plcp_fragment_len += txctl->icv_len;
|
||||
plcp_fragment_len += info->control.icv_len;
|
||||
|
||||
key_idx = b43legacy_kidx_to_fw(dev, key_idx);
|
||||
mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
|
||||
@ -254,7 +254,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
B43legacy_TX4_MAC_KEYALG_SHIFT) &
|
||||
B43legacy_TX4_MAC_KEYALG;
|
||||
wlhdr_len = ieee80211_get_hdrlen(fctl);
|
||||
iv_len = min((size_t)txctl->iv_len,
|
||||
iv_len = min((size_t)info->control.iv_len,
|
||||
ARRAY_SIZE(txhdr->iv));
|
||||
memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
|
||||
} else {
|
||||
@ -278,7 +278,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
phy_ctl |= B43legacy_TX4_PHY_OFDM;
|
||||
if (dev->short_preamble)
|
||||
phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
|
||||
switch (txctl->antenna_sel_tx) {
|
||||
switch (info->antenna_sel_tx) {
|
||||
case 0:
|
||||
phy_ctl |= B43legacy_TX4_PHY_ANTLAST;
|
||||
break;
|
||||
@ -293,21 +293,21 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
}
|
||||
|
||||
/* MAC control */
|
||||
if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK))
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
mac_ctl |= B43legacy_TX4_MAC_ACK;
|
||||
if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
|
||||
((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
|
||||
mac_ctl |= B43legacy_TX4_MAC_HWSEQ;
|
||||
if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
|
||||
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
|
||||
mac_ctl |= B43legacy_TX4_MAC_STMSDU;
|
||||
if (rate_fb_ofdm)
|
||||
mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
|
||||
if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
|
||||
if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
|
||||
mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
|
||||
|
||||
/* Generate the RTS or CTS-to-self frame */
|
||||
if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
|
||||
(txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
|
||||
if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
|
||||
(info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
|
||||
unsigned int len;
|
||||
struct ieee80211_hdr *hdr;
|
||||
int rts_rate;
|
||||
@ -315,26 +315,26 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
|
||||
int rts_rate_ofdm;
|
||||
int rts_rate_fb_ofdm;
|
||||
|
||||
rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, txctl)->hw_value;
|
||||
rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->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);
|
||||
if (rts_rate_fb_ofdm)
|
||||
mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM;
|
||||
|
||||
if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
|
||||
ieee80211_ctstoself_get(dev->wl->hw,
|
||||
txctl->vif,
|
||||
info->control.vif,
|
||||
fragment_data,
|
||||
fragment_len, txctl,
|
||||
fragment_len, info,
|
||||
(struct ieee80211_cts *)
|
||||
(txhdr->rts_frame));
|
||||
mac_ctl |= B43legacy_TX4_MAC_SENDCTS;
|
||||
len = sizeof(struct ieee80211_cts);
|
||||
} else {
|
||||
ieee80211_rts_get(dev->wl->hw,
|
||||
txctl->vif,
|
||||
fragment_data, fragment_len, txctl,
|
||||
info->control.vif,
|
||||
fragment_data, fragment_len, info,
|
||||
(struct ieee80211_rts *)
|
||||
(txhdr->rts_frame));
|
||||
mac_ctl |= B43legacy_TX4_MAC_SENDRTS;
|
||||
@ -365,12 +365,12 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
|
||||
u8 *txhdr,
|
||||
const unsigned char *fragment_data,
|
||||
unsigned int fragment_len,
|
||||
const struct ieee80211_tx_control *txctl,
|
||||
const struct ieee80211_tx_info *info,
|
||||
u16 cookie)
|
||||
{
|
||||
return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
|
||||
fragment_data, fragment_len,
|
||||
txctl, cookie);
|
||||
info, cookie);
|
||||
}
|
||||
|
||||
static s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev,
|
||||
|
@ -80,7 +80,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
|
||||
u8 *txhdr,
|
||||
const unsigned char *fragment_data,
|
||||
unsigned int fragment_len,
|
||||
const struct ieee80211_tx_control *txctl,
|
||||
const struct ieee80211_tx_info *info,
|
||||
u16 cookie);
|
||||
|
||||
|
||||
|
@ -445,8 +445,7 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
|
||||
*/
|
||||
static void rs_tx_status(void *priv_rate,
|
||||
struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *tx_resp)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
u8 retries, current_count;
|
||||
int scale_rate_index, first_index, last_index;
|
||||
@ -457,14 +456,15 @@ static void rs_tx_status(void *priv_rate,
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct iwl3945_rs_sta *rs_sta;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
IWL_DEBUG_RATE("enter\n");
|
||||
|
||||
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
|
||||
|
||||
|
||||
retries = tx_resp->retry_count;
|
||||
first_index = sband->bitrates[tx_resp->control.tx_rate_idx].hw_value;
|
||||
retries = info->status.retry_count;
|
||||
first_index = sband->bitrates[info->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;
|
||||
@ -525,11 +525,11 @@ static void rs_tx_status(void *priv_rate,
|
||||
/* Update the last index window with success/failure based on ACK */
|
||||
IWL_DEBUG_RATE("Update rate %d with %s.\n",
|
||||
last_index,
|
||||
(tx_resp->flags & IEEE80211_TX_STATUS_ACK) ?
|
||||
(info->flags & IEEE80211_TX_STAT_ACK) ?
|
||||
"success" : "failure");
|
||||
iwl3945_collect_tx_data(rs_sta,
|
||||
&rs_sta->win[last_index],
|
||||
tx_resp->flags & IEEE80211_TX_STATUS_ACK, 1);
|
||||
info->flags & IEEE80211_TX_STAT_ACK, 1);
|
||||
|
||||
/* We updated the rate scale window -- if its been more than
|
||||
* flush_time since the last run, schedule the flush
|
||||
|
@ -283,8 +283,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
|
||||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
|
||||
|
||||
tx_info = &txq->txb[txq->q.read_ptr];
|
||||
ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0],
|
||||
&tx_info->status);
|
||||
ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
|
||||
tx_info->skb[0] = NULL;
|
||||
iwl3945_hw_txq_free_tfd(priv, txq);
|
||||
}
|
||||
@ -306,7 +305,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
|
||||
int txq_id = SEQ_TO_QUEUE(sequence);
|
||||
int index = SEQ_TO_INDEX(sequence);
|
||||
struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
|
||||
struct ieee80211_tx_status *tx_status;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
||||
u32 status = le32_to_cpu(tx_resp->status);
|
||||
int rate_idx;
|
||||
@ -319,21 +318,22 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
tx_status = &(txq->txb[txq->q.read_ptr].status);
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
tx_status->retry_count = tx_resp->failure_frame;
|
||||
info->status.retry_count = tx_resp->failure_frame;
|
||||
/* tx_status->rts_retry_count = tx_resp->failure_rts; */
|
||||
tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
|
||||
IEEE80211_TX_STATUS_ACK : 0;
|
||||
info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
|
||||
IEEE80211_TX_STAT_ACK : 0;
|
||||
|
||||
IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
|
||||
txq_id, iwl3945_get_tx_fail_reason(status), status,
|
||||
tx_resp->rate, tx_resp->failure_frame);
|
||||
|
||||
rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
|
||||
if (tx_status->control.band == IEEE80211_BAND_5GHZ)
|
||||
if (info->band == IEEE80211_BAND_5GHZ)
|
||||
rate_idx -= IWL_FIRST_OFDM_RATE;
|
||||
tx_status->control.tx_rate_idx = rate_idx;
|
||||
info->tx_rate_idx = rate_idx;
|
||||
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
|
||||
iwl3945_tx_queue_reclaim(priv, txq_id, index);
|
||||
|
||||
@ -960,11 +960,11 @@ u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr)
|
||||
*/
|
||||
void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
|
||||
struct iwl3945_cmd *cmd,
|
||||
struct ieee80211_tx_control *ctrl,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr, int sta_id, int tx_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 hw_value = ieee80211_get_tx_rate(priv->hw, ctrl)->hw_value;
|
||||
u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
|
||||
u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1);
|
||||
u16 rate_mask;
|
||||
int rate;
|
||||
@ -977,7 +977,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
|
||||
tx_flags = cmd->cmd.tx.tx_flags;
|
||||
|
||||
/* We need to figure out how to get the sta->supp_rates while
|
||||
* in this running context; perhaps encoding into ctrl->tx_rate? */
|
||||
* in this running context */
|
||||
rate_mask = IWL_RATES_MASK;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
@ -124,7 +124,6 @@ int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i);
|
||||
|
||||
/* One for each TFD */
|
||||
struct iwl3945_tx_info {
|
||||
struct ieee80211_tx_status status;
|
||||
struct sk_buff *skb[MAX_NUM_OF_TBS];
|
||||
};
|
||||
|
||||
@ -645,7 +644,7 @@ extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
|
||||
extern int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv);
|
||||
extern void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
|
||||
struct iwl3945_cmd *cmd,
|
||||
struct ieee80211_tx_control *ctrl,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr,
|
||||
int sta_id, int tx_id);
|
||||
extern int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv);
|
||||
|
@ -785,8 +785,7 @@ out:
|
||||
* mac80211 sends us Tx status
|
||||
*/
|
||||
static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *tx_resp)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int status;
|
||||
u8 retries;
|
||||
@ -798,6 +797,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
||||
struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_hw *hw = local_to_hw(local);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl4965_rate_scale_data *window = NULL;
|
||||
struct iwl4965_rate_scale_data *search_win = NULL;
|
||||
u32 tx_rate;
|
||||
@ -813,11 +813,11 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
||||
return;
|
||||
|
||||
/* This packet was aggregated but doesn't carry rate scale info */
|
||||
if ((tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) &&
|
||||
!(tx_resp->flags & IEEE80211_TX_STATUS_AMPDU))
|
||||
if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
|
||||
!(info->flags & IEEE80211_TX_STAT_AMPDU))
|
||||
return;
|
||||
|
||||
retries = tx_resp->retry_count;
|
||||
retries = info->status.retry_count;
|
||||
|
||||
if (retries > 15)
|
||||
retries = 15;
|
||||
@ -862,20 +862,20 @@ 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_idx < 0) ||
|
||||
if ((info->tx_rate_idx < 0) ||
|
||||
(tbl_type.is_SGI ^
|
||||
!!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) ||
|
||||
!!(info->flags & IEEE80211_TX_CTL_SHORT_GI)) ||
|
||||
(tbl_type.is_fat ^
|
||||
!!(tx_resp->control.flags & IEEE80211_TXCTL_40_MHZ_WIDTH)) ||
|
||||
!!(info->flags & IEEE80211_TX_CTL_40_MHZ_WIDTH)) ||
|
||||
(tbl_type.is_dup ^
|
||||
!!(tx_resp->control.flags & IEEE80211_TXCTL_DUP_DATA)) ||
|
||||
(tbl_type.ant_type ^ tx_resp->control.antenna_sel_tx) ||
|
||||
!!(info->flags & IEEE80211_TX_CTL_DUP_DATA)) ||
|
||||
(tbl_type.ant_type ^ info->antenna_sel_tx) ||
|
||||
(!!(tx_rate & RATE_MCS_HT_MSK) ^
|
||||
!!(tx_resp->control.flags & IEEE80211_TXCTL_OFDM_HT)) ||
|
||||
!!(info->flags & IEEE80211_TX_CTL_OFDM_HT)) ||
|
||||
(!!(tx_rate & RATE_MCS_GF_MSK) ^
|
||||
!!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) ||
|
||||
!!(info->flags & IEEE80211_TX_CTL_GREEN_FIELD)) ||
|
||||
(hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
|
||||
hw->wiphy->bands[tx_resp->control.band]->bitrates[tx_resp->control.tx_rate_idx].bitrate)) {
|
||||
hw->wiphy->bands[info->band]->bitrates[info->tx_rate_idx].bitrate)) {
|
||||
IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate);
|
||||
goto out;
|
||||
}
|
||||
@ -929,10 +929,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
|
||||
|
||||
/* Update frame history window with "success" if Tx got ACKed ... */
|
||||
if (tx_resp->flags & IEEE80211_TX_STATUS_ACK)
|
||||
status = 1;
|
||||
else
|
||||
status = 0;
|
||||
status = !!(info->flags & IEEE80211_TX_STAT_ACK);
|
||||
|
||||
/* If type matches "search" table,
|
||||
* add final tx status to "search" history */
|
||||
@ -943,10 +940,10 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
||||
tpt = search_tbl->expected_tpt[rs_index];
|
||||
else
|
||||
tpt = 0;
|
||||
if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
rs_collect_tx_data(search_win, rs_index, tpt,
|
||||
tx_resp->ampdu_ack_len,
|
||||
tx_resp->ampdu_ack_map);
|
||||
info->status.ampdu_ack_len,
|
||||
info->status.ampdu_ack_map);
|
||||
else
|
||||
rs_collect_tx_data(search_win, rs_index, tpt,
|
||||
1, status);
|
||||
@ -959,10 +956,10 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
||||
tpt = curr_tbl->expected_tpt[rs_index];
|
||||
else
|
||||
tpt = 0;
|
||||
if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU)
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
rs_collect_tx_data(window, rs_index, tpt,
|
||||
tx_resp->ampdu_ack_len,
|
||||
tx_resp->ampdu_ack_map);
|
||||
info->status.ampdu_ack_len,
|
||||
info->status.ampdu_ack_map);
|
||||
else
|
||||
rs_collect_tx_data(window, rs_index, tpt,
|
||||
1, status);
|
||||
@ -971,10 +968,10 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev,
|
||||
/* If not searching for new mode, increment success/failed counter
|
||||
* ... these help determine when to start searching again */
|
||||
if (lq_sta->stay_in_tbl) {
|
||||
if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) {
|
||||
lq_sta->total_success += tx_resp->ampdu_ack_map;
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
lq_sta->total_success += info->status.ampdu_ack_map;
|
||||
lq_sta->total_failed +=
|
||||
(tx_resp->ampdu_ack_len - tx_resp->ampdu_ack_map);
|
||||
(info->status.ampdu_ack_len - info->status.ampdu_ack_map);
|
||||
} else {
|
||||
if (status)
|
||||
lq_sta->total_success++;
|
||||
|
@ -357,22 +357,22 @@ int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
|
||||
* translate ucode response to mac80211 tx status control values
|
||||
*/
|
||||
void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct ieee80211_tx_info *control)
|
||||
{
|
||||
int rate_index;
|
||||
|
||||
control->antenna_sel_tx =
|
||||
((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
|
||||
if (rate_n_flags & RATE_MCS_HT_MSK)
|
||||
control->flags |= IEEE80211_TXCTL_OFDM_HT;
|
||||
control->flags |= IEEE80211_TX_CTL_OFDM_HT;
|
||||
if (rate_n_flags & RATE_MCS_GF_MSK)
|
||||
control->flags |= IEEE80211_TXCTL_GREEN_FIELD;
|
||||
control->flags |= IEEE80211_TX_CTL_GREEN_FIELD;
|
||||
if (rate_n_flags & RATE_MCS_FAT_MSK)
|
||||
control->flags |= IEEE80211_TXCTL_40_MHZ_WIDTH;
|
||||
control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH;
|
||||
if (rate_n_flags & RATE_MCS_DUP_MSK)
|
||||
control->flags |= IEEE80211_TXCTL_DUP_DATA;
|
||||
control->flags |= IEEE80211_TX_CTL_DUP_DATA;
|
||||
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||
control->flags |= IEEE80211_TXCTL_SHORT_GI;
|
||||
control->flags |= IEEE80211_TX_CTL_SHORT_GI;
|
||||
rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
|
||||
if (control->band == IEEE80211_BAND_5GHZ)
|
||||
rate_index -= IWL_FIRST_OFDM_RATE;
|
||||
@ -3007,7 +3007,7 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
||||
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
|
||||
u64 bitmap;
|
||||
int successes = 0;
|
||||
struct ieee80211_tx_status *tx_status;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
if (unlikely(!agg->wait_for_ba)) {
|
||||
IWL_ERROR("Received BA when not expected\n");
|
||||
@ -3045,13 +3045,13 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
||||
agg->start_idx + i);
|
||||
}
|
||||
|
||||
tx_status = &priv->txq[scd_flow].txb[agg->start_idx].status;
|
||||
tx_status->flags = IEEE80211_TX_STATUS_ACK;
|
||||
tx_status->flags |= IEEE80211_TX_STATUS_AMPDU;
|
||||
tx_status->ampdu_ack_map = successes;
|
||||
tx_status->ampdu_ack_len = agg->frame_count;
|
||||
iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags,
|
||||
&tx_status->control);
|
||||
info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
info->flags = IEEE80211_TX_STAT_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
info->status.ampdu_ack_map = successes;
|
||||
info->status.ampdu_ack_len = agg->frame_count;
|
||||
iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
|
||||
|
||||
IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
|
||||
|
||||
|
@ -207,8 +207,7 @@ void iwl_rx_allocate(struct iwl_priv *priv);
|
||||
* TX
|
||||
******************************************************/
|
||||
int iwl_txq_ctx_reset(struct iwl_priv *priv);
|
||||
int iwl_tx_skb(struct iwl_priv *priv,
|
||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl);
|
||||
int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
||||
/* FIXME: remove when free Tx is fully merged into iwlcore */
|
||||
int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
|
||||
void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
|
||||
|
@ -119,7 +119,6 @@ struct iwl_queue {
|
||||
|
||||
/* One for each TFD */
|
||||
struct iwl_tx_info {
|
||||
struct ieee80211_tx_status status;
|
||||
struct sk_buff *skb[MAX_NUM_OF_TBS];
|
||||
};
|
||||
|
||||
@ -693,7 +692,7 @@ extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
|
||||
struct iwl_frame *frame, u8 rate);
|
||||
extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv,
|
||||
struct iwl_cmd *cmd,
|
||||
struct ieee80211_tx_control *ctrl,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr,
|
||||
int sta_id, int tx_id);
|
||||
extern int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv);
|
||||
@ -749,7 +748,7 @@ extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode);
|
||||
extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
|
||||
extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv,
|
||||
u32 rate_n_flags,
|
||||
struct ieee80211_tx_control *control);
|
||||
struct ieee80211_tx_info *info);
|
||||
|
||||
#ifdef CONFIG_IWL4965_HT
|
||||
extern void iwl4965_init_ht_hw_capab(const struct iwl_priv *priv,
|
||||
|
@ -502,7 +502,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
|
||||
*/
|
||||
static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
|
||||
struct iwl_tx_cmd *tx_cmd,
|
||||
struct ieee80211_tx_control *ctrl,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr,
|
||||
int is_unicast, u8 std_id)
|
||||
{
|
||||
@ -510,7 +510,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
|
||||
__le32 tx_flags = tx_cmd->tx_flags;
|
||||
|
||||
tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
tx_flags |= TX_CMD_FLG_ACK_MSK;
|
||||
if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
|
||||
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
@ -538,10 +538,10 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
|
||||
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
}
|
||||
|
||||
if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
|
||||
tx_flags |= TX_CMD_FLG_RTS_MSK;
|
||||
tx_flags &= ~TX_CMD_FLG_CTS_MSK;
|
||||
} else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
|
||||
} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
|
||||
tx_flags &= ~TX_CMD_FLG_RTS_MSK;
|
||||
tx_flags |= TX_CMD_FLG_CTS_MSK;
|
||||
}
|
||||
@ -570,7 +570,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
|
||||
|
||||
static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
|
||||
struct iwl_tx_cmd *tx_cmd,
|
||||
struct ieee80211_tx_control *ctrl,
|
||||
struct ieee80211_tx_info *info,
|
||||
u16 fc, int sta_id,
|
||||
int is_hcca)
|
||||
{
|
||||
@ -580,7 +580,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
|
||||
u16 rate_flags = 0;
|
||||
int rate_idx;
|
||||
|
||||
rate_idx = min(ieee80211_get_tx_rate(priv->hw, ctrl)->hw_value & 0xffff,
|
||||
rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff,
|
||||
IWL_RATE_COUNT - 1);
|
||||
|
||||
rate_plcp = iwl_rates[rate_idx].plcp;
|
||||
@ -637,18 +637,18 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
|
||||
struct ieee80211_tx_control *ctl,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct iwl_tx_cmd *tx_cmd,
|
||||
struct sk_buff *skb_frag,
|
||||
int sta_id)
|
||||
{
|
||||
struct ieee80211_key_conf *keyconf = ctl->hw_key;
|
||||
struct ieee80211_key_conf *keyconf = info->control.hw_key;
|
||||
|
||||
switch (keyconf->alg) {
|
||||
case ALG_CCMP:
|
||||
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
|
||||
memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
|
||||
if (ctl->flags & IEEE80211_TXCTL_AMPDU)
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
|
||||
IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
|
||||
break;
|
||||
@ -690,13 +690,13 @@ static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
|
||||
/*
|
||||
* start REPLY_TX command process
|
||||
*/
|
||||
int iwl_tx_skb(struct iwl_priv *priv,
|
||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
|
||||
int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl_tfd_frame *tfd;
|
||||
u32 *control_flags;
|
||||
int txq_id = ctl->queue;
|
||||
int txq_id = info->queue;
|
||||
struct iwl_tx_queue *txq = NULL;
|
||||
struct iwl_queue *q = NULL;
|
||||
dma_addr_t phys_addr;
|
||||
@ -726,7 +726,7 @@ int iwl_tx_skb(struct iwl_priv *priv,
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
if ((ieee80211_get_tx_rate(priv->hw, ctl)->hw_value & 0xFF) ==
|
||||
if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) ==
|
||||
IWL_INVALID_RATE) {
|
||||
IWL_ERROR("ERROR: No TX rate available.\n");
|
||||
goto drop_unlock;
|
||||
@ -782,7 +782,7 @@ int iwl_tx_skb(struct iwl_priv *priv,
|
||||
seq_number += 0x10;
|
||||
#ifdef CONFIG_IWL4965_HT
|
||||
/* aggregation is on for this <sta,tid> */
|
||||
if (ctl->flags & IEEE80211_TXCTL_AMPDU)
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
|
||||
priv->stations[sta_id].tid[tid].tfds_in_queue++;
|
||||
#endif /* CONFIG_IWL4965_HT */
|
||||
@ -803,8 +803,6 @@ int iwl_tx_skb(struct iwl_priv *priv,
|
||||
/* Set up driver data for this TFD */
|
||||
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
|
||||
txq->txb[q->write_ptr].skb[0] = skb;
|
||||
memcpy(&(txq->txb[q->write_ptr].status.control),
|
||||
ctl, sizeof(struct ieee80211_tx_control));
|
||||
|
||||
/* Set up first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_cmd = &txq->cmd[idx];
|
||||
@ -854,8 +852,8 @@ int iwl_tx_skb(struct iwl_priv *priv,
|
||||
* first entry */
|
||||
iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
|
||||
|
||||
if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
|
||||
iwl_tx_cmd_build_hwcrypto(priv, ctl, tx_cmd, skb, sta_id);
|
||||
if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT))
|
||||
iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
|
||||
|
||||
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
||||
* if any (802.11 null frames have no payload). */
|
||||
@ -874,10 +872,10 @@ int iwl_tx_skb(struct iwl_priv *priv,
|
||||
len = (u16)skb->len;
|
||||
tx_cmd->len = cpu_to_le16(len);
|
||||
/* TODO need this for burst mode later on */
|
||||
iwl_tx_cmd_build_basic(priv, tx_cmd, ctl, hdr, unicast, sta_id);
|
||||
iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, unicast, sta_id);
|
||||
|
||||
/* set is_hcca to 0; it probably will never be implemented */
|
||||
iwl_tx_cmd_build_rate(priv, tx_cmd, ctl, fc, sta_id, 0);
|
||||
iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
|
||||
|
||||
iwl_update_tx_stats(priv, fc, len);
|
||||
|
||||
@ -919,7 +917,7 @@ int iwl_tx_skb(struct iwl_priv *priv,
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
ieee80211_stop_queue(priv->hw, ctl->queue);
|
||||
ieee80211_stop_queue(priv->hw, info->queue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2376,13 +2376,13 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
|
||||
}
|
||||
|
||||
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
|
||||
struct ieee80211_tx_control *ctl,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct iwl3945_cmd *cmd,
|
||||
struct sk_buff *skb_frag,
|
||||
int last_frag)
|
||||
{
|
||||
struct iwl3945_hw_key *keyinfo =
|
||||
&priv->stations[ctl->hw_key->hw_key_idx].keyinfo;
|
||||
&priv->stations[info->control.hw_key->hw_key_idx].keyinfo;
|
||||
|
||||
switch (keyinfo->alg) {
|
||||
case ALG_CCMP:
|
||||
@ -2405,7 +2405,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
|
||||
|
||||
case ALG_WEP:
|
||||
cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP |
|
||||
(ctl->hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
|
||||
(info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
|
||||
|
||||
if (keyinfo->keylen == 13)
|
||||
cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128;
|
||||
@ -2413,7 +2413,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
|
||||
memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen);
|
||||
|
||||
IWL_DEBUG_TX("Configuring packet for WEP encryption "
|
||||
"with key %d\n", ctl->hw_key->hw_key_idx);
|
||||
"with key %d\n", info->control.hw_key->hw_key_idx);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -2427,7 +2427,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
|
||||
*/
|
||||
static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
|
||||
struct iwl3945_cmd *cmd,
|
||||
struct ieee80211_tx_control *ctrl,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr,
|
||||
int is_unicast, u8 std_id)
|
||||
{
|
||||
@ -2435,7 +2435,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
|
||||
__le32 tx_flags = cmd->cmd.tx.tx_flags;
|
||||
|
||||
cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
if (!(ctrl->flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
tx_flags |= TX_CMD_FLG_ACK_MSK;
|
||||
if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
|
||||
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
@ -2459,10 +2459,10 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
|
||||
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
}
|
||||
|
||||
if (ctrl->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
|
||||
tx_flags |= TX_CMD_FLG_RTS_MSK;
|
||||
tx_flags &= ~TX_CMD_FLG_CTS_MSK;
|
||||
} else if (ctrl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
|
||||
} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
|
||||
tx_flags &= ~TX_CMD_FLG_RTS_MSK;
|
||||
tx_flags |= TX_CMD_FLG_CTS_MSK;
|
||||
}
|
||||
@ -2546,13 +2546,13 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
|
||||
/*
|
||||
* start REPLY_TX command process
|
||||
*/
|
||||
static int iwl3945_tx_skb(struct iwl3945_priv *priv,
|
||||
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
|
||||
static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl3945_tfd_frame *tfd;
|
||||
u32 *control_flags;
|
||||
int txq_id = ctl->queue;
|
||||
int txq_id = info->queue;
|
||||
struct iwl3945_tx_queue *txq = NULL;
|
||||
struct iwl3945_queue *q = NULL;
|
||||
dma_addr_t phys_addr;
|
||||
@ -2581,7 +2581,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
|
||||
goto drop_unlock;
|
||||
}
|
||||
|
||||
if ((ieee80211_get_tx_rate(priv->hw, ctl)->hw_value & 0xFF) == IWL_INVALID_RATE) {
|
||||
if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
|
||||
IWL_ERROR("ERROR: No TX rate available.\n");
|
||||
goto drop_unlock;
|
||||
}
|
||||
@ -2650,8 +2650,6 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
|
||||
/* Set up driver data for this TFD */
|
||||
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info));
|
||||
txq->txb[q->write_ptr].skb[0] = skb;
|
||||
memcpy(&(txq->txb[q->write_ptr].status.control),
|
||||
ctl, sizeof(struct ieee80211_tx_control));
|
||||
|
||||
/* Init first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_cmd = &txq->cmd[idx];
|
||||
@ -2700,8 +2698,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
|
||||
* first entry */
|
||||
iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
|
||||
|
||||
if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
|
||||
iwl3945_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
|
||||
if (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT))
|
||||
iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, 0);
|
||||
|
||||
/* Set up TFD's 2nd entry to point directly to remainder of skb,
|
||||
* if any (802.11 null frames have no payload). */
|
||||
@ -2726,10 +2724,10 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
|
||||
out_cmd->cmd.tx.len = cpu_to_le16(len);
|
||||
|
||||
/* TODO need this for burst mode later on */
|
||||
iwl3945_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
|
||||
iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, unicast, sta_id);
|
||||
|
||||
/* set is_hcca to 0; it probably will never be implemented */
|
||||
iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
|
||||
iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
|
||||
|
||||
out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
|
||||
out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
|
||||
@ -2767,7 +2765,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv,
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
ieee80211_stop_queue(priv->hw, ctl->queue);
|
||||
ieee80211_stop_queue(priv->hw, info->queue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -3230,7 +3228,7 @@ static void iwl3945_bg_beacon_update(struct work_struct *work)
|
||||
struct sk_buff *beacon;
|
||||
|
||||
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif);
|
||||
|
||||
if (!beacon) {
|
||||
IWL_ERROR("update beacon failed\n");
|
||||
@ -6681,8 +6679,7 @@ static void iwl3945_mac_stop(struct ieee80211_hw *hw)
|
||||
IWL_DEBUG_MAC80211("leave\n");
|
||||
}
|
||||
|
||||
static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl3945_priv *priv = hw->priv;
|
||||
|
||||
@ -6694,9 +6691,9 @@ 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,
|
||||
ieee80211_get_tx_rate(hw, ctl)->bitrate);
|
||||
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
|
||||
|
||||
if (iwl3945_tx_skb(priv, skb, ctl))
|
||||
if (iwl3945_tx_skb(priv, skb))
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
IWL_DEBUG_MAC80211("leave\n");
|
||||
@ -7333,8 +7330,7 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
|
||||
|
||||
}
|
||||
|
||||
static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl3945_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
|
@ -1606,17 +1606,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
|
||||
static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
|
||||
struct iwl_tx_info *tx_sta)
|
||||
{
|
||||
|
||||
tx_sta->status.ack_signal = 0;
|
||||
tx_sta->status.excessive_retries = 0;
|
||||
|
||||
if (in_interrupt())
|
||||
ieee80211_tx_status_irqsafe(priv->hw,
|
||||
tx_sta->skb[0], &(tx_sta->status));
|
||||
else
|
||||
ieee80211_tx_status(priv->hw,
|
||||
tx_sta->skb[0], &(tx_sta->status));
|
||||
|
||||
ieee80211_tx_status_irqsafe(priv->hw, tx_sta->skb[0]);
|
||||
tx_sta->skb[0] = NULL;
|
||||
}
|
||||
|
||||
@ -1710,7 +1700,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
||||
{
|
||||
u16 status;
|
||||
struct agg_tx_status *frame_status = &tx_resp->status;
|
||||
struct ieee80211_tx_status *tx_status = NULL;
|
||||
struct ieee80211_tx_info *info = NULL;
|
||||
struct ieee80211_hdr *hdr = NULL;
|
||||
int i, sh;
|
||||
int txq_id, idx;
|
||||
@ -1736,14 +1726,14 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
||||
IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
|
||||
agg->frame_count, agg->start_idx, idx);
|
||||
|
||||
tx_status = &(priv->txq[txq_id].txb[idx].status);
|
||||
tx_status->retry_count = tx_resp->failure_frame;
|
||||
tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
|
||||
tx_status->flags = iwl4965_is_tx_success(status)?
|
||||
IEEE80211_TX_STATUS_ACK : 0;
|
||||
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
|
||||
info->status.retry_count = tx_resp->failure_frame;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
info->flags |= iwl4965_is_tx_success(status)?
|
||||
IEEE80211_TX_STAT_ACK : 0;
|
||||
iwl4965_hwrate_to_tx_control(priv,
|
||||
le32_to_cpu(tx_resp->rate_n_flags),
|
||||
&tx_status->control);
|
||||
info);
|
||||
/* FIXME: code repetition end */
|
||||
|
||||
IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
|
||||
@ -1830,7 +1820,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
||||
int txq_id = SEQ_TO_QUEUE(sequence);
|
||||
int index = SEQ_TO_INDEX(sequence);
|
||||
struct iwl_tx_queue *txq = &priv->txq[txq_id];
|
||||
struct ieee80211_tx_status *tx_status;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
||||
u32 status = le32_to_cpu(tx_resp->status);
|
||||
#ifdef CONFIG_IWL4965_HT
|
||||
@ -1848,6 +1838,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
#ifdef CONFIG_IWL4965_HT
|
||||
hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
|
||||
fc = le16_to_cpu(hdr->frame_control);
|
||||
@ -1902,13 +1895,12 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
||||
}
|
||||
} else {
|
||||
#endif /* CONFIG_IWL4965_HT */
|
||||
tx_status = &(txq->txb[txq->q.read_ptr].status);
|
||||
|
||||
tx_status->retry_count = tx_resp->failure_frame;
|
||||
tx_status->flags =
|
||||
iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
|
||||
info->status.retry_count = tx_resp->failure_frame;
|
||||
info->flags |=
|
||||
iwl4965_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0;
|
||||
iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
|
||||
&tx_status->control);
|
||||
info);
|
||||
|
||||
IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
|
||||
"retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
|
||||
@ -2053,7 +2045,7 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
|
||||
struct sk_buff *beacon;
|
||||
|
||||
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
|
||||
beacon = ieee80211_beacon_get(priv->hw, priv->vif);
|
||||
|
||||
if (!beacon) {
|
||||
IWL_ERROR("update beacon failed\n");
|
||||
@ -4268,8 +4260,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
|
||||
IWL_DEBUG_MAC80211("leave\n");
|
||||
}
|
||||
|
||||
static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
@ -4281,9 +4272,9 @@ 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,
|
||||
ieee80211_get_tx_rate(hw, ctl)->bitrate);
|
||||
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
|
||||
|
||||
if (iwl_tx_skb(priv, skb, ctl))
|
||||
if (iwl_tx_skb(priv, skb))
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
IWL_DEBUG_MAC80211("leave\n");
|
||||
@ -5065,8 +5056,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
|
||||
IWL_DEBUG_MAC80211("leave\n");
|
||||
}
|
||||
|
||||
static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
|
@ -394,7 +394,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
while (entry != (struct sk_buff *)&priv->tx_queue) {
|
||||
range = (struct memrecord *)&entry->cb;
|
||||
if (range->start_addr == addr) {
|
||||
struct ieee80211_tx_status status;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
|
||||
struct p54_control_hdr *entry_hdr;
|
||||
struct p54_tx_control_allocdata *entry_data;
|
||||
int pad = 0;
|
||||
@ -406,30 +406,23 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
|
||||
last_addr = range->end_addr;
|
||||
__skb_unlink(entry, &priv->tx_queue);
|
||||
if (!range->control) {
|
||||
kfree_skb(entry);
|
||||
break;
|
||||
}
|
||||
memset(&status, 0, sizeof(status));
|
||||
memcpy(&status.control, range->control,
|
||||
sizeof(status.control));
|
||||
kfree(range->control);
|
||||
priv->tx_stats[status.control.queue].len--;
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
priv->tx_stats[info->queue].len--;
|
||||
entry_hdr = (struct p54_control_hdr *) entry->data;
|
||||
entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
|
||||
if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
|
||||
pad = entry_data->align[0];
|
||||
|
||||
if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
if (!(payload->status & 0x01))
|
||||
status.flags |= IEEE80211_TX_STATUS_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
else
|
||||
status.excessive_retries = 1;
|
||||
info->status.excessive_retries = 1;
|
||||
}
|
||||
status.retry_count = payload->retries - 1;
|
||||
status.ack_signal = le16_to_cpu(payload->ack_rssi);
|
||||
info->status.retry_count = payload->retries - 1;
|
||||
info->status.ack_signal = le16_to_cpu(payload->ack_rssi);
|
||||
skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
|
||||
ieee80211_tx_status_irqsafe(dev, entry, &status);
|
||||
ieee80211_tx_status_irqsafe(dev, entry);
|
||||
break;
|
||||
} else
|
||||
last_addr = range->end_addr;
|
||||
@ -494,13 +487,11 @@ EXPORT_SYMBOL_GPL(p54_rx);
|
||||
* allocated areas.
|
||||
*/
|
||||
static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
struct p54_control_hdr *data, u32 len,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct p54_control_hdr *data, u32 len)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
struct sk_buff *entry = priv->tx_queue.next;
|
||||
struct sk_buff *target_skb = NULL;
|
||||
struct memrecord *range;
|
||||
u32 last_addr = priv->rx_start;
|
||||
u32 largest_hole = 0;
|
||||
u32 target_addr = priv->rx_start;
|
||||
@ -512,7 +503,8 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
left = skb_queue_len(&priv->tx_queue);
|
||||
while (left--) {
|
||||
u32 hole_size;
|
||||
range = (struct memrecord *)&entry->cb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
|
||||
struct memrecord *range = (void *)info->driver_data;
|
||||
hole_size = range->start_addr - last_addr;
|
||||
if (!target_skb && hole_size >= len) {
|
||||
target_skb = entry->prev;
|
||||
@ -527,17 +519,18 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
target_skb = priv->tx_queue.prev;
|
||||
largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
|
||||
if (!skb_queue_empty(&priv->tx_queue)) {
|
||||
range = (struct memrecord *)&target_skb->cb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb);
|
||||
struct memrecord *range = (void *)info->driver_data;
|
||||
target_addr = range->end_addr;
|
||||
}
|
||||
} else
|
||||
largest_hole = max(largest_hole, priv->rx_end - last_addr);
|
||||
|
||||
if (skb) {
|
||||
range = (struct memrecord *)&skb->cb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct memrecord *range = (void *)info->driver_data;
|
||||
range->start_addr = target_addr;
|
||||
range->end_addr = target_addr + len;
|
||||
range->control = control;
|
||||
__skb_queue_after(&priv->tx_queue, target_skb, skb);
|
||||
if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
|
||||
sizeof(struct p54_control_hdr))
|
||||
@ -548,32 +541,27 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
data->req_id = cpu_to_le32(target_addr + 0x70);
|
||||
}
|
||||
|
||||
static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_queue_stats *current_queue;
|
||||
struct p54_common *priv = dev->priv;
|
||||
struct p54_control_hdr *hdr;
|
||||
struct p54_tx_control_allocdata *txhdr;
|
||||
struct ieee80211_tx_control *control_copy;
|
||||
size_t padding, len;
|
||||
u8 rate;
|
||||
|
||||
current_queue = &priv->tx_stats[control->queue];
|
||||
current_queue = &priv->tx_stats[info->queue];
|
||||
if (unlikely(current_queue->len > current_queue->limit))
|
||||
return NETDEV_TX_BUSY;
|
||||
current_queue->len++;
|
||||
current_queue->count++;
|
||||
if (current_queue->len == current_queue->limit)
|
||||
ieee80211_stop_queue(dev, control->queue);
|
||||
ieee80211_stop_queue(dev, info->queue);
|
||||
|
||||
padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
|
||||
len = skb->len;
|
||||
|
||||
control_copy = kmalloc(sizeof(*control), GFP_ATOMIC);
|
||||
if (control_copy)
|
||||
memcpy(control_copy, control, sizeof(*control));
|
||||
|
||||
txhdr = (struct p54_tx_control_allocdata *)
|
||||
skb_push(skb, sizeof(*txhdr) + padding);
|
||||
hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
|
||||
@ -583,35 +571,37 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
else
|
||||
hdr->magic1 = cpu_to_le16(0x0010);
|
||||
hdr->len = cpu_to_le16(len);
|
||||
hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1);
|
||||
hdr->retry1 = hdr->retry2 = control->retry_limit;
|
||||
p54_assign_address(dev, skb, hdr, skb->len, control_copy);
|
||||
hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1);
|
||||
hdr->retry1 = hdr->retry2 = info->control.retry_limit;
|
||||
|
||||
memset(txhdr->wep_key, 0x0, 16);
|
||||
txhdr->padding = 0;
|
||||
txhdr->padding2 = 0;
|
||||
|
||||
/* TODO: add support for alternate retry TX rates */
|
||||
rate = ieee80211_get_tx_rate(dev, control)->hw_value;
|
||||
if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
|
||||
rate = ieee80211_get_tx_rate(dev, info)->hw_value;
|
||||
if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
|
||||
rate |= 0x10;
|
||||
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
rate |= 0x40;
|
||||
else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
|
||||
else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
||||
rate |= 0x20;
|
||||
memset(txhdr->rateset, rate, 8);
|
||||
txhdr->wep_key_present = 0;
|
||||
txhdr->wep_key_len = 0;
|
||||
txhdr->frame_type = cpu_to_le32(control->queue + 4);
|
||||
txhdr->frame_type = cpu_to_le32(info->queue + 4);
|
||||
txhdr->magic4 = 0;
|
||||
txhdr->antenna = (control->antenna_sel_tx == 0) ?
|
||||
2 : control->antenna_sel_tx - 1;
|
||||
txhdr->antenna = (info->antenna_sel_tx == 0) ?
|
||||
2 : info->antenna_sel_tx - 1;
|
||||
txhdr->output_power = 0x7f; // HW Maximum
|
||||
txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ?
|
||||
txhdr->magic5 = (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
|
||||
0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
|
||||
if (padding)
|
||||
txhdr->align[0] = padding;
|
||||
|
||||
/* modifies skb->cb and with it info, so must be last! */
|
||||
p54_assign_address(dev, skb, hdr, skb->len);
|
||||
|
||||
priv->tx(dev, hdr, skb->len, 0);
|
||||
return 0;
|
||||
}
|
||||
@ -634,7 +624,7 @@ static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
|
||||
filter = (struct p54_tx_control_filter *) hdr->data;
|
||||
hdr->magic1 = cpu_to_le16(0x8001);
|
||||
hdr->len = cpu_to_le16(sizeof(*filter));
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter));
|
||||
hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
|
||||
|
||||
filter->filter_type = cpu_to_le16(filter_type);
|
||||
@ -678,7 +668,7 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
|
||||
hdr->magic1 = cpu_to_le16(0x8001);
|
||||
hdr->len = cpu_to_le16(sizeof(*chan));
|
||||
hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len);
|
||||
|
||||
chan->magic1 = cpu_to_le16(0x1);
|
||||
chan->magic2 = cpu_to_le16(0x0);
|
||||
@ -751,7 +741,7 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
|
||||
hdr->magic1 = cpu_to_le16(0x8001);
|
||||
hdr->len = cpu_to_le16(sizeof(*led));
|
||||
hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led));
|
||||
|
||||
led = (struct p54_tx_control_led *) hdr->data;
|
||||
led->mode = cpu_to_le16(mode);
|
||||
@ -801,7 +791,7 @@ static void p54_set_vdcf(struct ieee80211_hw *dev)
|
||||
|
||||
hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
|
||||
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL);
|
||||
p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf));
|
||||
|
||||
vdcf = (struct p54_tx_control_vdcf *) hdr->data;
|
||||
|
||||
@ -837,12 +827,8 @@ static void p54_stop(struct ieee80211_hw *dev)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
struct sk_buff *skb;
|
||||
while ((skb = skb_dequeue(&priv->tx_queue))) {
|
||||
struct memrecord *range = (struct memrecord *)&skb->cb;
|
||||
if (range->control)
|
||||
kfree(range->control);
|
||||
while ((skb = skb_dequeue(&priv->tx_queue)))
|
||||
kfree_skb(skb);
|
||||
}
|
||||
priv->stop(dev);
|
||||
priv->mode = IEEE80211_IF_TYPE_INVALID;
|
||||
}
|
||||
|
@ -152,7 +152,6 @@ struct pda_pa_curve_data {
|
||||
struct memrecord {
|
||||
u32 start_addr;
|
||||
u32 end_addr;
|
||||
struct ieee80211_tx_control *control;
|
||||
};
|
||||
|
||||
struct p54_eeprom_lm86 {
|
||||
|
@ -1484,11 +1484,11 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
|
||||
return tsf;
|
||||
}
|
||||
|
||||
static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_intf *intf = vif_to_intf(control->vif);
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||
struct queue_entry_priv_pci *entry_priv;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct txentry_desc txdesc;
|
||||
@ -1504,7 +1504,7 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
* for our information.
|
||||
*/
|
||||
intf->beacon->skb = skb;
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control);
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
|
||||
|
||||
/*
|
||||
* Fill in skb descriptor
|
||||
|
@ -1799,11 +1799,11 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
|
||||
return tsf;
|
||||
}
|
||||
|
||||
static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_intf *intf = vif_to_intf(control->vif);
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||
struct queue_entry_priv_pci *entry_priv;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct txentry_desc txdesc;
|
||||
@ -1820,7 +1820,7 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
* for our information.
|
||||
*/
|
||||
intf->beacon->skb = skb;
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control);
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
|
||||
|
||||
/*
|
||||
* Fill in skb descriptor
|
||||
|
@ -1666,13 +1666,12 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* IEEE80211 stack callback functions.
|
||||
*/
|
||||
static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
|
||||
struct rt2x00_intf *intf = vif_to_intf(control->vif);
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||
struct queue_entry_priv_usb_bcn *bcn_priv;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct txentry_desc txdesc;
|
||||
@ -1691,7 +1690,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
|
||||
* for our information.
|
||||
*/
|
||||
intf->beacon->skb = skb;
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control);
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
|
||||
|
||||
/*
|
||||
* Add the descriptor in front of the skb.
|
||||
|
@ -542,8 +542,7 @@ struct rt2x00lib_ops {
|
||||
struct sk_buff *skb,
|
||||
struct txentry_desc *txdesc);
|
||||
int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
|
||||
struct data_queue *queue, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
struct data_queue *queue, struct sk_buff *skb);
|
||||
int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
|
||||
struct sk_buff *skb);
|
||||
void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
|
||||
@ -930,7 +929,6 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
|
||||
* rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input
|
||||
* @entry: The entry which will be used to transfer the TX frame.
|
||||
* @txdesc: rt2x00 TX descriptor which will be initialized by this function.
|
||||
* @control: mac80211 TX control structure from where we read the information.
|
||||
*
|
||||
* This function will initialize the &struct txentry_desc based on information
|
||||
* from mac80211. This descriptor can then be used by rt2x00lib and the drivers
|
||||
@ -943,8 +941,7 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
|
||||
* the &struct txentry_desc structure.
|
||||
*/
|
||||
void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
struct txentry_desc *txdesc,
|
||||
struct ieee80211_tx_control *control);
|
||||
struct txentry_desc *txdesc);
|
||||
|
||||
/**
|
||||
* rt2x00queue_write_tx_descriptor - Write TX descriptor to hardware
|
||||
@ -1001,8 +998,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry,
|
||||
/*
|
||||
* mac80211 handlers.
|
||||
*/
|
||||
int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
int rt2x00mac_tx(struct ieee80211_hw *hw, 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,
|
||||
|
@ -415,7 +415,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
|
||||
struct rt2x00_dev *rt2x00dev = data;
|
||||
struct rt2x00_intf *intf = vif_to_intf(vif);
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_control control;
|
||||
struct ieee80211_bss_conf conf;
|
||||
int delayed_flags;
|
||||
|
||||
@ -433,9 +432,9 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
|
||||
spin_unlock(&intf->lock);
|
||||
|
||||
if (delayed_flags & DELAYED_UPDATE_BEACON) {
|
||||
skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
|
||||
if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
|
||||
skb, &control))
|
||||
skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
|
||||
if (skb &&
|
||||
rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb))
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
@ -494,8 +493,13 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
struct txdone_entry_desc *txdesc)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct ieee80211_tx_status tx_status;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
|
||||
|
||||
/*
|
||||
* Send frame to debugfs immediately, after this call is completed
|
||||
* we are going to overwrite the skb->cb array.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
|
||||
|
||||
/*
|
||||
* Update TX statistics.
|
||||
@ -508,21 +512,20 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
/*
|
||||
* Initialize TX status
|
||||
*/
|
||||
tx_status.flags = 0;
|
||||
tx_status.ack_signal = 0;
|
||||
tx_status.excessive_retries =
|
||||
memset(&tx_info->status, 0, sizeof(tx_info->status));
|
||||
tx_info->status.ack_signal = 0;
|
||||
tx_info->status.excessive_retries =
|
||||
test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags);
|
||||
tx_status.retry_count = txdesc->retry;
|
||||
memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
|
||||
tx_info->status.retry_count = txdesc->retry;
|
||||
|
||||
if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
|
||||
tx_status.flags |= IEEE80211_TX_STATUS_ACK;
|
||||
tx_info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
|
||||
rt2x00dev->low_level_stats.dot11ACKFailureCount++;
|
||||
}
|
||||
|
||||
if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
|
||||
if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
|
||||
rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
|
||||
else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
|
||||
@ -530,19 +533,13 @@ void rt2x00lib_txdone(struct queue_entry *entry,
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the tx_status to debugfs. Only send the status report
|
||||
* to mac80211 when the frame originated from there. If this was
|
||||
* a extra frame coming through a mac80211 library call (RTS/CTS)
|
||||
* then we should not send the status report back.
|
||||
* If send to mac80211, mac80211 will clean up the skb structure,
|
||||
* otherwise we have to do it ourself.
|
||||
* Only send the status report to mac80211 when TX status was
|
||||
* requested by it. If this was a extra frame coming through
|
||||
* a mac80211 library call (RTS/CTS) then we should not send the
|
||||
* status report back.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
|
||||
|
||||
skbdesc = get_skb_frame_desc(entry->skb);
|
||||
if (!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED))
|
||||
ieee80211_tx_status_irqsafe(rt2x00dev->hw,
|
||||
entry->skb, &tx_status);
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
|
||||
ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
|
||||
else
|
||||
dev_kfree_skb_irq(entry->skb);
|
||||
entry->skb = NULL;
|
||||
|
@ -31,14 +31,15 @@
|
||||
|
||||
static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
||||
struct data_queue *queue,
|
||||
struct sk_buff *frag_skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct sk_buff *frag_skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct ieee80211_tx_info *rts_info;
|
||||
struct sk_buff *skb;
|
||||
int size;
|
||||
|
||||
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
||||
size = sizeof(struct ieee80211_cts);
|
||||
else
|
||||
size = sizeof(struct ieee80211_rts);
|
||||
@ -52,13 +53,33 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
||||
skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
|
||||
skb_put(skb, size);
|
||||
|
||||
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
|
||||
ieee80211_ctstoself_get(rt2x00dev->hw, control->vif,
|
||||
frag_skb->data, frag_skb->len, control,
|
||||
/*
|
||||
* Copy TX information over from original frame to
|
||||
* RTS/CTS frame. Note that we set the no encryption flag
|
||||
* since we don't want this frame to be encrypted.
|
||||
* RTS frames should be acked, while CTS-to-self frames
|
||||
* should not. The ready for TX flag is cleared to prevent
|
||||
* it being automatically send when the descriptor is
|
||||
* written to the hardware.
|
||||
*/
|
||||
memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
|
||||
rts_info = IEEE80211_SKB_CB(skb);
|
||||
rts_info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
|
||||
rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
|
||||
rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
||||
rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
else
|
||||
rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
||||
ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
|
||||
frag_skb->data, size, tx_info,
|
||||
(struct ieee80211_cts *)(skb->data));
|
||||
else
|
||||
ieee80211_rts_get(rt2x00dev->hw, control->vif,
|
||||
frag_skb->data, frag_skb->len, control,
|
||||
ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
|
||||
frag_skb->data, size, tx_info,
|
||||
(struct ieee80211_rts *)(skb->data));
|
||||
|
||||
/*
|
||||
@ -68,7 +89,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
|
||||
|
||||
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
|
||||
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) {
|
||||
WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
@ -76,14 +97,13 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
|
||||
enum data_queue_qid qid = mac80211_queue_to_qid(control->queue);
|
||||
enum data_queue_qid qid = mac80211_queue_to_qid(tx_info->queue);
|
||||
struct data_queue *queue;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
u16 frame_control;
|
||||
|
||||
/*
|
||||
@ -100,7 +120,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
/*
|
||||
* Determine which queue to put packet on.
|
||||
*/
|
||||
if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM &&
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
|
||||
test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
|
||||
queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM);
|
||||
else
|
||||
@ -125,33 +145,27 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
*/
|
||||
frame_control = le16_to_cpu(ieee80211hdr->frame_control);
|
||||
if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
|
||||
(control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
|
||||
IEEE80211_TXCTL_USE_CTS_PROTECT)) &&
|
||||
(tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS |
|
||||
IEEE80211_TX_CTL_USE_CTS_PROTECT)) &&
|
||||
!rt2x00dev->ops->hw->set_rts_threshold) {
|
||||
if (rt2x00queue_available(queue) <= 1) {
|
||||
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
|
||||
ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) {
|
||||
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
|
||||
if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) {
|
||||
ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize skb descriptor
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(skb);
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
|
||||
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) {
|
||||
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
|
||||
if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb)) {
|
||||
ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (rt2x00queue_full(queue))
|
||||
ieee80211_stop_queue(rt2x00dev->hw, control->queue);
|
||||
ieee80211_stop_queue(rt2x00dev->hw, tx_info->queue);
|
||||
|
||||
if (rt2x00dev->ops->lib->kick_tx_queue)
|
||||
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, qid);
|
||||
@ -380,9 +394,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
|
||||
if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon)
|
||||
return 0;
|
||||
|
||||
status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
|
||||
conf->beacon,
|
||||
conf->beacon_control);
|
||||
status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon);
|
||||
if (status)
|
||||
dev_kfree_skb(conf->beacon);
|
||||
|
||||
|
@ -35,8 +35,7 @@
|
||||
* TX data handlers.
|
||||
*/
|
||||
int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
struct data_queue *queue, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct data_queue *queue, struct sk_buff *skb)
|
||||
{
|
||||
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
|
||||
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
|
||||
@ -64,19 +63,19 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
* for our information.
|
||||
*/
|
||||
entry->skb = skb;
|
||||
rt2x00queue_create_tx_descriptor(entry, &txdesc, control);
|
||||
rt2x00queue_create_tx_descriptor(entry, &txdesc);
|
||||
|
||||
/*
|
||||
* Fill in skb descriptor
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(skb);
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->data = skb->data;
|
||||
skbdesc->data_len = skb->len;
|
||||
skbdesc->desc = entry_priv->desc;
|
||||
skbdesc->desc_len = queue->desc_size;
|
||||
skbdesc->entry = entry;
|
||||
|
||||
memcpy(&entry_priv->control, control, sizeof(entry_priv->control));
|
||||
memcpy(entry_priv->data, skb->data, skb->len);
|
||||
|
||||
rt2x00queue_write_tx_descriptor(entry, &txdesc);
|
||||
@ -164,9 +163,9 @@ void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
|
||||
struct txdone_entry_desc *txdesc)
|
||||
{
|
||||
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
|
||||
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
|
||||
u32 word;
|
||||
|
||||
txdesc->control = &entry_priv->control;
|
||||
rt2x00lib_txdone(entry, txdesc);
|
||||
|
||||
/*
|
||||
@ -187,7 +186,7 @@ void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
|
||||
* is reenabled when the txdone handler has finished.
|
||||
*/
|
||||
if (!rt2x00queue_full(entry->queue))
|
||||
ieee80211_wake_queue(rt2x00dev->hw, entry_priv->control.queue);
|
||||
ieee80211_wake_queue(rt2x00dev->hw, qid);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
|
||||
|
@ -91,8 +91,7 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
|
||||
* TX data handlers.
|
||||
*/
|
||||
int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
struct data_queue *queue, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
struct data_queue *queue, struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* struct queue_entry_priv_pci: Per entry PCI specific information
|
||||
@ -101,7 +100,6 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
* @desc_dma: DMA pointer to &desc.
|
||||
* @data: Pointer to device's entry memory.
|
||||
* @data_dma: DMA pointer to &data.
|
||||
* @control: mac80211 control structure used to transmit data.
|
||||
*/
|
||||
struct queue_entry_priv_pci {
|
||||
__le32 *desc;
|
||||
@ -109,8 +107,6 @@ struct queue_entry_priv_pci {
|
||||
|
||||
void *data;
|
||||
dma_addr_t data_dma;
|
||||
|
||||
struct ieee80211_tx_control control;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -30,13 +30,13 @@
|
||||
#include "rt2x00lib.h"
|
||||
|
||||
void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
struct txentry_desc *txdesc,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
|
||||
struct ieee80211_rate *rate =
|
||||
ieee80211_get_tx_rate(rt2x00dev->hw, control);
|
||||
ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
|
||||
const struct rt2x00_rate *hwrate;
|
||||
unsigned int data_length;
|
||||
unsigned int duration;
|
||||
@ -64,7 +64,7 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
/*
|
||||
* Check whether this frame is to be acked.
|
||||
*/
|
||||
if (!(control->flags & IEEE80211_TXCTL_NO_ACK))
|
||||
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
__set_bit(ENTRY_TXD_ACK, &txdesc->flags);
|
||||
|
||||
/*
|
||||
@ -72,23 +72,20 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
*/
|
||||
if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) {
|
||||
__set_bit(ENTRY_TXD_BURST, &txdesc->flags);
|
||||
if (is_rts_frame(frame_control)) {
|
||||
if (is_rts_frame(frame_control))
|
||||
__set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags);
|
||||
__set_bit(ENTRY_TXD_ACK, &txdesc->flags);
|
||||
} else {
|
||||
else
|
||||
__set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags);
|
||||
__clear_bit(ENTRY_TXD_ACK, &txdesc->flags);
|
||||
}
|
||||
if (control->rts_cts_rate_idx >= 0)
|
||||
if (tx_info->control.rts_cts_rate_idx >= 0)
|
||||
rate =
|
||||
ieee80211_get_rts_cts_rate(rt2x00dev->hw, control);
|
||||
ieee80211_get_rts_cts_rate(rt2x00dev->hw, tx_info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine retry information.
|
||||
*/
|
||||
txdesc->retry_limit = control->retry_limit;
|
||||
if (control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
|
||||
txdesc->retry_limit = tx_info->control.retry_limit;
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
|
||||
__set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags);
|
||||
|
||||
/*
|
||||
@ -113,7 +110,7 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
*/
|
||||
if (test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) {
|
||||
txdesc->ifs = IFS_SIFS;
|
||||
} else if (control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) {
|
||||
} else if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
|
||||
__set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags);
|
||||
txdesc->ifs = IFS_BACKOFF;
|
||||
} else {
|
||||
@ -179,8 +176,10 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
|
||||
|
||||
/*
|
||||
* We are done writing the frame to the queue entry,
|
||||
* if this entry is a RTS of CTS-to-self frame we are done,
|
||||
* otherwise we need to kick the queue.
|
||||
* also kick the queue in case the correct flags are set,
|
||||
* note that this will automatically filter beacons and
|
||||
* RTS/CTS frames since those frames don't have this flag
|
||||
* set.
|
||||
*/
|
||||
if (rt2x00dev->ops->lib->kick_tx_queue &&
|
||||
!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED))
|
||||
|
@ -105,8 +105,8 @@ enum skb_frame_desc_flags {
|
||||
/**
|
||||
* struct skb_frame_desc: Descriptor information for the skb buffer
|
||||
*
|
||||
* This structure is placed over the skb->cb array, this means that
|
||||
* this structure should not exceed the size of that array (48 bytes).
|
||||
* This structure is placed over the driver_data array, this means that
|
||||
* this structure should not exceed the size of that array (40 bytes).
|
||||
*
|
||||
* @flags: Frame flags, see &enum skb_frame_desc_flags.
|
||||
* @data: Pointer to data part of frame (Start of ieee80211 header).
|
||||
@ -129,10 +129,15 @@ struct skb_frame_desc {
|
||||
struct queue_entry *entry;
|
||||
};
|
||||
|
||||
/**
|
||||
* get_skb_frame_desc - Obtain the rt2x00 frame descriptor from a sk_buff.
|
||||
* @skb: &struct sk_buff from where we obtain the &struct skb_frame_desc
|
||||
*/
|
||||
static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(struct skb_frame_desc) > sizeof(skb->cb));
|
||||
return (struct skb_frame_desc *)&skb->cb[0];
|
||||
BUILD_BUG_ON(sizeof(struct skb_frame_desc) >
|
||||
IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
|
||||
return (struct skb_frame_desc *)&IEEE80211_SKB_CB(skb)->driver_data;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,12 +194,10 @@ enum txdone_entry_desc_flags {
|
||||
* Summary of information that has been read from the TX frame descriptor
|
||||
* after the device is done with transmission.
|
||||
*
|
||||
* @control: Control structure which was used to transmit the frame.
|
||||
* @flags: TX done flags (See &enum txdone_entry_desc_flags).
|
||||
* @retry: Retry count.
|
||||
*/
|
||||
struct txdone_entry_desc {
|
||||
struct ieee80211_tx_control *control;
|
||||
unsigned long flags;
|
||||
int retry;
|
||||
};
|
||||
|
@ -129,9 +129,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
|
||||
{
|
||||
struct queue_entry *entry = (struct queue_entry *)urb->context;
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
|
||||
struct txdone_entry_desc txdesc;
|
||||
__le32 *txd = (__le32 *)entry->skb->data;
|
||||
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
|
||||
u32 word;
|
||||
|
||||
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
|
||||
@ -159,7 +159,6 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
|
||||
else
|
||||
__set_bit(TXDONE_FAILURE, &txdesc.flags);
|
||||
txdesc.retry = 0;
|
||||
txdesc.control = &entry_priv->control;
|
||||
|
||||
rt2x00lib_txdone(entry, &txdesc);
|
||||
|
||||
@ -175,12 +174,11 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
|
||||
* is reenabled when the txdone handler has finished.
|
||||
*/
|
||||
if (!rt2x00queue_full(entry->queue))
|
||||
ieee80211_wake_queue(rt2x00dev->hw, entry_priv->control.queue);
|
||||
ieee80211_wake_queue(rt2x00dev->hw, qid);
|
||||
}
|
||||
|
||||
int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
struct data_queue *queue, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct data_queue *queue, struct sk_buff *skb)
|
||||
{
|
||||
struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev);
|
||||
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
|
||||
@ -206,7 +204,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
* for our information.
|
||||
*/
|
||||
entry->skb = skb;
|
||||
rt2x00queue_create_tx_descriptor(entry, &txdesc, control);
|
||||
rt2x00queue_create_tx_descriptor(entry, &txdesc);
|
||||
|
||||
/*
|
||||
* Add the descriptor in front of the skb.
|
||||
@ -218,13 +216,13 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
* Fill in skb descriptor
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(skb);
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->data = skb->data + queue->desc_size;
|
||||
skbdesc->data_len = skb->len - queue->desc_size;
|
||||
skbdesc->desc = skb->data;
|
||||
skbdesc->desc_len = queue->desc_size;
|
||||
skbdesc->entry = entry;
|
||||
|
||||
memcpy(&entry_priv->control, control, sizeof(entry_priv->control));
|
||||
rt2x00queue_write_tx_descriptor(entry, &txdesc);
|
||||
|
||||
/*
|
||||
|
@ -216,19 +216,15 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
* TX data handlers.
|
||||
*/
|
||||
int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
|
||||
struct data_queue *queue, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
struct data_queue *queue, struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* struct queue_entry_priv_usb: Per entry USB specific information
|
||||
*
|
||||
* @urb: Urb structure used for device communication.
|
||||
* @control: mac80211 control structure used to transmit data.
|
||||
*/
|
||||
struct queue_entry_priv_usb {
|
||||
struct urb *urb;
|
||||
|
||||
struct ieee80211_tx_control control;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -239,15 +235,12 @@ struct queue_entry_priv_usb {
|
||||
* with beacons.
|
||||
*
|
||||
* @urb: Urb structure used for device communication.
|
||||
* @control: mac80211 control structure used to transmit data.
|
||||
* @guardian_data: Set to 0, used for sending the guardian data.
|
||||
* @guardian_urb: Urb structure used to send the guardian data.
|
||||
*/
|
||||
struct queue_entry_priv_usb_bcn {
|
||||
struct urb *urb;
|
||||
|
||||
struct ieee80211_tx_control control;
|
||||
|
||||
unsigned int guardian_data;
|
||||
struct urb *guardian_urb;
|
||||
};
|
||||
|
@ -2357,11 +2357,11 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
|
||||
return tsf;
|
||||
}
|
||||
|
||||
static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_intf *intf = vif_to_intf(control->vif);
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||
struct queue_entry_priv_pci *entry_priv;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct txentry_desc txdesc;
|
||||
@ -2377,7 +2377,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
* for our information.
|
||||
*/
|
||||
intf->beacon->skb = skb;
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control);
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
|
||||
|
||||
entry_priv = intf->beacon->priv_data;
|
||||
memset(entry_priv->desc, 0, intf->beacon->queue->desc_size);
|
||||
|
@ -1948,11 +1948,11 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
|
||||
#define rt73usb_get_tsf NULL
|
||||
#endif
|
||||
|
||||
static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
struct rt2x00_intf *intf = vif_to_intf(control->vif);
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct txentry_desc txdesc;
|
||||
unsigned int beacon_base;
|
||||
@ -1967,7 +1967,7 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
* for our information.
|
||||
*/
|
||||
intf->beacon->skb = skb;
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control);
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
|
||||
|
||||
/*
|
||||
* Add the descriptor in front of the skb.
|
||||
|
@ -170,34 +170,29 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
|
||||
while (skb_queue_len(&ring->queue)) {
|
||||
struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_status status;
|
||||
struct ieee80211_tx_control *control;
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 flags = le32_to_cpu(entry->flags);
|
||||
|
||||
if (flags & RTL8180_TX_DESC_FLAG_OWN)
|
||||
return;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
|
||||
ring->idx = (ring->idx + 1) % ring->entries;
|
||||
skb = __skb_dequeue(&ring->queue);
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
|
||||
control = *((struct ieee80211_tx_control **)skb->cb);
|
||||
if (control)
|
||||
memcpy(&status.control, control, sizeof(*control));
|
||||
kfree(control);
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
if (flags & RTL8180_TX_DESC_FLAG_TX_OK)
|
||||
status.flags = IEEE80211_TX_STATUS_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
else
|
||||
status.excessive_retries = 1;
|
||||
info->status.excessive_retries = 1;
|
||||
}
|
||||
status.retry_count = flags & 0xFF;
|
||||
info->status.retry_count = flags & 0xFF;
|
||||
|
||||
ieee80211_tx_status_irqsafe(dev, skb, &status);
|
||||
ieee80211_tx_status_irqsafe(dev, skb);
|
||||
if (ring->entries - skb_queue_len(&ring->queue) == 2)
|
||||
ieee80211_wake_queue(dev, prio);
|
||||
}
|
||||
@ -238,9 +233,9 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
struct rtl8180_tx_ring *ring;
|
||||
struct rtl8180_tx_desc *entry;
|
||||
@ -251,7 +246,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
u16 plcp_len = 0;
|
||||
__le16 rts_duration = 0;
|
||||
|
||||
prio = control->queue;
|
||||
prio = info->queue;
|
||||
ring = &priv->tx_ring[prio];
|
||||
|
||||
mapping = pci_map_single(priv->pdev, skb->data,
|
||||
@ -259,35 +254,32 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
|
||||
tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
|
||||
RTL8180_TX_DESC_FLAG_LS |
|
||||
(ieee80211_get_tx_rate(dev, control)->hw_value << 24) |
|
||||
(ieee80211_get_tx_rate(dev, info)->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) {
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
|
||||
tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
|
||||
tx_flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
|
||||
} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
|
||||
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
|
||||
} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
|
||||
tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
|
||||
tx_flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
|
||||
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
|
||||
}
|
||||
|
||||
*((struct ieee80211_tx_control **) skb->cb) =
|
||||
kmemdup(control, sizeof(*control), GFP_ATOMIC);
|
||||
|
||||
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len,
|
||||
control);
|
||||
info);
|
||||
|
||||
if (!priv->r8185) {
|
||||
unsigned int remainder;
|
||||
|
||||
plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
|
||||
(ieee80211_get_tx_rate(dev, control)->bitrate * 2) / 10);
|
||||
(ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10);
|
||||
remainder = (16 * (skb->len + 4)) %
|
||||
((ieee80211_get_tx_rate(dev, control)->bitrate * 2) / 10);
|
||||
((ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10);
|
||||
if (remainder > 0 && remainder <= 6)
|
||||
plcp_len |= 1 << 15;
|
||||
}
|
||||
@ -300,13 +292,13 @@ 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_idx >= 0 ?
|
||||
ieee80211_get_alt_retry_rate(dev, control)->bitrate << 4 : 0;
|
||||
entry->retry_limit = control->retry_limit;
|
||||
entry->flags2 = info->control.alt_retry_rate_idx >= 0 ?
|
||||
ieee80211_get_alt_retry_rate(dev, info)->bitrate << 4 : 0;
|
||||
entry->retry_limit = info->control.retry_limit;
|
||||
entry->flags = cpu_to_le32(tx_flags);
|
||||
__skb_queue_tail(&ring->queue, skb);
|
||||
if (ring->entries - skb_queue_len(&ring->queue) < 2)
|
||||
ieee80211_stop_queue(dev, control->queue);
|
||||
ieee80211_stop_queue(dev, info->queue);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
|
||||
@ -522,7 +514,6 @@ static void rtl8180_free_tx_ring(struct ieee80211_hw *dev, unsigned int prio)
|
||||
|
||||
pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
|
||||
skb->len, PCI_DMA_TODEVICE);
|
||||
kfree(*((struct ieee80211_tx_control **) skb->cb));
|
||||
kfree_skb(skb);
|
||||
ring->idx = (ring->idx + 1) % ring->entries;
|
||||
}
|
||||
|
@ -44,12 +44,6 @@ struct rtl8187_rx_hdr {
|
||||
__le64 mac_time;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct rtl8187_tx_info {
|
||||
struct ieee80211_tx_control *control;
|
||||
struct urb *urb;
|
||||
struct ieee80211_hw *dev;
|
||||
};
|
||||
|
||||
struct rtl8187_tx_hdr {
|
||||
__le32 flags;
|
||||
#define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15)
|
||||
|
@ -145,27 +145,22 @@ void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
|
||||
|
||||
static void rtl8187_tx_cb(struct urb *urb)
|
||||
{
|
||||
struct ieee80211_tx_status status;
|
||||
struct sk_buff *skb = (struct sk_buff *)urb->context;
|
||||
struct rtl8187_tx_info *info = (struct rtl8187_tx_info *)skb->cb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hw *hw = info->driver_data[0];
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
|
||||
usb_free_urb(info->urb);
|
||||
if (info->control)
|
||||
memcpy(&status.control, info->control, sizeof(status.control));
|
||||
kfree(info->control);
|
||||
usb_free_urb(info->driver_data[1]);
|
||||
skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
|
||||
status.flags |= IEEE80211_TX_STATUS_ACK;
|
||||
ieee80211_tx_status_irqsafe(info->dev, skb, &status);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
}
|
||||
|
||||
static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct rtl8187_tx_hdr *hdr;
|
||||
struct rtl8187_tx_info *info;
|
||||
struct urb *urb;
|
||||
__le16 rts_dur = 0;
|
||||
u32 flags;
|
||||
@ -179,29 +174,27 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
flags = skb->len;
|
||||
flags |= RTL8187_TX_FLAG_NO_ENCRYPT;
|
||||
|
||||
flags |= ieee80211_get_tx_rate(dev, control)->hw_value << 24;
|
||||
flags |= ieee80211_get_tx_rate(dev, info)->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) {
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
|
||||
flags |= RTL8187_TX_FLAG_RTS;
|
||||
flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
|
||||
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
|
||||
rts_dur = ieee80211_rts_duration(dev, priv->vif,
|
||||
skb->len, control);
|
||||
} else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
|
||||
skb->len, info);
|
||||
} else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
|
||||
flags |= RTL8187_TX_FLAG_CTS;
|
||||
flags |= ieee80211_get_rts_cts_rate(dev, control)->hw_value << 19;
|
||||
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
|
||||
}
|
||||
|
||||
hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
|
||||
hdr->flags = cpu_to_le32(flags);
|
||||
hdr->len = 0;
|
||||
hdr->rts_duration = rts_dur;
|
||||
hdr->retry = cpu_to_le32(control->retry_limit << 8);
|
||||
hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
|
||||
|
||||
info = (struct rtl8187_tx_info *)skb->cb;
|
||||
info->control = kmemdup(control, sizeof(*control), GFP_ATOMIC);
|
||||
info->urb = urb;
|
||||
info->dev = dev;
|
||||
info->driver_data[0] = dev;
|
||||
info->driver_data[1] = urb;
|
||||
usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
|
||||
hdr, skb->len, rtl8187_tx_cb, skb);
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
@ -224,36 +224,6 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_tx_skb_control_block - clears the control block of tx skbuffs
|
||||
* @skb: a &struct sk_buff pointer
|
||||
*
|
||||
* This clears the control block of skbuff buffers, which were transmitted to
|
||||
* the device. Notify that the function is not thread-safe, so prevent
|
||||
* multiple calls.
|
||||
*/
|
||||
static void clear_tx_skb_control_block(struct sk_buff *skb)
|
||||
{
|
||||
struct zd_tx_skb_control_block *cb =
|
||||
(struct zd_tx_skb_control_block *)skb->cb;
|
||||
|
||||
kfree(cb->control);
|
||||
cb->control = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* kfree_tx_skb - frees a tx skbuff
|
||||
* @skb: a &struct sk_buff pointer
|
||||
*
|
||||
* Frees the tx skbuff. Frees also the allocated control structure in the
|
||||
* control block if necessary.
|
||||
*/
|
||||
static void kfree_tx_skb(struct sk_buff *skb)
|
||||
{
|
||||
clear_tx_skb_control_block(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
static void zd_op_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct zd_mac *mac = zd_hw_mac(hw);
|
||||
@ -276,40 +246,15 @@ static void zd_op_stop(struct ieee80211_hw *hw)
|
||||
|
||||
|
||||
while ((skb = skb_dequeue(ack_wait_queue)))
|
||||
kfree_tx_skb(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* init_tx_skb_control_block - initializes skb control block
|
||||
* @skb: a &sk_buff pointer
|
||||
* @dev: pointer to the mac80221 device
|
||||
* @control: mac80211 tx control applying for the frame in @skb
|
||||
*
|
||||
* Initializes the control block of the skbuff to be transmitted.
|
||||
*/
|
||||
static int init_tx_skb_control_block(struct sk_buff *skb,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_control *control)
|
||||
{
|
||||
struct zd_tx_skb_control_block *cb =
|
||||
(struct zd_tx_skb_control_block *)skb->cb;
|
||||
|
||||
ZD_ASSERT(sizeof(*cb) <= sizeof(skb->cb));
|
||||
memset(cb, 0, sizeof(*cb));
|
||||
cb->hw= hw;
|
||||
cb->control = kmalloc(sizeof(*control), GFP_ATOMIC);
|
||||
if (cb->control == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(cb->control, control, sizeof(*control));
|
||||
|
||||
return 0;
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* tx_status - reports tx status of a packet if required
|
||||
* @hw - a &struct ieee80211_hw pointer
|
||||
* @skb - a sk-buffer
|
||||
* @status - the tx status of the packet without control information
|
||||
* @flags: extra flags to set in the TX status info
|
||||
* @ackssi: ACK signal strength
|
||||
* @success - True for successfull transmission of the frame
|
||||
*
|
||||
* This information calls ieee80211_tx_status_irqsafe() if required by the
|
||||
@ -319,18 +264,17 @@ static int init_tx_skb_control_block(struct sk_buff *skb,
|
||||
* If no status information has been requested, the skb is freed.
|
||||
*/
|
||||
static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status,
|
||||
bool success)
|
||||
u32 flags, int ackssi, bool success)
|
||||
{
|
||||
struct zd_tx_skb_control_block *cb = (struct zd_tx_skb_control_block *)
|
||||
skb->cb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
ZD_ASSERT(cb->control != NULL);
|
||||
memcpy(&status->control, cb->control, sizeof(status->control));
|
||||
if (!success)
|
||||
status->excessive_retries = 1;
|
||||
clear_tx_skb_control_block(skb);
|
||||
ieee80211_tx_status_irqsafe(hw, skb, status);
|
||||
info->status.excessive_retries = 1;
|
||||
info->flags |= flags;
|
||||
info->status.ack_signal = ackssi;
|
||||
ieee80211_tx_status_irqsafe(hw, skb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -345,15 +289,12 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_status status;
|
||||
|
||||
skb = skb_dequeue(q);
|
||||
if (skb == NULL)
|
||||
return;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
|
||||
tx_status(hw, skb, &status, 0);
|
||||
tx_status(hw, skb, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -368,28 +309,20 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
|
||||
*/
|
||||
void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
|
||||
{
|
||||
struct zd_tx_skb_control_block *cb =
|
||||
(struct zd_tx_skb_control_block *)skb->cb;
|
||||
struct ieee80211_hw *hw = cb->hw;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hw *hw = info->driver_data[0];
|
||||
|
||||
if (likely(cb->control)) {
|
||||
skb_pull(skb, sizeof(struct zd_ctrlset));
|
||||
if (unlikely(error ||
|
||||
(cb->control->flags & IEEE80211_TXCTL_NO_ACK)))
|
||||
{
|
||||
struct ieee80211_tx_status status;
|
||||
memset(&status, 0, sizeof(status));
|
||||
tx_status(hw, skb, &status, !error);
|
||||
} else {
|
||||
struct sk_buff_head *q =
|
||||
&zd_hw_mac(hw)->ack_wait_queue;
|
||||
|
||||
skb_queue_tail(q, skb);
|
||||
while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
|
||||
zd_mac_tx_failed(hw);
|
||||
}
|
||||
skb_pull(skb, sizeof(struct zd_ctrlset));
|
||||
if (unlikely(error ||
|
||||
(info->flags & IEEE80211_TX_CTL_NO_ACK))) {
|
||||
tx_status(hw, skb, 0, 0, !error);
|
||||
} else {
|
||||
kfree_tx_skb(skb);
|
||||
struct sk_buff_head *q =
|
||||
&zd_hw_mac(hw)->ack_wait_queue;
|
||||
|
||||
skb_queue_tail(q, skb);
|
||||
while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
|
||||
zd_mac_tx_failed(hw);
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,7 +387,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
|
||||
cs->control = 0;
|
||||
|
||||
/* First fragment */
|
||||
if (flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
|
||||
if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
|
||||
cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
|
||||
|
||||
/* Multicast */
|
||||
@ -466,10 +399,10 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
|
||||
(IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL))
|
||||
cs->control |= ZD_CS_PS_POLL_FRAME;
|
||||
|
||||
if (flags & IEEE80211_TXCTL_USE_RTS_CTS)
|
||||
if (flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
cs->control |= ZD_CS_RTS;
|
||||
|
||||
if (flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
|
||||
if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
||||
cs->control |= ZD_CS_SELF_CTS;
|
||||
|
||||
/* FIXME: Management frame? */
|
||||
@ -516,8 +449,7 @@ void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
|
||||
}
|
||||
|
||||
static int fill_ctrlset(struct zd_mac *mac,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int r;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
@ -526,18 +458,19 @@ static int fill_ctrlset(struct zd_mac *mac,
|
||||
struct ieee80211_rate *txrate;
|
||||
struct zd_ctrlset *cs = (struct zd_ctrlset *)
|
||||
skb_push(skb, sizeof(struct zd_ctrlset));
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
ZD_ASSERT(frag_len <= 0xffff);
|
||||
|
||||
txrate = ieee80211_get_tx_rate(mac->hw, control);
|
||||
txrate = ieee80211_get_tx_rate(mac->hw, info);
|
||||
|
||||
cs->modulation = txrate->hw_value;
|
||||
if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE)
|
||||
if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
|
||||
cs->modulation = txrate->hw_value_short;
|
||||
|
||||
cs->tx_length = cpu_to_le16(frag_len);
|
||||
|
||||
cs_set_control(mac, cs, hdr, control->flags);
|
||||
cs_set_control(mac, cs, hdr, info->flags);
|
||||
|
||||
packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
|
||||
ZD_ASSERT(packet_length <= 0xffff);
|
||||
@ -582,24 +515,21 @@ 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 int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct zd_mac *mac = zd_hw_mac(hw);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int r;
|
||||
|
||||
r = fill_ctrlset(mac, skb, control);
|
||||
r = fill_ctrlset(mac, skb);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = init_tx_skb_control_block(skb, hw, control);
|
||||
info->driver_data[0] = hw;
|
||||
|
||||
r = zd_usb_tx(&mac->chip.usb, skb);
|
||||
if (r)
|
||||
return r;
|
||||
r = zd_usb_tx(&mac->chip.usb, skb);
|
||||
if (r) {
|
||||
clear_tx_skb_control_block(skb);
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -637,13 +567,8 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
|
||||
tx_hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
|
||||
{
|
||||
struct ieee80211_tx_status status;
|
||||
|
||||
memset(&status, 0, sizeof(status));
|
||||
status.flags = IEEE80211_TX_STATUS_ACK;
|
||||
status.ack_signal = stats->signal;
|
||||
__skb_unlink(skb, q);
|
||||
tx_status(hw, skb, &status, 1);
|
||||
tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -947,8 +872,7 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
static int zd_op_beacon_update(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *ctl)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct zd_mac *mac = zd_hw_mac(hw);
|
||||
zd_mac_config_beacon(hw, skb);
|
||||
|
@ -149,22 +149,6 @@ struct housekeeping {
|
||||
struct delayed_work link_led_work;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct zd_tx_skb_control_block - control block for tx skbuffs
|
||||
* @control: &struct ieee80211_tx_control pointer
|
||||
* @context: context pointer
|
||||
*
|
||||
* This structure is used to fill the cb field in an &sk_buff to transmit.
|
||||
* The control field is NULL, if there is no requirement from the mac80211
|
||||
* stack to report about the packet ACK. This is the case if the flag
|
||||
* IEEE80211_TXCTL_NO_ACK is not set in &struct ieee80211_tx_control.
|
||||
*/
|
||||
struct zd_tx_skb_control_block {
|
||||
struct ieee80211_tx_control *control;
|
||||
struct ieee80211_hw *hw;
|
||||
void *context;
|
||||
};
|
||||
|
||||
#define ZD_MAC_STATS_BUFFER_SIZE 16
|
||||
|
||||
#define ZD_MAC_MAX_ACK_WAITERS 10
|
||||
|
@ -869,7 +869,7 @@ static void tx_urb_complete(struct urb *urb)
|
||||
{
|
||||
int r;
|
||||
struct sk_buff *skb;
|
||||
struct zd_tx_skb_control_block *cb;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct zd_usb *usb;
|
||||
|
||||
switch (urb->status) {
|
||||
@ -893,8 +893,8 @@ free_urb:
|
||||
* grab 'usb' pointer before handing off the skb (since
|
||||
* it might be freed by zd_mac_tx_to_dev or mac80211)
|
||||
*/
|
||||
cb = (struct zd_tx_skb_control_block *)skb->cb;
|
||||
usb = &zd_hw_mac(cb->hw)->chip.usb;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
usb = &zd_hw_mac(info->driver_data[0])->chip.usb;
|
||||
zd_mac_tx_to_dev(skb, urb->status);
|
||||
free_tx_urb(usb, urb);
|
||||
tx_dec_submitted_urbs(usb);
|
||||
|
@ -201,101 +201,127 @@ struct ieee80211_bss_conf {
|
||||
};
|
||||
|
||||
/**
|
||||
* enum mac80211_tx_control_flags - flags to describe Tx configuration for
|
||||
* the Tx frame
|
||||
* enum mac80211_tx_flags - flags to transmission information/status
|
||||
*
|
||||
* These flags are used with the @flags member of &ieee80211_tx_control
|
||||
* These flags are used with the @flags member of &ieee80211_tx_info
|
||||
*
|
||||
* @IEEE80211_TXCTL_REQ_TX_STATUS: request TX status callback for this frame.
|
||||
* @IEEE80211_TXCTL_DO_NOT_ENCRYPT: send this frame without encryption;
|
||||
* e.g., for EAPOL frame
|
||||
* @IEEE80211_TXCTL_USE_RTS_CTS: use RTS-CTS before sending frame
|
||||
* @IEEE80211_TXCTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g.,
|
||||
* for combined 802.11g / 802.11b networks)
|
||||
* @IEEE80211_TXCTL_NO_ACK: tell the low level not to wait for an ack
|
||||
* @IEEE80211_TXCTL_RATE_CTRL_PROBE
|
||||
* @EEE80211_TXCTL_CLEAR_PS_FILT: clear powersave filter
|
||||
* for destination station
|
||||
* @IEEE80211_TXCTL_REQUEUE:
|
||||
* @IEEE80211_TXCTL_FIRST_FRAGMENT: this is a first fragment of the frame
|
||||
* @IEEE80211_TXCTL_LONG_RETRY_LIMIT: this frame should be send using the
|
||||
* through set_retry_limit configured long
|
||||
* retry value
|
||||
* @IEEE80211_TXCTL_EAPOL_FRAME: internal to mac80211
|
||||
* @IEEE80211_TXCTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
|
||||
* @IEEE80211_TXCTL_AMPDU: this frame should be sent as part of an A-MPDU
|
||||
* @IEEE80211_TXCTL_OFDM_HT: this frame can be sent in HT OFDM rates. number
|
||||
* of streams when this flag is on can be extracted
|
||||
* from antenna_sel_tx, so if 1 antenna is marked
|
||||
* use SISO, 2 antennas marked use MIMO, n antennas
|
||||
* marked use MIMO_n.
|
||||
* @IEEE80211_TXCTL_GREEN_FIELD: use green field protection for this frame
|
||||
* @IEEE80211_TXCTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width
|
||||
* @IEEE80211_TXCTL_DUP_DATA: duplicate data frame on both 20 Mhz channels
|
||||
* @IEEE80211_TXCTL_SHORT_GI: send this frame using short guard interval
|
||||
* @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame.
|
||||
* @IEEE80211_TX_CTL_DO_NOT_ENCRYPT: send this frame without encryption;
|
||||
* e.g., for EAPOL frame
|
||||
* @IEEE80211_TX_CTL_USE_RTS_CTS: use RTS-CTS before sending frame
|
||||
* @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g.,
|
||||
* for combined 802.11g / 802.11b networks)
|
||||
* @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack
|
||||
* @IEEE80211_TX_CTL_RATE_CTRL_PROBE
|
||||
* @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination
|
||||
* station
|
||||
* @IEEE80211_TX_CTL_REQUEUE:
|
||||
* @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame
|
||||
* @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the
|
||||
* through set_retry_limit configured long retry value
|
||||
* @IEEE80211_TX_CTL_EAPOL_FRAME: internal to mac80211
|
||||
* @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon
|
||||
* @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU
|
||||
* @IEEE80211_TX_CTL_OFDM_HT: this frame can be sent in HT OFDM rates. number
|
||||
* of streams when this flag is on can be extracted from antenna_sel_tx,
|
||||
* so if 1 antenna is marked use SISO, 2 antennas marked use MIMO, n
|
||||
* antennas marked use MIMO_n.
|
||||
* @IEEE80211_TX_CTL_GREEN_FIELD: use green field protection for this frame
|
||||
* @IEEE80211_TX_CTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width
|
||||
* @IEEE80211_TX_CTL_DUP_DATA: duplicate data frame on both 20 Mhz channels
|
||||
* @IEEE80211_TX_CTL_SHORT_GI: send this frame using short guard interval
|
||||
* @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted
|
||||
* because the destination STA was in powersave mode.
|
||||
* @IEEE80211_TX_STAT_ACK: Frame was acknowledged
|
||||
* @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status
|
||||
* is for the whole aggregation.
|
||||
*/
|
||||
enum mac80211_tx_control_flags {
|
||||
IEEE80211_TXCTL_REQ_TX_STATUS = (1<<0),
|
||||
IEEE80211_TXCTL_DO_NOT_ENCRYPT = (1<<1),
|
||||
IEEE80211_TXCTL_USE_RTS_CTS = (1<<2),
|
||||
IEEE80211_TXCTL_USE_CTS_PROTECT = (1<<3),
|
||||
IEEE80211_TXCTL_NO_ACK = (1<<4),
|
||||
IEEE80211_TXCTL_RATE_CTRL_PROBE = (1<<5),
|
||||
IEEE80211_TXCTL_CLEAR_PS_FILT = (1<<6),
|
||||
IEEE80211_TXCTL_REQUEUE = (1<<7),
|
||||
IEEE80211_TXCTL_FIRST_FRAGMENT = (1<<8),
|
||||
IEEE80211_TXCTL_SHORT_PREAMBLE = (1<<9),
|
||||
IEEE80211_TXCTL_LONG_RETRY_LIMIT = (1<<10),
|
||||
IEEE80211_TXCTL_EAPOL_FRAME = (1<<11),
|
||||
IEEE80211_TXCTL_SEND_AFTER_DTIM = (1<<12),
|
||||
IEEE80211_TXCTL_AMPDU = (1<<13),
|
||||
IEEE80211_TXCTL_OFDM_HT = (1<<14),
|
||||
IEEE80211_TXCTL_GREEN_FIELD = (1<<15),
|
||||
IEEE80211_TXCTL_40_MHZ_WIDTH = (1<<16),
|
||||
IEEE80211_TXCTL_DUP_DATA = (1<<17),
|
||||
IEEE80211_TXCTL_SHORT_GI = (1<<18),
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
|
||||
IEEE80211_TX_CTL_DO_NOT_ENCRYPT = BIT(1),
|
||||
IEEE80211_TX_CTL_USE_RTS_CTS = BIT(2),
|
||||
IEEE80211_TX_CTL_USE_CTS_PROTECT = BIT(3),
|
||||
IEEE80211_TX_CTL_NO_ACK = BIT(4),
|
||||
IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(5),
|
||||
IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(6),
|
||||
IEEE80211_TX_CTL_REQUEUE = BIT(7),
|
||||
IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(8),
|
||||
IEEE80211_TX_CTL_SHORT_PREAMBLE = BIT(9),
|
||||
IEEE80211_TX_CTL_LONG_RETRY_LIMIT = BIT(10),
|
||||
IEEE80211_TX_CTL_EAPOL_FRAME = BIT(11),
|
||||
IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(12),
|
||||
IEEE80211_TX_CTL_AMPDU = BIT(13),
|
||||
IEEE80211_TX_CTL_OFDM_HT = BIT(14),
|
||||
IEEE80211_TX_CTL_GREEN_FIELD = BIT(15),
|
||||
IEEE80211_TX_CTL_40_MHZ_WIDTH = BIT(16),
|
||||
IEEE80211_TX_CTL_DUP_DATA = BIT(17),
|
||||
IEEE80211_TX_CTL_SHORT_GI = BIT(18),
|
||||
IEEE80211_TX_CTL_INJECTED = BIT(19),
|
||||
IEEE80211_TX_STAT_TX_FILTERED = BIT(20),
|
||||
IEEE80211_TX_STAT_ACK = BIT(21),
|
||||
IEEE80211_TX_STAT_AMPDU = BIT(22),
|
||||
};
|
||||
|
||||
/* Transmit control fields. This data structure is passed to low-level driver
|
||||
* with each TX frame. The low-level driver is responsible for configuring
|
||||
* the hardware to use given values (depending on what is supported).
|
||||
|
||||
#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE \
|
||||
(sizeof(((struct sk_buff *)0)->cb) - 8)
|
||||
#define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \
|
||||
(IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *))
|
||||
|
||||
/**
|
||||
* struct ieee80211_tx_info - skb transmit information
|
||||
*
|
||||
* NOTE: Be careful with using the pointers outside of the ieee80211_ops->tx()
|
||||
* context (i.e. when defering the work to a workqueue).
|
||||
* The vif pointer is valid until the it has been removed with the
|
||||
* ieee80211_ops->remove_interface() callback funtion.
|
||||
* The hw_key pointer is valid until it has been removed with the
|
||||
* ieee80211_ops->set_key() callback function.
|
||||
* This structure is placed in skb->cb for three uses:
|
||||
* (1) mac80211 TX control - mac80211 tells the driver what to do
|
||||
* (2) driver internal use (if applicable)
|
||||
* (3) TX status information - driver tells mac80211 what happened
|
||||
*
|
||||
* @flags: transmit info flags, defined above
|
||||
* @retry_count: number of retries
|
||||
* @excessive_retries: set to 1 if the frame was retried many times
|
||||
* but not acknowledged
|
||||
* @ampdu_ack_len: number of aggregated frames.
|
||||
* relevant only if IEEE80211_TX_STATUS_AMPDU was set.
|
||||
* @ampdu_ack_map: block ack bit map for the aggregation.
|
||||
* relevant only if IEEE80211_TX_STATUS_AMPDU was set.
|
||||
* @ack_signal: signal strength of the ACK frame
|
||||
*/
|
||||
struct ieee80211_tx_control {
|
||||
u32 flags; /* tx control flags defined above */
|
||||
struct ieee80211_tx_info {
|
||||
/* common information */
|
||||
u32 flags;
|
||||
u8 band;
|
||||
s8 tx_rate_idx;
|
||||
u8 antenna_sel_tx;
|
||||
|
||||
s8 tx_rate_idx, /* Transmit rate (indexes registered rates) */
|
||||
rts_cts_rate_idx, /* Transmit rate for RTS/CTS frame */
|
||||
alt_retry_rate_idx; /* retry rate for the last retries */
|
||||
u8 queue; /* use skb_queue_mapping soon */
|
||||
|
||||
s8 retry_limit; /* 1 = only first attempt, 2 = one retry, ..
|
||||
* This could be used when set_retry_limit
|
||||
* is not implemented by the driver */
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
/* Key used for hardware encryption
|
||||
* NULL if IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */
|
||||
struct ieee80211_key_conf *hw_key;
|
||||
|
||||
enum ieee80211_band band;
|
||||
|
||||
u8 antenna_sel_tx; /* 0 = default/diversity, otherwise bit
|
||||
* position represents antenna number used */
|
||||
u8 icv_len; /* length of the ICV/MIC field in octets */
|
||||
u8 iv_len; /* length of the IV field in octets */
|
||||
u16 queue; /* hardware queue to use for this frame;
|
||||
* 0 = highest, hw->queues-1 = lowest */
|
||||
u16 aid; /* Station AID */
|
||||
int type; /* internal */
|
||||
union {
|
||||
struct {
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_key_conf *hw_key;
|
||||
unsigned long jiffies;
|
||||
int ifindex;
|
||||
u16 aid;
|
||||
s8 rts_cts_rate_idx, alt_retry_rate_idx;
|
||||
u8 retry_limit;
|
||||
u8 icv_len;
|
||||
u8 iv_len;
|
||||
} control;
|
||||
struct {
|
||||
u64 ampdu_ack_map;
|
||||
int ack_signal;
|
||||
u8 retry_count;
|
||||
bool excessive_retries;
|
||||
u8 ampdu_ack_len;
|
||||
} status;
|
||||
void *driver_data[IEEE80211_TX_INFO_DRIVER_DATA_PTRS];
|
||||
};
|
||||
};
|
||||
|
||||
static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb)
|
||||
{
|
||||
return (struct ieee80211_tx_info *)skb->cb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -362,52 +388,6 @@ struct ieee80211_rx_status {
|
||||
int flag;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ieee80211_tx_status_flags - transmit status flags
|
||||
*
|
||||
* Status flags to indicate various transmit conditions.
|
||||
*
|
||||
* @IEEE80211_TX_STATUS_TX_FILTERED: The frame was not transmitted
|
||||
* because the destination STA was in powersave mode.
|
||||
* @IEEE80211_TX_STATUS_ACK: Frame was acknowledged
|
||||
* @IEEE80211_TX_STATUS_AMPDU: The frame was aggregated, so status
|
||||
* is for the whole aggregation.
|
||||
*/
|
||||
enum ieee80211_tx_status_flags {
|
||||
IEEE80211_TX_STATUS_TX_FILTERED = 1<<0,
|
||||
IEEE80211_TX_STATUS_ACK = 1<<1,
|
||||
IEEE80211_TX_STATUS_AMPDU = 1<<2,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_tx_status - transmit status
|
||||
*
|
||||
* As much information as possible should be provided for each transmitted
|
||||
* frame with ieee80211_tx_status().
|
||||
*
|
||||
* @control: a copy of the &struct ieee80211_tx_control passed to the driver
|
||||
* in the tx() callback.
|
||||
* @flags: transmit status flags, defined above
|
||||
* @retry_count: number of retries
|
||||
* @excessive_retries: set to 1 if the frame was retried many times
|
||||
* but not acknowledged
|
||||
* @ampdu_ack_len: number of aggregated frames.
|
||||
* relevant only if IEEE80211_TX_STATUS_AMPDU was set.
|
||||
* @ampdu_ack_map: block ack bit map for the aggregation.
|
||||
* relevant only if IEEE80211_TX_STATUS_AMPDU was set.
|
||||
* @ack_signal: signal strength of the ACK frame either in dBm, dB or unspec
|
||||
* depending on hardware capabilites flags @IEEE80211_HW_SIGNAL_*
|
||||
*/
|
||||
struct ieee80211_tx_status {
|
||||
struct ieee80211_tx_control control;
|
||||
u8 flags;
|
||||
u8 retry_count;
|
||||
bool excessive_retries;
|
||||
u8 ampdu_ack_len;
|
||||
u64 ampdu_ack_map;
|
||||
int ack_signal;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum ieee80211_conf_flags - configuration flags
|
||||
*
|
||||
@ -563,7 +543,6 @@ struct ieee80211_if_conf {
|
||||
u8 *ssid;
|
||||
size_t ssid_len;
|
||||
struct sk_buff *beacon;
|
||||
struct ieee80211_tx_control *beacon_control;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -825,7 +804,7 @@ static inline void SET_IEEE80211_PERM_ADDR(struct ieee80211_hw *hw, u8 *addr)
|
||||
|
||||
static inline struct ieee80211_rate *
|
||||
ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
|
||||
const struct ieee80211_tx_control *c)
|
||||
const struct ieee80211_tx_info *c)
|
||||
{
|
||||
if (WARN_ON(c->tx_rate_idx < 0))
|
||||
return NULL;
|
||||
@ -834,20 +813,20 @@ ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
|
||||
|
||||
static inline struct ieee80211_rate *
|
||||
ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw,
|
||||
const struct ieee80211_tx_control *c)
|
||||
const struct ieee80211_tx_info *c)
|
||||
{
|
||||
if (c->rts_cts_rate_idx < 0)
|
||||
if (c->control.rts_cts_rate_idx < 0)
|
||||
return NULL;
|
||||
return &hw->wiphy->bands[c->band]->bitrates[c->rts_cts_rate_idx];
|
||||
return &hw->wiphy->bands[c->band]->bitrates[c->control.rts_cts_rate_idx];
|
||||
}
|
||||
|
||||
static inline struct ieee80211_rate *
|
||||
ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
|
||||
const struct ieee80211_tx_control *c)
|
||||
const struct ieee80211_tx_info *c)
|
||||
{
|
||||
if (c->alt_retry_rate_idx < 0)
|
||||
if (c->control.alt_retry_rate_idx < 0)
|
||||
return NULL;
|
||||
return &hw->wiphy->bands[c->band]->bitrates[c->alt_retry_rate_idx];
|
||||
return &hw->wiphy->bands[c->band]->bitrates[c->control.alt_retry_rate_idx];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1142,8 +1121,7 @@ enum ieee80211_ampdu_mlme_action {
|
||||
* that TX/RX_STOP can pass NULL for this parameter.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int (*start)(struct ieee80211_hw *hw);
|
||||
void (*stop)(struct ieee80211_hw *hw);
|
||||
int (*add_interface)(struct ieee80211_hw *hw,
|
||||
@ -1187,8 +1165,7 @@ struct ieee80211_ops {
|
||||
u64 (*get_tsf)(struct ieee80211_hw *hw);
|
||||
void (*reset_tsf)(struct ieee80211_hw *hw);
|
||||
int (*beacon_update)(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control);
|
||||
struct sk_buff *skb);
|
||||
int (*tx_last_beacon)(struct ieee80211_hw *hw);
|
||||
int (*ampdu_action)(struct ieee80211_hw *hw,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
@ -1384,13 +1361,9 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw,
|
||||
*
|
||||
* @hw: the hardware the frame was transmitted by
|
||||
* @skb: the frame that was transmitted, owned by mac80211 after this call
|
||||
* @status: status information for this frame; the status pointer need not
|
||||
* be valid after this function returns and is not freed by mac80211,
|
||||
* it is recommended that it points to a stack area
|
||||
*/
|
||||
void ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status);
|
||||
struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* ieee80211_tx_status_irqsafe - irq-safe transmit status callback
|
||||
@ -1403,13 +1376,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw,
|
||||
*
|
||||
* @hw: the hardware the frame was transmitted by
|
||||
* @skb: the frame that was transmitted, owned by mac80211 after this call
|
||||
* @status: status information for this frame; the status pointer need not
|
||||
* be valid after this function returns and is not freed by mac80211,
|
||||
* it is recommended that it points to a stack area
|
||||
*/
|
||||
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status);
|
||||
struct sk_buff *skb);
|
||||
|
||||
/**
|
||||
* ieee80211_beacon_get - beacon generation function
|
||||
@ -1425,8 +1394,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
||||
* is responsible of freeing it.
|
||||
*/
|
||||
struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_tx_control *control);
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_rts_get - RTS frame generation function
|
||||
@ -1434,7 +1402,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @frame: pointer to the frame that is going to be protected by the RTS.
|
||||
* @frame_len: the frame length (in octets).
|
||||
* @frame_txctl: &struct ieee80211_tx_control of the frame.
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
* @rts: The buffer where to store the RTS frame.
|
||||
*
|
||||
* If the RTS frames are generated by the host system (i.e., not in
|
||||
@ -1444,7 +1412,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
*/
|
||||
void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const void *frame, size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl,
|
||||
const struct ieee80211_tx_info *frame_txctl,
|
||||
struct ieee80211_rts *rts);
|
||||
|
||||
/**
|
||||
@ -1452,7 +1420,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @frame_len: the length of the frame that is going to be protected by the RTS.
|
||||
* @frame_txctl: &struct ieee80211_tx_control of the frame.
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
*
|
||||
* If the RTS is generated in firmware, but the host system must provide
|
||||
* the duration field, the low-level driver uses this function to receive
|
||||
@ -1460,7 +1428,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
*/
|
||||
__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl);
|
||||
const struct ieee80211_tx_info *frame_txctl);
|
||||
|
||||
/**
|
||||
* ieee80211_ctstoself_get - CTS-to-self frame generation function
|
||||
@ -1468,7 +1436,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @frame: pointer to the frame that is going to be protected by the CTS-to-self.
|
||||
* @frame_len: the frame length (in octets).
|
||||
* @frame_txctl: &struct ieee80211_tx_control of the frame.
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
* @cts: The buffer where to store the CTS-to-self frame.
|
||||
*
|
||||
* If the CTS-to-self frames are generated by the host system (i.e., not in
|
||||
@ -1479,7 +1447,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
|
||||
void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const void *frame, size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl,
|
||||
const struct ieee80211_tx_info *frame_txctl,
|
||||
struct ieee80211_cts *cts);
|
||||
|
||||
/**
|
||||
@ -1487,7 +1455,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
|
||||
* @hw: pointer obtained from ieee80211_alloc_hw().
|
||||
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
|
||||
* @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
|
||||
* @frame_txctl: &struct ieee80211_tx_control of the frame.
|
||||
* @frame_txctl: &struct ieee80211_tx_info of the frame.
|
||||
*
|
||||
* If the CTS-to-self is generated in firmware, but the host system must provide
|
||||
* the duration field, the low-level driver uses this function to receive
|
||||
@ -1496,7 +1464,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
|
||||
__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl);
|
||||
const struct ieee80211_tx_info *frame_txctl);
|
||||
|
||||
/**
|
||||
* ieee80211_generic_frame_duration - Calculate the duration field for a frame
|
||||
@ -1535,8 +1503,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
|
||||
* use common code for all beacons.
|
||||
*/
|
||||
struct sk_buff *
|
||||
ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_tx_control *control);
|
||||
ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* ieee80211_get_hdrlen_from_skb - get header length from data
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright 2002-2005, Instant802 Networks, Inc.
|
||||
* Copyright 2005, Devicescape Software, Inc.
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -147,7 +148,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result;
|
||||
#define IEEE80211_TX_UNICAST BIT(1)
|
||||
#define IEEE80211_TX_PS_BUFFERED BIT(2)
|
||||
#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3)
|
||||
#define IEEE80211_TX_INJECTED BIT(4)
|
||||
|
||||
struct ieee80211_tx_data {
|
||||
struct sk_buff *skb;
|
||||
@ -157,7 +157,6 @@ struct ieee80211_tx_data {
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_key *key;
|
||||
|
||||
struct ieee80211_tx_control *control;
|
||||
struct ieee80211_channel *channel;
|
||||
s8 rate_idx;
|
||||
/* use this rate (if set) for last fragment; rate can
|
||||
@ -207,22 +206,7 @@ struct ieee80211_rx_data {
|
||||
u16 tkip_iv16;
|
||||
};
|
||||
|
||||
/* flags used in struct ieee80211_tx_packet_data.flags */
|
||||
#define IEEE80211_TXPD_REQ_TX_STATUS BIT(0)
|
||||
#define IEEE80211_TXPD_DO_NOT_ENCRYPT BIT(1)
|
||||
#define IEEE80211_TXPD_REQUEUE BIT(2)
|
||||
#define IEEE80211_TXPD_EAPOL_FRAME BIT(3)
|
||||
#define IEEE80211_TXPD_AMPDU BIT(4)
|
||||
/* Stored in sk_buff->cb */
|
||||
struct ieee80211_tx_packet_data {
|
||||
int ifindex;
|
||||
unsigned long jiffies;
|
||||
unsigned int flags;
|
||||
u8 queue;
|
||||
};
|
||||
|
||||
struct ieee80211_tx_stored_packet {
|
||||
struct ieee80211_tx_control control;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff **extra_frag;
|
||||
s8 last_frag_rate_idx;
|
||||
|
@ -971,8 +971,7 @@ void ieee80211_if_setup(struct net_device *dev)
|
||||
/* everything else */
|
||||
|
||||
static int __ieee80211_if_config(struct net_device *dev,
|
||||
struct sk_buff *beacon,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct sk_buff *beacon)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
@ -990,13 +989,11 @@ static int __ieee80211_if_config(struct net_device *dev,
|
||||
conf.ssid_len = sdata->u.sta.ssid_len;
|
||||
} else if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
conf.beacon = beacon;
|
||||
conf.beacon_control = control;
|
||||
ieee80211_start_mesh(dev);
|
||||
} else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
|
||||
conf.ssid = sdata->u.ap.ssid;
|
||||
conf.ssid_len = sdata->u.ap.ssid_len;
|
||||
conf.beacon = beacon;
|
||||
conf.beacon_control = control;
|
||||
}
|
||||
return local->ops->config_interface(local_to_hw(local),
|
||||
&sdata->vif, &conf);
|
||||
@ -1009,23 +1006,21 @@ int ieee80211_if_config(struct net_device *dev)
|
||||
if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT &&
|
||||
(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
|
||||
return ieee80211_if_config_beacon(dev);
|
||||
return __ieee80211_if_config(dev, NULL, NULL);
|
||||
return __ieee80211_if_config(dev, NULL);
|
||||
}
|
||||
|
||||
int ieee80211_if_config_beacon(struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_tx_control control;
|
||||
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
|
||||
return 0;
|
||||
skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif,
|
||||
&control);
|
||||
skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
return __ieee80211_if_config(dev, skb, &control);
|
||||
return __ieee80211_if_config(dev, skb);
|
||||
}
|
||||
|
||||
int ieee80211_hw_config(struct ieee80211_local *local)
|
||||
@ -1180,38 +1175,20 @@ void ieee80211_reset_erp_info(struct net_device *dev)
|
||||
}
|
||||
|
||||
void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_tx_status *saved;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int tmp;
|
||||
|
||||
skb->dev = local->mdev;
|
||||
saved = kmalloc(sizeof(struct ieee80211_tx_status), GFP_ATOMIC);
|
||||
if (unlikely(!saved)) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_WARNING "%s: Not enough memory, "
|
||||
"dropping tx status", skb->dev->name);
|
||||
/* should be dev_kfree_skb_irq, but due to this function being
|
||||
* named _irqsafe instead of just _irq we can't be sure that
|
||||
* people won't call it from non-irq contexts */
|
||||
dev_kfree_skb_any(skb);
|
||||
return;
|
||||
}
|
||||
memcpy(saved, status, sizeof(struct ieee80211_tx_status));
|
||||
/* copy pointer to saved status into skb->cb for use by tasklet */
|
||||
memcpy(skb->cb, &saved, sizeof(saved));
|
||||
|
||||
skb->pkt_type = IEEE80211_TX_STATUS_MSG;
|
||||
skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
|
||||
skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ?
|
||||
&local->skb_queue : &local->skb_queue_unreliable, skb);
|
||||
tmp = skb_queue_len(&local->skb_queue) +
|
||||
skb_queue_len(&local->skb_queue_unreliable);
|
||||
while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
|
||||
(skb = skb_dequeue(&local->skb_queue_unreliable))) {
|
||||
memcpy(&saved, skb->cb, sizeof(saved));
|
||||
kfree(saved);
|
||||
dev_kfree_skb_irq(skb);
|
||||
tmp--;
|
||||
I802_DEBUG_INC(local->tx_status_drop);
|
||||
@ -1225,7 +1202,6 @@ static void ieee80211_tasklet_handler(unsigned long data)
|
||||
struct ieee80211_local *local = (struct ieee80211_local *) data;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct ieee80211_tx_status *tx_status;
|
||||
struct ieee80211_ra_tid *ra_tid;
|
||||
|
||||
while ((skb = skb_dequeue(&local->skb_queue)) ||
|
||||
@ -1240,12 +1216,8 @@ static void ieee80211_tasklet_handler(unsigned long data)
|
||||
__ieee80211_rx(local_to_hw(local), skb, &rx_status);
|
||||
break;
|
||||
case IEEE80211_TX_STATUS_MSG:
|
||||
/* get pointer to saved status out of skb->cb */
|
||||
memcpy(&tx_status, skb->cb, sizeof(tx_status));
|
||||
skb->pkt_type = 0;
|
||||
ieee80211_tx_status(local_to_hw(local),
|
||||
skb, tx_status);
|
||||
kfree(tx_status);
|
||||
ieee80211_tx_status(local_to_hw(local), skb);
|
||||
break;
|
||||
case IEEE80211_DELBA_MSG:
|
||||
ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
|
||||
@ -1274,24 +1246,15 @@ static void ieee80211_tasklet_handler(unsigned long data)
|
||||
* Also, tx_packet_data in cb is restored from tx_control. */
|
||||
static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
|
||||
struct ieee80211_key *key,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int hdrlen, iv_len, mic_len;
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
|
||||
pkt_data->ifindex = vif_to_sdata(control->vif)->dev->ifindex;
|
||||
pkt_data->flags = 0;
|
||||
if (control->flags & IEEE80211_TXCTL_REQ_TX_STATUS)
|
||||
pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
|
||||
if (control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)
|
||||
pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
|
||||
if (control->flags & IEEE80211_TXCTL_REQUEUE)
|
||||
pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
|
||||
if (control->flags & IEEE80211_TXCTL_EAPOL_FRAME)
|
||||
pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
|
||||
pkt_data->queue = control->queue;
|
||||
info->flags &= IEEE80211_TX_CTL_REQ_TX_STATUS |
|
||||
IEEE80211_TX_CTL_DO_NOT_ENCRYPT |
|
||||
IEEE80211_TX_CTL_REQUEUE |
|
||||
IEEE80211_TX_CTL_EAPOL_FRAME;
|
||||
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
|
||||
@ -1338,9 +1301,10 @@ no_key:
|
||||
|
||||
static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
sta->tx_filtered_count++;
|
||||
|
||||
/*
|
||||
@ -1382,18 +1346,16 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
*/
|
||||
if (test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb,
|
||||
&status->control);
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb);
|
||||
skb_queue_tail(&sta->tx_filtered, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
!(status->control.flags & IEEE80211_TXCTL_REQUEUE)) {
|
||||
!(info->flags & IEEE80211_TX_CTL_REQUEUE)) {
|
||||
/* Software retry the packet once */
|
||||
status->control.flags |= IEEE80211_TXCTL_REQUEUE;
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb,
|
||||
&status->control);
|
||||
info->flags |= IEEE80211_TX_CTL_REQUEUE;
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb);
|
||||
dev_queue_xmit(skb);
|
||||
return;
|
||||
}
|
||||
@ -1407,28 +1369,20 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
|
||||
void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status)
|
||||
void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *skb2;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
u16 frag, type;
|
||||
struct ieee80211_tx_status_rtap_hdr *rthdr;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct net_device *prev_dev = NULL;
|
||||
|
||||
if (!status) {
|
||||
printk(KERN_ERR
|
||||
"%s: ieee80211_tx_status called with NULL status\n",
|
||||
wiphy_name(local->hw.wiphy));
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (status->excessive_retries) {
|
||||
if (info->status.excessive_retries) {
|
||||
struct sta_info *sta;
|
||||
sta = sta_info_get(local, hdr->addr1);
|
||||
if (sta) {
|
||||
@ -1437,27 +1391,23 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
* The STA is in power save mode, so assume
|
||||
* that this TX packet failed because of that.
|
||||
*/
|
||||
status->excessive_retries = 0;
|
||||
status->flags |= IEEE80211_TX_STATUS_TX_FILTERED;
|
||||
ieee80211_handle_filtered_frame(local, sta,
|
||||
skb, status);
|
||||
ieee80211_handle_filtered_frame(local, sta, skb);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status->flags & IEEE80211_TX_STATUS_TX_FILTERED) {
|
||||
if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
|
||||
struct sta_info *sta;
|
||||
sta = sta_info_get(local, hdr->addr1);
|
||||
if (sta) {
|
||||
ieee80211_handle_filtered_frame(local, sta, skb,
|
||||
status);
|
||||
ieee80211_handle_filtered_frame(local, sta, skb);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
} else
|
||||
rate_control_tx_status(local->mdev, skb, status);
|
||||
rate_control_tx_status(local->mdev, skb);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -1471,14 +1421,14 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
|
||||
type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
|
||||
|
||||
if (status->flags & IEEE80211_TX_STATUS_ACK) {
|
||||
if (info->flags & IEEE80211_TX_STAT_ACK) {
|
||||
if (frag == 0) {
|
||||
local->dot11TransmittedFrameCount++;
|
||||
if (is_multicast_ether_addr(hdr->addr1))
|
||||
local->dot11MulticastTransmittedFrameCount++;
|
||||
if (status->retry_count > 0)
|
||||
if (info->status.retry_count > 0)
|
||||
local->dot11RetryCount++;
|
||||
if (status->retry_count > 1)
|
||||
if (info->status.retry_count > 1)
|
||||
local->dot11MultipleRetryCount++;
|
||||
}
|
||||
|
||||
@ -1524,17 +1474,17 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
|
||||
(1 << IEEE80211_RADIOTAP_DATA_RETRIES));
|
||||
|
||||
if (!(status->flags & IEEE80211_TX_STATUS_ACK) &&
|
||||
if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
|
||||
!is_multicast_ether_addr(hdr->addr1))
|
||||
rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
|
||||
|
||||
if ((status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) &&
|
||||
(status->control.flags & IEEE80211_TXCTL_USE_CTS_PROTECT))
|
||||
if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) &&
|
||||
(info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
|
||||
rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
|
||||
else if (status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS)
|
||||
else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
|
||||
|
||||
rthdr->data_retries = status->retry_count;
|
||||
rthdr->data_retries = info->status.retry_count;
|
||||
|
||||
/* XXX: is this sufficient for BPF? */
|
||||
skb_set_mac_header(skb, 0);
|
||||
@ -1895,7 +1845,9 @@ static int __init ieee80211_init(void)
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
|
||||
BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb));
|
||||
BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) +
|
||||
IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb));
|
||||
|
||||
ret = rc80211_pid_init();
|
||||
if (ret)
|
||||
|
@ -578,7 +578,7 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
|
||||
int encrypt)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
skb->dev = sdata->local->mdev;
|
||||
@ -586,11 +586,11 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
|
||||
skb_set_network_header(skb, 0);
|
||||
skb_set_transport_header(skb, 0);
|
||||
|
||||
pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
|
||||
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
|
||||
pkt_data->ifindex = sdata->dev->ifindex;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
memset(info, 0, sizeof(struct ieee80211_tx_info));
|
||||
info->control.ifindex = sdata->dev->ifindex;
|
||||
if (!encrypt)
|
||||
pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
|
||||
info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
|
||||
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
@ -2314,7 +2314,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
|
||||
int res, rates, i, j;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct ieee80211_tx_control control;
|
||||
struct ieee80211_tx_info *control;
|
||||
struct rate_selection ratesel;
|
||||
u8 *pos;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
@ -2404,21 +2404,22 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
|
||||
memcpy(pos, &bss->supp_rates[8], rates);
|
||||
}
|
||||
|
||||
memset(&control, 0, sizeof(control));
|
||||
control = IEEE80211_SKB_CB(skb);
|
||||
|
||||
rate_control_get_rate(dev, sband, skb, &ratesel);
|
||||
if (ratesel.rate_idx < 0) {
|
||||
printk(KERN_DEBUG "%s: Failed to determine TX rate "
|
||||
"for IBSS beacon\n", dev->name);
|
||||
break;
|
||||
}
|
||||
control.vif = &sdata->vif;
|
||||
control.tx_rate_idx = ratesel.rate_idx;
|
||||
control->control.vif = &sdata->vif;
|
||||
control->tx_rate_idx = ratesel.rate_idx;
|
||||
if (sdata->bss_conf.use_short_preamble &&
|
||||
sband->bitrates[ratesel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
|
||||
control.flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
|
||||
control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
|
||||
control.flags |= IEEE80211_TXCTL_NO_ACK;
|
||||
control.retry_limit = 1;
|
||||
control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
|
||||
control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
|
||||
control->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
control->control.retry_limit = 1;
|
||||
|
||||
ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
|
||||
if (ifsta->probe_resp) {
|
||||
@ -2433,8 +2434,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
|
||||
}
|
||||
|
||||
if (local->ops->beacon_update &&
|
||||
local->ops->beacon_update(local_to_hw(local),
|
||||
skb, &control) == 0) {
|
||||
local->ops->beacon_update(local_to_hw(local), skb) == 0) {
|
||||
printk(KERN_DEBUG "%s: Configured IBSS beacon "
|
||||
"template\n", dev->name);
|
||||
skb = NULL;
|
||||
|
@ -34,8 +34,7 @@ struct rate_control_ops {
|
||||
struct module *module;
|
||||
const char *name;
|
||||
void (*tx_status)(void *priv, struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status);
|
||||
struct sk_buff *skb);
|
||||
void (*get_rate)(void *priv, struct net_device *dev,
|
||||
struct ieee80211_supported_band *band,
|
||||
struct sk_buff *skb,
|
||||
@ -77,13 +76,12 @@ struct rate_control_ref *rate_control_get(struct rate_control_ref *ref);
|
||||
void rate_control_put(struct rate_control_ref *ref);
|
||||
|
||||
static inline void rate_control_tx_status(struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct rate_control_ref *ref = local->rate_ctrl;
|
||||
|
||||
ref->ops->tx_status(ref->priv, dev, skb, status);
|
||||
ref->ops->tx_status(ref->priv, dev, skb);
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,7 +61,7 @@ enum rc_pid_event_type {
|
||||
union rc_pid_event_data {
|
||||
/* RC_PID_EVENT_TX_STATUS */
|
||||
struct {
|
||||
struct ieee80211_tx_status tx_status;
|
||||
struct ieee80211_tx_info tx_status;
|
||||
};
|
||||
/* RC_PID_EVENT_TYPE_RATE_CHANGE */
|
||||
/* RC_PID_EVENT_TYPE_TX_RATE */
|
||||
@ -158,7 +158,7 @@ struct rc_pid_debugfs_entries {
|
||||
};
|
||||
|
||||
void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
|
||||
struct ieee80211_tx_status *stat);
|
||||
struct ieee80211_tx_info *stat);
|
||||
|
||||
void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf,
|
||||
int index, int rate);
|
||||
|
@ -237,8 +237,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
|
||||
}
|
||||
|
||||
static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_tx_status *status)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
@ -248,6 +247,7 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
|
||||
struct rc_pid_sta_info *spinfo;
|
||||
unsigned long period;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@ -266,28 +266,28 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
|
||||
|
||||
/* Ignore all frames that were sent with a different rate than the rate
|
||||
* we currently advise mac80211 to use. */
|
||||
if (status->control.tx_rate_idx != sta->txrate_idx)
|
||||
if (info->tx_rate_idx != sta->txrate_idx)
|
||||
goto unlock;
|
||||
|
||||
spinfo = sta->rate_ctrl_priv;
|
||||
spinfo->tx_num_xmit++;
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
rate_control_pid_event_tx_status(&spinfo->events, status);
|
||||
rate_control_pid_event_tx_status(&spinfo->events, info);
|
||||
#endif
|
||||
|
||||
/* We count frames that totally failed to be transmitted as two bad
|
||||
* frames, those that made it out but had some retries as one good and
|
||||
* one bad frame. */
|
||||
if (status->excessive_retries) {
|
||||
if (info->status.excessive_retries) {
|
||||
spinfo->tx_num_failed += 2;
|
||||
spinfo->tx_num_xmit++;
|
||||
} else if (status->retry_count) {
|
||||
} else if (info->status.retry_count) {
|
||||
spinfo->tx_num_failed++;
|
||||
spinfo->tx_num_xmit++;
|
||||
}
|
||||
|
||||
if (status->excessive_retries) {
|
||||
if (info->status.excessive_retries) {
|
||||
sta->tx_retry_failed++;
|
||||
sta->tx_num_consecutive_failures++;
|
||||
sta->tx_num_mpdu_fail++;
|
||||
@ -295,8 +295,8 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
|
||||
sta->tx_num_consecutive_failures = 0;
|
||||
sta->tx_num_mpdu_ok++;
|
||||
}
|
||||
sta->tx_retry_count += status->retry_count;
|
||||
sta->tx_num_mpdu_fail += status->retry_count;
|
||||
sta->tx_retry_count += info->status.retry_count;
|
||||
sta->tx_num_mpdu_fail += info->status.retry_count;
|
||||
|
||||
/* Update PID controller state. */
|
||||
period = (HZ * pinfo->sampling_period + 500) / 1000;
|
||||
|
@ -39,11 +39,11 @@ static void rate_control_pid_event(struct rc_pid_event_buffer *buf,
|
||||
}
|
||||
|
||||
void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
|
||||
struct ieee80211_tx_status *stat)
|
||||
struct ieee80211_tx_info *stat)
|
||||
{
|
||||
union rc_pid_event_data evd;
|
||||
|
||||
memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_status));
|
||||
memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info));
|
||||
rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd);
|
||||
}
|
||||
|
||||
@ -167,8 +167,8 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf,
|
||||
switch (ev->type) {
|
||||
case RC_PID_EVENT_TYPE_TX_STATUS:
|
||||
p += snprintf(pb + p, length - p, "tx_status %u %u",
|
||||
ev->data.tx_status.excessive_retries,
|
||||
ev->data.tx_status.retry_count);
|
||||
ev->data.tx_status.status.excessive_retries,
|
||||
ev->data.tx_status.status.retry_count);
|
||||
break;
|
||||
case RC_PID_EVENT_TYPE_RATE_CHANGE:
|
||||
p += snprintf(pb + p, length - p, "rate_change %d %d",
|
||||
|
@ -714,7 +714,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
|
||||
struct sk_buff *skb;
|
||||
int sent = 0;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
sdata = sta->sdata;
|
||||
@ -734,13 +734,13 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
|
||||
|
||||
/* Send all buffered frames to the station */
|
||||
while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
|
||||
pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
sent++;
|
||||
pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
|
||||
info->flags |= IEEE80211_TX_CTL_REQUEUE;
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
|
||||
pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
local->total_ps_buffered--;
|
||||
sent++;
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
@ -748,7 +748,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
|
||||
"since STA not sleeping anymore\n", dev->name,
|
||||
print_mac(mac, sta->addr), sta->aid);
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||
pkt_data->flags |= IEEE80211_TXPD_REQUEUE;
|
||||
info->flags |= IEEE80211_TX_CTL_REQUEUE;
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
|
||||
|
@ -511,20 +511,20 @@ static inline int sta_info_buffer_expired(struct ieee80211_local *local,
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info;
|
||||
int timeout;
|
||||
|
||||
if (!skb)
|
||||
return 0;
|
||||
|
||||
pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
/* Timeout: (2 * listen_interval * beacon_int * 1024 / 1000000) sec */
|
||||
timeout = (sta->listen_interval * local->hw.conf.beacon_int * 32 /
|
||||
15625) * HZ;
|
||||
if (timeout < STA_TX_BUFFER_EXPIRE)
|
||||
timeout = STA_TX_BUFFER_EXPIRE;
|
||||
return time_after(jiffies, pkt_data->jiffies + timeout);
|
||||
return time_after(jiffies, info->control.jiffies + timeout);
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
* @WLAN_STA_WDS: Station is one of our WDS peers.
|
||||
* @WLAN_STA_PSPOLL: Station has just PS-polled us.
|
||||
* @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
|
||||
* IEEE80211_TXCTL_CLEAR_PS_FILT control flag) when the next
|
||||
* IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
|
||||
* frame to this station is transmitted.
|
||||
*/
|
||||
enum ieee80211_sta_info_flags {
|
||||
|
@ -238,12 +238,12 @@ static ieee80211_tx_result
|
||||
ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
||||
struct sk_buff *skb = tx->skb;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
u32 sta_flags;
|
||||
|
||||
if (unlikely(tx->flags & IEEE80211_TX_INJECTED))
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
|
||||
return TX_CONTINUE;
|
||||
|
||||
if (unlikely(tx->local->sta_sw_scanning) &&
|
||||
@ -348,6 +348,8 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
|
||||
static ieee80211_tx_result
|
||||
ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
|
||||
/*
|
||||
* broadcast/multicast frame
|
||||
*
|
||||
@ -383,7 +385,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
}
|
||||
|
||||
/* buffered in hardware */
|
||||
tx->control->flags |= IEEE80211_TXCTL_SEND_AFTER_DTIM;
|
||||
info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
|
||||
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
@ -392,6 +394,7 @@ static ieee80211_tx_result
|
||||
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct sta_info *sta = tx->sta;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
u32 staflags;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
@ -404,7 +407,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
|
||||
if (unlikely((staflags & WLAN_STA_PS) &&
|
||||
!(staflags & WLAN_STA_PSPOLL))) {
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries "
|
||||
"before %d)\n",
|
||||
@ -428,8 +430,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
if (skb_queue_empty(&sta->ps_tx_buf))
|
||||
sta_info_set_tim_bit(sta);
|
||||
|
||||
pkt_data = (struct ieee80211_tx_packet_data *)tx->skb->cb;
|
||||
pkt_data->jiffies = jiffies;
|
||||
info->control.jiffies = jiffies;
|
||||
skb_queue_tail(&sta->ps_tx_buf, tx->skb);
|
||||
return TX_QUEUED;
|
||||
}
|
||||
@ -461,17 +462,18 @@ static ieee80211_tx_result
|
||||
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct ieee80211_key *key;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
u16 fc = tx->fc;
|
||||
|
||||
if (unlikely(tx->control->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT))
|
||||
tx->key = NULL;
|
||||
else if (tx->sta && (key = rcu_dereference(tx->sta->key)))
|
||||
tx->key = key;
|
||||
else if ((key = rcu_dereference(tx->sdata->default_key)))
|
||||
tx->key = key;
|
||||
else if (tx->sdata->drop_unencrypted &&
|
||||
!(tx->control->flags & IEEE80211_TXCTL_EAPOL_FRAME) &&
|
||||
!(tx->flags & IEEE80211_TX_INJECTED)) {
|
||||
!(info->flags & IEEE80211_TX_CTL_EAPOL_FRAME) &&
|
||||
!(info->flags & IEEE80211_TX_CTL_INJECTED)) {
|
||||
I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
|
||||
return TX_DROP;
|
||||
} else
|
||||
@ -500,7 +502,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
|
||||
}
|
||||
|
||||
if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
|
||||
tx->control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
|
||||
info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
|
||||
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
@ -510,6 +512,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct rate_selection rsel;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
|
||||
sband = tx->local->hw.wiphy->bands[tx->channel->band];
|
||||
|
||||
@ -517,18 +520,17 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
||||
rate_control_get_rate(tx->dev, sband, tx->skb, &rsel);
|
||||
tx->rate_idx = rsel.rate_idx;
|
||||
if (unlikely(rsel.probe_idx >= 0)) {
|
||||
tx->control->flags |=
|
||||
IEEE80211_TXCTL_RATE_CTRL_PROBE;
|
||||
info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
|
||||
tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
|
||||
tx->control->alt_retry_rate_idx = tx->rate_idx;
|
||||
info->control.alt_retry_rate_idx = tx->rate_idx;
|
||||
tx->rate_idx = rsel.probe_idx;
|
||||
} else
|
||||
tx->control->alt_retry_rate_idx = -1;
|
||||
info->control.alt_retry_rate_idx = -1;
|
||||
|
||||
if (unlikely(tx->rate_idx < 0))
|
||||
return TX_DROP;
|
||||
} else
|
||||
tx->control->alt_retry_rate_idx = -1;
|
||||
info->control.alt_retry_rate_idx = -1;
|
||||
|
||||
if (tx->sdata->bss_conf.use_cts_prot &&
|
||||
(tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) {
|
||||
@ -538,13 +540,13 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
|
||||
else
|
||||
tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG;
|
||||
tx->rate_idx = rsel.nonerp_idx;
|
||||
tx->control->tx_rate_idx = rsel.nonerp_idx;
|
||||
tx->control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
|
||||
info->tx_rate_idx = rsel.nonerp_idx;
|
||||
info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
|
||||
} else {
|
||||
tx->last_frag_rate_idx = tx->rate_idx;
|
||||
tx->control->tx_rate_idx = tx->rate_idx;
|
||||
info->tx_rate_idx = tx->rate_idx;
|
||||
}
|
||||
tx->control->tx_rate_idx = tx->rate_idx;
|
||||
info->tx_rate_idx = tx->rate_idx;
|
||||
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
@ -555,28 +557,32 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
|
||||
u16 fc = le16_to_cpu(hdr->frame_control);
|
||||
u16 dur;
|
||||
struct ieee80211_tx_control *control = tx->control;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
struct ieee80211_supported_band *sband;
|
||||
|
||||
sband = tx->local->hw.wiphy->bands[tx->channel->band];
|
||||
|
||||
if (!control->retry_limit) {
|
||||
if (tx->sta)
|
||||
info->control.aid = tx->sta->aid;
|
||||
|
||||
if (!info->control.retry_limit) {
|
||||
if (!is_multicast_ether_addr(hdr->addr1)) {
|
||||
if (tx->skb->len + FCS_LEN > tx->local->rts_threshold
|
||||
int len = min_t(int, tx->skb->len + FCS_LEN,
|
||||
tx->local->fragmentation_threshold);
|
||||
if (len > tx->local->rts_threshold
|
||||
&& tx->local->rts_threshold <
|
||||
IEEE80211_MAX_RTS_THRESHOLD) {
|
||||
control->flags |=
|
||||
IEEE80211_TXCTL_USE_RTS_CTS;
|
||||
control->flags |=
|
||||
IEEE80211_TXCTL_LONG_RETRY_LIMIT;
|
||||
control->retry_limit =
|
||||
IEEE80211_MAX_RTS_THRESHOLD) {
|
||||
info->flags |= IEEE80211_TX_CTL_USE_RTS_CTS;
|
||||
info->flags |=
|
||||
IEEE80211_TX_CTL_LONG_RETRY_LIMIT;
|
||||
info->control.retry_limit =
|
||||
tx->local->long_retry_limit;
|
||||
} else {
|
||||
control->retry_limit =
|
||||
info->control.retry_limit =
|
||||
tx->local->short_retry_limit;
|
||||
}
|
||||
} else {
|
||||
control->retry_limit = 1;
|
||||
info->control.retry_limit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +591,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
||||
* frames.
|
||||
* TODO: The last fragment could still use multiple retry
|
||||
* rates. */
|
||||
control->alt_retry_rate_idx = -1;
|
||||
info->control.alt_retry_rate_idx = -1;
|
||||
}
|
||||
|
||||
/* Use CTS protection for unicast frames sent using extended rates if
|
||||
@ -595,8 +601,8 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
||||
(sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) &&
|
||||
(tx->flags & IEEE80211_TX_UNICAST) &&
|
||||
tx->sdata->bss_conf.use_cts_prot &&
|
||||
!(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
|
||||
control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
|
||||
!(info->flags & IEEE80211_TX_CTL_USE_RTS_CTS))
|
||||
info->flags |= IEEE80211_TX_CTL_USE_CTS_PROTECT;
|
||||
|
||||
/* Transmit data frames using short preambles if the driver supports
|
||||
* short preambles at the selected rate and short preambles are
|
||||
@ -605,7 +611,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
||||
(sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) &&
|
||||
tx->sdata->bss_conf.use_short_preamble &&
|
||||
(!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) {
|
||||
tx->control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
|
||||
info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
|
||||
}
|
||||
|
||||
/* Setup duration field for the first fragment of the frame. Duration
|
||||
@ -616,8 +622,8 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
||||
tx->extra_frag[0]->len : 0);
|
||||
hdr->duration_id = cpu_to_le16(dur);
|
||||
|
||||
if ((control->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
|
||||
(control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
|
||||
if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
|
||||
(info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_rate *rate;
|
||||
s8 baserate = -1;
|
||||
@ -626,7 +632,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
||||
sband = tx->local->hw.wiphy->bands[tx->channel->band];
|
||||
|
||||
/* Do not use multiple retry rates when using RTS/CTS */
|
||||
control->alt_retry_rate_idx = -1;
|
||||
info->control.alt_retry_rate_idx = -1;
|
||||
|
||||
/* Use min(data rate, max base rate) as CTS/RTS rate */
|
||||
rate = &sband->bitrates[tx->rate_idx];
|
||||
@ -642,13 +648,13 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
|
||||
}
|
||||
|
||||
if (baserate >= 0)
|
||||
control->rts_cts_rate_idx = baserate;
|
||||
info->control.rts_cts_rate_idx = baserate;
|
||||
else
|
||||
control->rts_cts_rate_idx = 0;
|
||||
info->control.rts_cts_rate_idx = 0;
|
||||
}
|
||||
|
||||
if (tx->sta)
|
||||
control->aid = tx->sta->aid;
|
||||
info->control.aid = tx->sta->aid;
|
||||
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
@ -762,6 +768,7 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
|
||||
u32 load = 0, hdrtime;
|
||||
struct ieee80211_rate *rate;
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
sband = tx->local->hw.wiphy->bands[tx->channel->band];
|
||||
rate = &sband->bitrates[tx->rate_idx];
|
||||
@ -786,9 +793,9 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
|
||||
if (!is_multicast_ether_addr(hdr->addr1))
|
||||
load += hdrtime;
|
||||
|
||||
if (tx->control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
|
||||
if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
|
||||
load += 2 * hdrtime;
|
||||
else if (tx->control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
|
||||
else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
|
||||
load += hdrtime;
|
||||
|
||||
/* TODO: optimise again */
|
||||
@ -839,6 +846,7 @@ static ieee80211_tx_handler ieee80211_tx_handlers[] =
|
||||
ieee80211_tx_h_rate_ctrl,
|
||||
ieee80211_tx_h_misc,
|
||||
ieee80211_tx_h_fragment,
|
||||
/* handlers after fragment must be aware of tx info fragmentation! */
|
||||
ieee80211_tx_h_encrypt,
|
||||
ieee80211_tx_h_stats,
|
||||
NULL
|
||||
@ -867,12 +875,12 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
(struct ieee80211_radiotap_header *) skb->data;
|
||||
struct ieee80211_supported_band *sband;
|
||||
int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len);
|
||||
struct ieee80211_tx_control *control = tx->control;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
sband = tx->local->hw.wiphy->bands[tx->channel->band];
|
||||
|
||||
control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
|
||||
tx->flags |= IEEE80211_TX_INJECTED;
|
||||
info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
|
||||
info->flags |= IEEE80211_TX_CTL_INJECTED;
|
||||
tx->flags &= ~IEEE80211_TX_FRAGMENTED;
|
||||
|
||||
/*
|
||||
@ -920,7 +928,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
* radiotap uses 0 for 1st ant, mac80211 is 1 for
|
||||
* 1st ant
|
||||
*/
|
||||
control->antenna_sel_tx = (*iterator.this_arg) + 1;
|
||||
info->antenna_sel_tx = (*iterator.this_arg) + 1;
|
||||
break;
|
||||
|
||||
#if 0
|
||||
@ -944,8 +952,8 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
skb_trim(skb, skb->len - FCS_LEN);
|
||||
}
|
||||
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_WEP)
|
||||
control->flags &=
|
||||
~IEEE80211_TXCTL_DO_NOT_ENCRYPT;
|
||||
info->flags &=
|
||||
~IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
|
||||
if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FRAG)
|
||||
tx->flags |= IEEE80211_TX_FRAGMENTED;
|
||||
break;
|
||||
@ -980,12 +988,12 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
static ieee80211_tx_result
|
||||
__ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
int hdrlen;
|
||||
|
||||
@ -994,7 +1002,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
tx->dev = dev; /* use original interface */
|
||||
tx->local = local;
|
||||
tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
tx->control = control;
|
||||
tx->channel = local->hw.conf.channel;
|
||||
/*
|
||||
* Set this flag (used below to indicate "automatic fragmentation"),
|
||||
* it will be cleared/left by radiotap as desired.
|
||||
@ -1021,10 +1029,10 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
|
||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
tx->flags &= ~IEEE80211_TX_UNICAST;
|
||||
control->flags |= IEEE80211_TXCTL_NO_ACK;
|
||||
info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
} else {
|
||||
tx->flags |= IEEE80211_TX_UNICAST;
|
||||
control->flags &= ~IEEE80211_TXCTL_NO_ACK;
|
||||
info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
|
||||
}
|
||||
|
||||
if (tx->flags & IEEE80211_TX_FRAGMENTED) {
|
||||
@ -1037,16 +1045,16 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
}
|
||||
|
||||
if (!tx->sta)
|
||||
control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
|
||||
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||
else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT))
|
||||
control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
|
||||
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||
|
||||
hdrlen = ieee80211_get_hdrlen(tx->fc);
|
||||
if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) {
|
||||
u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)];
|
||||
tx->ethertype = (pos[0] << 8) | pos[1];
|
||||
}
|
||||
control->flags |= IEEE80211_TXCTL_FIRST_FRAGMENT;
|
||||
info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
|
||||
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
@ -1056,14 +1064,12 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
*/
|
||||
static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb,
|
||||
struct net_device *mdev,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct net_device *mdev)
|
||||
{
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct net_device *dev;
|
||||
|
||||
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
|
||||
dev = dev_get_by_index(&init_net, pkt_data->ifindex);
|
||||
dev = dev_get_by_index(&init_net, info->control.ifindex);
|
||||
if (unlikely(dev && !is_ieee80211_device(dev, mdev))) {
|
||||
dev_put(dev);
|
||||
dev = NULL;
|
||||
@ -1071,7 +1077,7 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
if (unlikely(!dev))
|
||||
return -ENODEV;
|
||||
/* initialises tx with control */
|
||||
__ieee80211_tx_prepare(tx, skb, dev, control);
|
||||
__ieee80211_tx_prepare(tx, skb, dev);
|
||||
dev_put(dev);
|
||||
return 0;
|
||||
}
|
||||
@ -1079,7 +1085,7 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
|
||||
struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct ieee80211_tx_control *control = tx->control;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int ret, i;
|
||||
|
||||
if (!ieee80211_qdisc_installed(local->mdev) &&
|
||||
@ -1090,39 +1096,39 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
|
||||
if (skb) {
|
||||
ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
|
||||
"TX to low-level driver", skb);
|
||||
ret = local->ops->tx(local_to_hw(local), skb, control);
|
||||
ret = local->ops->tx(local_to_hw(local), skb);
|
||||
if (ret)
|
||||
return IEEE80211_TX_AGAIN;
|
||||
local->mdev->trans_start = jiffies;
|
||||
ieee80211_led_tx(local, 1);
|
||||
}
|
||||
if (tx->extra_frag) {
|
||||
control->flags &= ~(IEEE80211_TXCTL_USE_RTS_CTS |
|
||||
IEEE80211_TXCTL_USE_CTS_PROTECT |
|
||||
IEEE80211_TXCTL_CLEAR_PS_FILT |
|
||||
IEEE80211_TXCTL_FIRST_FRAGMENT);
|
||||
for (i = 0; i < tx->num_extra_frag; i++) {
|
||||
if (!tx->extra_frag[i])
|
||||
continue;
|
||||
if (__ieee80211_queue_stopped(local, control->queue))
|
||||
info = IEEE80211_SKB_CB(tx->extra_frag[i]);
|
||||
info->flags &= ~(IEEE80211_TX_CTL_USE_RTS_CTS |
|
||||
IEEE80211_TX_CTL_USE_CTS_PROTECT |
|
||||
IEEE80211_TX_CTL_CLEAR_PS_FILT |
|
||||
IEEE80211_TX_CTL_FIRST_FRAGMENT);
|
||||
if (__ieee80211_queue_stopped(local, info->queue))
|
||||
return IEEE80211_TX_FRAG_AGAIN;
|
||||
if (i == tx->num_extra_frag) {
|
||||
control->tx_rate_idx = tx->last_frag_rate_idx;
|
||||
info->tx_rate_idx = tx->last_frag_rate_idx;
|
||||
|
||||
if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG)
|
||||
control->flags |=
|
||||
IEEE80211_TXCTL_RATE_CTRL_PROBE;
|
||||
info->flags |=
|
||||
IEEE80211_TX_CTL_RATE_CTRL_PROBE;
|
||||
else
|
||||
control->flags &=
|
||||
~IEEE80211_TXCTL_RATE_CTRL_PROBE;
|
||||
info->flags &=
|
||||
~IEEE80211_TX_CTL_RATE_CTRL_PROBE;
|
||||
}
|
||||
|
||||
ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
|
||||
"TX to low-level driver",
|
||||
tx->extra_frag[i]);
|
||||
ret = local->ops->tx(local_to_hw(local),
|
||||
tx->extra_frag[i],
|
||||
control);
|
||||
tx->extra_frag[i]);
|
||||
if (ret)
|
||||
return IEEE80211_TX_FRAG_AGAIN;
|
||||
local->mdev->trans_start = jiffies;
|
||||
@ -1135,17 +1141,18 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
|
||||
return IEEE80211_TX_OK;
|
||||
}
|
||||
|
||||
static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
|
||||
struct ieee80211_tx_control *control)
|
||||
static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct sta_info *sta;
|
||||
ieee80211_tx_handler *handler;
|
||||
struct ieee80211_tx_data tx;
|
||||
ieee80211_tx_result res = TX_DROP, res_prepare;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int ret, i;
|
||||
int queue = info->queue;
|
||||
|
||||
WARN_ON(__ieee80211_queue_pending(local, control->queue));
|
||||
WARN_ON(__ieee80211_queue_pending(local, queue));
|
||||
|
||||
if (unlikely(skb->len < 10)) {
|
||||
dev_kfree_skb(skb);
|
||||
@ -1155,7 +1162,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
|
||||
rcu_read_lock();
|
||||
|
||||
/* initialises tx */
|
||||
res_prepare = __ieee80211_tx_prepare(&tx, skb, dev, control);
|
||||
res_prepare = __ieee80211_tx_prepare(&tx, skb, dev);
|
||||
|
||||
if (res_prepare == TX_DROP) {
|
||||
dev_kfree_skb(skb);
|
||||
@ -1165,7 +1172,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
|
||||
|
||||
sta = tx.sta;
|
||||
tx.channel = local->hw.conf.channel;
|
||||
control->band = tx.channel->band;
|
||||
info->band = tx.channel->band;
|
||||
|
||||
for (handler = ieee80211_tx_handlers; *handler != NULL;
|
||||
handler++) {
|
||||
@ -1174,7 +1181,8 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
|
||||
break;
|
||||
}
|
||||
|
||||
skb = tx.skb; /* handlers are allowed to change skb */
|
||||
if (WARN_ON(tx.skb != skb))
|
||||
goto drop;
|
||||
|
||||
if (unlikely(res == TX_DROP)) {
|
||||
I802_DEBUG_INC(local->tx_handlers_drop);
|
||||
@ -1209,12 +1217,12 @@ retry:
|
||||
ret = __ieee80211_tx(local, skb, &tx);
|
||||
if (ret) {
|
||||
struct ieee80211_tx_stored_packet *store =
|
||||
&local->pending_packet[control->queue];
|
||||
&local->pending_packet[info->queue];
|
||||
|
||||
if (ret == IEEE80211_TX_FRAG_AGAIN)
|
||||
skb = NULL;
|
||||
set_bit(IEEE80211_LINK_STATE_PENDING,
|
||||
&local->state[control->queue]);
|
||||
&local->state[queue]);
|
||||
smp_mb();
|
||||
/* When the driver gets out of buffers during sending of
|
||||
* fragments and calls ieee80211_stop_queue, there is
|
||||
@ -1225,13 +1233,11 @@ retry:
|
||||
* called with IEEE80211_LINK_STATE_PENDING. Prevent this by
|
||||
* continuing transmitting here when that situation is
|
||||
* possible to have happened. */
|
||||
if (!__ieee80211_queue_stopped(local, control->queue)) {
|
||||
if (!__ieee80211_queue_stopped(local, queue)) {
|
||||
clear_bit(IEEE80211_LINK_STATE_PENDING,
|
||||
&local->state[control->queue]);
|
||||
&local->state[queue]);
|
||||
goto retry;
|
||||
}
|
||||
memcpy(&store->control, control,
|
||||
sizeof(struct ieee80211_tx_control));
|
||||
store->skb = skb;
|
||||
store->extra_frag = tx.extra_frag;
|
||||
store->num_extra_frag = tx.num_extra_frag;
|
||||
@ -1258,21 +1264,14 @@ retry:
|
||||
int ieee80211_master_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_tx_control control;
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct net_device *odev = NULL;
|
||||
struct ieee80211_sub_if_data *osdata;
|
||||
int headroom;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* copy control out of the skb so other people can use skb->cb
|
||||
*/
|
||||
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
|
||||
memset(&control, 0, sizeof(struct ieee80211_tx_control));
|
||||
|
||||
if (pkt_data->ifindex)
|
||||
odev = dev_get_by_index(&init_net, pkt_data->ifindex);
|
||||
if (info->control.ifindex)
|
||||
odev = dev_get_by_index(&init_net, info->control.ifindex);
|
||||
if (unlikely(odev && !is_ieee80211_device(odev, dev))) {
|
||||
dev_put(odev);
|
||||
odev = NULL;
|
||||
@ -1285,6 +1284,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
osdata = IEEE80211_DEV_TO_SUB_IF(odev);
|
||||
|
||||
headroom = osdata->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM;
|
||||
@ -1296,21 +1296,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
control.vif = &osdata->vif;
|
||||
control.type = osdata->vif.type;
|
||||
if (pkt_data->flags & IEEE80211_TXPD_REQ_TX_STATUS)
|
||||
control.flags |= IEEE80211_TXCTL_REQ_TX_STATUS;
|
||||
if (pkt_data->flags & IEEE80211_TXPD_DO_NOT_ENCRYPT)
|
||||
control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
|
||||
if (pkt_data->flags & IEEE80211_TXPD_REQUEUE)
|
||||
control.flags |= IEEE80211_TXCTL_REQUEUE;
|
||||
if (pkt_data->flags & IEEE80211_TXPD_EAPOL_FRAME)
|
||||
control.flags |= IEEE80211_TXCTL_EAPOL_FRAME;
|
||||
if (pkt_data->flags & IEEE80211_TXPD_AMPDU)
|
||||
control.flags |= IEEE80211_TXCTL_AMPDU;
|
||||
control.queue = pkt_data->queue;
|
||||
|
||||
ret = ieee80211_tx(odev, skb, &control);
|
||||
info->control.vif = &osdata->vif;
|
||||
ret = ieee80211_tx(odev, skb);
|
||||
dev_put(odev);
|
||||
|
||||
return ret;
|
||||
@ -1320,7 +1307,7 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_radiotap_header *prthdr =
|
||||
(struct ieee80211_radiotap_header *)skb->data;
|
||||
u16 len_rthdr;
|
||||
@ -1342,14 +1329,12 @@ int ieee80211_monitor_start_xmit(struct sk_buff *skb,
|
||||
|
||||
skb->dev = local->mdev;
|
||||
|
||||
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
|
||||
memset(pkt_data, 0, sizeof(*pkt_data));
|
||||
/* needed because we set skb device to master */
|
||||
pkt_data->ifindex = dev->ifindex;
|
||||
info->control.ifindex = dev->ifindex;
|
||||
|
||||
pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
|
||||
info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
|
||||
/* Interfaces should always request a status report */
|
||||
pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
|
||||
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
|
||||
/*
|
||||
* fix up the pointers accounting for the radiotap
|
||||
@ -1393,7 +1378,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
|
||||
struct ieee80211_tx_packet_data *pkt_data;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
int ret = 1, head_need;
|
||||
u16 ethertype, hdrlen, meshhdrlen = 0, fc;
|
||||
@ -1625,14 +1610,14 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
nh_pos += hdrlen;
|
||||
h_pos += hdrlen;
|
||||
|
||||
pkt_data = (struct ieee80211_tx_packet_data *)skb->cb;
|
||||
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
|
||||
pkt_data->ifindex = dev->ifindex;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->control.ifindex = dev->ifindex;
|
||||
if (ethertype == ETH_P_PAE)
|
||||
pkt_data->flags |= IEEE80211_TXPD_EAPOL_FRAME;
|
||||
info->flags |= IEEE80211_TX_CTL_EAPOL_FRAME;
|
||||
|
||||
/* Interfaces should always request a status report */
|
||||
pkt_data->flags |= IEEE80211_TXPD_REQ_TX_STATUS;
|
||||
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
|
||||
skb->dev = local->mdev;
|
||||
dev->stats.tx_packets++;
|
||||
@ -1693,7 +1678,6 @@ void ieee80211_tx_pending(unsigned long data)
|
||||
continue;
|
||||
}
|
||||
store = &local->pending_packet[i];
|
||||
tx.control = &store->control;
|
||||
tx.extra_frag = store->extra_frag;
|
||||
tx.num_extra_frag = store->num_extra_frag;
|
||||
tx.last_frag_rate_idx = store->last_frag_rate_idx;
|
||||
@ -1786,11 +1770,11 @@ static void ieee80211_beacon_add_tim(struct ieee80211_local *local,
|
||||
}
|
||||
|
||||
struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct net_device *bdev;
|
||||
struct ieee80211_sub_if_data *sdata = NULL;
|
||||
struct ieee80211_if_ap *ap = NULL;
|
||||
@ -1896,31 +1880,32 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (control) {
|
||||
control->band = band;
|
||||
rate_control_get_rate(local->mdev, sband, skb, &rsel);
|
||||
if (unlikely(rsel.rate_idx < 0)) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
|
||||
"no rate found\n",
|
||||
wiphy_name(local->hw.wiphy));
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
skb = NULL;
|
||||
goto out;
|
||||
}
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
control->vif = vif;
|
||||
control->tx_rate_idx = rsel.rate_idx;
|
||||
if (sdata->bss_conf.use_short_preamble &&
|
||||
sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
|
||||
control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE;
|
||||
control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
|
||||
control->flags |= IEEE80211_TXCTL_NO_ACK;
|
||||
control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
|
||||
control->retry_limit = 1;
|
||||
control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT;
|
||||
info->band = band;
|
||||
rate_control_get_rate(local->mdev, sband, skb, &rsel);
|
||||
|
||||
if (unlikely(rsel.rate_idx < 0)) {
|
||||
if (net_ratelimit()) {
|
||||
printk(KERN_DEBUG "%s: ieee80211_beacon_get: "
|
||||
"no rate found\n",
|
||||
wiphy_name(local->hw.wiphy));
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
skb = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info->control.vif = vif;
|
||||
info->tx_rate_idx = rsel.rate_idx;
|
||||
if (sdata->bss_conf.use_short_preamble &&
|
||||
sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
|
||||
info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
|
||||
info->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
|
||||
info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||
info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
|
||||
info->control.retry_limit = 1;
|
||||
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
|
||||
(*num_beacons)++;
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
@ -1930,7 +1915,7 @@ EXPORT_SYMBOL(ieee80211_beacon_get);
|
||||
|
||||
void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const void *frame, size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl,
|
||||
const struct ieee80211_tx_info *frame_txctl,
|
||||
struct ieee80211_rts *rts)
|
||||
{
|
||||
const struct ieee80211_hdr *hdr = frame;
|
||||
@ -1947,7 +1932,7 @@ EXPORT_SYMBOL(ieee80211_rts_get);
|
||||
|
||||
void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
const void *frame, size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl,
|
||||
const struct ieee80211_tx_info *frame_txctl,
|
||||
struct ieee80211_cts *cts)
|
||||
{
|
||||
const struct ieee80211_hdr *hdr = frame;
|
||||
@ -1963,8 +1948,7 @@ EXPORT_SYMBOL(ieee80211_ctstoself_get);
|
||||
|
||||
struct sk_buff *
|
||||
ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_tx_control *control)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct sk_buff *skb;
|
||||
@ -1976,6 +1960,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_if_ap *bss = NULL;
|
||||
struct beacon_data *beacon;
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
sdata = vif_to_sdata(vif);
|
||||
bdev = sdata->dev;
|
||||
@ -1995,7 +1980,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
|
||||
|
||||
if (bss->dtim_count != 0)
|
||||
return NULL; /* send buffered bc/mc only after DTIM beacon */
|
||||
memset(control, 0, sizeof(*control));
|
||||
|
||||
while (1) {
|
||||
skb = skb_dequeue(&bss->ps_bc_buf);
|
||||
if (!skb)
|
||||
@ -2012,21 +1997,26 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
|
||||
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
|
||||
}
|
||||
|
||||
if (!ieee80211_tx_prepare(&tx, skb, local->mdev, control))
|
||||
if (!ieee80211_tx_prepare(&tx, skb, local->mdev))
|
||||
break;
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
sta = tx.sta;
|
||||
tx.flags |= IEEE80211_TX_PS_BUFFERED;
|
||||
tx.channel = local->hw.conf.channel;
|
||||
control->band = tx.channel->band;
|
||||
info->band = tx.channel->band;
|
||||
|
||||
for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) {
|
||||
res = (*handler)(&tx);
|
||||
if (res == TX_DROP || res == TX_QUEUED)
|
||||
break;
|
||||
}
|
||||
skb = tx.skb; /* handlers are allowed to change skb */
|
||||
|
||||
if (WARN_ON(tx.skb != skb))
|
||||
return NULL;
|
||||
|
||||
if (res == TX_DROP) {
|
||||
I802_DEBUG_INC(local->tx_handlers_drop);
|
||||
|
@ -258,7 +258,7 @@ EXPORT_SYMBOL(ieee80211_generic_frame_duration);
|
||||
|
||||
__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl)
|
||||
const struct ieee80211_tx_info *frame_txctl)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_rate *rate;
|
||||
@ -272,7 +272,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
|
||||
|
||||
short_preamble = sdata->bss_conf.use_short_preamble;
|
||||
|
||||
rate = &sband->bitrates[frame_txctl->rts_cts_rate_idx];
|
||||
rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
|
||||
|
||||
erp = 0;
|
||||
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
|
||||
@ -295,7 +295,7 @@ EXPORT_SYMBOL(ieee80211_rts_duration);
|
||||
__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
size_t frame_len,
|
||||
const struct ieee80211_tx_control *frame_txctl)
|
||||
const struct ieee80211_tx_info *frame_txctl)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_rate *rate;
|
||||
@ -309,7 +309,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
|
||||
|
||||
short_preamble = sdata->bss_conf.use_short_preamble;
|
||||
|
||||
rate = &sband->bitrates[frame_txctl->rts_cts_rate_idx];
|
||||
rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
|
||||
erp = 0;
|
||||
if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
|
||||
erp = rate->flags & IEEE80211_RATE_ERP_G;
|
||||
@ -317,7 +317,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
|
||||
/* Data frame duration */
|
||||
dur = ieee80211_frame_duration(local, frame_len, rate->bitrate,
|
||||
erp, short_preamble);
|
||||
if (!(frame_txctl->flags & IEEE80211_TXCTL_NO_ACK)) {
|
||||
if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
/* ACK duration */
|
||||
dur += ieee80211_frame_duration(local, 10, rate->bitrate,
|
||||
erp, short_preamble);
|
||||
|
@ -333,11 +333,16 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
|
||||
|
||||
static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
info->control.iv_len = WEP_IV_LEN;
|
||||
info->control.icv_len = WEP_ICV_LEN;
|
||||
|
||||
if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
|
||||
info->control.hw_key = &tx->key->conf;
|
||||
if (ieee80211_wep_encrypt(tx->local, skb, tx->key))
|
||||
return -1;
|
||||
} else {
|
||||
tx->control->hw_key = &tx->key->conf;
|
||||
if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
|
||||
if (!ieee80211_wep_add_iv(tx->local, skb, tx->key))
|
||||
return -1;
|
||||
@ -349,8 +354,6 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
||||
ieee80211_tx_result
|
||||
ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
tx->control->iv_len = WEP_IV_LEN;
|
||||
tx->control->icv_len = WEP_ICV_LEN;
|
||||
ieee80211_tx_set_protected(tx);
|
||||
|
||||
if (wep_encrypt_skb(tx, tx->skb) < 0) {
|
||||
|
@ -149,8 +149,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
|
||||
struct ieee80211_local *local = wdev_priv(qd->dev->ieee80211_ptr);
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
struct ieee80211_sched_data *q = qdisc_priv(qd);
|
||||
struct ieee80211_tx_packet_data *pkt_data =
|
||||
(struct ieee80211_tx_packet_data *) skb->cb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
unsigned short fc = le16_to_cpu(hdr->frame_control);
|
||||
struct Qdisc *qdisc;
|
||||
@ -158,8 +157,8 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
|
||||
int err, queue;
|
||||
u8 tid;
|
||||
|
||||
if (pkt_data->flags & IEEE80211_TXPD_REQUEUE) {
|
||||
queue = pkt_data->queue;
|
||||
if (info->flags & IEEE80211_TX_CTL_REQUEUE) {
|
||||
queue = info->queue;
|
||||
rcu_read_lock();
|
||||
sta = sta_info_get(local, hdr->addr1);
|
||||
tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
|
||||
@ -168,9 +167,9 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
|
||||
if ((ampdu_queue < QD_NUM(hw)) &&
|
||||
test_bit(ampdu_queue, q->qdisc_pool)) {
|
||||
queue = ampdu_queue;
|
||||
pkt_data->flags |= IEEE80211_TXPD_AMPDU;
|
||||
info->flags |= IEEE80211_TX_CTL_AMPDU;
|
||||
} else {
|
||||
pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@ -206,9 +205,9 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
|
||||
if ((ampdu_queue < QD_NUM(hw)) &&
|
||||
test_bit(ampdu_queue, q->qdisc_pool)) {
|
||||
queue = ampdu_queue;
|
||||
pkt_data->flags |= IEEE80211_TXPD_AMPDU;
|
||||
info->flags |= IEEE80211_TX_CTL_AMPDU;
|
||||
} else {
|
||||
pkt_data->flags &= ~IEEE80211_TXPD_AMPDU;
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +219,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
|
||||
err = NET_XMIT_DROP;
|
||||
} else {
|
||||
tid = skb->priority & QOS_CONTROL_TAG1D_MASK;
|
||||
pkt_data->queue = (unsigned int) queue;
|
||||
info->queue = (unsigned int) queue;
|
||||
qdisc = q->queues[queue];
|
||||
err = qdisc->enqueue(skb, qdisc);
|
||||
if (err == NET_XMIT_SUCCESS) {
|
||||
@ -241,13 +240,12 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
|
||||
static int wme_qdiscop_requeue(struct sk_buff *skb, struct Qdisc* qd)
|
||||
{
|
||||
struct ieee80211_sched_data *q = qdisc_priv(qd);
|
||||
struct ieee80211_tx_packet_data *pkt_data =
|
||||
(struct ieee80211_tx_packet_data *) skb->cb;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct Qdisc *qdisc;
|
||||
int err;
|
||||
|
||||
/* we recorded which queue to use earlier! */
|
||||
qdisc = q->queues[pkt_data->queue];
|
||||
qdisc = q->queues[info->queue];
|
||||
|
||||
if ((err = qdisc->ops->requeue(skb, qdisc)) == 0) {
|
||||
qd->q.qlen++;
|
||||
|
@ -183,15 +183,25 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
|
||||
}
|
||||
|
||||
|
||||
static int tkip_encrypt_skb(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb, int test)
|
||||
static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_key *key = tx->key;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int hdrlen, len, tailneed;
|
||||
u16 fc;
|
||||
u8 *pos;
|
||||
|
||||
info->control.icv_len = TKIP_ICV_LEN;
|
||||
info->control.iv_len = TKIP_IV_LEN;
|
||||
|
||||
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
|
||||
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
|
||||
/* hwaccel - with no need for preallocated room for IV/ICV */
|
||||
info->control.hw_key = &tx->key->conf;
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
fc = le16_to_cpu(hdr->frame_control);
|
||||
hdrlen = ieee80211_get_hdrlen(fc);
|
||||
len = skb->len - hdrlen;
|
||||
@ -228,7 +238,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx,
|
||||
0x7f),
|
||||
(u8) key->u.tkip.tx.iv16);
|
||||
|
||||
tx->control->hw_key = &tx->key->conf;
|
||||
info->control.hw_key = &tx->key->conf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -246,28 +256,16 @@ ieee80211_tx_result
|
||||
ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct sk_buff *skb = tx->skb;
|
||||
int wpa_test = 0, test = 0;
|
||||
|
||||
tx->control->icv_len = TKIP_ICV_LEN;
|
||||
tx->control->iv_len = TKIP_IV_LEN;
|
||||
ieee80211_tx_set_protected(tx);
|
||||
|
||||
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
|
||||
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
|
||||
!wpa_test) {
|
||||
/* hwaccel - with no need for preallocated room for IV/ICV */
|
||||
tx->control->hw_key = &tx->key->conf;
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
if (tkip_encrypt_skb(tx, skb, test) < 0)
|
||||
if (tkip_encrypt_skb(tx, skb) < 0)
|
||||
return TX_DROP;
|
||||
|
||||
if (tx->extra_frag) {
|
||||
int i;
|
||||
for (i = 0; i < tx->num_extra_frag; i++) {
|
||||
if (tkip_encrypt_skb(tx, tx->extra_frag[i], test)
|
||||
< 0)
|
||||
if (tkip_encrypt_skb(tx, tx->extra_frag[i]) < 0)
|
||||
return TX_DROP;
|
||||
}
|
||||
}
|
||||
@ -429,16 +427,27 @@ static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr)
|
||||
}
|
||||
|
||||
|
||||
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb, int test)
|
||||
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_key *key = tx->key;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
int hdrlen, len, tailneed;
|
||||
u16 fc;
|
||||
u8 *pos, *pn, *b_0, *aad, *scratch;
|
||||
int i;
|
||||
|
||||
info->control.icv_len = CCMP_MIC_LEN;
|
||||
info->control.iv_len = CCMP_HDR_LEN;
|
||||
|
||||
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
|
||||
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
|
||||
/* hwaccel - with no need for preallocated room for CCMP "
|
||||
* header or MIC fields */
|
||||
info->control.hw_key = &tx->key->conf;
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
scratch = key->u.ccmp.tx_crypto_buf;
|
||||
b_0 = scratch + 3 * AES_BLOCK_LEN;
|
||||
aad = scratch + 4 * AES_BLOCK_LEN;
|
||||
@ -478,7 +487,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx,
|
||||
|
||||
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
|
||||
/* hwaccel - with preallocated room for CCMP header */
|
||||
tx->control->hw_key = &tx->key->conf;
|
||||
info->control.hw_key = &tx->key->conf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -495,28 +504,16 @@ ieee80211_tx_result
|
||||
ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct sk_buff *skb = tx->skb;
|
||||
int test = 0;
|
||||
|
||||
tx->control->icv_len = CCMP_MIC_LEN;
|
||||
tx->control->iv_len = CCMP_HDR_LEN;
|
||||
ieee80211_tx_set_protected(tx);
|
||||
|
||||
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
|
||||
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
|
||||
/* hwaccel - with no need for preallocated room for CCMP "
|
||||
* header or MIC fields */
|
||||
tx->control->hw_key = &tx->key->conf;
|
||||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
if (ccmp_encrypt_skb(tx, skb, test) < 0)
|
||||
if (ccmp_encrypt_skb(tx, skb) < 0)
|
||||
return TX_DROP;
|
||||
|
||||
if (tx->extra_frag) {
|
||||
int i;
|
||||
for (i = 0; i < tx->num_extra_frag; i++) {
|
||||
if (ccmp_encrypt_skb(tx, tx->extra_frag[i], test)
|
||||
< 0)
|
||||
if (ccmp_encrypt_skb(tx, tx->extra_frag[i]) < 0)
|
||||
return TX_DROP;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user