Message ID | 1360329197-72631-1-git-send-email-nbd@openwrt.org (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
Felix Fietkau wrote: > In many tests throughput with ath9k_rate_control has been shown to be > worse than with minstrel_ht (the mac8021 default RC). > > This module also has some other problems, like starting to use the > highest possible rate early in the connection, causing problems with > reliability of connection/authentication attempts. > > It also has a much more limited search space, ignoring many potentially > useful rates, caused by the design decision to operate on a sorted rate > set with the assumption that higher rates are always more unreliable > than lower rates. In some scenarios this assumption is not true, and > this can cause it to fall back to a really bad rate. > > minstrel_ht has been tested extensively in AP and client mode by lots of > users (mostly in the OpenWrt project, where it has been the default for > years). > > The only advantage that ath9k_rate_control previously had over minstrel_ht > was the support for using CCK rates as fall back in case MCS rates got > too bad, but this has now also been taken care of. Various rates are marked as invalid in the ath9k rate control module. I don't know all the reasons, but the recommendation to disable certain rates came from the internal algorithms team. How will this be handled ? Sujith -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-02-08 2:30 PM, Sujith Manoharan wrote: > Felix Fietkau wrote: >> In many tests throughput with ath9k_rate_control has been shown to be >> worse than with minstrel_ht (the mac8021 default RC). >> >> This module also has some other problems, like starting to use the >> highest possible rate early in the connection, causing problems with >> reliability of connection/authentication attempts. >> >> It also has a much more limited search space, ignoring many potentially >> useful rates, caused by the design decision to operate on a sorted rate >> set with the assumption that higher rates are always more unreliable >> than lower rates. In some scenarios this assumption is not true, and >> this can cause it to fall back to a really bad rate. >> >> minstrel_ht has been tested extensively in AP and client mode by lots of >> users (mostly in the OpenWrt project, where it has been the default for >> years). >> >> The only advantage that ath9k_rate_control previously had over minstrel_ht >> was the support for using CCK rates as fall back in case MCS rates got >> too bad, but this has now also been taken care of. > > Various rates are marked as invalid in the ath9k rate control module. I don't > know all the reasons, but the recommendation to disable certain rates came from > the internal algorithms team. How will this be handled ? I'm pretty sure it's because the algorithm isn't designed to handle more rates. It's a step-up/step-down type algorithm, and those typically only work with a sorted rateset, preferably duplicate free. Minstrel_ht selects rates in a different way that doesn't have the same limitations, so it can use the full rateset. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Felix Fietkau wrote: > I'm pretty sure it's because the algorithm isn't designed to handle more > rates. It's a step-up/step-down type algorithm, and those typically only > work with a sorted rateset, preferably duplicate free. > > Minstrel_ht selects rates in a different way that doesn't have the same > limitations, so it can use the full rateset. Makes sense. Sujith -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Felix Fietkau wrote: > In many tests throughput with ath9k_rate_control has been shown to be > worse than with minstrel_ht (the mac8021 default RC). > > This module also has some other problems, like starting to use the > highest possible rate early in the connection, causing problems with > reliability of connection/authentication attempts. > > It also has a much more limited search space, ignoring many potentially > useful rates, caused by the design decision to operate on a sorted rate > set with the assumption that higher rates are always more unreliable > than lower rates. In some scenarios this assumption is not true, and > this can cause it to fall back to a really bad rate. > > minstrel_ht has been tested extensively in AP and client mode by lots of > users (mostly in the OpenWrt project, where it has been the default for > years). I don't think managed mode would have received much testing in OpenWRT. > The only advantage that ath9k_rate_control previously had over minstrel_ht > was the support for using CCK rates as fall back in case MCS rates got > too bad, but this has now also been taken care of. > > Signed-off-by: Felix Fietkau <nbd@openwrt.org> Acked-by: Sujith Manoharan <c_manoha@qca.qualcomm.com> Sujith -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-02-08 3:08 PM, Sujith Manoharan wrote: > Felix Fietkau wrote: >> In many tests throughput with ath9k_rate_control has been shown to be >> worse than with minstrel_ht (the mac8021 default RC). >> >> This module also has some other problems, like starting to use the >> highest possible rate early in the connection, causing problems with >> reliability of connection/authentication attempts. >> >> It also has a much more limited search space, ignoring many potentially >> useful rates, caused by the design decision to operate on a sorted rate >> set with the assumption that higher rates are always more unreliable >> than lower rates. In some scenarios this assumption is not true, and >> this can cause it to fall back to a really bad rate. >> >> minstrel_ht has been tested extensively in AP and client mode by lots of >> users (mostly in the OpenWrt project, where it has been the default for >> years). > > I don't think managed mode would have received much testing in OpenWRT. I know quite a few people that use directional links with 4-addr AP/Station. I also know a few people that put up some devices that roam between multiple APs. Obviously it doesn't receive as much testing as AP mode, but there are some active users stress testing it. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Could you share some of the test results? I know with ChromeOS when we switched to 3.4, the first thing that tipped us off to the fact that we had inadvertently switch to minstrel was that our RvR throughput values had dropped significantly. Has anyone done an RvR comparison between minstrel and the ath9k internal rate control lately? -- Paul On Fri, Feb 8, 2013 at 6:16 AM, Felix Fietkau <nbd@openwrt.org> wrote: > On 2013-02-08 3:08 PM, Sujith Manoharan wrote: >> Felix Fietkau wrote: >>> In many tests throughput with ath9k_rate_control has been shown to be >>> worse than with minstrel_ht (the mac8021 default RC). >>> >>> This module also has some other problems, like starting to use the >>> highest possible rate early in the connection, causing problems with >>> reliability of connection/authentication attempts. >>> >>> It also has a much more limited search space, ignoring many potentially >>> useful rates, caused by the design decision to operate on a sorted rate >>> set with the assumption that higher rates are always more unreliable >>> than lower rates. In some scenarios this assumption is not true, and >>> this can cause it to fall back to a really bad rate. >>> >>> minstrel_ht has been tested extensively in AP and client mode by lots of >>> users (mostly in the OpenWrt project, where it has been the default for >>> years). >> >> I don't think managed mode would have received much testing in OpenWRT. > I know quite a few people that use directional links with 4-addr > AP/Station. I also know a few people that put up some devices that roam > between multiple APs. Obviously it doesn't receive as much testing as AP > mode, but there are some active users stress testing it. > > - Felix > > -- > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-02-08 5:38 PM, Paul Stewart wrote: > Could you share some of the test results? I know with ChromeOS when > we switched to 3.4, the first thing that tipped us off to the fact > that we had inadvertently switch to minstrel was that our RvR > throughput values had dropped significantly. Has anyone done an RvR > comparison between minstrel and the ath9k internal rate control > lately? Are you sure it was minstrel_ht, or could it also have been minstrel (the legacy version)? I don't have any recent RvR test results, however on every single link that I tested both rate control modules on (leaving everything else unchanged), minstrel_ht got slightly better results. Additionally, I occasionally get asked for help on debugging low throughput issues, and many of the people asking me have reported that simply switching to minstrel_ht fixed these issues in their tests. I would also like to see some real RvR tests comparing both, preferably before this gets merged, which is why I sent it as RFC. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Feb 08, 2013 at 05:53:50PM +0100, Felix Fietkau wrote: > On 2013-02-08 5:38 PM, Paul Stewart wrote: > > Could you share some of the test results? I know with ChromeOS when > > we switched to 3.4, the first thing that tipped us off to the fact > > that we had inadvertently switch to minstrel was that our RvR > > throughput values had dropped significantly. Has anyone done an RvR > > comparison between minstrel and the ath9k internal rate control > > lately? > Are you sure it was minstrel_ht, or could it also have been minstrel > (the legacy version)? I don't have any recent RvR test results, however > on every single link that I tested both rate control modules on (leaving > everything else unchanged), minstrel_ht got slightly better results. > Additionally, I occasionally get asked for help on debugging low > throughput issues, and many of the people asking me have reported that > simply switching to minstrel_ht fixed these issues in their tests. > > I would also like to see some real RvR tests comparing both, preferably > before this gets merged, which is why I sent it as RFC. Paul, curious if you've run any tests? Luis -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Why don't we just move the ath9k rate control code to another mac80211 rate control module, so it's available to other devices? It may not be a bad idea to keep it around as a reference and for people to do comparisons against. It just seems silly to have a rate control framework and then not use it.. Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-02-28 3:21 AM, Adrian Chadd wrote: > Why don't we just move the ath9k rate control code to another mac80211 > rate control module, so it's available to other devices? > > It may not be a bad idea to keep it around as a reference and for > people to do comparisons against. It just seems silly to have a rate > control framework and then not use it.. I don't see the point in keeping that algorithm around. It has known design flaws that make it perform poorly in several scenarios, and fixing some of the flaws require basically rewriting it. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Felix Fietkau wrote: > I don't see the point in keeping that algorithm around. It has known > design flaws that make it perform poorly in several scenarios, and > fixing some of the flaws require basically rewriting it. I ran some comparison throughput tests between minstrel_ht and ath9k RC and minstrel showed lower numbers (~10Mbps difference). This is in a clean environment (OTA). IMO, we can switch the default to minstrel_ht, but keep the ath9k RC until the perf. gap is fixed. I think this was Google's concern too, a drop in the average throughput. This was in the STA->AP direction. In the AP->STA direction (AP: DB120, STA: AR9280), the numbers were really low. The highest that I could see was ~165 Mbps, while with WNDR3700 (stock FW), the average throughput was ~185 Mbps and an occasional high of 190 and above. Sujith -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-02-28 4:54 AM, Sujith Manoharan wrote: > Felix Fietkau wrote: >> I don't see the point in keeping that algorithm around. It has known >> design flaws that make it perform poorly in several scenarios, and >> fixing some of the flaws require basically rewriting it. > > I ran some comparison throughput tests between minstrel_ht and ath9k RC > and minstrel showed lower numbers (~10Mbps difference). This is in a clean > environment (OTA). IMO, we can switch the default to minstrel_ht, but keep > the ath9k RC until the perf. gap is fixed. I think this was Google's concern too, > a drop in the average throughput. This was in the STA->AP direction. What was the distance and what was the rate used? > In the AP->STA direction (AP: DB120, STA: AR9280), the numbers were really low. > The highest that I could see was ~165 Mbps, while with WNDR3700 (stock FW), the > average throughput was ~185 Mbps and an occasional high of 190 and above. Comparing against stock FW (especially with different devices) is not useful, it could be anything. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Felix Fietkau wrote:
> What was the distance and what was the rate used?
The station was about a meter away from the AP. I don't have the rcstats,
debugfs was compiled out. I'll rerun the test and post the results.
Sujith
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Feb 28, 2013 at 04:24:49AM +0100, Felix Fietkau wrote: > On 2013-02-28 3:21 AM, Adrian Chadd wrote: > > It may not be a bad idea to keep it around as a reference and for > > people to do comparisons against. It just seems silly to have a rate > > control framework and then not use it.. > I don't see the point in keeping that algorithm around. It has known > design flaws that make it perform poorly in several scenarios, and > fixing some of the flaws require basically rewriting it. The same could be said of PID...
On 2013-02-28 12:47 PM, Bob Copeland wrote: > On Thu, Feb 28, 2013 at 04:24:49AM +0100, Felix Fietkau wrote: >> On 2013-02-28 3:21 AM, Adrian Chadd wrote: >> > It may not be a bad idea to keep it around as a reference and for >> > people to do comparisons against. It just seems silly to have a rate >> > control framework and then not use it.. >> I don't see the point in keeping that algorithm around. It has known >> design flaws that make it perform poorly in several scenarios, and >> fixing some of the flaws require basically rewriting it. > > The same could be said of PID... I agree, we should remove that one as well. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 28 February 2013 05:09, Felix Fietkau <nbd@openwrt.org> wrote: >> The same could be said of PID... > I agree, we should remove that one as well. One of the advantages of having multiple RC modules - even if they're not longer optimal - is to keep the API honest. :-) I still keep onoe/amrr working in FreeBSD's ath(4) driver, primarily to make sure that I don't change the API without thinking too much about what other rate control modules do, but also to provide a simpler example of how the API works. Personally, I'd like to see more examples of rate control modules in LInux/FreeBSD, especially ones that start demanding more 802.11 state (ie, air-time QoS.) Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-02-28 7:53 PM, Adrian Chadd wrote: > On 28 February 2013 05:09, Felix Fietkau <nbd@openwrt.org> wrote: > >>> The same could be said of PID... >> I agree, we should remove that one as well. > > One of the advantages of having multiple RC modules - even if they're > not longer optimal - is to keep the API honest. :-) > > I still keep onoe/amrr working in FreeBSD's ath(4) driver, primarily > to make sure that I don't change the API without thinking too much > about what other rate control modules do, but also to provide a > simpler example of how the API works. In that case I'd rather keep PID than the ath9k rate control. The ath9k rate control is a horrible example of how to use the rate control API, and fixing that is a waste of time in my opinion. By the way, minstrel and minstrel_ht are two mostly separate implementations using the same API, except for the fact that minstrel_ht falls back to minstrel for legacy clients. So we already do have multiple examples here :) > Personally, I'd like to see more examples of rate control modules in > LInux/FreeBSD, especially ones that start demanding more 802.11 state > (ie, air-time QoS.) Do you have any good ideas on what state information would be useful for a rate control to demand? - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Felix Fietkau wrote: > In that case I'd rather keep PID than the ath9k rate control. The ath9k > rate control is a horrible example of how to use the rate control API, > and fixing that is a waste of time in my opinion. I acked the earlier RFC patch to remove the ath9k RC as I assumed that minstrel_ht would perform adequately, if not better. But, there appear to be areas in which the numbers given by minstrel_ht are sub-optimal and which can be improved if we have something to compare it with. The ath9k RC code is crap, no doubt, but I'd prefer to have it for some time in the tree - we can switch the default RC to minstrel_ht by default. Can you also explain how the ath9k RC uses the mac80211 API horribly ? The algorithm might be terribly implemented and the internal code nasty, but how does it violate the API ? Sujith -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 28 February 2013 11:07, Felix Fietkau <nbd@openwrt.org> wrote: >> Personally, I'd like to see more examples of rate control modules in >> LInux/FreeBSD, especially ones that start demanding more 802.11 state >> (ie, air-time QoS.) > Do you have any good ideas on what state information would be useful for > a rate control to demand? Well, there are already hooks to fake the TX time spent, right? Having both TX and RX busy times available to rate control so it can better schedule TX loads based on current RX workloads would be nice. Having access to schedule which peer and how much to send to each peer would be nice. Stuff like "peer X only can have up to x ms in this WME class this round", so you don't have a busy, close peer monopolising the air. It also means you can start doing smart things with far away peers who retransmit a lot - they're likely tying up a lot of airtime. None of this is new. It's just, you know, new to open source. :-) Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-03-01 2:23 AM, Sujith Manoharan wrote: > Felix Fietkau wrote: >> In that case I'd rather keep PID than the ath9k rate control. The ath9k >> rate control is a horrible example of how to use the rate control API, >> and fixing that is a waste of time in my opinion. > > I acked the earlier RFC patch to remove the ath9k RC as I assumed that minstrel_ht > would perform adequately, if not better. But, there appear to be areas in which > the numbers given by minstrel_ht are sub-optimal and which can be improved if we > have something to compare it with. The ath9k RC code is crap, no doubt, but I'd > prefer to have it for some time in the tree - we can switch the default RC to minstrel_ht > by default. Right, I will only submit this patch again once more performance tests have been run. My own tests and tests of other people that I know of so far have shown minstrel_ht to perform better than ath9k_rate_control, whereas in your tests ath9k_rate_control seems to perform better. I'd like to get some more details on your tests, e.g. raw numbers, rate control stats, info on how much the throughput fluctuates, etc. > Can you also explain how the ath9k RC uses the mac80211 API horribly ? The algorithm might be > terribly implemented and the internal code nasty, but how does it violate the API ? When I called it a horrible example, I was referring to the bad code quality, not API violations. The API violations are only minor, there are a few places left where the rate control code accesses struct ath_softc. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-03-01 4:53 AM, Adrian Chadd wrote: > On 28 February 2013 11:07, Felix Fietkau <nbd@openwrt.org> wrote: > >>> Personally, I'd like to see more examples of rate control modules in >>> LInux/FreeBSD, especially ones that start demanding more 802.11 state >>> (ie, air-time QoS.) > >> Do you have any good ideas on what state information would be useful for >> a rate control to demand? > > Well, there are already hooks to fake the TX time spent, right? Having > both TX and RX busy times available to rate control so it can better > schedule TX loads based on current RX workloads would be nice. > > Having access to schedule which peer and how much to send to each peer > would be nice. Stuff like "peer X only can have up to x ms in this WME > class this round", so you don't have a busy, close peer monopolising > the air. It also means you can start doing smart things with far away > peers who retransmit a lot - they're likely tying up a lot of airtime. > > None of this is new. It's just, you know, new to open source. :-) In my opinion this doesn't really belong into a rate control module. There should be a tx scheduling API to take care of this. Before I implement something like this, I plan on exposing all per-station driver queues to mac80211. This is necessary for a few other things anyway, e.g. unifying software aggregation logic and fixing its buffer management. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 1 March 2013 02:14, Felix Fietkau <nbd@openwrt.org> wrote: >> Having access to schedule which peer and how much to send to each peer >> would be nice. Stuff like "peer X only can have up to x ms in this WME >> class this round", so you don't have a busy, close peer monopolising >> the air. It also means you can start doing smart things with far away >> peers who retransmit a lot - they're likely tying up a lot of airtime. >> >> None of this is new. It's just, you know, new to open source. :-) > In my opinion this doesn't really belong into a rate control module. > There should be a tx scheduling API to take care of this. Before I > implement something like this, I plan on exposing all per-station driver > queues to mac80211. This is necessary for a few other things anyway, > e.g. unifying software aggregation logic and fixing its buffer management. Sure, but then some more clever tricks end up being difficult to implement. For example, knowing if a client is tying up too much airtime at the given rate and whether to back them off for a bit. Or to use smaller aggregation limits for certain clients because your'e trying to be "fairer" when trying to keep latency low. That kind of thing. I think "rate control" should likely be expanded to "tx scheduling" as a whole, rather than sitting as a separate thing that just selects the rate for a node who has already been chosen to transmit. Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-03-01 11:22 AM, Adrian Chadd wrote: > On 1 March 2013 02:14, Felix Fietkau <nbd@openwrt.org> wrote: > >>> Having access to schedule which peer and how much to send to each peer >>> would be nice. Stuff like "peer X only can have up to x ms in this WME >>> class this round", so you don't have a busy, close peer monopolising >>> the air. It also means you can start doing smart things with far away >>> peers who retransmit a lot - they're likely tying up a lot of airtime. >>> >>> None of this is new. It's just, you know, new to open source. :-) > >> In my opinion this doesn't really belong into a rate control module. >> There should be a tx scheduling API to take care of this. Before I >> implement something like this, I plan on exposing all per-station driver >> queues to mac80211. This is necessary for a few other things anyway, >> e.g. unifying software aggregation logic and fixing its buffer management. > > Sure, but then some more clever tricks end up being difficult to > implement. For example, knowing if a client is tying up too much > airtime at the given rate and whether to back them off for a bit. Or > to use smaller aggregation limits for certain clients because your'e > trying to be "fairer" when trying to keep latency low. That kind of > thing. > > I think "rate control" should likely be expanded to "tx scheduling" as > a whole, rather than sitting as a separate thing that just selects the > rate for a node who has already been chosen to transmit. Even with client airtime use, I still don't see how tx scheduling and rate control belong together. In my opinion, the rate selection should not be based on client airtime usage or the current load, as it can optimize for throughput/airtime ratio without it. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Felix, On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <nbd@openwrt.org> wrote: > On 2013-03-01 11:22 AM, Adrian Chadd wrote: >> On 1 March 2013 02:14, Felix Fietkau <nbd@openwrt.org> wrote: >> >>>> Having access to schedule which peer and how much to send to each peer >>>> would be nice. Stuff like "peer X only can have up to x ms in this WME >>>> class this round", so you don't have a busy, close peer monopolising >>>> the air. It also means you can start doing smart things with far away >>>> peers who retransmit a lot - they're likely tying up a lot of airtime. >>>> >>>> None of this is new. It's just, you know, new to open source. :-) >> >>> In my opinion this doesn't really belong into a rate control module. >>> There should be a tx scheduling API to take care of this. Before I >>> implement something like this, I plan on exposing all per-station driver >>> queues to mac80211. This is necessary for a few other things anyway, >>> e.g. unifying software aggregation logic and fixing its buffer management. >> >> Sure, but then some more clever tricks end up being difficult to >> implement. For example, knowing if a client is tying up too much >> airtime at the given rate and whether to back them off for a bit. Or >> to use smaller aggregation limits for certain clients because your'e >> trying to be "fairer" when trying to keep latency low. That kind of >> thing. >> >> I think "rate control" should likely be expanded to "tx scheduling" as >> a whole, rather than sitting as a separate thing that just selects the >> rate for a node who has already been chosen to transmit. > Even with client airtime use, I still don't see how tx scheduling and > rate control belong together. In my opinion, the rate selection should > not be based on client airtime usage or the current load, as it can > optimize for throughput/airtime ratio without it. > Algorithm folks and Engineers had spent considerable time on ath9k rate control. Wouldn't be a great idea to remove it completely, We can have it optional. With lot of throughput tests ran over internally and with the test team verification, it wouldn't be fair to throw it away.
On 2013-03-01 12:18 PM, Mohammed Shafi wrote: > Hi Felix, > > On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <nbd@openwrt.org> wrote: >> On 2013-03-01 11:22 AM, Adrian Chadd wrote: >>> On 1 March 2013 02:14, Felix Fietkau <nbd@openwrt.org> wrote: >>> >>>>> Having access to schedule which peer and how much to send to each peer >>>>> would be nice. Stuff like "peer X only can have up to x ms in this WME >>>>> class this round", so you don't have a busy, close peer monopolising >>>>> the air. It also means you can start doing smart things with far away >>>>> peers who retransmit a lot - they're likely tying up a lot of airtime. >>>>> >>>>> None of this is new. It's just, you know, new to open source. :-) >>> >>>> In my opinion this doesn't really belong into a rate control module. >>>> There should be a tx scheduling API to take care of this. Before I >>>> implement something like this, I plan on exposing all per-station driver >>>> queues to mac80211. This is necessary for a few other things anyway, >>>> e.g. unifying software aggregation logic and fixing its buffer management. >>> >>> Sure, but then some more clever tricks end up being difficult to >>> implement. For example, knowing if a client is tying up too much >>> airtime at the given rate and whether to back them off for a bit. Or >>> to use smaller aggregation limits for certain clients because your'e >>> trying to be "fairer" when trying to keep latency low. That kind of >>> thing. >>> >>> I think "rate control" should likely be expanded to "tx scheduling" as >>> a whole, rather than sitting as a separate thing that just selects the >>> rate for a node who has already been chosen to transmit. >> Even with client airtime use, I still don't see how tx scheduling and >> rate control belong together. In my opinion, the rate selection should >> not be based on client airtime usage or the current load, as it can >> optimize for throughput/airtime ratio without it. >> > > Algorithm folks and Engineers had spent considerable time on ath9k rate control. > Wouldn't be a great idea to remove it completely, We can have it optional. > With lot of throughput tests ran over internally and with the test > team verification, > it wouldn't be fair to throw it away. Regardless of how much time was spent tuning it, it still has a really bad design, bad implementation and a number of practical issues. It seems to be tuned entirely for artificial benchmarks in clean air. It also starts with a very high rate without having proven that it works. I don't think anybody is going to fix all of these issues, and even if somebody does, it would invalidate pretty much all of the tuning/testing that went into this code. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, Mar 1, 2013 at 5:01 PM, Felix Fietkau <nbd@openwrt.org> wrote: > On 2013-03-01 12:18 PM, Mohammed Shafi wrote: >> Hi Felix, >> >> On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <nbd@openwrt.org> wrote: >>> On 2013-03-01 11:22 AM, Adrian Chadd wrote: >>>> On 1 March 2013 02:14, Felix Fietkau <nbd@openwrt.org> wrote: >>>> >>>>>> Having access to schedule which peer and how much to send to each peer >>>>>> would be nice. Stuff like "peer X only can have up to x ms in this WME >>>>>> class this round", so you don't have a busy, close peer monopolising >>>>>> the air. It also means you can start doing smart things with far away >>>>>> peers who retransmit a lot - they're likely tying up a lot of airtime. >>>>>> >>>>>> None of this is new. It's just, you know, new to open source. :-) >>>> >>>>> In my opinion this doesn't really belong into a rate control module. >>>>> There should be a tx scheduling API to take care of this. Before I >>>>> implement something like this, I plan on exposing all per-station driver >>>>> queues to mac80211. This is necessary for a few other things anyway, >>>>> e.g. unifying software aggregation logic and fixing its buffer management. >>>> >>>> Sure, but then some more clever tricks end up being difficult to >>>> implement. For example, knowing if a client is tying up too much >>>> airtime at the given rate and whether to back them off for a bit. Or >>>> to use smaller aggregation limits for certain clients because your'e >>>> trying to be "fairer" when trying to keep latency low. That kind of >>>> thing. >>>> >>>> I think "rate control" should likely be expanded to "tx scheduling" as >>>> a whole, rather than sitting as a separate thing that just selects the >>>> rate for a node who has already been chosen to transmit. >>> Even with client airtime use, I still don't see how tx scheduling and >>> rate control belong together. In my opinion, the rate selection should >>> not be based on client airtime usage or the current load, as it can >>> optimize for throughput/airtime ratio without it. >>> >> >> Algorithm folks and Engineers had spent considerable time on ath9k rate control. >> Wouldn't be a great idea to remove it completely, We can have it optional. >> With lot of throughput tests ran over internally and with the test >> team verification, >> it wouldn't be fair to throw it away. > Regardless of how much time was spent tuning it, it still has a really > bad design, bad implementation and a number of practical issues. > It seems to be tuned entirely for artificial benchmarks in clean air. It > also starts with a very high rate without having proven that it works. > I don't think anybody is going to fix all of these issues, and even if > somebody does, it would invalidate pretty much all of the tuning/testing > that went into this code. > We can certainly question the design and implementation, but it was proven to work well and had been tested by more hands(even with propitiatory stuff). Even if some one thinks it as bad, we should still allow it as an option. For instance if the environment is pretty good/pretty bad, we should give the users an option to choose between the two, that's why we should retain it. Further its been tested internally, by customers and more folks. Its been also worked by some serious developers and Engineers.
On 2013-03-01 1:32 PM, Mohammed Shafi wrote: > On Fri, Mar 1, 2013 at 5:01 PM, Felix Fietkau <nbd@openwrt.org> wrote: >> On 2013-03-01 12:18 PM, Mohammed Shafi wrote: >>> Hi Felix, >>> >>> On Fri, Mar 1, 2013 at 3:59 PM, Felix Fietkau <nbd@openwrt.org> wrote: >>>> On 2013-03-01 11:22 AM, Adrian Chadd wrote: >>>>> On 1 March 2013 02:14, Felix Fietkau <nbd@openwrt.org> wrote: >>>>> >>>>>>> Having access to schedule which peer and how much to send to each peer >>>>>>> would be nice. Stuff like "peer X only can have up to x ms in this WME >>>>>>> class this round", so you don't have a busy, close peer monopolising >>>>>>> the air. It also means you can start doing smart things with far away >>>>>>> peers who retransmit a lot - they're likely tying up a lot of airtime. >>>>>>> >>>>>>> None of this is new. It's just, you know, new to open source. :-) >>>>> >>>>>> In my opinion this doesn't really belong into a rate control module. >>>>>> There should be a tx scheduling API to take care of this. Before I >>>>>> implement something like this, I plan on exposing all per-station driver >>>>>> queues to mac80211. This is necessary for a few other things anyway, >>>>>> e.g. unifying software aggregation logic and fixing its buffer management. >>>>> >>>>> Sure, but then some more clever tricks end up being difficult to >>>>> implement. For example, knowing if a client is tying up too much >>>>> airtime at the given rate and whether to back them off for a bit. Or >>>>> to use smaller aggregation limits for certain clients because your'e >>>>> trying to be "fairer" when trying to keep latency low. That kind of >>>>> thing. >>>>> >>>>> I think "rate control" should likely be expanded to "tx scheduling" as >>>>> a whole, rather than sitting as a separate thing that just selects the >>>>> rate for a node who has already been chosen to transmit. >>>> Even with client airtime use, I still don't see how tx scheduling and >>>> rate control belong together. In my opinion, the rate selection should >>>> not be based on client airtime usage or the current load, as it can >>>> optimize for throughput/airtime ratio without it. >>>> >>> >>> Algorithm folks and Engineers had spent considerable time on ath9k rate control. >>> Wouldn't be a great idea to remove it completely, We can have it optional. >>> With lot of throughput tests ran over internally and with the test >>> team verification, >>> it wouldn't be fair to throw it away. >> Regardless of how much time was spent tuning it, it still has a really >> bad design, bad implementation and a number of practical issues. >> It seems to be tuned entirely for artificial benchmarks in clean air. It >> also starts with a very high rate without having proven that it works. >> I don't think anybody is going to fix all of these issues, and even if >> somebody does, it would invalidate pretty much all of the tuning/testing >> that went into this code. >> > > We can certainly question the design and implementation, but it was proven > to work well and had been tested by more hands(even with propitiatory stuff). > Even if some one thinks it as bad, we should still allow it as an option. > For instance if the environment is pretty good/pretty bad, we should give > the users an option to choose between the two, that's why we should retain > it. I agree that we should keep it for a while, but we should probably change the default soon. As for giving *users* the option of choosing rate control based on the environment, I think it's a bad idea! Regular users can't really be expected to know enough about the details of rate control to make a meaningful decision, nor should they be. Simply being lazy and telling every user to just test which one works better for them is also a bad idea. The default implementation needs to be good for all kinds of environments. minstrel_ht is already tuned to work quite well in tough environments with heavy interference, so closing the performance gap in clean environments should be quite easy. The main thing I need to get that done is good quality test feedback - something that I didn't get a lot of, neither from users, nor from QCA. > Further its been tested internally, by customers and more folks. Right, and a few of those customers complained about bad performance with ath9k, and also reported that switching to minstrel_ht fixed their issues :) Good to know that it's been tested, but where are the results? Who is going to take care of the long standing *known* issues? One of these issues (too high bitrate before rate feedback is available) led to somebody from Google hacking up a crappy workaround in wpa_supplicant that disables high bitrates during connect. Saying that it has been tested does not necessarily imply that it's any good or that it works properly in all normal scenarios ;) > Its been also worked by some serious developers and Engineers. Well, I do consider myself a serious developer and engineer as well :) - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Felix Fietkau wrote:
> What was the distance and what was the rate used?
A distance of about a meter between the AP and STA.
AP: DB120 - running an internal build.
STA: WB222 - wireless-testing HEAD.
Signal is about -43 dBm.
Channel 40, HT40-
I've attached sample runs with minstrel_ht and ath9k-rc. With minstrel_ht,
the numbers fluctuate between 180 and 190 Mbps and the average throughput
varies each time (185, 186 etc.). With ath9k-rc, it's 195+ always.
Sujith
root@linux-test ~# iperf -i1 -c 172.16.1.222 -t 120 -P 4
------------------------------------------------------------
Client connecting to 172.16.1.222, TCP port 5001
TCP window size: 22.9 KByte (default)
------------------------------------------------------------
[ 3] local 172.16.1.111 port 36815 connected with 172.16.1.222 port 5001
[ 4] local 172.16.1.111 port 36816 connected with 172.16.1.222 port 5001
[ 5] local 172.16.1.111 port 36817 connected with 172.16.1.222 port 5001
[ 6] local 172.16.1.111 port 36818 connected with 172.16.1.222 port 5001
19:[SUM] 0.0- 1.0 sec 22.8 MBytes 191 Mbits/sec
24:[SUM] 1.0- 2.0 sec 23.0 MBytes 193 Mbits/sec
29:[SUM] 2.0- 3.0 sec 23.6 MBytes 198 Mbits/sec
34:[SUM] 3.0- 4.0 sec 22.9 MBytes 192 Mbits/sec
39:[SUM] 4.0- 5.0 sec 23.2 MBytes 195 Mbits/sec
44:[SUM] 5.0- 6.0 sec 22.6 MBytes 190 Mbits/sec
49:[SUM] 6.0- 7.0 sec 23.2 MBytes 195 Mbits/sec
54:[SUM] 7.0- 8.0 sec 23.8 MBytes 199 Mbits/sec
59:[SUM] 8.0- 9.0 sec 23.1 MBytes 194 Mbits/sec
64:[SUM] 9.0-10.0 sec 23.4 MBytes 196 Mbits/sec
69:[SUM] 10.0-11.0 sec 23.0 MBytes 193 Mbits/sec
74:[SUM] 11.0-12.0 sec 23.2 MBytes 195 Mbits/sec
79:[SUM] 12.0-13.0 sec 22.8 MBytes 191 Mbits/sec
84:[SUM] 13.0-14.0 sec 23.0 MBytes 193 Mbits/sec
89:[SUM] 14.0-15.0 sec 23.1 MBytes 194 Mbits/sec
94:[SUM] 15.0-16.0 sec 23.0 MBytes 193 Mbits/sec
99:[SUM] 16.0-17.0 sec 22.5 MBytes 189 Mbits/sec
104:[SUM] 17.0-18.0 sec 23.2 MBytes 195 Mbits/sec
109:[SUM] 18.0-19.0 sec 23.4 MBytes 196 Mbits/sec
114:[SUM] 19.0-20.0 sec 23.4 MBytes 196 Mbits/sec
119:[SUM] 20.0-21.0 sec 22.9 MBytes 192 Mbits/sec
124:[SUM] 21.0-22.0 sec 22.6 MBytes 190 Mbits/sec
129:[SUM] 22.0-23.0 sec 23.4 MBytes 196 Mbits/sec
134:[SUM] 23.0-24.0 sec 23.0 MBytes 193 Mbits/sec
139:[SUM] 24.0-25.0 sec 22.6 MBytes 190 Mbits/sec
144:[SUM] 25.0-26.0 sec 23.5 MBytes 197 Mbits/sec
149:[SUM] 26.0-27.0 sec 23.1 MBytes 194 Mbits/sec
154:[SUM] 27.0-28.0 sec 23.2 MBytes 195 Mbits/sec
159:[SUM] 28.0-29.0 sec 23.8 MBytes 199 Mbits/sec
164:[SUM] 29.0-30.0 sec 23.4 MBytes 196 Mbits/sec
169:[SUM] 30.0-31.0 sec 22.8 MBytes 191 Mbits/sec
174:[SUM] 31.0-32.0 sec 23.5 MBytes 197 Mbits/sec
179:[SUM] 32.0-33.0 sec 22.8 MBytes 191 Mbits/sec
184:[SUM] 33.0-34.0 sec 23.1 MBytes 194 Mbits/sec
189:[SUM] 34.0-35.0 sec 23.2 MBytes 195 Mbits/sec
194:[SUM] 35.0-36.0 sec 23.2 MBytes 195 Mbits/sec
199:[SUM] 36.0-37.0 sec 23.1 MBytes 194 Mbits/sec
204:[SUM] 37.0-38.0 sec 23.0 MBytes 193 Mbits/sec
209:[SUM] 38.0-39.0 sec 23.2 MBytes 195 Mbits/sec
214:[SUM] 39.0-40.0 sec 23.8 MBytes 199 Mbits/sec
219:[SUM] 40.0-41.0 sec 23.0 MBytes 193 Mbits/sec
224:[SUM] 41.0-42.0 sec 23.4 MBytes 196 Mbits/sec
229:[SUM] 42.0-43.0 sec 23.5 MBytes 197 Mbits/sec
234:[SUM] 43.0-44.0 sec 23.5 MBytes 197 Mbits/sec
239:[SUM] 44.0-45.0 sec 22.6 MBytes 190 Mbits/sec
244:[SUM] 45.0-46.0 sec 23.2 MBytes 195 Mbits/sec
249:[SUM] 46.0-47.0 sec 23.2 MBytes 195 Mbits/sec
254:[SUM] 47.0-48.0 sec 23.1 MBytes 194 Mbits/sec
259:[SUM] 48.0-49.0 sec 24.1 MBytes 202 Mbits/sec
264:[SUM] 49.0-50.0 sec 23.0 MBytes 193 Mbits/sec
269:[SUM] 50.0-51.0 sec 23.4 MBytes 196 Mbits/sec
274:[SUM] 51.0-52.0 sec 23.4 MBytes 196 Mbits/sec
279:[SUM] 52.0-53.0 sec 23.4 MBytes 196 Mbits/sec
284:[SUM] 53.0-54.0 sec 23.5 MBytes 197 Mbits/sec
289:[SUM] 54.0-55.0 sec 23.2 MBytes 195 Mbits/sec
294:[SUM] 55.0-56.0 sec 23.2 MBytes 195 Mbits/sec
299:[SUM] 56.0-57.0 sec 23.2 MBytes 195 Mbits/sec
304:[SUM] 57.0-58.0 sec 22.8 MBytes 191 Mbits/sec
309:[SUM] 58.0-59.0 sec 23.6 MBytes 198 Mbits/sec
314:[SUM] 59.0-60.0 sec 23.1 MBytes 194 Mbits/sec
319:[SUM] 60.0-61.0 sec 22.9 MBytes 192 Mbits/sec
324:[SUM] 61.0-62.0 sec 23.4 MBytes 196 Mbits/sec
329:[SUM] 62.0-63.0 sec 23.4 MBytes 196 Mbits/sec
334:[SUM] 63.0-64.0 sec 22.5 MBytes 189 Mbits/sec
339:[SUM] 64.0-65.0 sec 23.8 MBytes 199 Mbits/sec
344:[SUM] 65.0-66.0 sec 23.0 MBytes 193 Mbits/sec
349:[SUM] 66.0-67.0 sec 24.1 MBytes 202 Mbits/sec
354:[SUM] 67.0-68.0 sec 22.6 MBytes 190 Mbits/sec
359:[SUM] 68.0-69.0 sec 23.0 MBytes 193 Mbits/sec
364:[SUM] 69.0-70.0 sec 23.2 MBytes 195 Mbits/sec
369:[SUM] 70.0-71.0 sec 23.2 MBytes 195 Mbits/sec
374:[SUM] 71.0-72.0 sec 22.2 MBytes 187 Mbits/sec
379:[SUM] 72.0-73.0 sec 23.1 MBytes 194 Mbits/sec
384:[SUM] 73.0-74.0 sec 23.9 MBytes 200 Mbits/sec
389:[SUM] 74.0-75.0 sec 22.9 MBytes 192 Mbits/sec
394:[SUM] 75.0-76.0 sec 23.6 MBytes 198 Mbits/sec
399:[SUM] 76.0-77.0 sec 23.1 MBytes 194 Mbits/sec
404:[SUM] 77.0-78.0 sec 23.1 MBytes 194 Mbits/sec
409:[SUM] 78.0-79.0 sec 23.8 MBytes 199 Mbits/sec
414:[SUM] 79.0-80.0 sec 23.8 MBytes 199 Mbits/sec
419:[SUM] 80.0-81.0 sec 23.1 MBytes 194 Mbits/sec
424:[SUM] 81.0-82.0 sec 22.9 MBytes 192 Mbits/sec
429:[SUM] 82.0-83.0 sec 23.4 MBytes 196 Mbits/sec
434:[SUM] 83.0-84.0 sec 23.4 MBytes 196 Mbits/sec
439:[SUM] 84.0-85.0 sec 23.5 MBytes 197 Mbits/sec
444:[SUM] 85.0-86.0 sec 23.9 MBytes 200 Mbits/sec
449:[SUM] 86.0-87.0 sec 22.9 MBytes 192 Mbits/sec
454:[SUM] 87.0-88.0 sec 23.4 MBytes 196 Mbits/sec
459:[SUM] 88.0-89.0 sec 23.4 MBytes 196 Mbits/sec
464:[SUM] 89.0-90.0 sec 23.4 MBytes 196 Mbits/sec
469:[SUM] 90.0-91.0 sec 22.9 MBytes 192 Mbits/sec
474:[SUM] 91.0-92.0 sec 23.6 MBytes 198 Mbits/sec
479:[SUM] 92.0-93.0 sec 23.1 MBytes 194 Mbits/sec
484:[SUM] 93.0-94.0 sec 23.2 MBytes 195 Mbits/sec
489:[SUM] 94.0-95.0 sec 23.2 MBytes 195 Mbits/sec
494:[SUM] 95.0-96.0 sec 23.1 MBytes 194 Mbits/sec
499:[SUM] 96.0-97.0 sec 22.9 MBytes 192 Mbits/sec
504:[SUM] 97.0-98.0 sec 23.2 MBytes 195 Mbits/sec
509:[SUM] 98.0-99.0 sec 23.4 MBytes 196 Mbits/sec
514:[SUM] 99.0-100.0 sec 23.5 MBytes 197 Mbits/sec
519:[SUM] 100.0-101.0 sec 24.0 MBytes 201 Mbits/sec
524:[SUM] 101.0-102.0 sec 23.5 MBytes 197 Mbits/sec
529:[SUM] 102.0-103.0 sec 23.0 MBytes 193 Mbits/sec
534:[SUM] 103.0-104.0 sec 23.1 MBytes 194 Mbits/sec
539:[SUM] 104.0-105.0 sec 23.4 MBytes 196 Mbits/sec
544:[SUM] 105.0-106.0 sec 23.0 MBytes 193 Mbits/sec
549:[SUM] 106.0-107.0 sec 23.5 MBytes 197 Mbits/sec
554:[SUM] 107.0-108.0 sec 23.4 MBytes 196 Mbits/sec
559:[SUM] 108.0-109.0 sec 23.0 MBytes 193 Mbits/sec
564:[SUM] 109.0-110.0 sec 22.6 MBytes 190 Mbits/sec
569:[SUM] 110.0-111.0 sec 23.8 MBytes 199 Mbits/sec
574:[SUM] 111.0-112.0 sec 23.2 MBytes 195 Mbits/sec
579:[SUM] 112.0-113.0 sec 23.6 MBytes 198 Mbits/sec
584:[SUM] 113.0-114.0 sec 24.1 MBytes 202 Mbits/sec
589:[SUM] 114.0-115.0 sec 22.4 MBytes 188 Mbits/sec
594:[SUM] 115.0-116.0 sec 23.1 MBytes 194 Mbits/sec
599:[SUM] 116.0-117.0 sec 23.4 MBytes 196 Mbits/sec
604:[SUM] 117.0-118.0 sec 22.9 MBytes 192 Mbits/sec
609:[SUM] 118.0-119.0 sec 22.9 MBytes 192 Mbits/sec
617:[SUM] 119.0-120.0 sec 23.4 MBytes 196 Mbits/sec
619:[SUM] 0.0-120.0 sec 2.72 GBytes 195 Mbits/sec
cat /sys/kernel/debug/ieee80211/phy2/netdev:wlan0/stations/00:03:7f:42:08:56/rc_stats
HT MCS Rate Success Retries XRetries PER
HT20 0 6.5: 0 0 0 0
HT40 0 13.5: 0 0 0 0
HT40 1 27.5: 0 0 0 0
HT40 2 40.5: 0 0 0 0
HT40 3 54.0: 0 0 0 0
HT40 4 81.5: 0 0 0 0
HT40 11 108.0: 0 0 0 0
HT40 12 162.0: 0 0 0 0
HT40 13 216.0: 1 0 0 0
HT40 14 243.0: 2 0 0 0
HT40 15 270.0: 314 35 0 0
HT40 15 300.0: 64236 6607 8 0
cat /sys/kernel/debug/ieee80211/phy2/ath9k/xmit
BE BK VI VO
MPDUs Queued: 2 0 0 53
MPDUs Completed: 2 0 0 53
MPDUs XRetried: 0 0 0 0
Aggregates: 64462 0 0 0
AMPDUs Queued HW: 46 0 0 0
AMPDUs Queued SW: 2018211 0 0 0
AMPDUs Completed: 2018257 0 0 0
AMPDUs Retried: 21058 0 0 0
AMPDUs XRetried: 0 0 0 0
FIFO Underrun: 0 0 0 0
TXOP Exceeded: 0 0 0 0
TXTIMER Expiry: 0 0 0 0
DESC CFG Error: 0 0 0 0
DATA Underrun: 0 0 0 0
DELIM Underrun: 0 0 0 0
TX-Pkts-All: 2018259 0 0 53
TX-Bytes-All: 3099857109 0 0 2440
HW-put-tx-buf: 64534 0 0 53
HW-tx-start: 0 0 0 0
HW-tx-proc-desc: 64534 0 0 53
TX-Failed: 0 0 0 0
root@linux-test ~# iperf -i1 -c 172.16.1.222 -t 120 -P 4
------------------------------------------------------------
Client connecting to 172.16.1.222, TCP port 5001
TCP window size: 22.9 KByte (default)
------------------------------------------------------------
[ 5] local 172.16.1.111 port 36820 connected with 172.16.1.222 port 5001
[ 4] local 172.16.1.111 port 36819 connected with 172.16.1.222 port 5001
[ 3] local 172.16.1.111 port 36821 connected with 172.16.1.222 port 5001
[ 6] local 172.16.1.111 port 36822 connected with 172.16.1.222 port 5001
685:[SUM] 0.0- 1.0 sec 21.0 MBytes 176 Mbits/sec
690:[SUM] 1.0- 2.0 sec 21.8 MBytes 182 Mbits/sec
695:[SUM] 2.0- 3.0 sec 21.8 MBytes 182 Mbits/sec
700:[SUM] 3.0- 4.0 sec 22.8 MBytes 191 Mbits/sec
705:[SUM] 4.0- 5.0 sec 22.5 MBytes 189 Mbits/sec
710:[SUM] 5.0- 6.0 sec 22.9 MBytes 192 Mbits/sec
715:[SUM] 6.0- 7.0 sec 22.2 MBytes 187 Mbits/sec
720:[SUM] 7.0- 8.0 sec 22.0 MBytes 185 Mbits/sec
725:[SUM] 8.0- 9.0 sec 23.1 MBytes 194 Mbits/sec
730:[SUM] 9.0-10.0 sec 21.9 MBytes 184 Mbits/sec
735:[SUM] 10.0-11.0 sec 22.5 MBytes 189 Mbits/sec
740:[SUM] 11.0-12.0 sec 22.1 MBytes 186 Mbits/sec
745:[SUM] 12.0-13.0 sec 22.5 MBytes 189 Mbits/sec
750:[SUM] 13.0-14.0 sec 23.0 MBytes 193 Mbits/sec
755:[SUM] 14.0-15.0 sec 21.5 MBytes 180 Mbits/sec
760:[SUM] 15.0-16.0 sec 22.5 MBytes 189 Mbits/sec
765:[SUM] 16.0-17.0 sec 22.8 MBytes 191 Mbits/sec
770:[SUM] 17.0-18.0 sec 22.8 MBytes 191 Mbits/sec
775:[SUM] 18.0-19.0 sec 21.9 MBytes 184 Mbits/sec
780:[SUM] 19.0-20.0 sec 21.1 MBytes 177 Mbits/sec
785:[SUM] 20.0-21.0 sec 22.8 MBytes 191 Mbits/sec
790:[SUM] 21.0-22.0 sec 22.5 MBytes 189 Mbits/sec
795:[SUM] 22.0-23.0 sec 22.5 MBytes 189 Mbits/sec
800:[SUM] 23.0-24.0 sec 22.6 MBytes 190 Mbits/sec
805:[SUM] 24.0-25.0 sec 21.5 MBytes 180 Mbits/sec
810:[SUM] 25.0-26.0 sec 22.1 MBytes 186 Mbits/sec
815:[SUM] 26.0-27.0 sec 22.1 MBytes 186 Mbits/sec
820:[SUM] 27.0-28.0 sec 21.6 MBytes 181 Mbits/sec
825:[SUM] 28.0-29.0 sec 22.6 MBytes 190 Mbits/sec
830:[SUM] 29.0-30.0 sec 23.0 MBytes 193 Mbits/sec
835:[SUM] 30.0-31.0 sec 22.8 MBytes 191 Mbits/sec
840:[SUM] 31.0-32.0 sec 22.6 MBytes 190 Mbits/sec
845:[SUM] 32.0-33.0 sec 21.9 MBytes 184 Mbits/sec
850:[SUM] 33.0-34.0 sec 21.6 MBytes 181 Mbits/sec
855:[SUM] 34.0-35.0 sec 22.9 MBytes 192 Mbits/sec
860:[SUM] 35.0-36.0 sec 22.0 MBytes 185 Mbits/sec
865:[SUM] 36.0-37.0 sec 22.6 MBytes 190 Mbits/sec
870:[SUM] 37.0-38.0 sec 22.2 MBytes 187 Mbits/sec
875:[SUM] 38.0-39.0 sec 22.5 MBytes 189 Mbits/sec
880:[SUM] 39.0-40.0 sec 21.9 MBytes 184 Mbits/sec
885:[SUM] 40.0-41.0 sec 22.6 MBytes 190 Mbits/sec
890:[SUM] 41.0-42.0 sec 22.2 MBytes 187 Mbits/sec
895:[SUM] 42.0-43.0 sec 21.9 MBytes 184 Mbits/sec
900:[SUM] 43.0-44.0 sec 22.4 MBytes 188 Mbits/sec
905:[SUM] 44.0-45.0 sec 20.5 MBytes 172 Mbits/sec
910:[SUM] 45.0-46.0 sec 22.4 MBytes 188 Mbits/sec
915:[SUM] 46.0-47.0 sec 23.0 MBytes 193 Mbits/sec
920:[SUM] 47.0-48.0 sec 21.8 MBytes 182 Mbits/sec
925:[SUM] 48.0-49.0 sec 22.2 MBytes 187 Mbits/sec
930:[SUM] 49.0-50.0 sec 22.4 MBytes 188 Mbits/sec
935:[SUM] 50.0-51.0 sec 22.4 MBytes 188 Mbits/sec
940:[SUM] 51.0-52.0 sec 23.1 MBytes 194 Mbits/sec
945:[SUM] 52.0-53.0 sec 22.4 MBytes 188 Mbits/sec
950:[SUM] 53.0-54.0 sec 22.6 MBytes 190 Mbits/sec
955:[SUM] 54.0-55.0 sec 22.8 MBytes 191 Mbits/sec
960:[SUM] 55.0-56.0 sec 22.4 MBytes 188 Mbits/sec
965:[SUM] 56.0-57.0 sec 22.5 MBytes 189 Mbits/sec
970:[SUM] 57.0-58.0 sec 23.0 MBytes 193 Mbits/sec
975:[SUM] 58.0-59.0 sec 22.1 MBytes 186 Mbits/sec
980:[SUM] 59.0-60.0 sec 21.8 MBytes 182 Mbits/sec
985:[SUM] 60.0-61.0 sec 21.6 MBytes 181 Mbits/sec
990:[SUM] 61.0-62.0 sec 22.6 MBytes 190 Mbits/sec
995:[SUM] 62.0-63.0 sec 22.1 MBytes 186 Mbits/sec
1000:[SUM] 63.0-64.0 sec 21.8 MBytes 182 Mbits/sec
1005:[SUM] 64.0-65.0 sec 22.2 MBytes 187 Mbits/sec
1010:[SUM] 65.0-66.0 sec 21.8 MBytes 182 Mbits/sec
1015:[SUM] 66.0-67.0 sec 22.2 MBytes 187 Mbits/sec
1020:[SUM] 67.0-68.0 sec 22.2 MBytes 187 Mbits/sec
1025:[SUM] 68.0-69.0 sec 23.2 MBytes 195 Mbits/sec
1030:[SUM] 69.0-70.0 sec 23.2 MBytes 195 Mbits/sec
1035:[SUM] 70.0-71.0 sec 22.5 MBytes 189 Mbits/sec
1040:[SUM] 71.0-72.0 sec 22.2 MBytes 187 Mbits/sec
1045:[SUM] 72.0-73.0 sec 22.0 MBytes 185 Mbits/sec
1050:[SUM] 73.0-74.0 sec 21.9 MBytes 184 Mbits/sec
1055:[SUM] 74.0-75.0 sec 22.5 MBytes 189 Mbits/sec
1060:[SUM] 75.0-76.0 sec 22.4 MBytes 188 Mbits/sec
1065:[SUM] 76.0-77.0 sec 22.6 MBytes 190 Mbits/sec
1070:[SUM] 77.0-78.0 sec 22.9 MBytes 192 Mbits/sec
1075:[SUM] 78.0-79.0 sec 22.1 MBytes 186 Mbits/sec
1080:[SUM] 79.0-80.0 sec 22.0 MBytes 185 Mbits/sec
1085:[SUM] 80.0-81.0 sec 21.9 MBytes 184 Mbits/sec
1090:[SUM] 81.0-82.0 sec 21.5 MBytes 180 Mbits/sec
1095:[SUM] 82.0-83.0 sec 22.4 MBytes 188 Mbits/sec
1100:[SUM] 83.0-84.0 sec 23.4 MBytes 196 Mbits/sec
1105:[SUM] 84.0-85.0 sec 22.0 MBytes 185 Mbits/sec
1110:[SUM] 85.0-86.0 sec 22.5 MBytes 189 Mbits/sec
1115:[SUM] 86.0-87.0 sec 22.8 MBytes 191 Mbits/sec
1120:[SUM] 87.0-88.0 sec 22.4 MBytes 188 Mbits/sec
1125:[SUM] 88.0-89.0 sec 22.1 MBytes 186 Mbits/sec
1130:[SUM] 89.0-90.0 sec 22.8 MBytes 191 Mbits/sec
1135:[SUM] 90.0-91.0 sec 21.4 MBytes 179 Mbits/sec
1140:[SUM] 91.0-92.0 sec 22.4 MBytes 188 Mbits/sec
1145:[SUM] 92.0-93.0 sec 22.9 MBytes 192 Mbits/sec
1150:[SUM] 93.0-94.0 sec 22.9 MBytes 192 Mbits/sec
1155:[SUM] 94.0-95.0 sec 23.4 MBytes 196 Mbits/sec
1160:[SUM] 95.0-96.0 sec 21.1 MBytes 177 Mbits/sec
1165:[SUM] 96.0-97.0 sec 22.0 MBytes 185 Mbits/sec
1170:[SUM] 97.0-98.0 sec 22.2 MBytes 187 Mbits/sec
1175:[SUM] 98.0-99.0 sec 22.5 MBytes 189 Mbits/sec
1180:[SUM] 99.0-100.0 sec 22.2 MBytes 187 Mbits/sec
1185:[SUM] 100.0-101.0 sec 22.4 MBytes 188 Mbits/sec
1190:[SUM] 101.0-102.0 sec 22.5 MBytes 189 Mbits/sec
1195:[SUM] 102.0-103.0 sec 23.0 MBytes 193 Mbits/sec
1200:[SUM] 103.0-104.0 sec 22.0 MBytes 185 Mbits/sec
1205:[SUM] 104.0-105.0 sec 22.0 MBytes 185 Mbits/sec
1210:[SUM] 105.0-106.0 sec 22.5 MBytes 189 Mbits/sec
1215:[SUM] 106.0-107.0 sec 22.1 MBytes 186 Mbits/sec
1220:[SUM] 107.0-108.0 sec 22.4 MBytes 188 Mbits/sec
1225:[SUM] 108.0-109.0 sec 22.8 MBytes 191 Mbits/sec
1230:[SUM] 109.0-110.0 sec 22.4 MBytes 188 Mbits/sec
1235:[SUM] 110.0-111.0 sec 22.2 MBytes 187 Mbits/sec
1240:[SUM] 111.0-112.0 sec 22.9 MBytes 192 Mbits/sec
1245:[SUM] 112.0-113.0 sec 23.1 MBytes 194 Mbits/sec
1250:[SUM] 113.0-114.0 sec 23.1 MBytes 194 Mbits/sec
1255:[SUM] 114.0-115.0 sec 21.8 MBytes 182 Mbits/sec
1260:[SUM] 115.0-116.0 sec 21.5 MBytes 180 Mbits/sec
1265:[SUM] 116.0-117.0 sec 22.0 MBytes 185 Mbits/sec
1270:[SUM] 117.0-118.0 sec 21.8 MBytes 182 Mbits/sec
1275:[SUM] 118.0-119.0 sec 23.1 MBytes 194 Mbits/sec
1283:[SUM] 119.0-120.0 sec 23.2 MBytes 195 Mbits/sec
1285:[SUM] 0.0-120.0 sec 2.62 GBytes 187 Mbits/sec
cat /sys/kernel/debug/ieee80211/phy3/netdev:wlan0/stations/00:03:7f:42:08:56/rc_stats
type rate throughput ewma prob this prob retry this succ/attempt success attempts
HT20/LGI MCS0 6.6 99.9 100.0 2 0( 0) 86 91
HT20/LGI MCS1 10.5 81.1 100.0 2 0( 0) 90 96
HT20/LGI MCS2 17.5 91.8 100.0 2 0( 0) 88 91
HT20/LGI MCS3 24.9 99.6 100.0 2 0( 0) 85 92
HT20/LGI MCS4 36.0 99.2 100.0 2 0( 0) 88 92
HT20/LGI MCS5 42.8 92.0 100.0 2 0( 0) 85 90
HT20/LGI MCS6 48.2 94.0 100.0 2 0( 0) 85 95
HT20/LGI MCS7 57.1 99.9 100.0 2 0( 0) 92 95
HT20/LGI MCS8 12.9 99.5 100.0 2 0( 0) 89 93
HT20/LGI MCS9 24.1 96.4 100.0 2 0( 0) 91 96
HT20/LGI MCS10 36.3 99.9 100.0 2 0( 0) 86 91
HT20/LGI MCS11 46.5 99.9 100.0 2 0( 0) 92 96
HT20/LGI MCS12 60.3 91.1 100.0 2 0( 0) 89 93
HT20/LGI MCS13 81.1 99.8 100.0 2 0( 0) 86 93
HT20/LGI MCS14 90.0 99.9 100.0 2 0( 0) 91 96
HT20/LGI MCS15 83.4 85.9 100.0 2 0( 0) 97 99
HT20/SGI MCS0 7.3 99.6 100.0 2 0( 0) 87 93
HT20/SGI MCS1 14.4 99.9 100.0 2 0( 0) 88 93
HT20/SGI MCS2 20.9 99.3 100.0 2 0( 0) 88 93
HT20/SGI MCS3 27.4 99.3 100.0 2 0( 0) 90 96
HT20/SGI MCS4 37.9 95.2 100.0 2 0( 0) 83 92
HT20/SGI MCS5 48.4 95.5 100.0 2 0( 0) 87 93
HT20/SGI MCS6 55.6 99.6 100.0 2 0( 0) 93 100
HT20/SGI MCS7 60.9 98.1 100.0 2 0( 0) 93 95
HT20/SGI MCS8 13.7 95.3 100.0 2 0( 0) 82 90
HT20/SGI MCS9 26.8 97.3 100.0 2 0( 0) 84 90
HT20/SGI MCS10 39.8 99.9 100.0 2 0( 0) 90 91
HT20/SGI MCS11 50.7 99.9 100.0 2 0( 0) 87 92
HT20/SGI MCS12 71.1 98.9 100.0 2 0( 0) 85 89
HT20/SGI MCS13 80.2 91.4 100.0 2 0( 0) 87 91
HT20/SGI MCS14 97.0 99.9 100.0 2 0( 0) 92 97
HT20/SGI MCS15 78.0 74.9 0.0 2 0( 0) 476 538
HT40/LGI MCS0 13.5 99.8 100.0 2 0( 0) 90 95
HT40/LGI MCS1 26.0 99.9 100.0 2 0( 0) 86 90
HT40/LGI MCS2 36.1 96.6 100.0 2 0( 0) 89 92
HT40/LGI MCS3 44.4 92.0 100.0 2 0( 0) 91 94
HT40/LGI MCS4 61.7 90.7 100.0 2 0( 0) 86 93
HT40/LGI MCS5 70.1 83.4 100.0 2 0( 0) 81 91
HT40/LGI MCS6 85.9 92.0 100.0 2 0( 0) 91 96
HT40/LGI MCS7 100.6 99.6 100.0 2 0( 0) 88 94
HT40/LGI MCS8 25.5 97.9 100.0 2 0( 0) 83 92
HT40/LGI MCS9 44.4 92.0 100.0 2 0( 0) 84 90
HT40/LGI MCS10 67.7 99.5 100.0 2 0( 0) 81 91
HT40/LGI MCS11 59.2 70.5 0.0 2 0( 0) 85 89
HT40/LGI MCS12 105.8 92.0 100.0 3 0( 0) 90 93
HT40/LGI MCS13 118.3 88.7 100.0 3 0( 0) 84 89
HT40/LGI MCS14 145.4 97.4 100.0 4 0( 0) 768 899
HT40/LGI MCS15 130.0 81.9 100.0 4 0( 0) 80856 88875
HT40/SGI MCS0 14.9 99.9 100.0 2 0( 0) 86 91
HT40/SGI MCS1 21.4 74.7 0.0 2 0( 0) 91 95
HT40/SGI MCS2 41.1 99.9 100.0 2 0( 0) 85 91
HT40/SGI MCS3 49.7 93.9 100.0 2 0( 0) 88 93
HT40/SGI MCS4 55.4 74.8 0.0 2 0( 0) 88 92
HT40/SGI MCS5 86.9 95.6 100.0 2 0( 0) 85 91
HT40/SGI MCS6 100.9 99.9 100.0 2 0( 0) 86 94
HT40/SGI P MCS7 106.9 98.4 100.0 5 0( 0) 4424 4980
HT40/SGI MCS8 28.6 99.8 100.0 2 0( 0) 87 89
HT40/SGI MCS9 45.1 85.3 100.0 2 0( 0) 85 91
HT40/SGI MCS10 72.6 98.1 100.0 2 0( 0) 88 90
HT40/SGI MCS11 89.9 98.9 100.0 2 0( 0) 80 88
HT40/SGI MCS12 121.9 98.7 100.0 3 0( 0) 86 92
HT40/SGI MCS13 132.4 94.0 100.0 3 0( 0) 85 89
HT40/SGI t MCS14 152.6 96.1 100.0 5 0( 0) 88243 96781
HT40/SGI T MCS15 161.8 97.1 100.0 5 1( 1) 1760690 1945362
Total packet count:: ideal 1934621 lookaround 5901
Average A-MPDU length: 4.4
cat /sys/kernel/debug/ieee80211/phy3/ath9k/xmit
BE BK VI VO
MPDUs Queued: 10 0 0 47
MPDUs Completed: 10 0 0 47
MPDUs XRetried: 0 0 0 0
Aggregates: 63956 0 0 0
AMPDUs Queued HW: 99 0 0 0
AMPDUs Queued SW: 1940401 0 0 0
AMPDUs Completed: 1940500 0 0 0
AMPDUs Retried: 14536 0 0 0
AMPDUs XRetried: 0 0 0 0
FIFO Underrun: 0 0 0 0
TXOP Exceeded: 0 0 0 0
TXTIMER Expiry: 0 0 0 0
DESC CFG Error: 0 0 0 0
DATA Underrun: 0 0 0 0
DELIM Underrun: 0 0 0 0
TX-Pkts-All: 1940510 0 0 47
TX-Bytes-All: 2980293154 0 0 2296
HW-put-tx-buf: 70308 0 0 47
HW-tx-start: 0 0 0 0
HW-tx-proc-desc: 70308 0 0 47
TX-Failed: 0 0 0 0
On 03/01/2013 06:31 AM, Sujith Manoharan wrote: > Felix Fietkau wrote: >> What was the distance and what was the rate used? > > A distance of about a meter between the AP and STA. > > AP: DB120 - running an internal build. > STA: WB222 - wireless-testing HEAD. > Signal is about -43 dBm. > Channel 40, HT40- > > I've attached sample runs with minstrel_ht and ath9k-rc. With minstrel_ht, > the numbers fluctuate between 180 and 190 Mbps and the average throughput > varies each time (185, 186 etc.). With ath9k-rc, it's 195+ always. We can run some tests through attenuators today. I assume UDP would be good, or is TCP traffic preferred? (In our tests, we see significantly more throughput with UDP than TCP, even when we hacked on TCP ack delay). Is wireless-testing the preferred tree to test against? Thanks, Ben > > Sujith >
On 1 March 2013 07:35, Ben Greear <greearb@candelatech.com> wrote: > I assume UDP would be good, or is TCP traffic preferred? > (In our tests, we see significantly more throughput with > UDP than TCP, even when we hacked on TCP ack delay). > > Is wireless-testing the preferred tree to test against? Do both. Failures at higher MCS rates -> extra latency -> TCP backoff -> crappier throughput. Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 1 March 2013 06:31, Sujith Manoharan <sujith@msujith.org> wrote: > Felix Fietkau wrote: >> What was the distance and what was the rate used? > > A distance of about a meter between the AP and STA. > > AP: DB120 - running an internal build. > STA: WB222 - wireless-testing HEAD. > Signal is about -43 dBm. > Channel 40, HT40- > > I've attached sample runs with minstrel_ht and ath9k-rc. With minstrel_ht, > the numbers fluctuate between 180 and 190 Mbps and the average throughput > varies each time (185, 186 etc.). With ath9k-rc, it's 195+ always. Right. And the reason that it fluctuates is quite likely because at the higher MCS rates (6,7/14,15/22,23) the channel behaviour is not consistent and there's varying levels of packet loss, so things oscillate between a bunch of MCS rates there. IIRC, the ath9k_rc algorithm is a lot more aggressive at sticking to a fixed, working MCS rate. (190mbit TCP on 2-stream? Damn. Looks like I have a little more optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.) Thanks, Adrian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Adrian Chadd wrote: > (190mbit TCP on 2-stream? Damn. Looks like I have a little more > optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on > AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.) I used a AR9462 card for this test. With AR9280/AR9287 I get abysmal numbers with both rate control algorithms. Maybe something has regressed in ath9k for the AR9002 family... Sujith -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 1 March 2013 18:19, Sujith Manoharan <sujith@msujith.org> wrote: > Adrian Chadd wrote: >> (190mbit TCP on 2-stream? Damn. Looks like I have a little more >> optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on >> AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.) > > I used a AR9462 card for this test. With AR9280/AR9287 I get abysmal > numbers with both rate control algorithms. Maybe something has regressed > in ath9k for the AR9002 family... It's almost like we need some kind of lab space set aside for running regression tests with all of the ath9k hardware ,dating back to AR5416, with some automated testing rigs.. I have the hardware. Who wants to do it? :) adrian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-03-01 21:40 -0800, Adrian Chadd wrote Sujith Manoharan: AC>On 1 March 2013 18:19, Sujith Manoharan <sujith@msujith.org> wrote: AC>> Adrian Chadd wrote: AC>>> (190mbit TCP on 2-stream? Damn. Looks like I have a little more AC>>> optimisation to do in FreeBSD. I'm only hitting 160/170mbit TCP on AC>>> AR9280<->AR9280 and AR9280<->AR9287. But I hit 220-240mbit UDP.) AC>> AC>> I used a AR9462 card for this test. With AR9280/AR9287 I get abysmal AC>> numbers with both rate control algorithms. Maybe something has regressed AC>> in ath9k for the AR9002 family... AC> AC>It's almost like we need some kind of lab space set aside for running AC>regression tests with all of the ath9k hardware ,dating back to AC>AR5416, with some automated testing rigs.. Think this is good idea, have same problem - no mo ~50 megabit on ar9002. AC>I have the hardware. Who wants to do it? :) C ????????? With Best Regards ???????????? ????. Georgiewskiy Yuriy +7 4872 711666 +7 4872 711666 ???? +7 4872 711143 fax +7 4872 711143 ???????? ??? "?? ?? ??????" IT Service Ltd http://nkoort.ru http://nkoort.ru JID: GHhost@icf.org.ru JID: GHhost@icf.org.ru YG129-RIPE YG129-RIPE
On 2013-03-01 3:31 PM, Sujith Manoharan wrote: > Felix Fietkau wrote: >> What was the distance and what was the rate used? > > A distance of about a meter between the AP and STA. > > AP: DB120 - running an internal build. > STA: WB222 - wireless-testing HEAD. > Signal is about -43 dBm. > Channel 40, HT40- > > I've attached sample runs with minstrel_ht and ath9k-rc. With minstrel_ht, > the numbers fluctuate between 180 and 190 Mbps and the average throughput > varies each time (185, 186 etc.). With ath9k-rc, it's 195+ always. I just sent some minstrel_ht improvements to linux-wireless@ Please test if they fix the throughput delta in your setup. In my tests they visibly reduce the number of unnecessary fallbacks to lower rates. Thanks, - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Felix Fietkau wrote: > I just sent some minstrel_ht improvements to linux-wireless@ > Please test if they fix the throughput delta in your setup. In my tests > they visibly reduce the number of unnecessary fallbacks to lower rates. With the fixes, the avg. TX throughput crept up to 188 Mbps, but I ran ath9k-rc once again and obtained 197 Mbps. There were lots of 200+ Mbps max. throughput too. This is not a synthetic benchmark with shield boxes, attenuators etc., just a simple over-the-air test with not much interference, so a gap of ~10 Mbps is somewhat surprising. Sujith -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 17507dc..037d919 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -92,14 +92,6 @@ config ATH9K_MAC_DEBUG This option enables collection of statistics for Rx/Tx status data and some other MAC related statistics -config ATH9K_RATE_CONTROL - bool "Atheros ath9k rate control" - depends on ATH9K - default y - ---help--- - Say Y, if you want to use the ath9k specific rate control - module instead of minstrel_ht. - config ATH9K_HTC tristate "Atheros HTC based wireless cards support" depends on USB && MAC80211 diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 2ad8f94..655e21d 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -8,7 +8,6 @@ ath9k-y += beacon.o \ antenna.o ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o -ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o ath9k-$(CONFIG_ATH9K_PCI) += pci.o ath9k-$(CONFIG_ATH9K_AHB) += ahb.o ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 410d6d8..06b5760 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -18,7 +18,6 @@ #define DEBUG_H #include "hw.h" -#include "rc.h" #include "dfs_debug.h" struct ath_txq; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 42cf3c7..6491973 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -21,7 +21,6 @@ #include "hw.h" #include "hw-ops.h" -#include "rc.h" #include "ar9003_mac.h" #include "ar9003_mci.h" #include "ar9003_phy.h" @@ -230,7 +229,7 @@ u32 ath9k_hw_reverse_bits(u32 val, u32 n) } u16 ath9k_hw_computetxtime(struct ath_hw *ah, - u8 phy, int kbps, + bool cck, int kbps, u32 frameLen, u16 rateix, bool shortPreamble) { @@ -239,15 +238,13 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, if (kbps == 0) return 0; - switch (phy) { - case WLAN_RC_PHY_CCK: + if (cck) { phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; if (shortPreamble) phyTime >>= 1; numBits = frameLen << 3; txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); - break; - case WLAN_RC_PHY_OFDM: + } else { if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) { bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; numBits = OFDM_PLCP_BITS + (frameLen << 3); @@ -270,12 +267,6 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME + (numSymbols * OFDM_SYMBOL_TIME); } - break; - default: - ath_err(ath9k_hw_common(ah), - "Unknown phy %u (rate ix %u)\n", phy, rateix); - txTime = 0; - break; } return txTime; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 784e81c..24f5b70 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -22,6 +22,8 @@ #include <linux/io.h> #include <linux/firmware.h> +struct ath_softc; + #include "mac.h" #include "ani.h" #include "eeprom.h" @@ -1013,7 +1015,7 @@ void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, int column, unsigned int *writecnt); u32 ath9k_hw_reverse_bits(u32 val, u32 n); u16 ath9k_hw_computetxtime(struct ath_hw *ah, - u8 phy, int kbps, + bool cck, int kbps, u32 frameLen, u16 rateix, bool shortPreamble); void ath9k_hw_get_channel_centers(struct ath_hw *ah, struct ath9k_channel *chan, diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index af932c9..c86cc70 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -809,10 +809,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) sc->ant_rx = hw->wiphy->available_antennas_rx; sc->ant_tx = hw->wiphy->available_antennas_tx; -#ifdef CONFIG_ATH9K_RATE_CONTROL - hw->rate_control_algorithm = "ath9k_rate_control"; -#endif - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; @@ -952,19 +948,11 @@ static int __init ath9k_init(void) { int error; - /* Register rate control algorithm */ - error = ath_rate_control_register(); - if (error != 0) { - pr_err("Unable to register rate control algorithm: %d\n", - error); - goto err_out; - } - error = ath_pci_init(); if (error < 0) { pr_err("No PCI devices found, driver not installed\n"); error = -ENODEV; - goto err_rate_unregister; + goto err_out; } error = ath_ahb_init(); @@ -978,8 +966,6 @@ static int __init ath9k_init(void) err_pci_exit: ath_pci_exit(); - err_rate_unregister: - ath_rate_control_unregister(); err_out: return error; } @@ -990,7 +976,6 @@ static void __exit ath9k_exit(void) is_ath9k_unloaded = true; ath_ahb_exit(); ath_pci_exit(); - ath_rate_control_unregister(); pr_info("%s: Driver unloaded\n", dev_info); } module_exit(ath9k_exit); diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c deleted file mode 100644 index 714558d..0000000 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ /dev/null @@ -1,1501 +0,0 @@ -/* - * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2004-2011 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <linux/slab.h> -#include <linux/export.h> - -#include "ath9k.h" - -static const struct ath_rate_table ar5416_11na_ratetable = { - 68, - 8, /* MCS start */ - { - [0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, - 5400, 0, 12 }, /* 6 Mb */ - [1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, - 7800, 1, 18 }, /* 9 Mb */ - [2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, - 10000, 2, 24 }, /* 12 Mb */ - [3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, - 13900, 3, 36 }, /* 18 Mb */ - [4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, - 17300, 4, 48 }, /* 24 Mb */ - [5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, - 23000, 5, 72 }, /* 36 Mb */ - [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, - 27400, 6, 96 }, /* 48 Mb */ - [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, - 29300, 7, 108 }, /* 54 Mb */ - [8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500, - 6400, 0, 0 }, /* 6.5 Mb */ - [9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, - 12700, 1, 1 }, /* 13 Mb */ - [10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, - 18800, 2, 2 }, /* 19.5 Mb */ - [11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, - 25000, 3, 3 }, /* 26 Mb */ - [12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, - 36700, 4, 4 }, /* 39 Mb */ - [13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, - 48100, 5, 5 }, /* 52 Mb */ - [14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, - 53500, 6, 6 }, /* 58.5 Mb */ - [15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, - 59000, 7, 7 }, /* 65 Mb */ - [16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, - 65400, 7, 7 }, /* 75 Mb */ - [17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, - 12700, 8, 8 }, /* 13 Mb */ - [18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, - 24800, 9, 9 }, /* 26 Mb */ - [19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, - 36600, 10, 10 }, /* 39 Mb */ - [20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, - 48100, 11, 11 }, /* 52 Mb */ - [21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, - 69500, 12, 12 }, /* 78 Mb */ - [22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, - 89500, 13, 13 }, /* 104 Mb */ - [23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, - 98900, 14, 14 }, /* 117 Mb */ - [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, - 108300, 15, 15 }, /* 130 Mb */ - [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, - 120000, 15, 15 }, /* 144.4 Mb */ - [26] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, - 17400, 16, 16 }, /* 19.5 Mb */ - [27] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, - 35100, 17, 17 }, /* 39 Mb */ - [28] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, - 52600, 18, 18 }, /* 58.5 Mb */ - [29] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, - 70400, 19, 19 }, /* 78 Mb */ - [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, - 104900, 20, 20 }, /* 117 Mb */ - [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, - 115800, 20, 20 }, /* 130 Mb*/ - [32] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, - 137200, 21, 21 }, /* 156 Mb */ - [33] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, - 151100, 21, 21 }, /* 173.3 Mb */ - [34] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, - 152800, 22, 22 }, /* 175.5 Mb */ - [35] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, - 168400, 22, 22 }, /* 195 Mb*/ - [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, - 168400, 23, 23 }, /* 195 Mb */ - [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, - 185000, 23, 23 }, /* 216.7 Mb */ - [38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, - 13200, 0, 0 }, /* 13.5 Mb*/ - [39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, - 25900, 1, 1 }, /* 27.0 Mb*/ - [40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, - 38600, 2, 2 }, /* 40.5 Mb*/ - [41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, - 49800, 3, 3 }, /* 54 Mb */ - [42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, - 72200, 4, 4 }, /* 81 Mb */ - [43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000, - 92900, 5, 5 }, /* 108 Mb */ - [44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, - 102700, 6, 6 }, /* 121.5 Mb*/ - [45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, - 112000, 7, 7 }, /* 135 Mb */ - [46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, - 122000, 7, 7 }, /* 150 Mb */ - [47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, - 25800, 8, 8 }, /* 27 Mb */ - [48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, - 49800, 9, 9 }, /* 54 Mb */ - [49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, - 71900, 10, 10 }, /* 81 Mb */ - [50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, - 92500, 11, 11 }, /* 108 Mb */ - [51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, - 130300, 12, 12 }, /* 162 Mb */ - [52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, - 162800, 13, 13 }, /* 216 Mb */ - [53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, - 178200, 14, 14 }, /* 243 Mb */ - [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, - 192100, 15, 15 }, /* 270 Mb */ - [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, - 207000, 15, 15 }, /* 300 Mb */ - [56] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, - 36100, 16, 16 }, /* 40.5 Mb */ - [57] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, - 72900, 17, 17 }, /* 81 Mb */ - [58] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, - 108300, 18, 18 }, /* 121.5 Mb */ - [59] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, - 142000, 19, 19 }, /* 162 Mb */ - [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, - 205100, 20, 20 }, /* 243 Mb */ - [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, - 224700, 20, 20 }, /* 270 Mb */ - [62] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, - 263100, 21, 21 }, /* 324 Mb */ - [63] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, - 288000, 21, 21 }, /* 360 Mb */ - [64] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, - 290700, 22, 22 }, /* 364.5 Mb */ - [65] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, - 317200, 22, 22 }, /* 405 Mb */ - [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, - 317200, 23, 23 }, /* 405 Mb */ - [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, - 346400, 23, 23 }, /* 450 Mb */ - }, - 50, /* probe interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ -}; - -/* 4ms frame limit not used for NG mode. The values filled - * for HT are the 64K max aggregate limit */ - -static const struct ath_rate_table ar5416_11ng_ratetable = { - 72, - 12, /* MCS start */ - { - [0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000, - 900, 0, 2 }, /* 1 Mb */ - [1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000, - 1900, 1, 4 }, /* 2 Mb */ - [2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500, - 4900, 2, 11 }, /* 5.5 Mb */ - [3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000, - 8100, 3, 22 }, /* 11 Mb */ - [4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, - 5400, 4, 12 }, /* 6 Mb */ - [5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, - 7800, 5, 18 }, /* 9 Mb */ - [6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, - 10100, 6, 24 }, /* 12 Mb */ - [7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, - 14100, 7, 36 }, /* 18 Mb */ - [8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, - 17700, 8, 48 }, /* 24 Mb */ - [9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, - 23700, 9, 72 }, /* 36 Mb */ - [10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, - 27400, 10, 96 }, /* 48 Mb */ - [11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, - 30900, 11, 108 }, /* 54 Mb */ - [12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500, - 6400, 0, 0 }, /* 6.5 Mb */ - [13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000, - 12700, 1, 1 }, /* 13 Mb */ - [14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500, - 18800, 2, 2 }, /* 19.5 Mb*/ - [15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000, - 25000, 3, 3 }, /* 26 Mb */ - [16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000, - 36700, 4, 4 }, /* 39 Mb */ - [17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000, - 48100, 5, 5 }, /* 52 Mb */ - [18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500, - 53500, 6, 6 }, /* 58.5 Mb */ - [19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000, - 59000, 7, 7 }, /* 65 Mb */ - [20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200, - 65400, 7, 7 }, /* 65 Mb*/ - [21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000, - 12700, 8, 8 }, /* 13 Mb */ - [22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000, - 24800, 9, 9 }, /* 26 Mb */ - [23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000, - 36600, 10, 10 }, /* 39 Mb */ - [24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000, - 48100, 11, 11 }, /* 52 Mb */ - [25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000, - 69500, 12, 12 }, /* 78 Mb */ - [26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000, - 89500, 13, 13 }, /* 104 Mb */ - [27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000, - 98900, 14, 14 }, /* 117 Mb */ - [28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000, - 108300, 15, 15 }, /* 130 Mb */ - [29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400, - 120000, 15, 15 }, /* 144.4 Mb */ - [30] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500, - 17400, 16, 16 }, /* 19.5 Mb */ - [31] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000, - 35100, 17, 17 }, /* 39 Mb */ - [32] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500, - 52600, 18, 18 }, /* 58.5 Mb */ - [33] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000, - 70400, 19, 19 }, /* 78 Mb */ - [34] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000, - 104900, 20, 20 }, /* 117 Mb */ - [35] = { RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000, - 115800, 20, 20 }, /* 130 Mb */ - [36] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000, - 137200, 21, 21 }, /* 156 Mb */ - [37] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300, - 151100, 21, 21 }, /* 173.3 Mb */ - [38] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500, - 152800, 22, 22 }, /* 175.5 Mb */ - [39] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000, - 168400, 22, 22 }, /* 195 Mb */ - [40] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000, - 168400, 23, 23 }, /* 195 Mb */ - [41] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700, - 185000, 23, 23 }, /* 216.7 Mb */ - [42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500, - 13200, 0, 0 }, /* 13.5 Mb */ - [43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500, - 25900, 1, 1 }, /* 27.0 Mb */ - [44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500, - 38600, 2, 2 }, /* 40.5 Mb */ - [45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000, - 49800, 3, 3 }, /* 54 Mb */ - [46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500, - 72200, 4, 4 }, /* 81 Mb */ - [47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000, - 92900, 5, 5 }, /* 108 Mb */ - [48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500, - 102700, 6, 6 }, /* 121.5 Mb */ - [49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000, - 112000, 7, 7 }, /* 135 Mb */ - [50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, - 122000, 7, 7 }, /* 150 Mb */ - [51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000, - 25800, 8, 8 }, /* 27 Mb */ - [52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000, - 49800, 9, 9 }, /* 54 Mb */ - [53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000, - 71900, 10, 10 }, /* 81 Mb */ - [54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000, - 92500, 11, 11 }, /* 108 Mb */ - [55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000, - 130300, 12, 12 }, /* 162 Mb */ - [56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000, - 162800, 13, 13 }, /* 216 Mb */ - [57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000, - 178200, 14, 14 }, /* 243 Mb */ - [58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000, - 192100, 15, 15 }, /* 270 Mb */ - [59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000, - 207000, 15, 15 }, /* 300 Mb */ - [60] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500, - 36100, 16, 16 }, /* 40.5 Mb */ - [61] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000, - 72900, 17, 17 }, /* 81 Mb */ - [62] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500, - 108300, 18, 18 }, /* 121.5 Mb */ - [63] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000, - 142000, 19, 19 }, /* 162 Mb */ - [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, - 205100, 20, 20 }, /* 243 Mb */ - [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, - 224700, 20, 20 }, /* 270 Mb */ - [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, - 263100, 21, 21 }, /* 324 Mb */ - [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, - 288000, 21, 21 }, /* 360 Mb */ - [68] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500, - 290700, 22, 22 }, /* 364.5 Mb */ - [69] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000, - 317200, 22, 22 }, /* 405 Mb */ - [70] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000, - 317200, 23, 23 }, /* 405 Mb */ - [71] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000, - 346400, 23, 23 }, /* 450 Mb */ - }, - 50, /* probe interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ -}; - -static const struct ath_rate_table ar5416_11a_ratetable = { - 8, - 0, - { - { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0, 12}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 1, 18}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 2, 24}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 3, 36}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 4, 48}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 5, 72}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 6, 96}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 7, 108}, - }, - 50, /* probe interval */ - 0, /* Phy rates allowed initially */ -}; - -static const struct ath_rate_table ar5416_11g_ratetable = { - 12, - 0, - { - { RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0, 2}, - { RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 1, 4}, - { RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 2, 11}, - { RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 3, 22}, - { RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 4, 12}, - { RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 5, 18}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 6, 24}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 7, 36}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 8, 48}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 9, 72}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 10, 96}, - { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 11, 108}, - }, - 50, /* probe interval */ - 0, /* Phy rates allowed initially */ -}; - -static int ath_rc_get_rateindex(struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_rate *rate) -{ - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - int rix, i, idx = 0; - - if (!(rate->flags & IEEE80211_TX_RC_MCS)) - return rate->idx; - - for (i = 0; i < ath_rc_priv->max_valid_rate; i++) { - idx = ath_rc_priv->valid_rate_index[i]; - - if (WLAN_RC_PHY_HT(rate_table->info[idx].phy) && - rate_table->info[idx].ratecode == rate->idx) - break; - } - - rix = idx; - - if (rate->flags & IEEE80211_TX_RC_SHORT_GI) - rix++; - - return rix; -} - -static void ath_rc_sort_validrates(struct ath_rate_priv *ath_rc_priv) -{ - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - u8 i, j, idx, idx_next; - - for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) { - for (j = 0; j <= i-1; j++) { - idx = ath_rc_priv->valid_rate_index[j]; - idx_next = ath_rc_priv->valid_rate_index[j+1]; - - if (rate_table->info[idx].ratekbps > - rate_table->info[idx_next].ratekbps) { - ath_rc_priv->valid_rate_index[j] = idx_next; - ath_rc_priv->valid_rate_index[j+1] = idx; - } - } - } -} - -static inline -int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, - u8 *next_idx) -{ - u8 i; - - for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) { - if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { - *next_idx = ath_rc_priv->valid_rate_index[i+1]; - return 1; - } - } - - /* No more valid rates */ - *next_idx = 0; - - return 0; -} - -/* Return true only for single stream */ - -static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) -{ - if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) - return 0; - if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) - return 0; - if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG)) - return 0; - if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) - return 0; - if (!ignore_cw && WLAN_RC_PHY_HT(phy)) - if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) - return 0; - return 1; -} - -static inline int -ath_rc_get_lower_rix(struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, u8 *next_idx) -{ - int8_t i; - - for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) { - if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { - *next_idx = ath_rc_priv->valid_rate_index[i-1]; - return 1; - } - } - - return 0; -} - -static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv) -{ - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - u8 i, hi = 0; - - for (i = 0; i < rate_table->rate_cnt; i++) { - if (rate_table->info[i].rate_flags & RC_LEGACY) { - u32 phy = rate_table->info[i].phy; - u8 valid_rate_count = 0; - - if (!ath_rc_valid_phyrate(phy, ath_rc_priv->ht_cap, 0)) - continue; - - valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; - - ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_priv->valid_rate_index[i] = true; - hi = i; - } - } - - return hi; -} - -static inline bool ath_rc_check_legacy(u8 rate, u8 dot11rate, u16 rate_flags, - u32 phy, u32 capflag) -{ - if (rate != dot11rate || WLAN_RC_PHY_HT(phy)) - return false; - - if ((rate_flags & WLAN_RC_CAP_MODE(capflag)) != WLAN_RC_CAP_MODE(capflag)) - return false; - - if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag))) - return false; - - return true; -} - -static inline bool ath_rc_check_ht(u8 rate, u8 dot11rate, u16 rate_flags, - u32 phy, u32 capflag) -{ - if (rate != dot11rate || !WLAN_RC_PHY_HT(phy)) - return false; - - if (!WLAN_RC_PHY_HT_VALID(rate_flags, capflag)) - return false; - - if (!(rate_flags & WLAN_RC_CAP_STREAM(capflag))) - return false; - - return true; -} - -static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, bool legacy) -{ - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - struct ath_rateset *rateset; - u32 phy, capflag = ath_rc_priv->ht_cap; - u16 rate_flags; - u8 i, j, hi = 0, rate, dot11rate, valid_rate_count; - - if (legacy) - rateset = &ath_rc_priv->neg_rates; - else - rateset = &ath_rc_priv->neg_ht_rates; - - for (i = 0; i < rateset->rs_nrates; i++) { - for (j = 0; j < rate_table->rate_cnt; j++) { - phy = rate_table->info[j].phy; - rate_flags = rate_table->info[j].rate_flags; - rate = rateset->rs_rates[i]; - dot11rate = rate_table->info[j].dot11rate; - - if (legacy && - !ath_rc_check_legacy(rate, dot11rate, - rate_flags, phy, capflag)) - continue; - - if (!legacy && - !ath_rc_check_ht(rate, dot11rate, - rate_flags, phy, capflag)) - continue; - - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; - ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = j; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_priv->valid_rate_index[j] = true; - hi = max(hi, j); - } - } - - return hi; -} - -static u8 ath_rc_get_highest_rix(struct ath_rate_priv *ath_rc_priv, - int *is_probing) -{ - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - u32 best_thruput, this_thruput, now_msec; - u8 rate, next_rate, best_rate, maxindex, minindex; - int8_t index = 0; - - now_msec = jiffies_to_msecs(jiffies); - *is_probing = 0; - best_thruput = 0; - maxindex = ath_rc_priv->max_valid_rate-1; - minindex = 0; - best_rate = minindex; - - /* - * Try the higher rate first. It will reduce memory moving time - * if we have very good channel characteristics. - */ - for (index = maxindex; index >= minindex ; index--) { - u8 per_thres; - - rate = ath_rc_priv->valid_rate_index[index]; - if (rate > ath_rc_priv->rate_max_phy) - continue; - - /* - * For TCP the average collision rate is around 11%, - * so we ignore PERs less than this. This is to - * prevent the rate we are currently using (whose - * PER might be in the 10-15 range because of TCP - * collisions) looking worse than the next lower - * rate whose PER has decayed close to 0. If we - * used to next lower rate, its PER would grow to - * 10-15 and we would be worse off then staying - * at the current rate. - */ - per_thres = ath_rc_priv->per[rate]; - if (per_thres < 12) - per_thres = 12; - - this_thruput = rate_table->info[rate].user_ratekbps * - (100 - per_thres); - - if (best_thruput <= this_thruput) { - best_thruput = this_thruput; - best_rate = rate; - } - } - - rate = best_rate; - - /* - * Must check the actual rate (ratekbps) to account for - * non-monoticity of 11g's rate table - */ - - if (rate >= ath_rc_priv->rate_max_phy) { - rate = ath_rc_priv->rate_max_phy; - - /* Probe the next allowed phy state */ - if (ath_rc_get_nextvalid_txrate(rate_table, - ath_rc_priv, rate, &next_rate) && - (now_msec - ath_rc_priv->probe_time > - rate_table->probe_interval) && - (ath_rc_priv->hw_maxretry_pktcnt >= 1)) { - rate = next_rate; - ath_rc_priv->probe_rate = rate; - ath_rc_priv->probe_time = now_msec; - ath_rc_priv->hw_maxretry_pktcnt = 0; - *is_probing = 1; - } - } - - if (rate > (ath_rc_priv->rate_table_size - 1)) - rate = ath_rc_priv->rate_table_size - 1; - - if (RC_TS_ONLY(rate_table->info[rate].rate_flags) && - (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG)) - return rate; - - if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) && - (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG))) - return rate; - - if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags)) - return rate; - - /* This should not happen */ - WARN_ON_ONCE(1); - - rate = ath_rc_priv->valid_rate_index[0]; - - return rate; -} - -static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table, - struct ieee80211_tx_rate *rate, - struct ieee80211_tx_rate_control *txrc, - u8 tries, u8 rix, int rtsctsenable) -{ - rate->count = tries; - rate->idx = rate_table->info[rix].ratecode; - - if (txrc->rts || rtsctsenable) - rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; - - if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) { - rate->flags |= IEEE80211_TX_RC_MCS; - if (WLAN_RC_PHY_40(rate_table->info[rix].phy) && - conf_is_ht40(&txrc->hw->conf)) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) - rate->flags |= IEEE80211_TX_RC_SHORT_GI; - } -} - -static void ath_rc_rate_set_rtscts(struct ath_softc *sc, - const struct ath_rate_table *rate_table, - struct ieee80211_tx_info *tx_info) -{ - struct ieee80211_bss_conf *bss_conf; - - if (!tx_info->control.vif) - return; - /* - * For legacy frames, mac80211 takes care of CTS protection. - */ - if (!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) - return; - - bss_conf = &tx_info->control.vif->bss_conf; - - if (!bss_conf->basic_rates) - return; - - /* - * For now, use the lowest allowed basic rate for HT frames. - */ - tx_info->control.rts_cts_rate_idx = __ffs(bss_conf->basic_rates); -} - -static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, - struct ieee80211_tx_rate_control *txrc) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - const struct ath_rate_table *rate_table; - struct sk_buff *skb = txrc->skb; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->control.rates; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc = hdr->frame_control; - u8 try_per_rate, i = 0, rix; - int is_probe = 0; - - if (rate_control_send_low(sta, priv_sta, txrc)) - return; - - /* - * For Multi Rate Retry we use a different number of - * retry attempt counts. This ends up looking like this: - * - * MRR[0] = 4 - * MRR[1] = 4 - * MRR[2] = 4 - * MRR[3] = 8 - * - */ - try_per_rate = 4; - - rate_table = ath_rc_priv->rate_table; - rix = ath_rc_get_highest_rix(ath_rc_priv, &is_probe); - - if (conf_is_ht(&sc->hw->conf) && - (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) - tx_info->flags |= IEEE80211_TX_CTL_LDPC; - - if (conf_is_ht(&sc->hw->conf) && - (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) - tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT); - - if (is_probe) { - /* - * Set one try for probe rates. For the - * probes don't enable RTS. - */ - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - 1, rix, 0); - /* - * Get the next tried/allowed rate. - * No RTS for the next series after the probe rate. - */ - ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, rix, 0); - - tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; - } else { - /* - * Set the chosen rate. No RTS for first series entry. - */ - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, rix, 0); - } - - for ( ; i < 4; i++) { - /* - * Use twice the number of tries for the last MRR segment. - */ - if (i + 1 == 4) - try_per_rate = 8; - - ath_rc_get_lower_rix(ath_rc_priv, rix, &rix); - - /* - * All other rates in the series have RTS enabled. - */ - ath_rc_rate_set_series(rate_table, &rates[i], txrc, - try_per_rate, rix, 1); - } - - /* - * NB:Change rate series to enable aggregation when operating - * at lower MCS rates. When first rate in series is MCS2 - * in HT40 @ 2.4GHz, series should look like: - * - * {MCS2, MCS1, MCS0, MCS0}. - * - * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should - * look like: - * - * {MCS3, MCS2, MCS1, MCS1} - * - * So, set fourth rate in series to be same as third one for - * above conditions. - */ - if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) && - (conf_is_ht(&sc->hw->conf))) { - u8 dot11rate = rate_table->info[rix].dot11rate; - u8 phy = rate_table->info[rix].phy; - if (i == 4 && - ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || - (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { - rates[3].idx = rates[2].idx; - rates[3].flags = rates[2].flags; - } - } - - /* - * Force hardware to use computed duration for next - * fragment by disabling multi-rate retry, which - * updates duration based on the multi-rate duration table. - * - * FIXME: Fix duration - */ - if (ieee80211_has_morefrags(fc) || - (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { - rates[1].count = rates[2].count = rates[3].count = 0; - rates[1].idx = rates[2].idx = rates[3].idx = 0; - rates[0].count = ATH_TXMAXTRY; - } - - ath_rc_rate_set_rtscts(sc, rate_table, tx_info); -} - -static void ath_rc_update_per(struct ath_softc *sc, - const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_info *tx_info, - int tx_rate, int xretries, int retries, - u32 now_msec) -{ - int count, n_bad_frames; - u8 last_per; - static const u32 nretry_to_per_lookup[10] = { - 100 * 0 / 1, - 100 * 1 / 4, - 100 * 1 / 2, - 100 * 3 / 4, - 100 * 4 / 5, - 100 * 5 / 6, - 100 * 6 / 7, - 100 * 7 / 8, - 100 * 8 / 9, - 100 * 9 / 10 - }; - - last_per = ath_rc_priv->per[tx_rate]; - n_bad_frames = tx_info->status.ampdu_len - tx_info->status.ampdu_ack_len; - - if (xretries) { - if (xretries == 1) { - ath_rc_priv->per[tx_rate] += 30; - if (ath_rc_priv->per[tx_rate] > 100) - ath_rc_priv->per[tx_rate] = 100; - } else { - /* xretries == 2 */ - count = ARRAY_SIZE(nretry_to_per_lookup); - if (retries >= count) - retries = count - 1; - - /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ - ath_rc_priv->per[tx_rate] = - (u8)(last_per - (last_per >> 3) + (100 >> 3)); - } - - /* xretries == 1 or 2 */ - - if (ath_rc_priv->probe_rate == tx_rate) - ath_rc_priv->probe_rate = 0; - - } else { /* xretries == 0 */ - count = ARRAY_SIZE(nretry_to_per_lookup); - if (retries >= count) - retries = count - 1; - - if (n_bad_frames) { - /* new_PER = 7/8*old_PER + 1/8*(currentPER) - * Assuming that n_frames is not 0. The current PER - * from the retries is 100 * retries / (retries+1), - * since the first retries attempts failed, and the - * next one worked. For the one that worked, - * n_bad_frames subframes out of n_frames wored, - * so the PER for that part is - * 100 * n_bad_frames / n_frames, and it contributes - * 100 * n_bad_frames / (n_frames * (retries+1)) to - * the above PER. The expression below is a - * simplified version of the sum of these two terms. - */ - if (tx_info->status.ampdu_len > 0) { - int n_frames, n_bad_tries; - u8 cur_per, new_per; - - n_bad_tries = retries * tx_info->status.ampdu_len + - n_bad_frames; - n_frames = tx_info->status.ampdu_len * (retries + 1); - cur_per = (100 * n_bad_tries / n_frames) >> 3; - new_per = (u8)(last_per - (last_per >> 3) + cur_per); - ath_rc_priv->per[tx_rate] = new_per; - } - } else { - ath_rc_priv->per[tx_rate] = - (u8)(last_per - (last_per >> 3) + - (nretry_to_per_lookup[retries] >> 3)); - } - - - /* - * If we got at most one retry then increase the max rate if - * this was a probe. Otherwise, ignore the probe. - */ - if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { - if (retries > 0 || 2 * n_bad_frames > tx_info->status.ampdu_len) { - /* - * Since we probed with just a single attempt, - * any retries means the probe failed. Also, - * if the attempt worked, but more than half - * the subframes were bad then also consider - * the probe a failure. - */ - ath_rc_priv->probe_rate = 0; - } else { - u8 probe_rate = 0; - - ath_rc_priv->rate_max_phy = - ath_rc_priv->probe_rate; - probe_rate = ath_rc_priv->probe_rate; - - if (ath_rc_priv->per[probe_rate] > 30) - ath_rc_priv->per[probe_rate] = 20; - - ath_rc_priv->probe_rate = 0; - - /* - * Since this probe succeeded, we allow the next - * probe twice as soon. This allows the maxRate - * to move up faster if the probes are - * successful. - */ - ath_rc_priv->probe_time = - now_msec - rate_table->probe_interval / 2; - } - } - - if (retries > 0) { - /* - * Don't update anything. We don't know if - * this was because of collisions or poor signal. - */ - ath_rc_priv->hw_maxretry_pktcnt = 0; - } else { - /* - * It worked with no retries. First ignore bogus (small) - * rssi_ack values. - */ - if (tx_rate == ath_rc_priv->rate_max_phy && - ath_rc_priv->hw_maxretry_pktcnt < 255) { - ath_rc_priv->hw_maxretry_pktcnt++; - } - - } - } -} - -static void ath_rc_update_ht(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_info *tx_info, - int tx_rate, int xretries, int retries) -{ - u32 now_msec = jiffies_to_msecs(jiffies); - int rate; - u8 last_per; - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - int size = ath_rc_priv->rate_table_size; - - if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) - return; - - last_per = ath_rc_priv->per[tx_rate]; - - /* Update PER first */ - ath_rc_update_per(sc, rate_table, ath_rc_priv, - tx_info, tx_rate, xretries, - retries, now_msec); - - /* - * If this rate looks bad (high PER) then stop using it for - * a while (except if we are probing). - */ - if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 && - rate_table->info[tx_rate].ratekbps <= - rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { - ath_rc_get_lower_rix(ath_rc_priv, (u8)tx_rate, - &ath_rc_priv->rate_max_phy); - - /* Don't probe for a little while. */ - ath_rc_priv->probe_time = now_msec; - } - - /* Make sure the rates below this have lower PER */ - /* Monotonicity is kept only for rates below the current rate. */ - if (ath_rc_priv->per[tx_rate] < last_per) { - for (rate = tx_rate - 1; rate >= 0; rate--) { - - if (ath_rc_priv->per[rate] > - ath_rc_priv->per[rate+1]) { - ath_rc_priv->per[rate] = - ath_rc_priv->per[rate+1]; - } - } - } - - /* Maintain monotonicity for rates above the current rate */ - for (rate = tx_rate; rate < size - 1; rate++) { - if (ath_rc_priv->per[rate+1] < - ath_rc_priv->per[rate]) - ath_rc_priv->per[rate+1] = - ath_rc_priv->per[rate]; - } - - /* Every so often, we reduce the thresholds - * and PER (different for CCK and OFDM). */ - if (now_msec - ath_rc_priv->per_down_time >= - rate_table->probe_interval) { - for (rate = 0; rate < size; rate++) { - ath_rc_priv->per[rate] = - 7 * ath_rc_priv->per[rate] / 8; - } - - ath_rc_priv->per_down_time = now_msec; - } - - ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries, - ath_rc_priv->per[tx_rate]); - -} - -static void ath_rc_tx_status(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->status.rates; - struct ieee80211_tx_rate *rate; - int final_ts_idx = 0, xretries = 0, long_retry = 0; - u8 flags; - u32 i = 0, rix; - - for (i = 0; i < sc->hw->max_rates; i++) { - rate = &tx_info->status.rates[i]; - if (rate->idx < 0 || !rate->count) - break; - - final_ts_idx = i; - long_retry = rate->count - 1; - } - - if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) - xretries = 1; - - /* - * If the first rate is not the final index, there - * are intermediate rate failures to be processed. - */ - if (final_ts_idx != 0) { - for (i = 0; i < final_ts_idx ; i++) { - if (rates[i].count != 0 && (rates[i].idx >= 0)) { - flags = rates[i].flags; - - /* If HT40 and we have switched mode from - * 40 to 20 => don't update */ - - if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) - return; - - rix = ath_rc_get_rateindex(ath_rc_priv, &rates[i]); - ath_rc_update_ht(sc, ath_rc_priv, tx_info, - rix, xretries ? 1 : 2, - rates[i].count); - } - } - } - - flags = rates[final_ts_idx].flags; - - /* If HT40 and we have switched mode from 40 to 20 => don't update */ - if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) - return; - - rix = ath_rc_get_rateindex(ath_rc_priv, &rates[final_ts_idx]); - ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry); - ath_debug_stat_rc(ath_rc_priv, rix); -} - -static const -struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, - enum ieee80211_band band, - bool is_ht) -{ - switch(band) { - case IEEE80211_BAND_2GHZ: - if (is_ht) - return &ar5416_11ng_ratetable; - return &ar5416_11g_ratetable; - case IEEE80211_BAND_5GHZ: - if (is_ht) - return &ar5416_11na_ratetable; - return &ar5416_11a_ratetable; - default: - return NULL; - } -} - -static void ath_rc_init(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv) -{ - const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; - struct ath_rateset *rateset = &ath_rc_priv->neg_rates; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - u8 i, j, k, hi = 0, hthi = 0; - - ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; - - for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { - ath_rc_priv->per[i] = 0; - ath_rc_priv->valid_rate_index[i] = 0; - } - - for (i = 0; i < WLAN_RC_PHY_MAX; i++) { - for (j = 0; j < RATE_TABLE_SIZE; j++) - ath_rc_priv->valid_phy_rateidx[i][j] = 0; - ath_rc_priv->valid_phy_ratecnt[i] = 0; - } - - if (!rateset->rs_nrates) { - hi = ath_rc_init_validrates(ath_rc_priv); - } else { - hi = ath_rc_setvalid_rates(ath_rc_priv, true); - - if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) - hthi = ath_rc_setvalid_rates(ath_rc_priv, false); - - hi = max(hi, hthi); - } - - ath_rc_priv->rate_table_size = hi + 1; - ath_rc_priv->rate_max_phy = 0; - WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); - - for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { - for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { - ath_rc_priv->valid_rate_index[k++] = - ath_rc_priv->valid_phy_rateidx[i][j]; - } - - if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) || - !ath_rc_priv->valid_phy_ratecnt[i]) - continue; - - ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; - } - WARN_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); - WARN_ON(k > RATE_TABLE_SIZE); - - ath_rc_priv->max_valid_rate = k; - ath_rc_sort_validrates(ath_rc_priv); - ath_rc_priv->rate_max_phy = (k > 4) ? - ath_rc_priv->valid_rate_index[k-4] : - ath_rc_priv->valid_rate_index[k-1]; - - ath_dbg(common, CONFIG, "RC Initialized with capabilities: 0x%x\n", - ath_rc_priv->ht_cap); -} - -static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta) -{ - u8 caps = 0; - - if (sta->ht_cap.ht_supported) { - caps = WLAN_RC_HT_FLAG; - if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2]) - caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG; - else if (sta->ht_cap.mcs.rx_mask[1]) - caps |= WLAN_RC_DS_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { - caps |= WLAN_RC_40_FLAG; - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) - caps |= WLAN_RC_SGI_FLAG; - } else { - if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) - caps |= WLAN_RC_SGI_FLAG; - } - } - - return caps; -} - -static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta, - u8 tidno) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; - struct ath_atx_tid *txtid; - - if (!sta->ht_cap.ht_supported) - return false; - - txtid = ATH_AN_2_TID(an, tidno); - - if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) - return true; - return false; -} - - -/***********************************/ -/* mac80211 Rate Control callbacks */ -/***********************************/ - -static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc = hdr->frame_control; - - if (!priv_sta || !ieee80211_is_data(fc)) - return; - - /* This packet was aggregated but doesn't carry status info */ - if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && - !(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) - return; - - if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) - return; - - ath_rc_tx_status(sc, ath_rc_priv, skb); - - /* Check if aggregation has to be enabled for this tid */ - if (conf_is_ht(&sc->hw->conf) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc) && - skb_get_queue_mapping(skb) != IEEE80211_AC_VO) { - u8 *qc, tid; - - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - - if(ath_tx_aggr_check(sc, sta, tid)) - ieee80211_start_tx_ba_session(sta, tid, 0); - } - } -} - -static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) -{ - struct ath_softc *sc = priv; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_rate_priv *ath_rc_priv = priv_sta; - int i, j = 0; - - for (i = 0; i < sband->n_bitrates; i++) { - if (sta->supp_rates[sband->band] & BIT(i)) { - ath_rc_priv->neg_rates.rs_rates[j] - = (sband->bitrates[i].bitrate * 2) / 10; - j++; - } - } - ath_rc_priv->neg_rates.rs_nrates = j; - - if (sta->ht_cap.ht_supported) { - for (i = 0, j = 0; i < 77; i++) { - if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) - ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; - if (j == ATH_RATE_MAX) - break; - } - ath_rc_priv->neg_ht_rates.rs_nrates = j; - } - - ath_rc_priv->rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported); - if (!ath_rc_priv->rate_table) { - ath_err(common, "No rate table chosen\n"); - return; - } - - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); - ath_rc_init(sc, priv_sta); -} - -static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - u32 changed) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - - if (changed & IEEE80211_RC_BW_CHANGED) { - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta); - ath_rc_init(sc, priv_sta); - - ath_dbg(ath9k_hw_common(sc->sc_ah), CONFIG, - "Operating HT Bandwidth changed to: %d\n", - sc->hw->conf.channel_type); - } -} - -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) - -void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) -{ - struct ath_rc_stats *stats; - - stats = &rc->rcstats[final_rate]; - stats->success++; -} - -void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, - int xretries, int retries, u8 per) -{ - struct ath_rc_stats *stats = &rc->rcstats[rix]; - - stats->xretries += xretries; - stats->retries += retries; - stats->per = per; -} - -static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_rate_priv *rc = file->private_data; - char *buf; - unsigned int len = 0, max; - int rix; - ssize_t retval; - - if (rc->rate_table == NULL) - return 0; - - max = 80 + rc->rate_table_size * 1024 + 1; - buf = kmalloc(max, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - len += sprintf(buf, "%6s %6s %6s " - "%10s %10s %10s %10s\n", - "HT", "MCS", "Rate", - "Success", "Retries", "XRetries", "PER"); - - for (rix = 0; rix < rc->max_valid_rate; rix++) { - u8 i = rc->valid_rate_index[rix]; - u32 ratekbps = rc->rate_table->info[i].ratekbps; - struct ath_rc_stats *stats = &rc->rcstats[i]; - char mcs[5]; - char htmode[5]; - int used_mcs = 0, used_htmode = 0; - - if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) { - used_mcs = snprintf(mcs, 5, "%d", - rc->rate_table->info[i].ratecode); - - if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy)) - used_htmode = snprintf(htmode, 5, "HT40"); - else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy)) - used_htmode = snprintf(htmode, 5, "HT20"); - else - used_htmode = snprintf(htmode, 5, "????"); - } - - mcs[used_mcs] = '\0'; - htmode[used_htmode] = '\0'; - - len += snprintf(buf + len, max - len, - "%6s %6s %3u.%d: " - "%10u %10u %10u %10u\n", - htmode, - mcs, - ratekbps / 1000, - (ratekbps % 1000) / 100, - stats->success, - stats->retries, - stats->xretries, - stats->per); - } - - if (len > max) - len = max; - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - return retval; -} - -static const struct file_operations fops_rcstat = { - .read = read_file_rcstat, - .open = simple_open, - .owner = THIS_MODULE -}; - -static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta, - struct dentry *dir) -{ - struct ath_rate_priv *rc = priv_sta; - rc->debugfs_rcstats = debugfs_create_file("rc_stats", S_IRUGO, - dir, rc, &fops_rcstat); -} - -static void ath_rate_remove_sta_debugfs(void *priv, void *priv_sta) -{ - struct ath_rate_priv *rc = priv_sta; - debugfs_remove(rc->debugfs_rcstats); -} - -#endif /* CONFIG_MAC80211_DEBUGFS && CONFIG_ATH9K_DEBUGFS */ - -static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) -{ - return hw->priv; -} - -static void ath_rate_free(void *priv) -{ - return; -} - -static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *rate_priv; - - rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); - if (!rate_priv) { - ath_err(ath9k_hw_common(sc->sc_ah), - "Unable to allocate private rc structure\n"); - return NULL; - } - - return rate_priv; -} - -static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, - void *priv_sta) -{ - struct ath_rate_priv *rate_priv = priv_sta; - kfree(rate_priv); -} - -static struct rate_control_ops ath_rate_ops = { - .module = NULL, - .name = "ath9k_rate_control", - .tx_status = ath_tx_status, - .get_rate = ath_get_rate, - .rate_init = ath_rate_init, - .rate_update = ath_rate_update, - .alloc = ath_rate_alloc, - .free = ath_rate_free, - .alloc_sta = ath_rate_alloc_sta, - .free_sta = ath_rate_free_sta, - -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) - .add_sta_debugfs = ath_rate_add_sta_debugfs, - .remove_sta_debugfs = ath_rate_remove_sta_debugfs, -#endif -}; - -int ath_rate_control_register(void) -{ - return ieee80211_rate_control_register(&ath_rate_ops); -} - -void ath_rate_control_unregister(void) -{ - ieee80211_rate_control_unregister(&ath_rate_ops); -} diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h deleted file mode 100644 index 267dbfc..0000000 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2004 Sam Leffler, Errno Consulting - * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2008-2011 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef RC_H -#define RC_H - -#include "hw.h" - -struct ath_softc; - -#define ATH_RATE_MAX 30 -#define RATE_TABLE_SIZE 72 - -#define RC_INVALID 0x0000 -#define RC_LEGACY 0x0001 -#define RC_SS 0x0002 -#define RC_DS 0x0004 -#define RC_TS 0x0008 -#define RC_HT_20 0x0010 -#define RC_HT_40 0x0020 - -#define RC_STREAM_MASK 0xe -#define RC_DS_OR_LATER(f) ((((f) & RC_STREAM_MASK) == RC_DS) || \ - (((f) & RC_STREAM_MASK) == (RC_DS | RC_TS))) -#define RC_TS_ONLY(f) (((f) & RC_STREAM_MASK) == RC_TS) -#define RC_SS_OR_LEGACY(f) ((f) & (RC_SS | RC_LEGACY)) - -#define RC_HT_2040 (RC_HT_20 | RC_HT_40) -#define RC_ALL_STREAM (RC_SS | RC_DS | RC_TS) -#define RC_L_SD (RC_LEGACY | RC_SS | RC_DS) -#define RC_L_SDT (RC_LEGACY | RC_SS | RC_DS | RC_TS) -#define RC_HT_S_20 (RC_HT_20 | RC_SS) -#define RC_HT_D_20 (RC_HT_20 | RC_DS) -#define RC_HT_T_20 (RC_HT_20 | RC_TS) -#define RC_HT_S_40 (RC_HT_40 | RC_SS) -#define RC_HT_D_40 (RC_HT_40 | RC_DS) -#define RC_HT_T_40 (RC_HT_40 | RC_TS) - -#define RC_HT_SD_20 (RC_HT_20 | RC_SS | RC_DS) -#define RC_HT_DT_20 (RC_HT_20 | RC_DS | RC_TS) -#define RC_HT_SD_40 (RC_HT_40 | RC_SS | RC_DS) -#define RC_HT_DT_40 (RC_HT_40 | RC_DS | RC_TS) - -#define RC_HT_SD_2040 (RC_HT_2040 | RC_SS | RC_DS) -#define RC_HT_SDT_2040 (RC_HT_2040 | RC_SS | RC_DS | RC_TS) - -#define RC_HT_SDT_20 (RC_HT_20 | RC_SS | RC_DS | RC_TS) -#define RC_HT_SDT_40 (RC_HT_40 | RC_SS | RC_DS | RC_TS) - -#define RC_ALL (RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM) - -enum { - WLAN_RC_PHY_OFDM, - WLAN_RC_PHY_CCK, - WLAN_RC_PHY_HT_20_SS, - WLAN_RC_PHY_HT_20_DS, - WLAN_RC_PHY_HT_20_TS, - WLAN_RC_PHY_HT_40_SS, - WLAN_RC_PHY_HT_40_DS, - WLAN_RC_PHY_HT_40_TS, - WLAN_RC_PHY_HT_20_SS_HGI, - WLAN_RC_PHY_HT_20_DS_HGI, - WLAN_RC_PHY_HT_20_TS_HGI, - WLAN_RC_PHY_HT_40_SS_HGI, - WLAN_RC_PHY_HT_40_DS_HGI, - WLAN_RC_PHY_HT_40_TS_HGI, - WLAN_RC_PHY_MAX -}; - -#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) -#define WLAN_RC_PHY_TS(_phy) ((_phy == WLAN_RC_PHY_HT_20_TS) \ - || (_phy == WLAN_RC_PHY_HT_40_TS) \ - || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_TS_HGI)) -#define WLAN_RC_PHY_20(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS) \ - || (_phy == WLAN_RC_PHY_HT_20_DS) \ - || (_phy == WLAN_RC_PHY_HT_20_TS) \ - || (_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_TS_HGI)) -#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_TS) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_TS_HGI)) -#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_TS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_TS_HGI)) - -#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) - -#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ - ((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY)) - -#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ? \ - (RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS))) - -/* Return TRUE if flag supports HT20 && client supports HT20 or - * return TRUE if flag supports HT40 && client supports HT40. - * This is used becos some rates overlap between HT20/HT40. - */ -#define WLAN_RC_PHY_HT_VALID(flag, capflag) \ - (((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \ - ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG))) - -#define WLAN_RC_DS_FLAG (0x01) -#define WLAN_RC_TS_FLAG (0x02) -#define WLAN_RC_40_FLAG (0x04) -#define WLAN_RC_SGI_FLAG (0x08) -#define WLAN_RC_HT_FLAG (0x10) - -/** - * struct ath_rate_table - Rate Control table - * @rate_cnt: total number of rates for the given wireless mode - * @mcs_start: MCS rate index offset - * @rate_flags: Rate Control flags - * @phy: CCK/OFDM/HT20/HT40 - * @ratekbps: rate in Kbits per second - * @user_ratekbps: user rate in Kbits per second - * @ratecode: rate that goes into HW descriptors - * @dot11rate: value that goes into supported - * rates info element of MLME - * @ctrl_rate: Index of next lower basic rate, used for duration computation - * @cw40index: Index of rates having 40MHz channel width - * @sgi_index: Index of rates having Short Guard Interval - * @ht_index: high throughput rates having 40MHz channel width and - * Short Guard Interval - * @probe_interval: interval for rate control to probe for other rates - * @initial_ratemax: initial ratemax value - */ -struct ath_rate_table { - int rate_cnt; - int mcs_start; - struct { - u16 rate_flags; - u8 phy; - u32 ratekbps; - u32 user_ratekbps; - u8 ratecode; - u8 dot11rate; - } info[RATE_TABLE_SIZE]; - u32 probe_interval; - u8 initial_ratemax; -}; - -struct ath_rateset { - u8 rs_nrates; - u8 rs_rates[ATH_RATE_MAX]; -}; - -struct ath_rc_stats { - u32 success; - u32 retries; - u32 xretries; - u8 per; -}; - -/** - * struct ath_rate_priv - Rate Control priv data - * @state: RC state - * @probe_rate: rate we are probing at - * @probe_time: msec timestamp for last probe - * @hw_maxretry_pktcnt: num of packets since we got HW max retry error - * @max_valid_rate: maximum number of valid rate - * @per_down_time: msec timestamp for last PER down step - * @valid_phy_ratecnt: valid rate count - * @rate_max_phy: phy index for the max rate - * @per: PER for every valid rate in % - * @probe_interval: interval for ratectrl to probe for other rates - * @ht_cap: HT capabilities - * @neg_rates: Negotatied rates - * @neg_ht_rates: Negotiated HT rates - */ -struct ath_rate_priv { - u8 rate_table_size; - u8 probe_rate; - u8 hw_maxretry_pktcnt; - u8 max_valid_rate; - u8 valid_rate_index[RATE_TABLE_SIZE]; - u8 ht_cap; - u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; - u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; - u8 rate_max_phy; - u8 per[RATE_TABLE_SIZE]; - u32 probe_time; - u32 per_down_time; - u32 probe_interval; - struct ath_rateset neg_rates; - struct ath_rateset neg_ht_rates; - const struct ath_rate_table *rate_table; - -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) - struct dentry *debugfs_rcstats; - struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; -#endif -}; - -#if defined(CONFIG_MAC80211_DEBUGFS) && defined(CONFIG_ATH9K_DEBUGFS) -void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate); -void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, - int xretries, int retries, u8 per); -#else -static inline void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) -{ -} -static inline void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, - int xretries, int retries, u8 per) -{ -} -#endif - -#ifdef CONFIG_ATH9K_RATE_CONTROL -int ath_rate_control_register(void); -void ath_rate_control_unregister(void); -#else -static inline int ath_rate_control_register(void) -{ - return 0; -} - -static inline void ath_rate_control_unregister(void) -{ -} -#endif - -#endif /* RC_H */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index feacaaf..b32fda8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1008,8 +1008,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, info->rtscts_rate = fi->rtscts_rate; for (i = 0; i < 4; i++) { - bool is_40, is_sgi, is_sp; - int phy; + bool is_40, is_sgi, is_sp, cck = false; if (!rates[i].count || (rates[i].idx < 0)) continue; @@ -1050,9 +1049,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; if ((tx_info->band == IEEE80211_BAND_2GHZ) && !(rate->flags & IEEE80211_RATE_ERP_G)) - phy = WLAN_RC_PHY_CCK; - else - phy = WLAN_RC_PHY_OFDM; + cck = true; info->rates[i].Rate = rate->hw_value; if (rate->hw_value_short) { @@ -1069,7 +1066,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, ah->txchainmask, info->rates[i].Rate); info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, - phy, rate->bitrate * 100, len, rix, is_sp); + cck, rate->bitrate * 100, len, rix, is_sp); } /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
In many tests throughput with ath9k_rate_control has been shown to be worse than with minstrel_ht (the mac8021 default RC). This module also has some other problems, like starting to use the highest possible rate early in the connection, causing problems with reliability of connection/authentication attempts. It also has a much more limited search space, ignoring many potentially useful rates, caused by the design decision to operate on a sorted rate set with the assumption that higher rates are always more unreliable than lower rates. In some scenarios this assumption is not true, and this can cause it to fall back to a really bad rate. minstrel_ht has been tested extensively in AP and client mode by lots of users (mostly in the OpenWrt project, where it has been the default for years). The only advantage that ath9k_rate_control previously had over minstrel_ht was the support for using CCK rates as fall back in case MCS rates got too bad, but this has now also been taken care of. Signed-off-by: Felix Fietkau <nbd@openwrt.org> --- drivers/net/wireless/ath/ath9k/Kconfig | 8 - drivers/net/wireless/ath/ath9k/Makefile | 1 - drivers/net/wireless/ath/ath9k/debug.h | 1 - drivers/net/wireless/ath/ath9k/hw.c | 15 +- drivers/net/wireless/ath/ath9k/hw.h | 4 +- drivers/net/wireless/ath/ath9k/init.c | 17 +- drivers/net/wireless/ath/ath9k/rc.c | 1501 ------------------------------- drivers/net/wireless/ath/ath9k/rc.h | 248 ----- drivers/net/wireless/ath/ath9k/xmit.c | 9 +- 9 files changed, 10 insertions(+), 1794 deletions(-) delete mode 100644 drivers/net/wireless/ath/ath9k/rc.c delete mode 100644 drivers/net/wireless/ath/ath9k/rc.h