@@ -482,6 +482,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
}
rate_control_tx_status(local, sband, sta, skb);
+ if (ieee80211_vif_is_mesh(&sta->sdata->vif))
+ ieee80211s_update_metric(local, sta, skb);
}
rcu_read_unlock();
@@ -226,6 +226,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb,
void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
void ieee80211s_init(void);
+void ieee80211s_update_metric(struct ieee80211_local *local,
+ struct sta_info *stainfo, struct sk_buff *skb);
void ieee80211s_stop(void);
void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result
@@ -201,6 +201,24 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra,
return 0;
}
+void ieee80211s_update_metric(struct ieee80211_local *local,
+ struct sta_info *stainfo, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ int failed;
+
+ if (!ieee80211_is_data(hdr->frame_control))
+ return;
+
+ failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK);
+
+ /* moving average, scaled to 100 */
+ stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed);
+ if (stainfo->fail_avg > 95)
+ mesh_plink_broken(stainfo);
+}
+
static u32 airtime_link_metric_get(struct ieee80211_local *local,
struct sta_info *sta)
{
@@ -51,7 +51,6 @@
#include <linux/random.h>
#include <linux/ieee80211.h>
#include <net/mac80211.h>
-#include "mesh.h"
#include "rate.h"
#include "rc80211_minstrel.h"
@@ -156,16 +155,12 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct sk_buff *skb)
{
struct minstrel_sta_info *mi = priv_sta;
- struct minstrel_priv *mp = (struct minstrel_priv *)priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates;
- struct ieee80211_local *local = hw_to_local(mp->hw);
- struct sta_info *si;
int i, ndx;
int success;
success = !!(info->flags & IEEE80211_TX_STAT_ACK);
- si = sta_info_get(local, sta->addr);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if (ar[i].idx < 0)
@@ -177,17 +172,8 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
mi->r[ndx].attempts += ar[i].count;
- if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
+ if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
mi->r[ndx].success += success;
- if (si) {
- si->fail_avg = (18050 - mi->r[ndx].probability)
- / 180;
- WARN_ON(si->fail_avg > 100);
- if (si->fail_avg == 100 &&
- ieee80211_vif_is_mesh(&si->sdata->vif))
- mesh_plink_broken(si);
- }
- }
}
if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
@@ -169,19 +169,9 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
* still a good measurement and copy it. */
if (unlikely(spinfo->tx_num_xmit == 0))
pf = spinfo->last_pf;
- else {
- /* XXX: BAD HACK!!! */
- struct sta_info *si = container_of(sta, struct sta_info, sta);
-
+ else
pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
- if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100)
- mesh_plink_broken(si);
- pf <<= RC_PID_ARITH_SHIFT;
- si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
- >> RC_PID_ARITH_SHIFT;
- }
-
spinfo->tx_num_xmit = 0;
spinfo->tx_num_failed = 0;
@@ -348,9 +338,6 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband,
}
spinfo->txrate_idx = rate_lowest_index(sband, sta);
- /* HACK */
- si = container_of(sta, struct sta_info, sta);
- si->fail_avg = 0;
}
static void *rate_control_pid_alloc(struct ieee80211_hw *hw,