aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);