diff mbox

[3/6] Add a function for evaluating rate changes for possible notification

Message ID 20101013224851.B8E5D20465@glenhelen.mtv.corp.google.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Paul Stewart Oct. 13, 2010, 10:13 p.m. UTC
None
diff mbox

Patch

diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 4f772de..5e39494 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -399,3 +399,77 @@  void rate_control_deinitialize(struct ieee80211_local *local)
 	rate_control_put(ref);
 }
 
+u32 ieee80211_rate_calculate(struct ieee80211_local *local,
+			     struct ieee80211_if_managed *ifmgd)
+{
+	u32 rate_val;
+	u32 modulation, streams, base_rate, mcs, gi_div;
+	struct ieee80211_tx_rate *rate_ptr = &ifmgd->last_cqm_tx_rate;
+	struct ieee80211_supported_band *sband;
+	static int mod_table[8] = { 1, 2, 3, 4, 6, 8, 9, 10 };
+
+	if (!(rate_ptr->flags & IEEE80211_TX_RC_MCS)) {
+		sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+		return sband->bitrates[ifmgd->last_cqm_tx_rate.idx].bitrate;
+	}
+
+	mcs = rate_ptr->idx;
+
+	/* MCS values over 32 are not yet supported */
+	if (mcs >= 32)
+		return 0;
+
+	modulation = mcs & 7;
+	streams = (mcs >> 3) + 1;
+	base_rate = (rate_ptr->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ?
+		13500000 : 6500000;
+	gi_div = (rate_ptr->flags & IEEE80211_TX_RC_SHORT_GI) ? 9 : 10;
+	rate_val = base_rate * mod_table[modulation] * streams / gi_div;
+
+	return ((rate_val + 5000) / 10000) * 100;
+}
+
+void ieee80211_cqm_bitrate_notify(struct ieee80211_local *local)
+{
+	struct ieee80211_sub_if_data *sdata;
+	struct ieee80211_if_managed *ifmgd;
+	struct ieee80211_bss_conf *bss_conf;
+	u32 bitrate, threshold;
+	int prev_state, new_state;
+
+        WARN_ON(!mutex_is_locked(&local->iflist_mtx));
+
+        list_for_each_entry(sdata, &local->interfaces, list) {
+                if (!netif_running(sdata->dev) ||
+		    sdata->vif.type != NL80211_IFTYPE_STATION)
+                        continue;
+
+		ifmgd = &sdata->u.mgd;
+		bss_conf = &sdata->vif.bss_conf;
+
+		if (!(ifmgd->flags & IEEE80211_STA_TX_RATE_CHANGED) ||
+		    bss_conf->cqm_bitrate_thold == 0)
+			continue;
+
+		bitrate = ieee80211_rate_calculate(local, ifmgd);
+		threshold = bss_conf->cqm_bitrate_thold;
+		prev_state = (ifmgd->last_cqm_bitrate < threshold);
+		new_state = (bitrate < threshold);
+
+		/*
+		 * Trigger a bitrate notification if one of the following is
+		 * true:
+		 *   - We haven't sent one since the threshold was reconfigured
+		 *   - We have crossed the threshold in either direction
+		 *   - We are below threshold, and the bitrate has decreased yet
+		 *     again.
+		 */
+		if (ifmgd->last_cqm_bitrate == 0 || prev_state != new_state ||
+		    (new_state && bitrate < ifmgd->last_cqm_bitrate)) {
+			cfg80211_cqm_bitrate_notify(sdata->dev, bitrate,
+						    GFP_KERNEL);
+			ifmgd->last_cqm_bitrate = bitrate;
+		}
+		ifmgd->flags &= ~IEEE80211_STA_TX_RATE_CHANGED;
+	}
+}
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 168427b..33e4ca3 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -120,6 +120,14 @@  int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
 void rate_control_deinitialize(struct ieee80211_local *local);
 
 
+/* Notify listeners about transmit rate changes */
+void ieee80211_cqm_bitrate_notify(struct ieee80211_local *local);
+
+/* Convert rate into cfg80211-compatible struct? */
+void ieee80211_rate_convert_cfg(struct ieee80211_local *local,
+				struct ieee80211_if_managed *ifmgd,
+				struct rate_info *rate);
+
 /* Rate control algorithms */
 #ifdef CONFIG_MAC80211_RC_PID
 extern int rc80211_pid_init(void);