diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-11-18 19:08:30 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-19 11:08:56 -0500 |
commit | 7351c6bd482712e5e3ec9dffc547de0e0863efb0 (patch) | |
tree | 1847c0470af79727b58611a69fa82384bd904d60 | |
parent | ad4bb6f8883a13bb0f65b194dae36c62a02ac779 (diff) |
mac80211: request TX status where needed
Right now all frames mac80211 hands to the driver
have the IEEE80211_TX_CTL_REQ_TX_STATUS flag set to
request TX status. This isn't really necessary, only
the injected frames need TX status (the latter for
hostapd) so move setting this flag.
The rate control algorithms also need TX status, but
they don't require it.
Also, rt2x00 uses that bit for its own purposes and
seems to require it being set for all frames, but
that can be fixed in rt2x00.
This doesn't really change anything for any drivers
but in the future drivers using hw-rate control may
opt to not report TX status for frames that don't
have the IEEE80211_TX_CTL_REQ_TX_STATUS flag set.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com> [rt2x00 bits]
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00lib.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 5 | ||||
-rw-r--r-- | include/net/mac80211.h | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 4 |
7 files changed, 23 insertions, 14 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6c6d0ac35549..4a4b7e42fe6e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -205,6 +205,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
205 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); | 205 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); |
206 | unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); | 206 | unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); |
207 | u8 rate_idx, rate_flags, retry_rates; | 207 | u8 rate_idx, rate_flags, retry_rates; |
208 | u8 skbdesc_flags = skbdesc->flags; | ||
208 | unsigned int i; | 209 | unsigned int i; |
209 | bool success; | 210 | bool success; |
210 | 211 | ||
@@ -287,12 +288,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
287 | } | 288 | } |
288 | 289 | ||
289 | /* | 290 | /* |
290 | * Only send the status report to mac80211 when TX status was | 291 | * Only send the status report to mac80211 when it's a frame |
291 | * requested by it. If this was a extra frame coming through | 292 | * that originated in mac80211. If this was a extra frame coming |
292 | * a mac80211 library call (RTS/CTS) then we should not send the | 293 | * through a mac80211 library call (RTS/CTS) then we should not |
293 | * status report back. | 294 | * send the status report back. |
294 | */ | 295 | */ |
295 | if (tx_info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) | 296 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) |
296 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | 297 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); |
297 | else | 298 | else |
298 | dev_kfree_skb_irq(entry->skb); | 299 | dev_kfree_skb_irq(entry->skb); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index c1f48acaee41..be2e37fb4071 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -162,8 +162,10 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length); | |||
162 | * rt2x00queue_write_tx_frame - Write TX frame to hardware | 162 | * rt2x00queue_write_tx_frame - Write TX frame to hardware |
163 | * @queue: Queue over which the frame should be send | 163 | * @queue: Queue over which the frame should be send |
164 | * @skb: The skb to send | 164 | * @skb: The skb to send |
165 | * @local: frame is not from mac80211 | ||
165 | */ | 166 | */ |
166 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); | 167 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, |
168 | bool local); | ||
167 | 169 | ||
168 | /** | 170 | /** |
169 | * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware | 171 | * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index eed093d34532..9c90ceb0ffcc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -66,7 +66,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
66 | rts_info = IEEE80211_SKB_CB(skb); | 66 | rts_info = IEEE80211_SKB_CB(skb); |
67 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; | 67 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; |
68 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; | 68 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; |
69 | rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
70 | 69 | ||
71 | if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) | 70 | if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) |
72 | rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; | 71 | rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; |
@@ -91,7 +90,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
91 | frag_skb->data, data_length, tx_info, | 90 | frag_skb->data, data_length, tx_info, |
92 | (struct ieee80211_rts *)(skb->data)); | 91 | (struct ieee80211_rts *)(skb->data)); |
93 | 92 | ||
94 | retval = rt2x00queue_write_tx_frame(queue, skb); | 93 | retval = rt2x00queue_write_tx_frame(queue, skb, true); |
95 | if (retval) { | 94 | if (retval) { |
96 | dev_kfree_skb_any(skb); | 95 | dev_kfree_skb_any(skb); |
97 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); | 96 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); |
@@ -153,7 +152,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
153 | goto exit_fail; | 152 | goto exit_fail; |
154 | } | 153 | } |
155 | 154 | ||
156 | if (rt2x00queue_write_tx_frame(queue, skb)) | 155 | if (rt2x00queue_write_tx_frame(queue, skb, false)) |
157 | goto exit_fail; | 156 | goto exit_fail; |
158 | 157 | ||
159 | if (rt2x00queue_threshold(queue)) | 158 | if (rt2x00queue_threshold(queue)) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 02972a036bce..eaedee8c05c8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -454,7 +454,8 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | |||
454 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); | 454 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); |
455 | } | 455 | } |
456 | 456 | ||
457 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | 457 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, |
458 | bool local) | ||
458 | { | 459 | { |
459 | struct ieee80211_tx_info *tx_info; | 460 | struct ieee80211_tx_info *tx_info; |
460 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 461 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
@@ -495,6 +496,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
495 | skbdesc->tx_rate_idx = rate_idx; | 496 | skbdesc->tx_rate_idx = rate_idx; |
496 | skbdesc->tx_rate_flags = rate_flags; | 497 | skbdesc->tx_rate_flags = rate_flags; |
497 | 498 | ||
499 | if (local) | ||
500 | skbdesc->flags |= SKBDESC_NOT_MAC80211; | ||
501 | |||
498 | /* | 502 | /* |
499 | * When hardware encryption is supported, and this frame | 503 | * When hardware encryption is supported, and this frame |
500 | * is to be encrypted, we should strip the IV/EIV data from | 504 | * is to be encrypted, we should strip the IV/EIV data from |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 97c7895c0ece..70775e5ba1ac 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -94,12 +94,15 @@ enum data_queue_qid { | |||
94 | * mac80211 but was stripped for processing by the driver. | 94 | * mac80211 but was stripped for processing by the driver. |
95 | * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, | 95 | * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, |
96 | * the padded bytes are located between header and payload. | 96 | * the padded bytes are located between header and payload. |
97 | * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, | ||
98 | * don't try to pass it back. | ||
97 | */ | 99 | */ |
98 | enum skb_frame_desc_flags { | 100 | enum skb_frame_desc_flags { |
99 | SKBDESC_DMA_MAPPED_RX = 1 << 0, | 101 | SKBDESC_DMA_MAPPED_RX = 1 << 0, |
100 | SKBDESC_DMA_MAPPED_TX = 1 << 1, | 102 | SKBDESC_DMA_MAPPED_TX = 1 << 1, |
101 | SKBDESC_IV_STRIPPED = 1 << 2, | 103 | SKBDESC_IV_STRIPPED = 1 << 2, |
102 | SKBDESC_L2_PADDED = 1 << 3 | 104 | SKBDESC_L2_PADDED = 1 << 3, |
105 | SKBDESC_NOT_MAC80211 = 1 << 4, | ||
103 | }; | 106 | }; |
104 | 107 | ||
105 | /** | 108 | /** |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f34f4ca7016c..3754ea405c88 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -219,7 +219,7 @@ struct ieee80211_bss_conf { | |||
219 | * | 219 | * |
220 | * These flags are used with the @flags member of &ieee80211_tx_info. | 220 | * These flags are used with the @flags member of &ieee80211_tx_info. |
221 | * | 221 | * |
222 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. | 222 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame. |
223 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence | 223 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence |
224 | * number to this frame, taking care of not overwriting the fragment | 224 | * number to this frame, taking care of not overwriting the fragment |
225 | * number and increasing the sequence number only when the | 225 | * number and increasing the sequence number only when the |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 5af2f40ea4db..943def2b07df 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1443,8 +1443,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1443 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1443 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1444 | } | 1444 | } |
1445 | 1445 | ||
1446 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1447 | |||
1448 | rcu_read_lock(); | 1446 | rcu_read_lock(); |
1449 | 1447 | ||
1450 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { | 1448 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
@@ -1575,6 +1573,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1575 | 1573 | ||
1576 | memset(info, 0, sizeof(*info)); | 1574 | memset(info, 0, sizeof(*info)); |
1577 | 1575 | ||
1576 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1577 | |||
1578 | /* pass the radiotap header up to xmit */ | 1578 | /* pass the radiotap header up to xmit */ |
1579 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); | 1579 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); |
1580 | return NETDEV_TX_OK; | 1580 | return NETDEV_TX_OK; |