[PATCH 2/2 v2] wlcore: Remove wl pointer from wl_sta structure

2016-08-15 Thread Maxim Altshul
This field was added to wl_sta struct to get hw in situations
where it was not given to driver by mac80211.

In our case, get_expected_throughput op did not send hw to driver.

This patch reverts the change, as it is no longer needed due to
get_expected_throughput op change (hw is now sent as a parameter)

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
Changed the commit message to better explain the changey

 drivers/net/wireless/ti/wlcore/main.c | 1 -
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 1ec3545..8589e5a 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5043,7 +5043,6 @@ static int wl12xx_sta_add(struct wl1271 *wl,
return ret;
 
wl_sta = (struct wl1271_station *)sta->drv_priv;
-   wl_sta->wl = wl;
hlid = wl_sta->hlid;
 
ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h 
b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 3875190..8ee5206 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -352,7 +352,6 @@ struct wl1271_station {
 * Used in both AP and STA mode.
 */
u64 total_freed_pkts;
-   struct wl1271 *wl;
 };
 
 struct wl12xx_vif {
-- 
2.9.0



[PATCH 2/2 v2] wlcore: Remove wl pointer from wl_sta structure

2016-08-15 Thread Maxim Altshul
This field was added to wl_sta struct to get hw in situations
where it was not given to driver by mac80211.

In our case, get_expected_throughput op did not send hw to driver.

This patch reverts the change, as it is no longer needed due to
get_expected_throughput op change (hw is now sent as a parameter)

Signed-off-by: Maxim Altshul 
---
Changed the commit message to better explain the changey

 drivers/net/wireless/ti/wlcore/main.c | 1 -
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 1ec3545..8589e5a 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5043,7 +5043,6 @@ static int wl12xx_sta_add(struct wl1271 *wl,
return ret;
 
wl_sta = (struct wl1271_station *)sta->drv_priv;
-   wl_sta->wl = wl;
hlid = wl_sta->hlid;
 
ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h 
b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 3875190..8ee5206 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -352,7 +352,6 @@ struct wl1271_station {
 * Used in both AP and STA mode.
 */
u64 total_freed_pkts;
-   struct wl1271 *wl;
 };
 
 struct wl12xx_vif {
-- 
2.9.0



[PATCH 2/2] wlcore: Remove wl pointer from wl_sta structure

2016-08-04 Thread Maxim Altshul
No longer needed due to get_expected_throughput op change

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 1 -
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 1ec3545..8589e5a 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5043,7 +5043,6 @@ static int wl12xx_sta_add(struct wl1271 *wl,
return ret;
 
wl_sta = (struct wl1271_station *)sta->drv_priv;
-   wl_sta->wl = wl;
hlid = wl_sta->hlid;
 
ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h 
b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 3875190..8ee5206 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -352,7 +352,6 @@ struct wl1271_station {
 * Used in both AP and STA mode.
 */
u64 total_freed_pkts;
-   struct wl1271 *wl;
 };
 
 struct wl12xx_vif {
-- 
2.9.0



[PATCH 2/2] wlcore: Remove wl pointer from wl_sta structure

2016-08-04 Thread Maxim Altshul
No longer needed due to get_expected_throughput op change

Signed-off-by: Maxim Altshul 
---
 drivers/net/wireless/ti/wlcore/main.c | 1 -
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 1ec3545..8589e5a 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5043,7 +5043,6 @@ static int wl12xx_sta_add(struct wl1271 *wl,
return ret;
 
wl_sta = (struct wl1271_station *)sta->drv_priv;
-   wl_sta->wl = wl;
hlid = wl_sta->hlid;
 
ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h 
b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 3875190..8ee5206 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -352,7 +352,6 @@ struct wl1271_station {
 * Used in both AP and STA mode.
 */
u64 total_freed_pkts;
-   struct wl1271 *wl;
 };
 
 struct wl12xx_vif {
-- 
2.9.0



[PATCH 1/2] mac80211/wlcore: Add ieee80211_hw variable to get_expected_throughput

2016-08-04 Thread Maxim Altshul
- The variable is added to allow the driver an easy access
to it's own hw->priv when the op is invoked.

- Change wlcore op accordingly.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 5 +++--
 include/net/mac80211.h| 3 ++-
 net/mac80211/driver-ops.h | 2 +-
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 4573614..1ec3545 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5803,10 +5803,11 @@ out:
mutex_unlock(>mutex);
 }
 
-static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_hw *hw,
+   struct ieee80211_sta *sta)
 {
struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
-   struct wl1271 *wl = wl_sta->wl;
+   struct wl1271 *wl = hw->priv;
u8 hlid = wl_sta->hlid;
 
/* return in units of Kbps */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c328f35..464eb97 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3484,7 +3484,8 @@ struct ieee80211_ops {
 
int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-   u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
+   u32 (*get_expected_throughput)(struct ieee80211_hw *hw,
+   struct ieee80211_sta *sta);
int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
   int *dbm);
 
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 154ce4b..1f75195 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1081,7 +1081,7 @@ static inline u32 drv_get_expected_throughput(struct 
ieee80211_local *local,
 
trace_drv_get_expected_throughput(sta);
if (local->ops->get_expected_throughput)
-   ret = local->ops->get_expected_throughput(sta);
+   ret = local->ops->get_expected_throughput(>hw, sta);
trace_drv_return_u32(local, ret);
 
return ret;
-- 
2.9.0



[PATCH 1/2] mac80211/wlcore: Add ieee80211_hw variable to get_expected_throughput

2016-08-04 Thread Maxim Altshul
- The variable is added to allow the driver an easy access
to it's own hw->priv when the op is invoked.

- Change wlcore op accordingly.

Signed-off-by: Maxim Altshul 
---
 drivers/net/wireless/ti/wlcore/main.c | 5 +++--
 include/net/mac80211.h| 3 ++-
 net/mac80211/driver-ops.h | 2 +-
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 4573614..1ec3545 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5803,10 +5803,11 @@ out:
mutex_unlock(>mutex);
 }
 
-static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_hw *hw,
+   struct ieee80211_sta *sta)
 {
struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
-   struct wl1271 *wl = wl_sta->wl;
+   struct wl1271 *wl = hw->priv;
u8 hlid = wl_sta->hlid;
 
/* return in units of Kbps */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c328f35..464eb97 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3484,7 +3484,8 @@ struct ieee80211_ops {
 
int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-   u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
+   u32 (*get_expected_throughput)(struct ieee80211_hw *hw,
+   struct ieee80211_sta *sta);
int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
   int *dbm);
 
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 154ce4b..1f75195 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1081,7 +1081,7 @@ static inline u32 drv_get_expected_throughput(struct 
ieee80211_local *local,
 
trace_drv_get_expected_throughput(sta);
if (local->ops->get_expected_throughput)
-   ret = local->ops->get_expected_throughput(sta);
+   ret = local->ops->get_expected_throughput(>hw, sta);
trace_drv_return_u32(local, ret);
 
return ret;
-- 
2.9.0



[PATCH 0/2] get_expected_throughput interface update

2016-08-04 Thread Maxim Altshul
These two patches are two important patches (mainly 1/2)
that solve a regression issue that was found in wlcore
(where wl was found to be null in some cases)

Also, they make it easier for driver to get hw->priv when op is invoked. 


Maxim Altshul (2):
  mac80211/wlcore: Add ieee80211_hw variable to get_expected_throughput
  wlcore: Remove wl pointer from wl_sta structure

 drivers/net/wireless/ti/wlcore/main.c | 6 +++---
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 -
 include/net/mac80211.h| 3 ++-
 net/mac80211/driver-ops.h | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

-- 
2.9.0



[PATCH 0/2] get_expected_throughput interface update

2016-08-04 Thread Maxim Altshul
These two patches are two important patches (mainly 1/2)
that solve a regression issue that was found in wlcore
(where wl was found to be null in some cases)

Also, they make it easier for driver to get hw->priv when op is invoked. 


Maxim Altshul (2):
  mac80211/wlcore: Add ieee80211_hw variable to get_expected_throughput
  wlcore: Remove wl pointer from wl_sta structure

 drivers/net/wireless/ti/wlcore/main.c | 6 +++---
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 -
 include/net/mac80211.h| 3 ++-
 net/mac80211/driver-ops.h | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

-- 
2.9.0



[PATCH 2/2 v4] wlcore: Add support for get_expected_throughput opcode

2016-07-11 Thread Maxim Altshul
Adding this opcode, allows the TI wireless driver,
to report throughput directly from FW to mac80211.

This is used mainly for mesh metric calculation.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
 drivers/net/wireless/ti/wlcore/main.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 39dec7d..237dae8c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5851,6 +5851,16 @@ out:
mutex_unlock(>mutex);
 }
 
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+{
+   struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
+   struct wl1271 *wl = wl_sta->wl;
+   u8 hlid = wl_sta->hlid;
+
+   /* return in units of Kbps */
+   return (wl->links[hlid].fw_rate_mbps * 1000);
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
struct wl1271 *wl = hw->priv;
@@ -6051,6 +6061,7 @@ static const struct ieee80211_ops wl1271_ops = {
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
.sta_rc_update = wlcore_op_sta_rc_update,
.sta_statistics = wlcore_op_sta_statistics,
+   .get_expected_throughput = wlcore_op_get_expected_throughput,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
-- 
2.9.0



[PATCH 2/2 v4] wlcore: Add support for get_expected_throughput opcode

2016-07-11 Thread Maxim Altshul
Adding this opcode, allows the TI wireless driver,
to report throughput directly from FW to mac80211.

This is used mainly for mesh metric calculation.

Signed-off-by: Maxim Altshul 
---
 drivers/net/wireless/ti/wlcore/main.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 39dec7d..237dae8c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5851,6 +5851,16 @@ out:
mutex_unlock(>mutex);
 }
 
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+{
+   struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
+   struct wl1271 *wl = wl_sta->wl;
+   u8 hlid = wl_sta->hlid;
+
+   /* return in units of Kbps */
+   return (wl->links[hlid].fw_rate_mbps * 1000);
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
struct wl1271 *wl = hw->priv;
@@ -6051,6 +6061,7 @@ static const struct ieee80211_ops wl1271_ops = {
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
.sta_rc_update = wlcore_op_sta_rc_update,
.sta_statistics = wlcore_op_sta_statistics,
+   .get_expected_throughput = wlcore_op_get_expected_throughput,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
-- 
2.9.0



[PATCH 1/2 v4] wlcore/wl18xx: Add functionality to accept TX rate per link

2016-07-11 Thread Maxim Altshul
FW will provide a TX rate per link for each FW status,
and wlcore will be able to store the information for
the use of the mesh hwmp module.

This is used mainly in mesh.
Rates are reported when a mesh interface is up.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
Send both patches + fixes for reduntant null checks and units

 drivers/net/wireless/ti/wl18xx/main.c |  4 
 drivers/net/wireless/ti/wl18xx/tx.c   | 22 ++
 drivers/net/wireless/ti/wl18xx/wl18xx.h   |  6 +-
 drivers/net/wireless/ti/wlcore/main.c |  1 +
 drivers/net/wireless/ti/wlcore/rx.c   |  7 +++
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 13 +
 6 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ti/wl18xx/main.c 
b/drivers/net/wireless/ti/wl18xx/main.c
index 6e89e13..a7913ec 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1214,6 +1214,10 @@ static void wl18xx_convert_fw_status(struct wl1271 *wl, 
void *raw_fw_status,
int_fw_status->counters.tx_voice_released_blks;
fw_status->counters.tx_last_rate =
int_fw_status->counters.tx_last_rate;
+   fw_status->counters.tx_last_rate_mbps =
+   int_fw_status->counters.tx_last_rate_mbps;
+   fw_status->counters.hlid =
+   int_fw_status->counters.hlid;
 
fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
 
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c 
b/drivers/net/wireless/ti/wl18xx/tx.c
index 3406ffb..d198827 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.c
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -30,9 +30,9 @@
 
 static
 void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
-u8 band, struct ieee80211_tx_rate *rate)
+u8 band, struct ieee80211_tx_rate *rate, u8 hlid)
 {
-   u8 fw_rate = wl->fw_status->counters.tx_last_rate;
+   u8 fw_rate = wl->links[hlid].fw_rate_idx;
 
if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
wl1271_error("last Tx rate invalid: %d", fw_rate);
@@ -79,6 +79,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 
tx_stat_byte)
struct sk_buff *skb;
int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK;
bool tx_success;
+   struct wl1271_tx_hw_descr *tx_desc;
 
/* check for id legality */
if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) {
@@ -91,6 +92,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 
tx_stat_byte)
 
skb = wl->tx_frames[id];
info = IEEE80211_SKB_CB(skb);
+   tx_desc = (struct wl1271_tx_hw_descr *)skb->data;
 
if (wl12xx_is_dummy_packet(wl, skb)) {
wl1271_free_tx_id(wl, id);
@@ -105,7 +107,9 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 
tx_stat_byte)
 * the info->status structures
 */
wl18xx_get_last_tx_rate(wl, info->control.vif,
-   info->band, >status.rates[0]);
+   info->band,
+   >status.rates[0],
+   tx_desc->hlid);
 
info->status.rates[0].count = 1; /* no data about retries */
info->status.ack_signal = -1;
@@ -144,12 +148,22 @@ void wl18xx_tx_immediate_complete(struct wl1271 *wl)
struct wl18xx_fw_status_priv *status_priv =
(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
struct wl18xx_priv *priv = wl->priv;
-   u8 i;
+   u8 i, hlid;
 
/* nothing to do here */
if (priv->last_fw_rls_idx == status_priv->fw_release_idx)
return;
 
+   /* update rates per link */
+   hlid = wl->fw_status->counters.hlid;
+
+   if (hlid < WLCORE_MAX_LINKS) {
+   wl->links[hlid].fw_rate_idx =
+   wl->fw_status->counters.tx_last_rate;
+   wl->links[hlid].fw_rate_mbps =
+   wl->fw_status->counters.tx_last_rate_mbps;
+   }
+
/* freed Tx descriptors */
wl1271_debug(DEBUG_TX, "last released desc = %d, current idx = %d",
 priv->last_fw_rls_idx, status_priv->fw_release_idx);
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h 
b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index d65cc6d..5371cbd 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -125,7 +125,11 @@ struct wl18xx_fw_packet_counters {
/* Tx rate of the last transmitted packet */
u8 tx_last_rate;
 
-   u8 padding[2];
+   /* Tx rate or Tx rate estimate pre-calculated by fw in mbps units */
+   u8 tx_last_rate_mbps

[PATCH 1/2 v4] wlcore/wl18xx: Add functionality to accept TX rate per link

2016-07-11 Thread Maxim Altshul
FW will provide a TX rate per link for each FW status,
and wlcore will be able to store the information for
the use of the mesh hwmp module.

This is used mainly in mesh.
Rates are reported when a mesh interface is up.

Signed-off-by: Maxim Altshul 
---
Send both patches + fixes for reduntant null checks and units

 drivers/net/wireless/ti/wl18xx/main.c |  4 
 drivers/net/wireless/ti/wl18xx/tx.c   | 22 ++
 drivers/net/wireless/ti/wl18xx/wl18xx.h   |  6 +-
 drivers/net/wireless/ti/wlcore/main.c |  1 +
 drivers/net/wireless/ti/wlcore/rx.c   |  7 +++
 drivers/net/wireless/ti/wlcore/wlcore_i.h | 13 +
 6 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ti/wl18xx/main.c 
b/drivers/net/wireless/ti/wl18xx/main.c
index 6e89e13..a7913ec 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1214,6 +1214,10 @@ static void wl18xx_convert_fw_status(struct wl1271 *wl, 
void *raw_fw_status,
int_fw_status->counters.tx_voice_released_blks;
fw_status->counters.tx_last_rate =
int_fw_status->counters.tx_last_rate;
+   fw_status->counters.tx_last_rate_mbps =
+   int_fw_status->counters.tx_last_rate_mbps;
+   fw_status->counters.hlid =
+   int_fw_status->counters.hlid;
 
fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
 
diff --git a/drivers/net/wireless/ti/wl18xx/tx.c 
b/drivers/net/wireless/ti/wl18xx/tx.c
index 3406ffb..d198827 100644
--- a/drivers/net/wireless/ti/wl18xx/tx.c
+++ b/drivers/net/wireless/ti/wl18xx/tx.c
@@ -30,9 +30,9 @@
 
 static
 void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
-u8 band, struct ieee80211_tx_rate *rate)
+u8 band, struct ieee80211_tx_rate *rate, u8 hlid)
 {
-   u8 fw_rate = wl->fw_status->counters.tx_last_rate;
+   u8 fw_rate = wl->links[hlid].fw_rate_idx;
 
if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
wl1271_error("last Tx rate invalid: %d", fw_rate);
@@ -79,6 +79,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 
tx_stat_byte)
struct sk_buff *skb;
int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK;
bool tx_success;
+   struct wl1271_tx_hw_descr *tx_desc;
 
/* check for id legality */
if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) {
@@ -91,6 +92,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 
tx_stat_byte)
 
skb = wl->tx_frames[id];
info = IEEE80211_SKB_CB(skb);
+   tx_desc = (struct wl1271_tx_hw_descr *)skb->data;
 
if (wl12xx_is_dummy_packet(wl, skb)) {
wl1271_free_tx_id(wl, id);
@@ -105,7 +107,9 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 
tx_stat_byte)
 * the info->status structures
 */
wl18xx_get_last_tx_rate(wl, info->control.vif,
-   info->band, >status.rates[0]);
+   info->band,
+   >status.rates[0],
+   tx_desc->hlid);
 
info->status.rates[0].count = 1; /* no data about retries */
info->status.ack_signal = -1;
@@ -144,12 +148,22 @@ void wl18xx_tx_immediate_complete(struct wl1271 *wl)
struct wl18xx_fw_status_priv *status_priv =
(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
struct wl18xx_priv *priv = wl->priv;
-   u8 i;
+   u8 i, hlid;
 
/* nothing to do here */
if (priv->last_fw_rls_idx == status_priv->fw_release_idx)
return;
 
+   /* update rates per link */
+   hlid = wl->fw_status->counters.hlid;
+
+   if (hlid < WLCORE_MAX_LINKS) {
+   wl->links[hlid].fw_rate_idx =
+   wl->fw_status->counters.tx_last_rate;
+   wl->links[hlid].fw_rate_mbps =
+   wl->fw_status->counters.tx_last_rate_mbps;
+   }
+
/* freed Tx descriptors */
wl1271_debug(DEBUG_TX, "last released desc = %d, current idx = %d",
 priv->last_fw_rls_idx, status_priv->fw_release_idx);
diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h 
b/drivers/net/wireless/ti/wl18xx/wl18xx.h
index d65cc6d..5371cbd 100644
--- a/drivers/net/wireless/ti/wl18xx/wl18xx.h
+++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h
@@ -125,7 +125,11 @@ struct wl18xx_fw_packet_counters {
/* Tx rate of the last transmitted packet */
u8 tx_last_rate;
 
-   u8 padding[2];
+   /* Tx rate or Tx rate estimate pre-calculated by fw in mbps units */
+   u8 tx_last_rate_mbps;
+
+   /* hlid for whic

[PATCH v3] mac80211: mesh: Add support for HW RC implementation

2016-07-11 Thread Maxim Altshul
Mesh HWMP module will be able to rely on the HW
RC algorithm if it exists, for path metric calculations.

This allows the metric calculation mechanism to calculate
a correct metric, based on PER and last TX rate both via
HW RC algorithm if it exists or via parameters collected
by the SW.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
1. Added DIV_ROUND_UP to protect from rate < 100Kbps
2. Removed redudant initialization

 net/mac80211/mesh_hwmp.c | 27 +++
 net/mac80211/sta_info.c  | 23 +++
 net/mac80211/sta_info.h  |  2 ++
 3 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4..befb1e7 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -326,22 +326,33 @@ static u32 airtime_link_metric_get(struct ieee80211_local 
*local,
u32 tx_time, estimated_retx;
u64 result;
 
-   if (sta->mesh->fail_avg >= 100)
-   return MAX_METRIC;
+   /* Try to get rate based on HW/SW RC algorithm.
+* Rate is returned in units of Kbps, correct this
+* to comply with airtime calculation units
+* Round up in case we get rate < 100Kbps
+*/
+   rate = DIV_ROUND_UP(sta_get_expected_throughput(sta), 100);
+   
+   if (rate) {
+   err = 0;
+   } else {
+   if (sta->mesh->fail_avg >= 100)
+   return MAX_METRIC;
 
-   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
-   rate = cfg80211_calculate_bitrate();
-   if (WARN_ON(!rate))
-   return MAX_METRIC;
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   rate = cfg80211_calculate_bitrate();
+   if (WARN_ON(!rate))
+   return MAX_METRIC;
 
-   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   }
 
/* bitrate is in units of 100 Kbps, while we need rate in units of
 * 1Mbps. This will be corrected on tx_time computation.
 */
tx_time = (device_constant + 10 * test_frame_len / rate);
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
-   result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
+   result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT);
return (u32)result;
 }
 
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 63ea6cb..fa2c507 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2069,14 +2069,29 @@ void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 
+   thr = sta_get_expected_throughput(sta);
+
+   if (thr != 0) {
+   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
+   sinfo->expected_throughput = thr;
+   }
+}
+
+u32 sta_get_expected_throughput(struct sta_info *sta)
+{
+   struct ieee80211_sub_if_data *sdata = sta->sdata;
+   struct ieee80211_local *local = sdata->local;
+   struct rate_control_ref *ref = NULL;
+   u32 thr = 0;
+
+   if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+   ref = local->rate_ctrl;
+
/* check if the driver has a SW RC implementation */
if (ref && ref->ops->get_expected_throughput)
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
else
thr = drv_get_expected_throughput(local, >sta);
 
-   if (thr != 0) {
-   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
-   sinfo->expected_throughput = thr;
-   }
+   return thr;
 }
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21..5c9c8be 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -661,6 +661,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
  struct rate_info *rinfo);
 void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
 
+u32 sta_get_expected_throughput(struct sta_info *sta);
+
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
  unsigned long exp_time);
 u8 sta_info_tx_streams(struct sta_info *sta);
-- 
2.9.0



[PATCH v3] mac80211: mesh: Add support for HW RC implementation

2016-07-11 Thread Maxim Altshul
Mesh HWMP module will be able to rely on the HW
RC algorithm if it exists, for path metric calculations.

This allows the metric calculation mechanism to calculate
a correct metric, based on PER and last TX rate both via
HW RC algorithm if it exists or via parameters collected
by the SW.

Signed-off-by: Maxim Altshul 
---
1. Added DIV_ROUND_UP to protect from rate < 100Kbps
2. Removed redudant initialization

 net/mac80211/mesh_hwmp.c | 27 +++
 net/mac80211/sta_info.c  | 23 +++
 net/mac80211/sta_info.h  |  2 ++
 3 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4..befb1e7 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -326,22 +326,33 @@ static u32 airtime_link_metric_get(struct ieee80211_local 
*local,
u32 tx_time, estimated_retx;
u64 result;
 
-   if (sta->mesh->fail_avg >= 100)
-   return MAX_METRIC;
+   /* Try to get rate based on HW/SW RC algorithm.
+* Rate is returned in units of Kbps, correct this
+* to comply with airtime calculation units
+* Round up in case we get rate < 100Kbps
+*/
+   rate = DIV_ROUND_UP(sta_get_expected_throughput(sta), 100);
+   
+   if (rate) {
+   err = 0;
+   } else {
+   if (sta->mesh->fail_avg >= 100)
+   return MAX_METRIC;
 
-   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
-   rate = cfg80211_calculate_bitrate();
-   if (WARN_ON(!rate))
-   return MAX_METRIC;
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   rate = cfg80211_calculate_bitrate();
+   if (WARN_ON(!rate))
+   return MAX_METRIC;
 
-   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   }
 
/* bitrate is in units of 100 Kbps, while we need rate in units of
 * 1Mbps. This will be corrected on tx_time computation.
 */
tx_time = (device_constant + 10 * test_frame_len / rate);
estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err));
-   result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ;
+   result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT);
return (u32)result;
 }
 
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 63ea6cb..fa2c507 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2069,14 +2069,29 @@ void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 
+   thr = sta_get_expected_throughput(sta);
+
+   if (thr != 0) {
+   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
+   sinfo->expected_throughput = thr;
+   }
+}
+
+u32 sta_get_expected_throughput(struct sta_info *sta)
+{
+   struct ieee80211_sub_if_data *sdata = sta->sdata;
+   struct ieee80211_local *local = sdata->local;
+   struct rate_control_ref *ref = NULL;
+   u32 thr = 0;
+
+   if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+   ref = local->rate_ctrl;
+
/* check if the driver has a SW RC implementation */
if (ref && ref->ops->get_expected_throughput)
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
else
thr = drv_get_expected_throughput(local, >sta);
 
-   if (thr != 0) {
-   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
-   sinfo->expected_throughput = thr;
-   }
+   return thr;
 }
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21..5c9c8be 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -661,6 +661,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
  struct rate_info *rinfo);
 void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
 
+u32 sta_get_expected_throughput(struct sta_info *sta);
+
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
  unsigned long exp_time);
 u8 sta_info_tx_streams(struct sta_info *sta);
-- 
2.9.0



[PATCH v3] wlcore: Add support for get_expected_throughput opcode

2016-06-30 Thread Maxim Altshul
Adding this opcode, allows the TI wireless driver,
to report throughput directly from FW to mac80211.

This is used mainly for mesh metric calculation.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
Removed ret and NULL test.

 drivers/net/wireless/ti/wlcore/main.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 39dec7d..237dae8c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5851,6 +5851,16 @@ out:
mutex_unlock(>mutex);
 }
 
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+{
+   struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
+   struct wl1271 *wl = wl_sta->wl;
+   u8 hlid = wl_sta->hlid;
+
+   /* return in units of Kbps */
+   return (wl->links[hlid].fw_rate_mbps * 1000);
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
struct wl1271 *wl = hw->priv;
@@ -6051,6 +6061,7 @@ static const struct ieee80211_ops wl1271_ops = {
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
.sta_rc_update = wlcore_op_sta_rc_update,
.sta_statistics = wlcore_op_sta_statistics,
+   .get_expected_throughput = wlcore_op_get_expected_throughput,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
-- 
2.9.0



[PATCH v3] wlcore: Add support for get_expected_throughput opcode

2016-06-30 Thread Maxim Altshul
Adding this opcode, allows the TI wireless driver,
to report throughput directly from FW to mac80211.

This is used mainly for mesh metric calculation.

Signed-off-by: Maxim Altshul 
---
Removed ret and NULL test.

 drivers/net/wireless/ti/wlcore/main.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 39dec7d..237dae8c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5851,6 +5851,16 @@ out:
mutex_unlock(>mutex);
 }
 
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+{
+   struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
+   struct wl1271 *wl = wl_sta->wl;
+   u8 hlid = wl_sta->hlid;
+
+   /* return in units of Kbps */
+   return (wl->links[hlid].fw_rate_mbps * 1000);
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
struct wl1271 *wl = hw->priv;
@@ -6051,6 +6061,7 @@ static const struct ieee80211_ops wl1271_ops = {
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
.sta_rc_update = wlcore_op_sta_rc_update,
.sta_statistics = wlcore_op_sta_statistics,
+   .get_expected_throughput = wlcore_op_get_expected_throughput,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
-- 
2.9.0



[PATCH v2] mac80211: mesh: Add support for HW RC implementation

2016-06-30 Thread Maxim Altshul
Mesh HWMP module will be able to rely on the HW
RC algorithm if it exists, for path metric calculations.

This allows the metric calculation mechanism to calculate
a correct metric, based on PER and last TX rate both via
HW RC algorithm if it exists or via parameters collected
by the SW.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
Changed the function to return u32, I agree that this
is much clearer.
As for the rate, two things:
1. I had to divide the returned value by 100, since
drv_get_expected_throughput returns values in units of Kbps.
On the contrary, the function cfg80211_calculate_bitrate
returns in units of 100Kbps, so a correction is needed.
2. Why return the value into rate?
As I understand, rate here is actually bitrate,
and so, we have two possible outcomes:
- A SW/HW RC algo does exist, and an estimated throughput is
returned. err is set to 0 (as it is already included in the RC algo)
and the airtime is calculated using the estimated throughput.
- A SW/HW RC algo does not exist, and thus the regular calculation
takes place, in which an estimated throughput is calculated
using the bitrate and the err parameter.
>From this calculation the airtime is calculated.

 net/mac80211/mesh_hwmp.c | 25 +
 net/mac80211/sta_info.c  | 23 +++
 net/mac80211/sta_info.h  |  2 ++
 3 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4..ad67f46 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -322,19 +322,28 @@ static u32 airtime_link_metric_get(struct ieee80211_local 
*local,
int device_constant = 1 << ARITH_SHIFT;
int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
int s_unit = 1 << ARITH_SHIFT;
-   int rate, err;
+   int rate = 0, err = 0;
u32 tx_time, estimated_retx;
u64 result;
 
-   if (sta->mesh->fail_avg >= 100)
-   return MAX_METRIC;
+   /* Try to get rate based on HW/SW RC algorithm.
+* Rate is returned in units of Kbps, correct this
+* to comply with airtime calculation units
+*/
+   rate = sta_get_expected_throughput(sta) / 100;
+
+   /* if we did not get a rate */
+   if (!rate) {
+   if (sta->mesh->fail_avg >= 100)
+   return MAX_METRIC;
 
-   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
-   rate = cfg80211_calculate_bitrate();
-   if (WARN_ON(!rate))
-   return MAX_METRIC;
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   rate = cfg80211_calculate_bitrate();
+   if (WARN_ON(!rate))
+   return MAX_METRIC;
 
-   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   }
 
/* bitrate is in units of 100 Kbps, while we need rate in units of
 * 1Mbps. This will be corrected on tx_time computation.
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 63ea6cb..fa2c507 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2069,14 +2069,29 @@ void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 
+   thr = sta_get_expected_throughput(sta);
+
+   if (thr != 0) {
+   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
+   sinfo->expected_throughput = thr;
+   }
+}
+
+u32 sta_get_expected_throughput(struct sta_info *sta)
+{
+   struct ieee80211_sub_if_data *sdata = sta->sdata;
+   struct ieee80211_local *local = sdata->local;
+   struct rate_control_ref *ref = NULL;
+   u32 thr = 0;
+
+   if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+   ref = local->rate_ctrl;
+
/* check if the driver has a SW RC implementation */
if (ref && ref->ops->get_expected_throughput)
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
else
thr = drv_get_expected_throughput(local, >sta);
 
-   if (thr != 0) {
-   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
-   sinfo->expected_throughput = thr;
-   }
+   return thr;
 }
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21..5c9c8be 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -661,6 +661,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
  struct rate_info *rinfo);
 void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
 
+u32 sta_get_expected_throughput(struct sta_info *sta);
+
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
  unsigned long exp_time);
 u8 sta_info_tx_streams(struct sta_info *sta);
-- 
2.9.0



[PATCH v2] mac80211: mesh: Add support for HW RC implementation

2016-06-30 Thread Maxim Altshul
Mesh HWMP module will be able to rely on the HW
RC algorithm if it exists, for path metric calculations.

This allows the metric calculation mechanism to calculate
a correct metric, based on PER and last TX rate both via
HW RC algorithm if it exists or via parameters collected
by the SW.

Signed-off-by: Maxim Altshul 
---
Changed the function to return u32, I agree that this
is much clearer.
As for the rate, two things:
1. I had to divide the returned value by 100, since
drv_get_expected_throughput returns values in units of Kbps.
On the contrary, the function cfg80211_calculate_bitrate
returns in units of 100Kbps, so a correction is needed.
2. Why return the value into rate?
As I understand, rate here is actually bitrate,
and so, we have two possible outcomes:
- A SW/HW RC algo does exist, and an estimated throughput is
returned. err is set to 0 (as it is already included in the RC algo)
and the airtime is calculated using the estimated throughput.
- A SW/HW RC algo does not exist, and thus the regular calculation
takes place, in which an estimated throughput is calculated
using the bitrate and the err parameter.
>From this calculation the airtime is calculated.

 net/mac80211/mesh_hwmp.c | 25 +
 net/mac80211/sta_info.c  | 23 +++
 net/mac80211/sta_info.h  |  2 ++
 3 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4..ad67f46 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -322,19 +322,28 @@ static u32 airtime_link_metric_get(struct ieee80211_local 
*local,
int device_constant = 1 << ARITH_SHIFT;
int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
int s_unit = 1 << ARITH_SHIFT;
-   int rate, err;
+   int rate = 0, err = 0;
u32 tx_time, estimated_retx;
u64 result;
 
-   if (sta->mesh->fail_avg >= 100)
-   return MAX_METRIC;
+   /* Try to get rate based on HW/SW RC algorithm.
+* Rate is returned in units of Kbps, correct this
+* to comply with airtime calculation units
+*/
+   rate = sta_get_expected_throughput(sta) / 100;
+
+   /* if we did not get a rate */
+   if (!rate) {
+   if (sta->mesh->fail_avg >= 100)
+   return MAX_METRIC;
 
-   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
-   rate = cfg80211_calculate_bitrate();
-   if (WARN_ON(!rate))
-   return MAX_METRIC;
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   rate = cfg80211_calculate_bitrate();
+   if (WARN_ON(!rate))
+   return MAX_METRIC;
 
-   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   }
 
/* bitrate is in units of 100 Kbps, while we need rate in units of
 * 1Mbps. This will be corrected on tx_time computation.
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 63ea6cb..fa2c507 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2069,14 +2069,29 @@ void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 
+   thr = sta_get_expected_throughput(sta);
+
+   if (thr != 0) {
+   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
+   sinfo->expected_throughput = thr;
+   }
+}
+
+u32 sta_get_expected_throughput(struct sta_info *sta)
+{
+   struct ieee80211_sub_if_data *sdata = sta->sdata;
+   struct ieee80211_local *local = sdata->local;
+   struct rate_control_ref *ref = NULL;
+   u32 thr = 0;
+
+   if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+   ref = local->rate_ctrl;
+
/* check if the driver has a SW RC implementation */
if (ref && ref->ops->get_expected_throughput)
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
else
thr = drv_get_expected_throughput(local, >sta);
 
-   if (thr != 0) {
-   sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
-   sinfo->expected_throughput = thr;
-   }
+   return thr;
 }
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21..5c9c8be 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -661,6 +661,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
  struct rate_info *rinfo);
 void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
 
+u32 sta_get_expected_throughput(struct sta_info *sta);
+
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
  unsigned long exp_time);
 u8 sta_info_tx_streams(struct sta_info *sta);
-- 
2.9.0



[PATCH v2] wlcore: Add support for get_expected_throughput opcode

2016-06-30 Thread Maxim Altshul
Adding this opcode, allows the TI wireless driver,
to report throughput directly from FW to mac80211.

This is used mainly for mesh metric calculation.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
Changed the units of returned value.
drv_get_expected_throughput returns units of Kbps 
by definition, and thus we must comply as well.
Mbps * 1000 = Kbps.

 drivers/net/wireless/ti/wlcore/main.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 39dec7d..cb1103b 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5851,6 +5851,20 @@ out:
mutex_unlock(>mutex);
 }
 
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+{
+   struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
+   struct wl1271 *wl = wl_sta->wl;
+   u8 hlid = wl_sta->hlid;
+   u32 ret = 0;
+
+   /* return in units of Kbps */
+   if (wl)
+   ret = (wl->links[hlid].fw_rate_mbps * 1000);
+
+   return ret;
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
struct wl1271 *wl = hw->priv;
@@ -6051,6 +6065,7 @@ static const struct ieee80211_ops wl1271_ops = {
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
.sta_rc_update = wlcore_op_sta_rc_update,
.sta_statistics = wlcore_op_sta_statistics,
+   .get_expected_throughput = wlcore_op_get_expected_throughput,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
-- 
2.9.0



[PATCH v2] wlcore: Add support for get_expected_throughput opcode

2016-06-30 Thread Maxim Altshul
Adding this opcode, allows the TI wireless driver,
to report throughput directly from FW to mac80211.

This is used mainly for mesh metric calculation.

Signed-off-by: Maxim Altshul 
---
Changed the units of returned value.
drv_get_expected_throughput returns units of Kbps 
by definition, and thus we must comply as well.
Mbps * 1000 = Kbps.

 drivers/net/wireless/ti/wlcore/main.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 39dec7d..cb1103b 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5851,6 +5851,20 @@ out:
mutex_unlock(>mutex);
 }
 
+static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
+{
+   struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
+   struct wl1271 *wl = wl_sta->wl;
+   u8 hlid = wl_sta->hlid;
+   u32 ret = 0;
+
+   /* return in units of Kbps */
+   if (wl)
+   ret = (wl->links[hlid].fw_rate_mbps * 1000);
+
+   return ret;
+}
+
 static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
 {
struct wl1271 *wl = hw->priv;
@@ -6051,6 +6065,7 @@ static const struct ieee80211_ops wl1271_ops = {
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
.sta_rc_update = wlcore_op_sta_rc_update,
.sta_statistics = wlcore_op_sta_statistics,
+   .get_expected_throughput = wlcore_op_get_expected_throughput,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
-- 
2.9.0



[PATCH v2] mac80211: mesh: Add support for HW RC implementation

2016-06-23 Thread Maxim Altshul
Mesh HWMP module will be able to rely on the HW
RC algorithm if it exists, for path metric calculations.

This allows the metric calculation mechanism to calculate
a correct metric, based on PER and last TX rate both via
HW RC algorithm if it exists or via parameters collected
by the SW.

Signed-off-by: Maxim Altshul <maxim.alts...@ti.com>
---
Changed previous implementation according to Johannes's
comment. Combined the RC test and throughput assignment
to a sta_get_expected_throughput function.
Using the function both from airtime_link_metric and
from sta_set_sinfo. 

 net/mac80211/mesh_hwmp.c | 22 ++
 net/mac80211/sta_info.c  | 22 +-
 net/mac80211/sta_info.h  |  2 ++
 3 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4..39f9541 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -322,19 +322,25 @@ static u32 airtime_link_metric_get(struct ieee80211_local 
*local,
int device_constant = 1 << ARITH_SHIFT;
int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
int s_unit = 1 << ARITH_SHIFT;
-   int rate, err;
+   int rate = 0, err = 0;
u32 tx_time, estimated_retx;
u64 result;
 
-   if (sta->mesh->fail_avg >= 100)
-   return MAX_METRIC;
+   /* try to get rate based on HW/SW RC algorithm */
+   sta_get_expected_throughput(sta, );
 
-   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
-   rate = cfg80211_calculate_bitrate();
-   if (WARN_ON(!rate))
-   return MAX_METRIC;
+   /* if we did not get a rate */
+   if (!rate) {
+   if (sta->mesh->fail_avg >= 100)
+   return MAX_METRIC;
 
-   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   rate = cfg80211_calculate_bitrate();
+   if (WARN_ON(!rate))
+   return MAX_METRIC;
+
+   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   }
 
/* bitrate is in units of 100 Kbps, while we need rate in units of
 * 1Mbps. This will be corrected on tx_time computation.
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 63ea6cb..9580946 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2069,14 +2069,26 @@ void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 
-   /* check if the driver has a SW RC implementation */
-   if (ref && ref->ops->get_expected_throughput)
-   thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
-   else
-   thr = drv_get_expected_throughput(local, >sta);
+   sta_get_expected_throughput(sta, );
 
if (thr != 0) {
sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
sinfo->expected_throughput = thr;
}
 }
+
+void sta_get_expected_throughput(struct sta_info *sta, u32 *thr)
+{
+   struct ieee80211_sub_if_data *sdata = sta->sdata;
+   struct ieee80211_local *local = sdata->local;
+   struct rate_control_ref *ref = NULL;
+
+   if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+   ref = local->rate_ctrl;
+
+   /* check if the driver has a SW RC implementation */
+   if (ref && ref->ops->get_expected_throughput)
+   *thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
+   else
+   *thr = drv_get_expected_throughput(local, >sta);
+}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21..8535443 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -661,6 +661,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
  struct rate_info *rinfo);
 void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
 
+void sta_get_expected_throughput(struct sta_info *sta, u32 *thr);
+
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
  unsigned long exp_time);
 u8 sta_info_tx_streams(struct sta_info *sta);
-- 
2.9.0



[PATCH v2] mac80211: mesh: Add support for HW RC implementation

2016-06-23 Thread Maxim Altshul
Mesh HWMP module will be able to rely on the HW
RC algorithm if it exists, for path metric calculations.

This allows the metric calculation mechanism to calculate
a correct metric, based on PER and last TX rate both via
HW RC algorithm if it exists or via parameters collected
by the SW.

Signed-off-by: Maxim Altshul 
---
Changed previous implementation according to Johannes's
comment. Combined the RC test and throughput assignment
to a sta_get_expected_throughput function.
Using the function both from airtime_link_metric and
from sta_set_sinfo. 

 net/mac80211/mesh_hwmp.c | 22 ++
 net/mac80211/sta_info.c  | 22 +-
 net/mac80211/sta_info.h  |  2 ++
 3 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4..39f9541 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -322,19 +322,25 @@ static u32 airtime_link_metric_get(struct ieee80211_local 
*local,
int device_constant = 1 << ARITH_SHIFT;
int test_frame_len = TEST_FRAME_LEN << ARITH_SHIFT;
int s_unit = 1 << ARITH_SHIFT;
-   int rate, err;
+   int rate = 0, err = 0;
u32 tx_time, estimated_retx;
u64 result;
 
-   if (sta->mesh->fail_avg >= 100)
-   return MAX_METRIC;
+   /* try to get rate based on HW/SW RC algorithm */
+   sta_get_expected_throughput(sta, );
 
-   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
-   rate = cfg80211_calculate_bitrate();
-   if (WARN_ON(!rate))
-   return MAX_METRIC;
+   /* if we did not get a rate */
+   if (!rate) {
+   if (sta->mesh->fail_avg >= 100)
+   return MAX_METRIC;
 
-   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   rate = cfg80211_calculate_bitrate();
+   if (WARN_ON(!rate))
+   return MAX_METRIC;
+
+   err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100;
+   }
 
/* bitrate is in units of 100 Kbps, while we need rate in units of
 * 1Mbps. This will be corrected on tx_time computation.
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 63ea6cb..9580946 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2069,14 +2069,26 @@ void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
 
-   /* check if the driver has a SW RC implementation */
-   if (ref && ref->ops->get_expected_throughput)
-   thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
-   else
-   thr = drv_get_expected_throughput(local, >sta);
+   sta_get_expected_throughput(sta, );
 
if (thr != 0) {
sinfo->filled |= BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
sinfo->expected_throughput = thr;
}
 }
+
+void sta_get_expected_throughput(struct sta_info *sta, u32 *thr)
+{
+   struct ieee80211_sub_if_data *sdata = sta->sdata;
+   struct ieee80211_local *local = sdata->local;
+   struct rate_control_ref *ref = NULL;
+
+   if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
+   ref = local->rate_ctrl;
+
+   /* check if the driver has a SW RC implementation */
+   if (ref && ref->ops->get_expected_throughput)
+   *thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
+   else
+   *thr = drv_get_expected_throughput(local, >sta);
+}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21..8535443 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -661,6 +661,8 @@ void sta_set_rate_info_tx(struct sta_info *sta,
  struct rate_info *rinfo);
 void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo);
 
+void sta_get_expected_throughput(struct sta_info *sta, u32 *thr);
+
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
  unsigned long exp_time);
 u8 sta_info_tx_streams(struct sta_info *sta);
-- 
2.9.0