diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 81 |
1 files changed, 80 insertions, 1 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 0d79278a0a19..56f9d0df9c61 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -302,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, | |||
302 | } | 302 | } |
303 | } | 303 | } |
304 | 304 | ||
305 | static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry, | ||
306 | struct txentry_desc *txdesc, | ||
307 | const struct rt2x00_rate *hwrate) | ||
308 | { | ||
309 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | ||
310 | struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; | ||
311 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; | ||
312 | |||
313 | if (tx_info->control.sta) | ||
314 | txdesc->u.ht.mpdu_density = | ||
315 | tx_info->control.sta->ht_cap.ampdu_density; | ||
316 | |||
317 | txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ | ||
318 | |||
319 | /* | ||
320 | * Only one STBC stream is supported for now. | ||
321 | */ | ||
322 | if (tx_info->flags & IEEE80211_TX_CTL_STBC) | ||
323 | txdesc->u.ht.stbc = 1; | ||
324 | |||
325 | /* | ||
326 | * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the | ||
327 | * mcs rate to be used | ||
328 | */ | ||
329 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | ||
330 | txdesc->u.ht.mcs = txrate->idx; | ||
331 | |||
332 | /* | ||
333 | * MIMO PS should be set to 1 for STA's using dynamic SM PS | ||
334 | * when using more then one tx stream (>MCS7). | ||
335 | */ | ||
336 | if (tx_info->control.sta && txdesc->u.ht.mcs > 7 && | ||
337 | ((tx_info->control.sta->ht_cap.cap & | ||
338 | IEEE80211_HT_CAP_SM_PS) >> | ||
339 | IEEE80211_HT_CAP_SM_PS_SHIFT) == | ||
340 | WLAN_HT_CAP_SM_PS_DYNAMIC) | ||
341 | __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); | ||
342 | } else { | ||
343 | txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); | ||
344 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
345 | txdesc->u.ht.mcs |= 0x08; | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * This frame is eligible for an AMPDU, however, don't aggregate | ||
350 | * frames that are intended to probe a specific tx rate. | ||
351 | */ | ||
352 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && | ||
353 | !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) | ||
354 | __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); | ||
355 | |||
356 | /* | ||
357 | * Set 40Mhz mode if necessary (for legacy rates this will | ||
358 | * duplicate the frame to both channels). | ||
359 | */ | ||
360 | if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || | ||
361 | txrate->flags & IEEE80211_TX_RC_DUP_DATA) | ||
362 | __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); | ||
363 | if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
364 | __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); | ||
365 | |||
366 | /* | ||
367 | * Determine IFS values | ||
368 | * - Use TXOP_BACKOFF for management frames except beacons | ||
369 | * - Use TXOP_SIFS for fragment bursts | ||
370 | * - Use TXOP_HTTXOP for everything else | ||
371 | * | ||
372 | * Note: rt2800 devices won't use CTS protection (if used) | ||
373 | * for frames not transmitted with TXOP_HTTXOP | ||
374 | */ | ||
375 | if (ieee80211_is_mgmt(hdr->frame_control) && | ||
376 | !ieee80211_is_beacon(hdr->frame_control)) | ||
377 | txdesc->u.ht.txop = TXOP_BACKOFF; | ||
378 | else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) | ||
379 | txdesc->u.ht.txop = TXOP_SIFS; | ||
380 | else | ||
381 | txdesc->u.ht.txop = TXOP_HTTXOP; | ||
382 | } | ||
383 | |||
305 | static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | 384 | static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, |
306 | struct txentry_desc *txdesc) | 385 | struct txentry_desc *txdesc) |
307 | { | 386 | { |
@@ -397,7 +476,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
397 | rt2x00queue_create_tx_descriptor_seq(entry, txdesc); | 476 | rt2x00queue_create_tx_descriptor_seq(entry, txdesc); |
398 | 477 | ||
399 | if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) | 478 | if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) |
400 | rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); | 479 | rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate); |
401 | else | 480 | else |
402 | rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); | 481 | rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); |
403 | } | 482 | } |