forked from Minki/linux
rt2x00: Fix QOS sequence counting
When IEEE80211_TX_CTL_ASSIGN_SEQ is not set, the driver should disable hardware sequence counting to make sure the mac80211 provided counter is used. This fixes QOS sequence counting, since that is one of the cases where mac80211 provides a seperate sequence counter. By moving the sequence counting code to rt2x00queue we make sure that _all_ frames get the sequence counter, including RTS/CTS and Beacon frames. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
b93ce437eb
commit
5adf6d63c1
@ -96,7 +96,6 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
|
||||
enum data_queue_qid qid = skb_get_queue_mapping(skb);
|
||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||
struct data_queue *queue;
|
||||
u16 frame_control;
|
||||
|
||||
@ -152,18 +151,6 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: This is as wrong as the old mac80211 code was,
|
||||
* due to beacons not getting sequence numbers assigned
|
||||
* properly.
|
||||
*/
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
|
||||
intf->seqno += 0x10;
|
||||
ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||
ieee80211hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
|
||||
}
|
||||
|
||||
if (rt2x00queue_write_tx_frame(queue, skb)) {
|
||||
ieee80211_stop_queue(rt2x00dev->hw, qid);
|
||||
return NETDEV_TX_BUSY;
|
||||
|
@ -120,6 +120,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
|
||||
struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
|
||||
struct ieee80211_rate *rate =
|
||||
ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
|
||||
@ -199,6 +200,31 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
txdesc->ifs = IFS_SIFS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hardware should insert sequence counter.
|
||||
* FIXME: We insert a software sequence counter first for
|
||||
* hardware that doesn't support hardware sequence counting.
|
||||
*
|
||||
* This is wrong because beacons are not getting sequence
|
||||
* numbers assigned properly.
|
||||
*
|
||||
* A secondary problem exists for drivers that cannot toggle
|
||||
* sequence counting per-frame, since those will override the
|
||||
* sequence counter given by mac80211.
|
||||
*/
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
||||
spin_lock(&intf->lock);
|
||||
|
||||
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
|
||||
intf->seqno += 0x10;
|
||||
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||
hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
|
||||
|
||||
spin_unlock(&intf->lock);
|
||||
|
||||
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* PLCP setup
|
||||
* Length calculation depends on OFDM/CCK rate.
|
||||
|
@ -199,6 +199,7 @@ struct txdone_entry_desc {
|
||||
* @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame.
|
||||
* @ENTRY_TXD_CTS_FRAME: This frame is a CTS-to-self frame.
|
||||
* @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate.
|
||||
* @ENTRY_TXD_GENERATE_SEQ: This frame requires sequence counter.
|
||||
* @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame.
|
||||
* @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment.
|
||||
* @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted.
|
||||
@ -210,6 +211,7 @@ enum txentry_desc_flags {
|
||||
ENTRY_TXD_RTS_FRAME,
|
||||
ENTRY_TXD_CTS_FRAME,
|
||||
ENTRY_TXD_OFDM_RATE,
|
||||
ENTRY_TXD_GENERATE_SEQ,
|
||||
ENTRY_TXD_FIRST_FRAGMENT,
|
||||
ENTRY_TXD_MORE_FRAG,
|
||||
ENTRY_TXD_REQ_TIMESTAMP,
|
||||
|
@ -1544,7 +1544,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
|
||||
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
|
||||
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
|
||||
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
|
||||
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
|
||||
rt2x00_desc_write(txd, 1, word);
|
||||
|
||||
|
@ -1281,7 +1281,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
|
||||
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
|
||||
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1);
|
||||
rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE,
|
||||
test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
|
||||
rt2x00_desc_write(txd, 1, word);
|
||||
|
||||
rt2x00_desc_read(txd, 2, &word);
|
||||
|
Loading…
Reference in New Issue
Block a user