2016-06-20 13:00:03

by Altshul, Maxim

[permalink] [raw]
Subject: [PATCH 0/3] *** Mesh Path Selection Metric Calculation ***

Hi All,
This patch series focuses on metric calculation that
occurs during the path selection phase of a mesh network.

During the path selection phase, the mesh hwmp module
performs metric calculations, that take as parameters
the last TX rate that was used for a specific link,
and the packet error rate.

These parameters should be reported by the FW to the driver
constantly for the mechanism to work properly.

In case that a vendor offloads the rate control mechanism
to the FW, these parameters will be rarely updated,
or updated incorrectly.

This situation causes the mesh hwmp module to calculate incorrect
metrics and as a consequence, not to choose the best paths possible.


This patch series is divided to three patches and does the following:

1. Modifies mesh hwmp module and allows vendors that offload the
rate control mechanism to their FW, to report last TX rates and PER
to the mesh hwmp module by using an existing op called
get_expected_throughput.
In case that a vendor does not implement the op, all previous
functionality still applies.

2. Implements the opcode and the mechanism that reports the rates
in TI driver.

Maxim Altshul (3):
wlcore/wl18xx: Add functionality to accept TX rate per link
wlcore: Add support for get_expected_throughput opcode
mac80211: mesh: Add support for HW RC implementation

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 | 16 ++++++++++++++++
drivers/net/wireless/ti/wlcore/rx.c | 7 +++++++
drivers/net/wireless/ti/wlcore/wlcore_i.h | 13 +++++++++++++
net/mac80211/mesh_hwmp.c | 23 +++++++++++++++--------
7 files changed, 78 insertions(+), 13 deletions(-)

--
2.7.2



2016-06-20 13:00:03

by Altshul, Maxim

[permalink] [raw]
Subject: [PATCH 1/3] wlcore/wl18xx: Add functionality to accept TX rate per link

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 <[email protected]>
---
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, &info->status.rates[0]);
+ info->band,
+ &info->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 which the rates were reported */
+ u8 hlid;
} __packed;

/* FW status registers */
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 926d9b4..39dec7d 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5091,6 +5091,7 @@ 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/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index 438f271..c87d1d4 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -228,6 +228,13 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status)
enum wl_rx_buf_align rx_align;
int ret = 0;

+ /* update rates per link */
+ hlid = status->counters.hlid;
+
+ if (hlid < WLCORE_MAX_LINKS)
+ wl->links[hlid].fw_rate_mbps =
+ status->counters.tx_last_rate_mbps;
+
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
rx_counter = drv_rx_counter;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index cb72b2b..3875190 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -174,6 +174,12 @@ struct wl_fw_status {

/* Tx rate of the last transmitted packet */
u8 tx_last_rate;
+
+ /* Tx rate or Tx rate estimate pre calculated by fw in mbps */
+ u8 tx_last_rate_mbps;
+
+ /* hlid for which the rates were reported */
+ u8 hlid;
} counters;

u32 log_start_addr;
@@ -278,6 +284,12 @@ struct wl1271_link {
/* bitmap of TIDs where RX BA sessions are active for this link */
u8 ba_bitmap;

+ /* the last fw rate index we used for this link */
+ u8 fw_rate_idx;
+
+ /* the last fw rate [Mbps] we used for this link */
+ u8 fw_rate_mbps;
+
/* The wlvif this link belongs to. Might be null for global links */
struct wl12xx_vif *wlvif;

@@ -340,6 +352,7 @@ struct wl1271_station {
* Used in both AP and STA mode.
*/
u64 total_freed_pkts;
+ struct wl1271 *wl;
};

struct wl12xx_vif {
--
2.7.2


2016-06-21 09:18:29

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 3/3] mac80211: mesh: Add support for HW RC implementation

> - if (sta->mesh->fail_avg >= 100)
> - return MAX_METRIC;
> + /* try to get rate based on HW RC algorithm */
> + rate = drv_get_expected_throughput(local, &sta->sta);

This doesn't look correct, since you should use the rate control op if
available, to get data from rate control algorithms.

You should call sta_set_sinfo(), but that's far too much, so more
likely you should factor out the last few lines of that into a new
function and call that new function in both places.

johannes

2016-06-21 12:19:22

by Bob Copeland

[permalink] [raw]
Subject: Re: [PATCH 0/3] *** Mesh Path Selection Metric Calculation ***

On Mon, Jun 20, 2016 at 04:00:19PM +0300, Maxim Altshul wrote:
> 2. Implements the opcode and the mechanism that reports the rates
> in TI driver.

Does this mean TI driver will support mesh at some point?

--
Bob Copeland %% http://bobcopeland.com/

2016-06-20 13:00:03

by Altshul, Maxim

[permalink] [raw]
Subject: [PATCH 2/3] wlcore: Add support for get_expected_throughput opcode

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 <[email protected]>
---
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..cf4c6af 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5851,6 +5851,20 @@ out:
mutex_unlock(&wl->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 100kbps */
+ if (wl)
+ ret = (wl->links[hlid].fw_rate_mbps * 10);
+
+ 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.7.2


2016-06-21 00:16:22

by Peter Oh

[permalink] [raw]
Subject: Re: [PATCH 0/3] *** Mesh Path Selection Metric Calculation ***

where is 2/3 ?
On 06/20/2016 06:00 AM, Maxim Altshul wrote:
> Hi All,
> This patch series focuses on metric calculation that
> occurs during the path selection phase of a mesh network.
>
> During the path selection phase, the mesh hwmp module
> performs metric calculations, that take as parameters
> the last TX rate that was used for a specific link,
> and the packet error rate.
>
> These parameters should be reported by the FW to the driver
> constantly for the mechanism to work properly.
>
> In case that a vendor offloads the rate control mechanism
> to the FW, these parameters will be rarely updated,
> or updated incorrectly.
>
> This situation causes the mesh hwmp module to calculate incorrect
> metrics and as a consequence, not to choose the best paths possible.
>
>
> This patch series is divided to three patches and does the following:
>
> 1. Modifies mesh hwmp module and allows vendors that offload the
> rate control mechanism to their FW, to report last TX rates and PER
> to the mesh hwmp module by using an existing op called
> get_expected_throughput.
> In case that a vendor does not implement the op, all previous
> functionality still applies.
>
> 2. Implements the opcode and the mechanism that reports the rates
> in TI driver.
>
> Maxim Altshul (3):
> wlcore/wl18xx: Add functionality to accept TX rate per link
> wlcore: Add support for get_expected_throughput opcode
> mac80211: mesh: Add support for HW RC implementation
>
> 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 | 16 ++++++++++++++++
> drivers/net/wireless/ti/wlcore/rx.c | 7 +++++++
> drivers/net/wireless/ti/wlcore/wlcore_i.h | 13 +++++++++++++
> net/mac80211/mesh_hwmp.c | 23 +++++++++++++++--------
> 7 files changed, 78 insertions(+), 13 deletions(-)
>


2016-06-20 13:00:03

by Altshul, Maxim

[permalink] [raw]
Subject: [PATCH 3/3] mac80211: mesh: Add support for HW RC implementation

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 <[email protected]>
---
net/mac80211/mesh_hwmp.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4..e3ce40d 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -12,6 +12,7 @@
#include <asm/unaligned.h>
#include "wme.h"
#include "mesh.h"
+#include "driver-ops.h"

#define TEST_FRAME_LEN 8192
#define MAX_METRIC 0xffffffff
@@ -322,19 +323,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, 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 RC algorithm */
+ rate = drv_get_expected_throughput(local, &sta->sta);

- sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo);
- rate = cfg80211_calculate_bitrate(&rinfo);
- if (WARN_ON(!rate))
- return MAX_METRIC;
+ /* if HW does not provide us with 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, &sta->tx_stats.last_rate, &rinfo);
+ rate = cfg80211_calculate_bitrate(&rinfo);
+ 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.
--
2.7.2


2016-06-21 12:29:35

by Yaniv Machani

[permalink] [raw]
Subject: RE: [PATCH 0/3] *** Mesh Path Selection Metric Calculation ***

Yes,
TI driver have added support in our latest release (TI git).
http://software-dl.ti.com/ecs/WiLink8/R8_7/exports/release_notes_R8_7.html

Patches will be shared with mainline in the near future.

Thanks,
Yaniv Machani

-----Original Message-----
From: Bob Copeland [mailto:[email protected]]
Sent: Tuesday, June 21, 2016 15:19
To: Altshul, Maxim
Cc: [email protected]; [email protected]; [email protected]; Machani, Yaniv; Mishol, Guy; [email protected]; [email protected]; [email protected]; [email protected]
Subject: Re: [PATCH 0/3] *** Mesh Path Selection Metric Calculation ***

On Mon, Jun 20, 2016 at 04:00:19PM +0300, Maxim Altshul wrote:
> 2. Implements the opcode and the mechanism that reports the rates in
> TI driver.

Does this mean TI driver will support mesh at some point?

--
Bob Copeland %% http://bobcopeland.com/