diff options
author | Andrea Merello <andrea.merello@gmail.com> | 2014-03-26 16:00:57 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-03-27 14:20:08 -0400 |
commit | 3ee44d6011f5df36c9b062cbf25536c3691235e3 (patch) | |
tree | d8b278507f4407fd5aabb52b8e23bf3635b05174 /drivers/net/wireless/rtl818x/rtl8180/dev.c | |
parent | f18f112bde931faa25b33f7fa97281be5ef5e2c4 (diff) |
rtl8180: add TX queue mapping and support for rtl8187se
This patch adds tx queue mapping for rtl8187se and a long comment
block about their usages.
It adapts the TX function to use that map and it sets properly
the TX descriptor rtl8187se-only fields
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtl818x/rtl8180/dev.c')
-rw-r--r-- | drivers/net/wireless/rtl818x/rtl8180/dev.c | 84 |
1 files changed, 79 insertions, 5 deletions
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index cce972d289ef..eb86ede246d2 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
@@ -85,6 +85,52 @@ static const struct ieee80211_channel rtl818x_channels[] = { | |||
85 | { .center_freq = 2484 }, | 85 | { .center_freq = 2484 }, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | /* Queues for rtl8187se card | ||
89 | * | ||
90 | * name | reg | queue | ||
91 | * BC | 7 | 6 | ||
92 | * MG | 1 | 0 | ||
93 | * HI | 6 | 1 | ||
94 | * VO | 5 | 2 | ||
95 | * VI | 4 | 3 | ||
96 | * BE | 3 | 4 | ||
97 | * BK | 2 | 5 | ||
98 | * | ||
99 | * The complete map for DMA kick reg using use all queue is: | ||
100 | * static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = | ||
101 | * {1, 6, 5, 4, 3, 2, 7}; | ||
102 | * | ||
103 | * .. but.. Because for mac80211 4 queues are enough for QoS we use this | ||
104 | * | ||
105 | * name | reg | queue | ||
106 | * BC | 7 | 4 <- currently not used yet | ||
107 | * MG | 1 | x <- Not used | ||
108 | * HI | 6 | x <- Not used | ||
109 | * VO | 5 | 0 <- used | ||
110 | * VI | 4 | 1 <- used | ||
111 | * BE | 3 | 2 <- used | ||
112 | * BK | 2 | 3 <- used | ||
113 | * | ||
114 | * Beacon queue could be used, but this is not finished yet. | ||
115 | * | ||
116 | * I thougth about using the other two queues but I decided not to do this: | ||
117 | * | ||
118 | * - I'm unsure whether the mac80211 will ever try to use more than 4 queues | ||
119 | * by itself. | ||
120 | * | ||
121 | * - I could route MGMT frames (currently sent over VO queue) to the MGMT | ||
122 | * queue but since mac80211 will do not know about it, I will probably gain | ||
123 | * some HW priority whenever the VO queue is not empty, but this gain is | ||
124 | * limited by the fact that I had to stop the mac80211 queue whenever one of | ||
125 | * the VO or MGMT queues is full, stopping also submitting of MGMT frame | ||
126 | * to the driver. | ||
127 | * | ||
128 | * - I don't know how to set in the HW the contention window params for MGMT | ||
129 | * and HI-prio queues. | ||
130 | */ | ||
131 | |||
132 | static const int rtl8187se_queues_map[RTL8187SE_NR_TX_QUEUES] = {5, 4, 3, 2, 7}; | ||
133 | |||
88 | /* Queues for rtl8180/rtl8185 cards | 134 | /* Queues for rtl8180/rtl8185 cards |
89 | * | 135 | * |
90 | * name | reg | prio | 136 | * name | reg | prio |
@@ -358,6 +404,8 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
358 | u8 rc_flags; | 404 | u8 rc_flags; |
359 | u16 plcp_len = 0; | 405 | u16 plcp_len = 0; |
360 | __le16 rts_duration = 0; | 406 | __le16 rts_duration = 0; |
407 | /* do arithmetic and then convert to le16 */ | ||
408 | u16 frame_duration = 0; | ||
361 | 409 | ||
362 | prio = skb_get_queue_mapping(skb); | 410 | prio = skb_get_queue_mapping(skb); |
363 | ring = &priv->tx_ring[prio]; | 411 | ring = &priv->tx_ring[prio]; |
@@ -369,7 +417,6 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
369 | kfree_skb(skb); | 417 | kfree_skb(skb); |
370 | dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); | 418 | dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); |
371 | return; | 419 | return; |
372 | |||
373 | } | 420 | } |
374 | 421 | ||
375 | tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | | 422 | tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | |
@@ -405,6 +452,18 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
405 | plcp_len |= 1 << 15; | 452 | plcp_len |= 1 << 15; |
406 | } | 453 | } |
407 | 454 | ||
455 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { | ||
456 | __le16 duration; | ||
457 | /* SIFS time (required by HW) is already included by | ||
458 | * ieee80211_generic_frame_duration | ||
459 | */ | ||
460 | duration = ieee80211_generic_frame_duration(dev, priv->vif, | ||
461 | IEEE80211_BAND_2GHZ, skb->len, | ||
462 | ieee80211_get_tx_rate(dev, info)); | ||
463 | |||
464 | frame_duration = priv->ack_time + le16_to_cpu(duration); | ||
465 | } | ||
466 | |||
408 | spin_lock_irqsave(&priv->lock, flags); | 467 | spin_lock_irqsave(&priv->lock, flags); |
409 | 468 | ||
410 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 469 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
@@ -417,10 +476,19 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
417 | idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; | 476 | idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; |
418 | entry = &ring->desc[idx]; | 477 | entry = &ring->desc[idx]; |
419 | 478 | ||
479 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { | ||
480 | entry->frame_duration = cpu_to_le16(frame_duration); | ||
481 | entry->frame_len_se = cpu_to_le16(skb->len); | ||
482 | |||
483 | /* tpc polarity */ | ||
484 | entry->flags3 = cpu_to_le16(1<<4); | ||
485 | } else | ||
486 | entry->frame_len = cpu_to_le32(skb->len); | ||
487 | |||
420 | entry->rts_duration = rts_duration; | 488 | entry->rts_duration = rts_duration; |
421 | entry->plcp_len = cpu_to_le16(plcp_len); | 489 | entry->plcp_len = cpu_to_le16(plcp_len); |
422 | entry->tx_buf = cpu_to_le32(mapping); | 490 | entry->tx_buf = cpu_to_le32(mapping); |
423 | entry->frame_len = cpu_to_le32(skb->len); | 491 | |
424 | entry->flags2 = info->control.rates[1].idx >= 0 ? | 492 | entry->flags2 = info->control.rates[1].idx >= 0 ? |
425 | ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; | 493 | ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; |
426 | entry->retry_limit = info->control.rates[0].count; | 494 | entry->retry_limit = info->control.rates[0].count; |
@@ -442,11 +510,17 @@ static void rtl8180_tx(struct ieee80211_hw *dev, | |||
442 | 510 | ||
443 | spin_unlock_irqrestore(&priv->lock, flags); | 511 | spin_unlock_irqrestore(&priv->lock, flags); |
444 | 512 | ||
445 | hw_prio = rtl8180_queues_map[prio]; | 513 | if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8187SE) { |
446 | 514 | /* just poll: rings are stopped with TPPollStop reg */ | |
447 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, | 515 | hw_prio = rtl8187se_queues_map[prio]; |
516 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, | ||
517 | (1 << hw_prio)); | ||
518 | } else { | ||
519 | hw_prio = rtl8180_queues_map[prio]; | ||
520 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, | ||
448 | (1 << hw_prio) | /* ring to poll */ | 521 | (1 << hw_prio) | /* ring to poll */ |
449 | (1<<1) | (1<<2));/* stopped rings */ | 522 | (1<<1) | (1<<2));/* stopped rings */ |
523 | } | ||
450 | } | 524 | } |
451 | 525 | ||
452 | void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) | 526 | void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) |