aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-21 12:40:02 +0200
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:23 -0400
commite6a9854b05c1a6af1308fe2b8c68f35abf28a3ee (patch)
tree241f611f8194586ccabf61bacb060508773b9d05 /drivers/net/wireless/rt2x00
parentcb121bad67a32cde37adc2729b7e18aa4fd3063e (diff)
mac80211/drivers: rewrite the rate control API
So after the previous changes we were still unhappy with how convoluted the API is and decided to make things simpler for everybody. This completely changes the rate control API, now taking into account 802.11n with MCS rates and more control, most drivers don't support that though. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c22
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h9
4 files changed, 42 insertions, 17 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 697806cf94e..e1feab8b6b0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -498,7 +498,9 @@ void rt2x00lib_txdone(struct queue_entry *entry,
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
+ u8 rate_idx, rate_flags;
/*
* Unmap the skb.
@@ -528,14 +530,18 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->link.qual.tx_failed +=
test_bit(TXDONE_FAILURE, &txdesc->flags);
+ rate_idx = skbdesc->tx_rate_idx;
+ rate_flags = skbdesc->tx_rate_flags;
+
/*
* Initialize TX status
*/
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_info->status.retry_count = txdesc->retry;
+ tx_info->status.rates[0].idx = rate_idx;
+ tx_info->status.rates[0].flags = rate_flags;
+ tx_info->status.rates[0].count = txdesc->retry + 1;
+ tx_info->status.rates[1].idx = -1; /* terminate */
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
@@ -544,7 +550,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->low_level_stats.dot11ACKFailureCount++;
}
- if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 931183369f0..b32d59eafaa 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -39,7 +39,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
unsigned int data_length;
int retval = 0;
- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
data_length = sizeof(struct ieee80211_cts);
else
data_length = sizeof(struct ieee80211_rts);
@@ -64,11 +64,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
*/
memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
rts_info = IEEE80211_SKB_CB(skb);
- rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS;
- rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
+ rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
+ rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT;
rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
else
rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
@@ -84,7 +84,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
data_length += rt2x00crypto_tx_overhead(tx_info);
#endif /* CONFIG_RT2X00_LIB_CRYPTO */
- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
frag_skb->data, data_length, tx_info,
(struct ieee80211_cts *)(skb->data));
@@ -146,8 +146,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* inside the hardware.
*/
frame_control = le16_to_cpu(ieee80211hdr->frame_control);
- if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS |
- IEEE80211_TX_CTL_USE_CTS_PROTECT)) &&
+ if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
+ IEEE80211_TX_RC_USE_CTS_PROTECT)) &&
!rt2x00dev->ops->hw->set_rts_threshold) {
if (rt2x00queue_available(queue) <= 1)
goto exit_fail;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 451d410ecda..070786ebd07 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -230,8 +230,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Determine retry information.
*/
- txdesc->retry_limit = tx_info->control.retry_limit;
- if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
+ txdesc->retry_limit = tx_info->control.rates[0].count - 1;
+ /*
+ * XXX: If at this point we knew whether the HW is going to use
+ * the RETRY_MODE bit or the retry_limit (currently all
+ * use the RETRY_MODE bit) we could do something like b43
+ * does, set the RETRY_MODE bit when the RC algorithm is
+ * requesting more than the long retry limit.
+ */
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
__set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags);
/*
@@ -371,10 +378,12 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
{
+ struct ieee80211_tx_info *tx_info;
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
struct txentry_desc txdesc;
struct skb_frame_desc *skbdesc;
unsigned int iv_len = 0;
+ u8 rate_idx, rate_flags;
if (unlikely(rt2x00queue_full(queue)))
return -EINVAL;
@@ -399,13 +408,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
/*
- * All information is retreived from the skb->cb array,
+ * All information is retrieved from the skb->cb array,
* now we should claim ownership of the driver part of that
- * array.
+ * array, preserving the bitrate index and flags.
*/
+ tx_info = IEEE80211_SKB_CB(skb);
+ rate_idx = tx_info->control.rates[0].idx;
+ rate_flags = tx_info->control.rates[0].flags;
skbdesc = get_skb_frame_desc(entry->skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->entry = entry;
+ skbdesc->tx_rate_idx = rate_idx;
+ skbdesc->tx_rate_flags = rate_flags;
/*
* When hardware encryption is supported, and this frame
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 9dbf04f0f04..4d3c7246f9a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -104,6 +104,8 @@ enum skb_frame_desc_flags {
*
* @flags: Frame flags, see &enum skb_frame_desc_flags.
* @desc_len: Length of the frame descriptor.
+ * @tx_rate_idx: the index of the TX rate, used for TX status reporting
+ * @tx_rate_flags: the TX rate flags, used for TX status reporting
* @desc: Pointer to descriptor part of the frame.
* Note that this pointer could point to something outside
* of the scope of the skb->data pointer.
@@ -113,9 +115,12 @@ enum skb_frame_desc_flags {
* @entry: The entry to which this sk buffer belongs.
*/
struct skb_frame_desc {
- unsigned int flags;
+ u8 flags;
+
+ u8 desc_len;
+ u8 tx_rate_idx;
+ u8 tx_rate_flags;
- unsigned int desc_len;
void *desc;
__le32 iv;