aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMeenakshi Venkataraman <meenakshi.venkataraman@intel.com>2011-07-08 11:46:22 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-11 15:02:06 -0400
commit615f7b9bb1f8e0e3188470245cec44f175189084 (patch)
tree4c0803460f682c34b11929a1fe22e150839efedb
parent0a49b2c2a6bf2f774675e472afe68951900596fb (diff)
mac80211: add driver RSSI threshold events
mac80211 maintains a running average of the RSSI when a STA is associated to an AP. Report threshold events to any driver that has registered callbacks for getting RSSI measurements. Implement callbacks in mac80211 so that driver can set thresholds. Add callbacks in mac80211 which is invoked when an RSSI threshold event occurs. mac80211: add tracing to rssi_reports api and remove extraneous fn argument mac80211: scale up rssi thresholds from driver by 16 before storing Signed-off-by: Meenakshi Venkataraman <meenakshi.venkataraman@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/mac80211.h20
-rw-r--r--net/mac80211/driver-ops.h8
-rw-r--r--net/mac80211/driver-trace.h46
-rw-r--r--net/mac80211/ieee80211_i.h8
-rw-r--r--net/mac80211/mlme.c23
-rw-r--r--net/mac80211/util.c40
6 files changed, 145 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b29456a945c2..8ff3d8a1377c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -194,6 +194,17 @@ enum ieee80211_bss_change {
194#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4 194#define IEEE80211_BSS_ARP_ADDR_LIST_LEN 4
195 195
196/** 196/**
197 * enum ieee80211_rssi_event - RSSI threshold event
198 * An indicator for when RSSI goes below/above a certain threshold.
199 * @RSSI_EVENT_HIGH: AP's rssi crossed the high threshold set by the driver.
200 * @RSSI_EVENT_LOW: AP's rssi crossed the low threshold set by the driver.
201 */
202enum ieee80211_rssi_event {
203 RSSI_EVENT_HIGH,
204 RSSI_EVENT_LOW,
205};
206
207/**
197 * struct ieee80211_bss_conf - holds the BSS's changing parameters 208 * struct ieee80211_bss_conf - holds the BSS's changing parameters
198 * 209 *
199 * This structure keeps information about a BSS (and an association 210 * This structure keeps information about a BSS (and an association
@@ -1867,6 +1878,8 @@ enum ieee80211_ampdu_mlme_action {
1867 * @set_bitrate_mask: Set a mask of rates to be used for rate control selection 1878 * @set_bitrate_mask: Set a mask of rates to be used for rate control selection
1868 * when transmitting a frame. Currently only legacy rates are handled. 1879 * when transmitting a frame. Currently only legacy rates are handled.
1869 * The callback can sleep. 1880 * The callback can sleep.
1881 * @rssi_callback: Notify driver when the average RSSI goes above/below
1882 * thresholds that were registered previously. The callback can sleep.
1870 */ 1883 */
1871struct ieee80211_ops { 1884struct ieee80211_ops {
1872 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); 1885 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1975,6 +1988,8 @@ struct ieee80211_ops {
1975 bool (*tx_frames_pending)(struct ieee80211_hw *hw); 1988 bool (*tx_frames_pending)(struct ieee80211_hw *hw);
1976 int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 1989 int (*set_bitrate_mask)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1977 const struct cfg80211_bitrate_mask *mask); 1990 const struct cfg80211_bitrate_mask *mask);
1991 void (*rssi_callback)(struct ieee80211_hw *hw,
1992 enum ieee80211_rssi_event rssi_event);
1978}; 1993};
1979 1994
1980/** 1995/**
@@ -3316,4 +3331,9 @@ ieee80211_vif_type_p2p(struct ieee80211_vif *vif)
3316 return ieee80211_iftype_p2p(vif->type, vif->p2p); 3331 return ieee80211_iftype_p2p(vif->type, vif->p2p);
3317} 3332}
3318 3333
3334void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
3335 int rssi_min_thold,
3336 int rssi_max_thold);
3337
3338void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
3319#endif /* MAC80211_H */ 3339#endif /* MAC80211_H */
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index edd2dd79c9be..b2d6bba44054 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -657,4 +657,12 @@ static inline void drv_set_rekey_data(struct ieee80211_local *local,
657 trace_drv_return_void(local); 657 trace_drv_return_void(local);
658} 658}
659 659
660static inline void drv_rssi_callback(struct ieee80211_local *local,
661 const enum ieee80211_rssi_event event)
662{
663 trace_drv_rssi_callback(local, event);
664 if (local->ops->rssi_callback)
665 local->ops->rssi_callback(&local->hw, event);
666 trace_drv_return_void(local);
667}
660#endif /* __MAC80211_DRIVER_OPS */ 668#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 31a9dfa81f65..4470f6e8b845 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -1052,6 +1052,28 @@ TRACE_EVENT(drv_set_rekey_data,
1052 LOCAL_PR_ARG, VIF_PR_ARG) 1052 LOCAL_PR_ARG, VIF_PR_ARG)
1053); 1053);
1054 1054
1055TRACE_EVENT(drv_rssi_callback,
1056 TP_PROTO(struct ieee80211_local *local,
1057 enum ieee80211_rssi_event rssi_event),
1058
1059 TP_ARGS(local, rssi_event),
1060
1061 TP_STRUCT__entry(
1062 LOCAL_ENTRY
1063 __field(u32, rssi_event)
1064 ),
1065
1066 TP_fast_assign(
1067 LOCAL_ASSIGN;
1068 __entry->rssi_event = rssi_event;
1069 ),
1070
1071 TP_printk(
1072 LOCAL_PR_FMT " rssi_event:%d",
1073 LOCAL_PR_ARG, __entry->rssi_event
1074 )
1075);
1076
1055/* 1077/*
1056 * Tracing for API calls that drivers call. 1078 * Tracing for API calls that drivers call.
1057 */ 1079 */
@@ -1342,6 +1364,30 @@ TRACE_EVENT(api_gtk_rekey_notify,
1342 TP_printk(VIF_PR_FMT, VIF_PR_ARG) 1364 TP_printk(VIF_PR_FMT, VIF_PR_ARG)
1343); 1365);
1344 1366
1367TRACE_EVENT(api_enable_rssi_reports,
1368 TP_PROTO(struct ieee80211_sub_if_data *sdata,
1369 int rssi_min_thold, int rssi_max_thold),
1370
1371 TP_ARGS(sdata, rssi_min_thold, rssi_max_thold),
1372
1373 TP_STRUCT__entry(
1374 VIF_ENTRY
1375 __field(int, rssi_min_thold)
1376 __field(int, rssi_max_thold)
1377 ),
1378
1379 TP_fast_assign(
1380 VIF_ASSIGN;
1381 __entry->rssi_min_thold = rssi_min_thold;
1382 __entry->rssi_max_thold = rssi_max_thold;
1383 ),
1384
1385 TP_printk(
1386 VIF_PR_FMT " rssi_min_thold =%d, rssi_max_thold = %d",
1387 VIF_PR_ARG, __entry->rssi_min_thold, __entry->rssi_max_thold
1388 )
1389);
1390
1345/* 1391/*
1346 * Tracing for internal functions 1392 * Tracing for internal functions
1347 * (which may also be called in response to driver calls) 1393 * (which may also be called in response to driver calls)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4c7a831e7d1e..96600bec44c5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -432,6 +432,14 @@ struct ieee80211_if_managed {
432 * generated for the current association. 432 * generated for the current association.
433 */ 433 */
434 int last_cqm_event_signal; 434 int last_cqm_event_signal;
435
436 /*
437 * State variables for keeping track of RSSI of the AP currently
438 * connected to and informing driver when RSSI has gone
439 * below/above a certain threshold.
440 */
441 int rssi_min_thold, rssi_max_thold;
442 int last_ave_beacon_signal;
435}; 443};
436 444
437struct ieee80211_if_ibss { 445struct ieee80211_if_ibss {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b6d9bd5f4d3c..4b0460ad8c8f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1763,6 +1763,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1763 ifmgd->ave_beacon_signal = rx_status->signal * 16; 1763 ifmgd->ave_beacon_signal = rx_status->signal * 16;
1764 ifmgd->last_cqm_event_signal = 0; 1764 ifmgd->last_cqm_event_signal = 0;
1765 ifmgd->count_beacon_signal = 1; 1765 ifmgd->count_beacon_signal = 1;
1766 ifmgd->last_ave_beacon_signal = 0;
1766 } else { 1767 } else {
1767 ifmgd->ave_beacon_signal = 1768 ifmgd->ave_beacon_signal =
1768 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + 1769 (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 +
@@ -1770,6 +1771,28 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1770 ifmgd->ave_beacon_signal) / 16; 1771 ifmgd->ave_beacon_signal) / 16;
1771 ifmgd->count_beacon_signal++; 1772 ifmgd->count_beacon_signal++;
1772 } 1773 }
1774
1775 if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
1776 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
1777 int sig = ifmgd->ave_beacon_signal;
1778 int last_sig = ifmgd->last_ave_beacon_signal;
1779
1780 /*
1781 * if signal crosses either of the boundaries, invoke callback
1782 * with appropriate parameters
1783 */
1784 if (sig > ifmgd->rssi_max_thold &&
1785 (last_sig <= ifmgd->rssi_min_thold || last_sig == 0)) {
1786 ifmgd->last_ave_beacon_signal = sig;
1787 drv_rssi_callback(local, RSSI_EVENT_HIGH);
1788 } else if (sig < ifmgd->rssi_min_thold &&
1789 (last_sig >= ifmgd->rssi_max_thold ||
1790 last_sig == 0)) {
1791 ifmgd->last_ave_beacon_signal = sig;
1792 drv_rssi_callback(local, RSSI_EVENT_LOW);
1793 }
1794 }
1795
1773 if (bss_conf->cqm_rssi_thold && 1796 if (bss_conf->cqm_rssi_thold &&
1774 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT && 1797 ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT &&
1775 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { 1798 !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 652e5695225a..190132063c99 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1450,3 +1450,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
1450 1450
1451 return pos; 1451 return pos;
1452} 1452}
1453
1454static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata,
1455 int rssi_min_thold,
1456 int rssi_max_thold)
1457{
1458 trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold);
1459
1460 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
1461 return;
1462
1463 /*
1464 * Scale up threshold values before storing it, as the RSSI averaging
1465 * algorithm uses a scaled up value as well. Change this scaling
1466 * factor if the RSSI averaging algorithm changes.
1467 */
1468 sdata->u.mgd.rssi_min_thold = rssi_min_thold*16;
1469 sdata->u.mgd.rssi_max_thold = rssi_max_thold*16;
1470}
1471
1472void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
1473 int rssi_min_thold,
1474 int rssi_max_thold)
1475{
1476 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1477
1478 WARN_ON(rssi_min_thold == rssi_max_thold ||
1479 rssi_min_thold > rssi_max_thold);
1480
1481 _ieee80211_enable_rssi_reports(sdata, rssi_min_thold,
1482 rssi_max_thold);
1483}
1484EXPORT_SYMBOL(ieee80211_enable_rssi_reports);
1485
1486void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
1487{
1488 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
1489
1490 _ieee80211_enable_rssi_reports(sdata, 0, 0);
1491}
1492EXPORT_SYMBOL(ieee80211_disable_rssi_reports);