12c8dccc7SJohannes Berg /* 22c8dccc7SJohannes Berg * Copyright 2002-2005, Instant802 Networks, Inc. 32c8dccc7SJohannes Berg * Copyright 2005, Devicescape Software, Inc. 42c8dccc7SJohannes Berg * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> 52c8dccc7SJohannes Berg * 62c8dccc7SJohannes Berg * This program is free software; you can redistribute it and/or modify 72c8dccc7SJohannes Berg * it under the terms of the GNU General Public License version 2 as 82c8dccc7SJohannes Berg * published by the Free Software Foundation. 92c8dccc7SJohannes Berg */ 102c8dccc7SJohannes Berg 112c8dccc7SJohannes Berg #ifndef IEEE80211_RATE_H 122c8dccc7SJohannes Berg #define IEEE80211_RATE_H 132c8dccc7SJohannes Berg 142c8dccc7SJohannes Berg #include <linux/netdevice.h> 152c8dccc7SJohannes Berg #include <linux/skbuff.h> 162c8dccc7SJohannes Berg #include <linux/types.h> 172c8dccc7SJohannes Berg #include <net/mac80211.h> 182c8dccc7SJohannes Berg #include "ieee80211_i.h" 192c8dccc7SJohannes Berg #include "sta_info.h" 208f727ef3SJohannes Berg #include "driver-ops.h" 212c8dccc7SJohannes Berg 222c8dccc7SJohannes Berg struct rate_control_ref { 234b7679a5SJohannes Berg struct ieee80211_local *local; 24631ad703SJohannes Berg const struct rate_control_ops *ops; 252c8dccc7SJohannes Berg void *priv; 262c8dccc7SJohannes Berg }; 272c8dccc7SJohannes Berg 284b7679a5SJohannes Berg void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, 29e6a9854bSJohannes Berg struct sta_info *sta, 30e6a9854bSJohannes Berg struct ieee80211_tx_rate_control *txrc); 312c8dccc7SJohannes Berg 324b7679a5SJohannes Berg static inline void rate_control_tx_status(struct ieee80211_local *local, 334b7679a5SJohannes Berg struct ieee80211_supported_band *sband, 344b7679a5SJohannes Berg struct sta_info *sta, 35e039fa4aSJohannes Berg struct sk_buff *skb) 362c8dccc7SJohannes Berg { 372c8dccc7SJohannes Berg struct rate_control_ref *ref = local->rate_ctrl; 384b7679a5SJohannes Berg struct ieee80211_sta *ista = &sta->sta; 394b7679a5SJohannes Berg void *priv_sta = sta->rate_ctrl_priv; 40f684565eSFelix Fietkau struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 413c384053SVasanthakumar 422cfc6fc5SFelix Fietkau if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) 433c384053SVasanthakumar return; 443c384053SVasanthakumar 45f684565eSFelix Fietkau if (ref->ops->tx_status) 464b7679a5SJohannes Berg ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); 47f684565eSFelix Fietkau else 48f684565eSFelix Fietkau ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); 492c8dccc7SJohannes Berg } 502c8dccc7SJohannes Berg 51*f027c2acSFelix Fietkau static inline void 52*f027c2acSFelix Fietkau rate_control_tx_status_noskb(struct ieee80211_local *local, 53*f027c2acSFelix Fietkau struct ieee80211_supported_band *sband, 54*f027c2acSFelix Fietkau struct sta_info *sta, 55*f027c2acSFelix Fietkau struct ieee80211_tx_info *info) 56*f027c2acSFelix Fietkau { 57*f027c2acSFelix Fietkau struct rate_control_ref *ref = local->rate_ctrl; 58*f027c2acSFelix Fietkau struct ieee80211_sta *ista = &sta->sta; 59*f027c2acSFelix Fietkau void *priv_sta = sta->rate_ctrl_priv; 60*f027c2acSFelix Fietkau 61*f027c2acSFelix Fietkau if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) 62*f027c2acSFelix Fietkau return; 63*f027c2acSFelix Fietkau 64*f027c2acSFelix Fietkau if (WARN_ON_ONCE(!ref->ops->tx_status_noskb)) 65*f027c2acSFelix Fietkau return; 66*f027c2acSFelix Fietkau 67*f027c2acSFelix Fietkau ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); 68*f027c2acSFelix Fietkau } 692c8dccc7SJohannes Berg 704b7679a5SJohannes Berg static inline void rate_control_rate_init(struct sta_info *sta) 712c8dccc7SJohannes Berg { 724b7679a5SJohannes Berg struct ieee80211_local *local = sta->sdata->local; 732c8dccc7SJohannes Berg struct rate_control_ref *ref = sta->rate_ctrl; 744b7679a5SJohannes Berg struct ieee80211_sta *ista = &sta->sta; 754b7679a5SJohannes Berg void *priv_sta = sta->rate_ctrl_priv; 764b7679a5SJohannes Berg struct ieee80211_supported_band *sband; 7755de908aSJohannes Berg struct ieee80211_chanctx_conf *chanctx_conf; 784b7679a5SJohannes Berg 79ddcc347bSMichal Kazior ieee80211_sta_set_rx_nss(sta); 80ddcc347bSMichal Kazior 81af65cd96SJohannes Berg if (!ref) 82af65cd96SJohannes Berg return; 83af65cd96SJohannes Berg 8455de908aSJohannes Berg rcu_read_lock(); 8555de908aSJohannes Berg 8655de908aSJohannes Berg chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); 8755de908aSJohannes Berg if (WARN_ON(!chanctx_conf)) { 8855de908aSJohannes Berg rcu_read_unlock(); 8955de908aSJohannes Berg return; 9055de908aSJohannes Berg } 9155de908aSJohannes Berg 924bf88530SJohannes Berg sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; 934b7679a5SJohannes Berg 943de805cfSSimon Wunderlich ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, 953de805cfSSimon Wunderlich priv_sta); 963de805cfSSimon Wunderlich rcu_read_unlock(); 97e1936e94SJohannes Berg set_sta_flag(sta, WLAN_STA_RATE_CONTROL); 982c8dccc7SJohannes Berg } 992c8dccc7SJohannes Berg 10081cb7623SSujith static inline void rate_control_rate_update(struct ieee80211_local *local, 10181cb7623SSujith struct ieee80211_supported_band *sband, 10264f68e5dSJohannes Berg struct sta_info *sta, u32 changed) 10381cb7623SSujith { 10481cb7623SSujith struct rate_control_ref *ref = local->rate_ctrl; 10581cb7623SSujith struct ieee80211_sta *ista = &sta->sta; 10681cb7623SSujith void *priv_sta = sta->rate_ctrl_priv; 1073de805cfSSimon Wunderlich struct ieee80211_chanctx_conf *chanctx_conf; 10881cb7623SSujith 1093de805cfSSimon Wunderlich if (ref && ref->ops->rate_update) { 1103de805cfSSimon Wunderlich rcu_read_lock(); 1113de805cfSSimon Wunderlich 1123de805cfSSimon Wunderlich chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); 1133de805cfSSimon Wunderlich if (WARN_ON(!chanctx_conf)) { 1143de805cfSSimon Wunderlich rcu_read_unlock(); 1153de805cfSSimon Wunderlich return; 1163de805cfSSimon Wunderlich } 1173de805cfSSimon Wunderlich 1183de805cfSSimon Wunderlich ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def, 1193de805cfSSimon Wunderlich ista, priv_sta, changed); 1203de805cfSSimon Wunderlich rcu_read_unlock(); 1213de805cfSSimon Wunderlich } 1228f727ef3SJohannes Berg drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); 12381cb7623SSujith } 1242c8dccc7SJohannes Berg 1252c8dccc7SJohannes Berg static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, 1264b7679a5SJohannes Berg struct ieee80211_sta *sta, 1272c8dccc7SJohannes Berg gfp_t gfp) 1282c8dccc7SJohannes Berg { 1294b7679a5SJohannes Berg return ref->ops->alloc_sta(ref->priv, sta, gfp); 1302c8dccc7SJohannes Berg } 1312c8dccc7SJohannes Berg 1324b7679a5SJohannes Berg static inline void rate_control_free_sta(struct sta_info *sta) 1332c8dccc7SJohannes Berg { 1344b7679a5SJohannes Berg struct rate_control_ref *ref = sta->rate_ctrl; 1354b7679a5SJohannes Berg struct ieee80211_sta *ista = &sta->sta; 1364b7679a5SJohannes Berg void *priv_sta = sta->rate_ctrl_priv; 1374b7679a5SJohannes Berg 1384b7679a5SJohannes Berg ref->ops->free_sta(ref->priv, ista, priv_sta); 1392c8dccc7SJohannes Berg } 1402c8dccc7SJohannes Berg 1412c8dccc7SJohannes Berg static inline void rate_control_add_sta_debugfs(struct sta_info *sta) 1422c8dccc7SJohannes Berg { 1432c8dccc7SJohannes Berg #ifdef CONFIG_MAC80211_DEBUGFS 1442c8dccc7SJohannes Berg struct rate_control_ref *ref = sta->rate_ctrl; 145af65cd96SJohannes Berg if (ref && sta->debugfs.dir && ref->ops->add_sta_debugfs) 1462c8dccc7SJohannes Berg ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv, 1472c8dccc7SJohannes Berg sta->debugfs.dir); 1482c8dccc7SJohannes Berg #endif 1492c8dccc7SJohannes Berg } 1502c8dccc7SJohannes Berg 1512c8dccc7SJohannes Berg static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) 1522c8dccc7SJohannes Berg { 1532c8dccc7SJohannes Berg #ifdef CONFIG_MAC80211_DEBUGFS 1542c8dccc7SJohannes Berg struct rate_control_ref *ref = sta->rate_ctrl; 155af65cd96SJohannes Berg if (ref && ref->ops->remove_sta_debugfs) 1562c8dccc7SJohannes Berg ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv); 1572c8dccc7SJohannes Berg #endif 1582c8dccc7SJohannes Berg } 1592c8dccc7SJohannes Berg 160209c671dSAndres Salomon /* Get a reference to the rate control algorithm. If `name' is NULL, get the 161209c671dSAndres Salomon * first available algorithm. */ 1622c8dccc7SJohannes Berg int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, 1632c8dccc7SJohannes Berg const char *name); 1642c8dccc7SJohannes Berg void rate_control_deinitialize(struct ieee80211_local *local); 1652c8dccc7SJohannes Berg 1662c8dccc7SJohannes Berg 1672c8dccc7SJohannes Berg /* Rate control algorithms */ 168cccf129fSFelix Fietkau #ifdef CONFIG_MAC80211_RC_MINSTREL 169c1b1203dSJoe Perches int rc80211_minstrel_init(void); 170c1b1203dSJoe Perches void rc80211_minstrel_exit(void); 171cccf129fSFelix Fietkau #else 172cccf129fSFelix Fietkau static inline int rc80211_minstrel_init(void) 173cccf129fSFelix Fietkau { 174cccf129fSFelix Fietkau return 0; 175cccf129fSFelix Fietkau } 176cccf129fSFelix Fietkau static inline void rc80211_minstrel_exit(void) 177cccf129fSFelix Fietkau { 178cccf129fSFelix Fietkau } 179cccf129fSFelix Fietkau #endif 180cccf129fSFelix Fietkau 181ec8aa669SFelix Fietkau #ifdef CONFIG_MAC80211_RC_MINSTREL_HT 182c1b1203dSJoe Perches int rc80211_minstrel_ht_init(void); 183c1b1203dSJoe Perches void rc80211_minstrel_ht_exit(void); 184ec8aa669SFelix Fietkau #else 185ec8aa669SFelix Fietkau static inline int rc80211_minstrel_ht_init(void) 186ec8aa669SFelix Fietkau { 187ec8aa669SFelix Fietkau return 0; 188ec8aa669SFelix Fietkau } 189ec8aa669SFelix Fietkau static inline void rc80211_minstrel_ht_exit(void) 190ec8aa669SFelix Fietkau { 191ec8aa669SFelix Fietkau } 192ec8aa669SFelix Fietkau #endif 193ec8aa669SFelix Fietkau 194cccf129fSFelix Fietkau 1952c8dccc7SJohannes Berg #endif /* IEEE80211_RATE_H */ 196