aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl1251/acx.c25
-rw-r--r--drivers/net/wireless/wl1251/acx.h45
-rw-r--r--drivers/net/wireless/wl1251/event.c18
-rw-r--r--drivers/net/wireless/wl1251/main.c15
-rw-r--r--drivers/net/wireless/wl1251/wl1251.h5
5 files changed, 107 insertions, 1 deletions
diff --git a/drivers/net/wireless/wl1251/acx.c b/drivers/net/wireless/wl1251/acx.c
index 8c943661f2d..ef8370edace 100644
--- a/drivers/net/wireless/wl1251/acx.c
+++ b/drivers/net/wireless/wl1251/acx.c
@@ -776,6 +776,31 @@ out:
776 return ret; 776 return ret;
777} 777}
778 778
779int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
780 u8 depth, enum wl1251_acx_low_rssi_type type)
781{
782 struct acx_low_rssi *rssi;
783 int ret;
784
785 wl1251_debug(DEBUG_ACX, "acx low rssi");
786
787 rssi = kzalloc(sizeof(*rssi), GFP_KERNEL);
788 if (!rssi)
789 return -ENOMEM;
790
791 rssi->threshold = threshold;
792 rssi->weight = weight;
793 rssi->depth = depth;
794 rssi->type = type;
795
796 ret = wl1251_cmd_configure(wl, ACX_LOW_RSSI, rssi, sizeof(*rssi));
797 if (ret < 0)
798 wl1251_warning("failed to set low rssi threshold: %d", ret);
799
800 kfree(rssi);
801 return ret;
802}
803
779int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble) 804int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
780{ 805{
781 struct acx_preamble *acx; 806 struct acx_preamble *acx;
diff --git a/drivers/net/wireless/wl1251/acx.h b/drivers/net/wireless/wl1251/acx.h
index 6a19f38958f..c2ba100f9b1 100644
--- a/drivers/net/wireless/wl1251/acx.h
+++ b/drivers/net/wireless/wl1251/acx.h
@@ -399,6 +399,49 @@ struct acx_rts_threshold {
399 u8 pad[2]; 399 u8 pad[2];
400} __packed; 400} __packed;
401 401
402enum wl1251_acx_low_rssi_type {
403 /*
404 * The event is a "Level" indication which keeps triggering
405 * as long as the average RSSI is below the threshold.
406 */
407 WL1251_ACX_LOW_RSSI_TYPE_LEVEL = 0,
408
409 /*
410 * The event is an "Edge" indication which triggers
411 * only when the RSSI threshold is crossed from above.
412 */
413 WL1251_ACX_LOW_RSSI_TYPE_EDGE = 1,
414};
415
416struct acx_low_rssi {
417 struct acx_header header;
418
419 /*
420 * The threshold (in dBm) below (or above after low rssi
421 * indication) which the firmware generates an interrupt to the
422 * host. This parameter is signed.
423 */
424 s8 threshold;
425
426 /*
427 * The weight of the current RSSI sample, before adding the new
428 * sample, that is used to calculate the average RSSI.
429 */
430 u8 weight;
431
432 /*
433 * The number of Beacons/Probe response frames that will be
434 * received before issuing the Low or Regained RSSI event.
435 */
436 u8 depth;
437
438 /*
439 * Configures how the Low RSSI Event is triggered. Refer to
440 * enum wl1251_acx_low_rssi_type for more.
441 */
442 u8 type;
443} __packed;
444
402struct acx_beacon_filter_option { 445struct acx_beacon_filter_option {
403 struct acx_header header; 446 struct acx_header header;
404 447
@@ -1418,6 +1461,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl);
1418int wl1251_acx_bcn_dtim_options(struct wl1251 *wl); 1461int wl1251_acx_bcn_dtim_options(struct wl1251 *wl);
1419int wl1251_acx_aid(struct wl1251 *wl, u16 aid); 1462int wl1251_acx_aid(struct wl1251 *wl, u16 aid);
1420int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask); 1463int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask);
1464int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
1465 u8 depth, enum wl1251_acx_low_rssi_type type);
1421int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble); 1466int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble);
1422int wl1251_acx_cts_protect(struct wl1251 *wl, 1467int wl1251_acx_cts_protect(struct wl1251 *wl,
1423 enum acx_ctsprotect_type ctsprotect); 1468 enum acx_ctsprotect_type ctsprotect);
diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c
index 712372e50a8..dfc4579acb0 100644
--- a/drivers/net/wireless/wl1251/event.c
+++ b/drivers/net/wireless/wl1251/event.c
@@ -90,6 +90,24 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
90 } 90 }
91 } 91 }
92 92
93 if (wl->vif && wl->rssi_thold) {
94 if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) {
95 wl1251_debug(DEBUG_EVENT,
96 "ROAMING_TRIGGER_LOW_RSSI_EVENT");
97 ieee80211_cqm_rssi_notify(wl->vif,
98 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
99 GFP_KERNEL);
100 }
101
102 if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) {
103 wl1251_debug(DEBUG_EVENT,
104 "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
105 ieee80211_cqm_rssi_notify(wl->vif,
106 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
107 GFP_KERNEL);
108 }
109 }
110
93 return 0; 111 return 0;
94} 112}
95 113
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index 012e1a4016f..0325643b707 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -502,6 +502,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
502 wl->psm = 0; 502 wl->psm = 0;
503 wl->tx_queue_stopped = false; 503 wl->tx_queue_stopped = false;
504 wl->power_level = WL1251_DEFAULT_POWER_LEVEL; 504 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
505 wl->rssi_thold = 0;
505 wl->channel = WL1251_DEFAULT_CHANNEL; 506 wl->channel = WL1251_DEFAULT_CHANNEL;
506 507
507 wl1251_debugfs_reset(wl); 508 wl1251_debugfs_reset(wl);
@@ -959,6 +960,16 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
959 if (ret < 0) 960 if (ret < 0)
960 goto out; 961 goto out;
961 962
963 if (changed & BSS_CHANGED_CQM) {
964 ret = wl1251_acx_low_rssi(wl, bss_conf->cqm_rssi_thold,
965 WL1251_DEFAULT_LOW_RSSI_WEIGHT,
966 WL1251_DEFAULT_LOW_RSSI_DEPTH,
967 WL1251_ACX_LOW_RSSI_TYPE_EDGE);
968 if (ret < 0)
969 goto out;
970 wl->rssi_thold = bss_conf->cqm_rssi_thold;
971 }
972
962 if (changed & BSS_CHANGED_BSSID) { 973 if (changed & BSS_CHANGED_BSSID) {
963 memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); 974 memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
964 975
@@ -1310,7 +1321,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
1310 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | 1321 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
1311 IEEE80211_HW_SUPPORTS_PS | 1322 IEEE80211_HW_SUPPORTS_PS |
1312 IEEE80211_HW_BEACON_FILTER | 1323 IEEE80211_HW_BEACON_FILTER |
1313 IEEE80211_HW_SUPPORTS_UAPSD; 1324 IEEE80211_HW_SUPPORTS_UAPSD |
1325 IEEE80211_HW_SUPPORTS_CQM_RSSI;
1314 1326
1315 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 1327 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1316 wl->hw->wiphy->max_scan_ssids = 1; 1328 wl->hw->wiphy->max_scan_ssids = 1;
@@ -1374,6 +1386,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
1374 wl->psm_requested = false; 1386 wl->psm_requested = false;
1375 wl->tx_queue_stopped = false; 1387 wl->tx_queue_stopped = false;
1376 wl->power_level = WL1251_DEFAULT_POWER_LEVEL; 1388 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
1389 wl->rssi_thold = 0;
1377 wl->beacon_int = WL1251_DEFAULT_BEACON_INT; 1390 wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
1378 wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; 1391 wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
1379 wl->vif = NULL; 1392 wl->vif = NULL;
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h
index 462ac5b2058..bb23cd522b2 100644
--- a/drivers/net/wireless/wl1251/wl1251.h
+++ b/drivers/net/wireless/wl1251/wl1251.h
@@ -370,6 +370,8 @@ struct wl1251 {
370 /* in dBm */ 370 /* in dBm */
371 int power_level; 371 int power_level;
372 372
373 int rssi_thold;
374
373 struct wl1251_stats stats; 375 struct wl1251_stats stats;
374 struct wl1251_debugfs debugfs; 376 struct wl1251_debugfs debugfs;
375 377
@@ -433,4 +435,7 @@ void wl1251_disable_interrupts(struct wl1251 *wl);
433#define WL1251_PART_WORK_REG_START REGISTERS_BASE 435#define WL1251_PART_WORK_REG_START REGISTERS_BASE
434#define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE 436#define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE
435 437
438#define WL1251_DEFAULT_LOW_RSSI_WEIGHT 10
439#define WL1251_DEFAULT_LOW_RSSI_DEPTH 10
440
436#endif 441#endif