wlcore: report rssi from roaming statistics
authorNadim Zubidat <nadimz@ti.com>
Tue, 12 Mar 2013 15:19:39 +0000 (17:19 +0200)
committerLuciano Coelho <coelho@ti.com>
Mon, 25 Mar 2013 10:33:11 +0000 (12:33 +0200)
report the average beacon rssi which is calculated
by firmware for roaming statistics instead of the
last rx packet rssi. this results a more accurate
rssi reporting

Signed-off-by: Nadim Zubidat <nadimz@ti.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
drivers/net/wireless/ti/wlcore/acx.c
drivers/net/wireless/ti/wlcore/acx.h
drivers/net/wireless/ti/wlcore/main.c

index c796543..7a970cd 100644 (file)
@@ -1736,6 +1736,35 @@ out:
 
 }
 
+int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+                           s8 *avg_rssi)
+{
+       struct acx_roaming_stats *acx;
+       int ret = 0;
+
+       wl1271_debug(DEBUG_ACX, "acx roaming statistics");
+
+       acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+       if (!acx) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       acx->role_id = wlvif->role_id;
+       ret = wl1271_cmd_interrogate(wl, ACX_ROAMING_STATISTICS_TBL,
+                                    acx, sizeof(*acx));
+       if (ret < 0) {
+               wl1271_warning("acx roaming statistics failed: %d", ret);
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       *avg_rssi = acx->rssi_beacon;
+out:
+       kfree(acx);
+       return ret;
+}
+
 #ifdef CONFIG_PM
 /* Set the global behaviour of RX filters - On/Off + default action */
 int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
index 1a61e85..6dcfad9 100644 (file)
@@ -953,6 +953,18 @@ struct acx_rx_filter_cfg {
        u8 fields[0];
 } __packed;
 
+struct acx_roaming_stats {
+       struct acx_header header;
+
+       u8      role_id;
+       u8      pad[3];
+       u32     missed_beacons;
+       u8      snr_data;
+       u8      snr_bacon;
+       s8      rssi_data;
+       s8      rssi_beacon;
+} __packed;
+
 enum {
        ACX_WAKE_UP_CONDITIONS           = 0x0000,
        ACX_MEM_CFG                      = 0x0001,
@@ -1110,6 +1122,8 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
 int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
 int wl12xx_acx_config_hangover(struct wl1271 *wl);
+int wlcore_acx_average_rssi(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+                           s8 *avg_rssi);
 
 #ifdef CONFIG_PM
 int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable,
index c1a60cd..bf86c71 100644 (file)
@@ -5094,6 +5094,39 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
        wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
 }
 
+static int wlcore_op_get_rssi(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif,
+                              struct ieee80211_sta *sta,
+                              s8 *rssi_dbm)
+{
+       struct wl1271 *wl = hw->priv;
+       struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+       int ret = 0;
+
+       wl1271_debug(DEBUG_MAC80211, "mac80211 get_rssi");
+
+       mutex_lock(&wl->mutex);
+
+       if (unlikely(wl->state != WLCORE_STATE_ON))
+               goto out;
+
+       ret = wl1271_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out_sleep;
+
+       ret = wlcore_acx_average_rssi(wl, wlvif, rssi_dbm);
+       if (ret < 0)
+               goto out_sleep;
+
+out_sleep:
+       wl1271_ps_elp_sleep(wl);
+
+out:
+       mutex_unlock(&wl->mutex);
+
+       return ret;
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
        struct wl1271 *wl = hw->priv;
@@ -5293,6 +5326,7 @@ static const struct ieee80211_ops wl1271_ops = {
        .assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
        .unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
        .sta_rc_update = wlcore_op_sta_rc_update,
+       .get_rssi = wlcore_op_get_rssi,
        CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };