ath9k: properly use the mac80211 rate control api
PATCH 1/2 ath9k: properly use the mac80211 rate control api
This patch changes ath9k to pass proper MCS indexes and flags between the RC and the rest of the driver code. sc->cur_rate_table remains, as it's used by the RC code internally, but the rest of the driver code no longer uses it, so a potential new RC for ath9k would not have to update it.
---
- replaces sc->hw usage with common->hw
- initializes unused tx status rates to -1 for minstrel compatibility
- split up for easier review
- tested in ap mode with minstrel against a legacy STA
drivers/net/wireless/ath/ath9k/rc.c +47 -48
@@ -19,6 +19,7 @@static const struct ath_rate_table ar5416_11na_ratetable = {42 , +8 ,/* MCS start */ { {VALID ,VALID ,WLAN_RC_PHY_OFDM ,6000 ,/* 6 Mb */ 5400 ,0x0b ,0x00 ,12 ,
@@ -156,6 +157,7 @@ static const struct ath_rate_table ar541static const struct ath_rate_table ar5416_11ng_ratetable = {46 , +12 ,/* MCS start */ { {VALID_ALL ,VALID_ALL ,WLAN_RC_PHY_CCK ,1000 ,/* 1 Mb */ 900 ,0x1b ,0x00 ,2 ,
@@ -302,6 +304,7 @@ static const struct ath_rate_table ar541static const struct ath_rate_table ar5416_11a_ratetable = {8 , +0 , { {VALID ,VALID ,WLAN_RC_PHY_OFDM ,6000 ,/* 6 Mb */ 5400 ,0x0b ,0x00 , (0x80 |12 ),
@@ -334,6 +337,7 @@ static const struct ath_rate_table ar541static const struct ath_rate_table ar5416_11g_ratetable = {12 , +0 , { {VALID ,VALID ,WLAN_RC_PHY_CCK ,1000 ,/* 1 Mb */ 900 ,0x1b ,0x00 ,2 ,
@@ -376,6 +380,20 @@ static const struct ath_rate_table ar541 0, /* Phy rates allowed initially */ }; +static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX ] = { + [ATH9K_MODE_11A ] = &ar5416_11a_ratetable, + [ATH9K_MODE_11G ] = &ar5416_11g_ratetable, + [ATH9K_MODE_11NA_HT20 ] = &ar5416_11na_ratetable, + [ATH9K_MODE_11NG_HT20 ] = &ar5416_11ng_ratetable, + [ATH9K_MODE_11NA_HT40PLUS ] = &ar5416_11na_ratetable, + [ATH9K_MODE_11NA_HT40MINUS ] = &ar5416_11na_ratetable, + [ATH9K_MODE_11NG_HT40PLUS ] = &ar5416_11ng_ratetable, + [ATH9K_MODE_11NG_HT40MINUS ] = &ar5416_11ng_ratetable, +}; + +static int ath_rc_get_rateindex (const struct ath_rate_table *rate_table, +struct ieee80211_tx_rate *rate); +static inline int8_t median (int8_t a,int8_t b,int8_t c) {if (a >= b) {
@@ -534,7 +552,7 @@ static u8 ath_rc_setvalid_rates(struct a* capflag matches one of the validity * (VALID/VALID_20/VALID_40) flags */ -if (((rate &0x7F ) == (dot11rate &0x7F )) && +if ((rate == dot11rate) && ((valid &WLAN_RC_CAP_MODE (capflag)) ==WLAN_RC_CAP_MODE (capflag)) && !WLAN_RC_PHY_HT (phy)) {
@@ -576,8 +594,7 @@ static u8 ath_rc_setvalid_htrates(structu8 rate = rateset->rs_rates[i];u8 dot11rate = rate_table->info[j].dot11rate; -if (((rate &0x7F ) != (dot11rate &0x7F )) || - !WLAN_RC_PHY_HT (phy) || +if ((rate != dot11rate) || !WLAN_RC_PHY_HT (phy) || !WLAN_RC_PHY_HT_VALID (valid, capflag))continue ;
@@ -696,18 +713,20 @@ static void ath_rc_rate_set_series(const u8 tries, u8 rix, int rtsctsenable) { rate->count = tries; - rate->idx = rix; + rate->idx = rate_table->info[rix].ratecode;if (txrc->short_preamble) rate->flags |=IEEE80211_TX_RC_USE_SHORT_PREAMBLE ;if (txrc->rts || rtsctsenable) rate->flags |=IEEE80211_TX_RC_USE_RTS_CTS ; -if (WLAN_RC_PHY_40 (rate_table->info[rix].phy)) - 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 ; -if (WLAN_RC_PHY_HT (rate_table->info[rix].phy)) + +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)) + 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,
@@ -720,7 +739,7 @@ static void ath_rc_rate_set_rtscts(struc/* get the cix for the lowest valid rix */ for (i =3 ; i >=0 ; i--) {if (rates[i].count && (rates[i].idx >=0 )) { - rix = rates[i].idx; + rix =ath_rc_get_rateindex (rate_table, &rates[i]);break ; } }
@@ -1080,15 +1099,19 @@ static int ath_rc_get_rateindex(const st {int rix; +if (!(rate->flags &IEEE80211_TX_RC_MCS )) +return rate->idx; + + rix = rate->idx + rate_table->mcs_start;if ((rate->flags &IEEE80211_TX_RC_40_MHZ_WIDTH ) && (rate->flags &IEEE80211_TX_RC_SHORT_GI )) - rix = rate_table->info[rate->idx].ht_index; + rix = rate_table->info[rix].ht_index;else if (rate->flags &IEEE80211_TX_RC_SHORT_GI ) - rix = rate_table->info[rate->idx].sgi_index; + rix = rate_table->info[rix].sgi_index;else if (rate->flags &IEEE80211_TX_RC_40_MHZ_WIDTH ) - rix = rate_table->info[rate->idx].cw40index; + rix = rate_table->info[rix].cw40index;else - rix = rate_table->info[rate->idx].base_index; + rix = rate_table->info[rix].base_index;return rix; }
@@ -1183,7 +1206,9 @@ struct ath_rate_table *ath_choose_rate_tath_print (common,ATH_DBG_CONFIG ,"Choosing rate table for mode: %d\n" , mode); -return sc->hw_rate_table[mode]; + + sc->cur_rate_mode = mode; +return hw_rate_table[mode]; } static void ath_rc_init(struct ath_softc *sc,
@@ -1197,12 +1222,6 @@ static void ath_rc_init(struct ath_softcu8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;u8 i, j, k, hi =0 , hthi =0 ; -if (!rate_table) { -ath_print (common,ATH_DBG_FATAL , -"Rate table not initialized\n" ); -return ; - } -/* Initial rate table size. Will change depending * on the working rate set */ ath_rc_priv->rate_table_size =RATE_TABLE_SIZE ;
@@ -1357,7 +1376,8 @@ static void ath_tx_status(void *priv, st } } -ath_debug_stat_rc (sc, skb); +ath_debug_stat_rc (sc,ath_rc_get_rateindex (sc->cur_rate_table, + &tx_info->status.rates[final_ts_idx])); } static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
@@ -1365,7 +1385,7 @@ static void ath_rate_init(void *priv, st {struct ath_softc *sc = priv;struct ath_rate_priv *ath_rc_priv = priv_sta; -const struct ath_rate_table *rate_table =NULL ; +const struct ath_rate_table *rate_table;bool is_cw40, is_sgi40;int i, j =0 ;
@@ -1397,11 +1417,9 @@ static void ath_rate_init(void *priv, st (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, - is_cw40); - } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { -/* cur_rate_table would be set on init through config() */ - rate_table = sc->cur_rate_table; + sta->ht_cap.ht_supported, is_cw40); + } else { + rate_table = hw_rate_table[sc->cur_rate_mode]; } ath_rc_priv->ht_cap =ath_rc_build_ht_caps (sc, sta, is_cw40, is_sgi40);
@@ -1445,6 +1463,7 @@ static void ath_rate_update(void *priv,ath_print (ath9k_hw_common (sc->sc_ah),ATH_DBG_CONFIG ,"Operating HT Bandwidth changed to: %d\n" , sc->hw->conf.channel_type); + sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode]; } } }
@@ -1497,26 +1516,6 @@ static struct rate_control_ops ath_rate_ .free_sta = ath_rate_free_sta, }; -void ath_rate_attach (struct ath_softc *sc) -{ - sc->hw_rate_table[ATH9K_MODE_11A ] = - &ar5416_11a_ratetable; - sc->hw_rate_table[ATH9K_MODE_11G ] = - &ar5416_11g_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT20 ] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT20 ] = - &ar5416_11ng_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS ] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS ] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS ] = - &ar5416_11ng_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS ] = - &ar5416_11ng_ratetable; -} -int ath_rate_control_register (void ) {return ieee80211_rate_control_register (&ath_rate_ops);
drivers/net/wireless/ath/ath9k/xmit.c +77 -33
215 lines not on this page · raw message
drivers/net/wireless/ath/ath9k/ath9k.h +2 -3
@@ -21,7 +21,6 @@#include <linux/device.h> #include <linux/leds.h> -#include "rc.h" #include "debug.h" #include "common.h"
@@ -433,6 +432,7 @@ struct ath_led {#define SC_OP_BT_PRIORITY_DETECTED BIT(21)struct ath_wiphy ; +struct ath_rate_table ;struct ath_softc {struct ieee80211_hw *hw;
@@ -477,9 +477,8 @@ struct ath_softc {struct ath_rx rx;struct ath_tx tx;struct ath_beacon beacon; -struct ieee80211_rate rates[IEEE80211_NUM_BANDS ][ATH_RATE_MAX ]; -const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX ];const struct ath_rate_table *cur_rate_table; +enum wireless_mode cur_rate_mode;struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS ];struct ath_led radio_led;
drivers/net/wireless/ath/ath9k/main.c +41 -71
160 lines not on this page · raw message
drivers/net/wireless/ath/ath9k/rc.h +1 -2
@@ -104,6 +104,7 @@ enum {*/ struct ath_rate_table {int rate_cnt; +int mcs_start;struct {int valid;int valid_single_stream;
@@ -179,8 +180,6 @@ enum ath9k_internal_frame_type { ATH9K_INT_UNPAUSE }; -void ath_rate_attach (struct ath_softc *sc); -u8 ath_rate_findrateix (struct ath_softc *sc,u8 dot11_rate);int ath_rate_control_register (void );void ath_rate_control_unregister (void );
drivers/net/wireless/ath/ath9k/beacon.c +5 -5
@@ -65,9 +65,9 @@ static void ath_beacon_setup(struct ath_struct ath_common *common =ath9k_hw_common (ah);struct ath_desc *ds;struct ath9k_11n_rate_series series[4 ]; -const struct ath_rate_table *rt;int flags, antenna, ctsrate =0 , ctsduration =0 ; -u8 rate; +struct ieee80211_supported_band *sband; +u8 rate =0 ; ds = bf->bf_desc; flags =ATH9K_TXDESC_NOACK ;
@@ -91,10 +91,10 @@ static void ath_beacon_setup(struct ath_ ds->ds_data = bf->bf_buf_addr; - rt = sc->cur_rate_table; - rate = rt->info[0 ].ratecode; + sband = &sc->sbands[common->hw->conf.channel->band]; + rate = sband->bitrates[0 ].hw_value;if (sc->sc_flags &SC_OP_PREAMBLE_SHORT ) - rate |= rt->info[0 ].short_preamble; + rate |= sband->bitrates[0 ].hw_value_short; ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, ATH9K_PKT_TYPE_BEACON,
drivers/net/wireless/ath/ath9k/debug.h +2 -1
@@ -18,6 +18,7 @@#define DEBUG_H #include "hw.h" +#include "rc.h" struct ath_txq ;struct ath_buf ;
@@ -138,7 +139,7 @@ void ath9k_exit_debug(struct ath_hw *ah)int ath9k_debug_create_root (void );void ath9k_debug_remove_root (void );void ath_debug_stat_interrupt (struct ath_softc *sc,enum ath9k_int status); -void ath_debug_stat_rc (struct ath_softc *sc,struct sk_buff *skb); +void ath_debug_stat_rc (struct ath_softc *sc,int final_rate);void ath_debug_stat_tx (struct ath_softc *sc,struct ath_txq *txq,struct ath_buf *bf); void ath_debug_stat_retries(struct ath_softc *sc, int rix,
drivers/net/wireless/ath/ath9k/debug.c +2 -12
@@ -255,21 +255,11 @@ static const struct file_operations fops .owner = THIS_MODULE }; -void ath_debug_stat_rc (struct ath_softc *sc,struct sk_buff *skb) +void ath_debug_stat_rc (struct ath_softc *sc,int final_rate) { -struct ieee80211_tx_info *tx_info =IEEE80211_SKB_CB (skb); -struct ieee80211_tx_rate *rates = tx_info->status.rates; -int final_ts_idx =0 , idx, i;struct ath_rc_stats *stats; -for (i =0 ; i <IEEE80211_TX_MAX_RATES ; i++) { -if (!rates[i].count) -break ; - - final_ts_idx = i; - } - idx = rates[final_ts_idx].idx; - stats = &sc->debug.stats.rcstats[idx]; + stats = &sc->debug.stats.rcstats[final_rate]; stats->success++; }
drivers/net/wireless/ath/ath9k/hw.c +4 -8
@@ -149,22 +149,19 @@ bool ath9k_get_channel_edges(struct ath_ }u16 ath9k_hw_computetxtime (struct ath_hw *ah, -const struct ath_rate_table *rates, +u8 phy,int kbps,u32 frameLen,u16 rateix,bool shortPreamble) {u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; -u32 kbps; - - kbps = rates->info[rateix].ratekbps;if (kbps ==0 )return 0 ; -switch (rates->info[rateix].phy) { +switch (phy) {case WLAN_RC_PHY_CCK : phyTime =CCK_PREAMBLE_BITS +CCK_PLCP_BITS ; -if (shortPreamble && rates->info[rateix].short_preamble) +if (shortPreamble) phyTime >>=1 ; numBits = frameLen <<3 ; txTime =CCK_SIFS_TIME + phyTime + ((numBits *1000 ) / kbps);
@@ -195,8 +192,7 @@ u16 ath9k_hw_computetxtime(struct ath_hwbreak ;default :ath_print (ath9k_hw_common (ah),ATH_DBG_FATAL , -"Unknown phy %u (rate ix %u)\n" , - rates->info[rateix].phy, rateix); +"Unknown phy %u (rate ix %u)\n" , phy, rateix); txTime =0 ;break ; }
drivers/net/wireless/ath/ath9k/hw.h +1 -1
@@ -670,7 +670,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u3u32 ath9k_hw_reverse_bits (u32 val,u32 n);bool ath9k_get_channel_edges (struct ath_hw *ah,u16 flags,u16 *low,u16 *high);u16 ath9k_hw_computetxtime (struct ath_hw *ah, -const struct ath_rate_table *rates, +u8 phy,int kbps,u32 frameLen,u16 rateix,bool shortPreamble); void ath9k_hw_get_channel_centers(struct ath_hw *ah, struct ath9k_channel *chan,
drivers/net/wireless/ath/ath9k/mac.h +0 -1
@@ -616,7 +616,6 @@ enum ath9k_cipher {struct ath_hw ;struct ath9k_channel ; -struct ath_rate_table ;u32 ath9k_hw_gettxbuf (struct ath_hw *ah,u32 q);void ath9k_hw_puttxbuf (struct ath_hw *ah,u32 q,u32 txdp);
PATCH 2/2 ath9k: clean up rc rate table
Remove some fields from struct ath_rate_table that are now unused.
---
drivers/net/wireless/ath/ath9k/rc.h +0 -2
@@ -112,14 +112,12 @@ struct ath_rate_table {u32 ratekbps;u32 user_ratekbps;u8 ratecode; -u8 short_preamble;u8 dot11rate;u8 ctrl_rate;u8 base_index;u8 cw40index;u8 sgi_index;u8 ht_index; -u32 max_4ms_framelen; } info[RATE_TABLE_SIZE ];u32 probe_interval;u8 initial_ratemax;
drivers/net/wireless/ath/ath9k/rc.c +109 -217
454 lines not on this page · raw message
Quoted 6 lines · Felix Fietkau
This patch changes ath9k to pass proper MCS indexes and flags between the RC and the rest of the driver code.
sc->cur_rate_tableremains, as it's used by the RC code internally, but the rest of the driver code no longer uses it, so a potential new RC for ath9k would not have to update it.
Quoted 6 lines
Signed-off-by Felix Fietkau <[email protected]>---
- replacessc->hwusage withcommon->hw
- initializes unused tx status rates to -1 for minstrel compatibility
- split up for easier review
- tested in ap mode with minstrel against a legacy STA
Sorry, disregard that patch. It doesn't really work when split up this way, as I still need to adjust the MCS indexes, which is currently done in the second patch. I'll resend later...
- Felix