Skip to content

Commit

Permalink
rt2x00: Fix QOS sequence counting
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ivo van Doorn authored and John W. Linville committed Jul 29, 2008
1 parent b93ce43 commit 5adf6d6
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 15 deletions.
13 changes: 0 additions & 13 deletions drivers/net/wireless/rt2x00/rt2x00mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions drivers/net/wireless/rt2x00/rt2x00queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/rt2x00/rt2x00queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/rt2x00/rt61pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/wireless/rt2x00/rt73usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 5adf6d6

Please sign in to comment.