diff mbox

wlcore: mesh: add zone time sync support

Message ID 20160808085706.22668-1-guym@ti.com (mailing list archive)
State Rejected
Delegated to: Kalle Valo
Headers show

Commit Message

Guy Mishol Aug. 8, 2016, 8:57 a.m. UTC
Add zone time sync support for mesh role.
This allows to configure the mesh peer
master of each zone for time synchronization.

Signed-off-by: Guy Mishol <guym@ti.com>
---
 drivers/net/wireless/ti/wl18xx/acx.c     | 29 ++++++++++++++++
 drivers/net/wireless/ti/wl18xx/acx.h     | 13 +++++++
 drivers/net/wireless/ti/wl18xx/debugfs.c | 59 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ti/wl18xx/event.c   |  1 +
 drivers/net/wireless/ti/wlcore/wlcore.h  |  3 ++
 5 files changed, 105 insertions(+)

Comments

Pedersen, Thomas Aug. 18, 2016, 4:42 p.m. UTC | #1
On Mon, 2016-08-08 at 11:57 +0300, Guy Mishol wrote:
> Add zone time sync support for mesh role.

> This allows to configure the mesh peer

> master of each zone for time synchronization.


What is this? mac80211 already tries to maintain TSF sync with mesh
peers if get/set TSF ops are supported by the driver.

> Signed-off-by: Guy Mishol <guym@ti.com>

> ---

>  drivers/net/wireless/ti/wl18xx/acx.c     | 29 ++++++++++++++++

>  drivers/net/wireless/ti/wl18xx/acx.h     | 13 +++++++

>  drivers/net/wireless/ti/wl18xx/debugfs.c | 59 ++++++++++++++++++++++++++++++++

>  drivers/net/wireless/ti/wl18xx/event.c   |  1 +

>  drivers/net/wireless/ti/wlcore/wlcore.h  |  3 ++

>  5 files changed, 105 insertions(+)

> 

> diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c

> index 4be0409..b5525a3 100644

> --- a/drivers/net/wireless/ti/wl18xx/acx.c

> +++ b/drivers/net/wireless/ti/wl18xx/acx.c

> @@ -309,3 +309,32 @@ out:

>  	kfree(acx);

>  	return ret;

>  }

> +

> +int wl18xx_acx_time_sync_cfg(struct wl1271 *wl)

> +{

> +	struct acx_time_sync_cfg *acx;

> +	int ret;

> +

> +	wl1271_debug(DEBUG_ACX, "acx time sync cfg: mode %d, addr: %pM",

> +		     wl->conf.sg.params[WL18XX_CONF_SG_TIME_SYNC],

> +		     wl->zone_master_mac_addr);

> +

> +	acx = kzalloc(sizeof(*acx), GFP_KERNEL);

> +	if (!acx) {

> +		ret = -ENOMEM;

> +		goto out;

> +	}

> +

> +	acx->sync_mode = wl->conf.sg.params[WL18XX_CONF_SG_TIME_SYNC];

> +	memcpy(acx->zone_mac_addr, wl->zone_master_mac_addr, ETH_ALEN);

> +

> +	ret = wl1271_cmd_configure(wl, ACX_TIME_SYNC_CFG,

> +				   acx, sizeof(*acx));

> +	if (ret < 0) {

> +		wl1271_warning("acx time sync cfg failed: %d", ret);

> +		goto out;

> +	}

> +out:

> +	kfree(acx);

> +	return ret;

> +}

> diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h

> index 342a299..2edbbbf 100644

> --- a/drivers/net/wireless/ti/wl18xx/acx.h

> +++ b/drivers/net/wireless/ti/wl18xx/acx.h

> @@ -37,6 +37,7 @@ enum {

>  	ACX_RX_BA_FILTER		 = 0x0058,

>  	ACX_AP_SLEEP_CFG                 = 0x0059,

>  	ACX_DYNAMIC_TRACES_CFG		 = 0x005A,

> +	ACX_TIME_SYNC_CFG		 = 0x005B,

>  };

>  

>  /* numbers of bits the length field takes (add 1 for the actual number) */

> @@ -388,6 +389,17 @@ struct acx_dynamic_fw_traces_cfg {

>  	__le32 dynamic_fw_traces;

>  } __packed;

>  

> +/*

> + * ACX_TIME_SYNC_CFG

> + * configure the time sync parameters

> + */

> +struct acx_time_sync_cfg {

> +	struct acx_header header;

> +	u8 sync_mode;

> +	u8 zone_mac_addr[ETH_ALEN];

> +	u8 padding[1];

> +} __packed;

> +

>  int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,

>  				  u32 sdio_blk_size, u32 extra_mem_blks,

>  				  u32 len_field_size);

> @@ -402,5 +414,6 @@ int wl18xx_acx_interrupt_notify_config(struct wl1271 *wl, bool action);

>  int wl18xx_acx_rx_ba_filter(struct wl1271 *wl, bool action);

>  int wl18xx_acx_ap_sleep(struct wl1271 *wl);

>  int wl18xx_acx_dynamic_fw_traces(struct wl1271 *wl);

> +int wl18xx_acx_time_sync_cfg(struct wl1271 *wl);

>  

>  #endif /* __WL18XX_ACX_H__ */

> diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c

> index 86ccf84..9e28748 100644

> --- a/drivers/net/wireless/ti/wl18xx/debugfs.c

> +++ b/drivers/net/wireless/ti/wl18xx/debugfs.c

> @@ -408,6 +408,64 @@ static const struct file_operations radar_debug_mode_ops = {

>  };

>  #endif /* CFG80211_CERTIFICATION_ONUS */

>  

> +static ssize_t time_sync_zone_addr_write(struct file *file,

> +					 const char __user *user_buf,

> +					 size_t count, loff_t *ppos) {

> +	struct wl1271 *wl = file->private_data;

> +	char buf[(ETH_ALEN * 2)];

> +	int ret;

> +

> +	if (count < (ETH_ALEN * 2 + 1)) {

> +		wl1271_warning("Illegal MAC address: wrong size");

> +		return -EINVAL;

> +	}

> +

> +	ret = copy_from_user(buf, user_buf, (ETH_ALEN * 2));

> +	if (ret < 0)

> +		return ret;

> +

> +	ret = hex2bin(wl->zone_master_mac_addr, buf, ETH_ALEN);

> +	if (ret < 0) {

> +		wl1271_warning("Illegal MAC address: invalid characters");

> +		return ret;

> +	}

> +

> +	mutex_lock(&wl->mutex);

> +

> +	if (unlikely(wl->state != WLCORE_STATE_ON))

> +		goto out;

> +

> +	ret = wl1271_ps_elp_wakeup(wl);

> +	if (ret < 0)

> +		goto out;

> +

> +	ret = wl18xx_acx_time_sync_cfg(wl);

> +	if (ret < 0)

> +		count = ret;

> +

> +	wl1271_ps_elp_sleep(wl);

> +out:

> +	mutex_unlock(&wl->mutex);

> +	return count;

> +}

> +

> +static ssize_t time_sync_zone_addr_read(struct file *file,

> +					char __user *userbuf,

> +					size_t count, loff_t *ppos)

> +{

> +	struct wl1271 *wl = file->private_data;

> +

> +	return wl1271_format_buffer(userbuf, count, ppos,

> +				    "%pM\n", wl->zone_master_mac_addr);

> +}

> +

> +static const struct file_operations time_sync_zone_addr_ops = {

> +	.write  = time_sync_zone_addr_write,

> +	.read = time_sync_zone_addr_read,

> +	.open   = simple_open,

> +	.llseek = default_llseek,

> +};

> +

>  int wl18xx_debugfs_add_files(struct wl1271 *wl,

>  			     struct dentry *rootdir)

>  {

> @@ -576,6 +634,7 @@ int wl18xx_debugfs_add_files(struct wl1271 *wl,

>  #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS

>  	DEBUGFS_ADD(radar_debug_mode, moddir);

>  #endif

> +	DEBUGFS_ADD(time_sync_zone_addr, moddir);

>  	DEBUGFS_ADD(dynamic_fw_traces, moddir);

>  

>  	return 0;

> diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c

> index 2c5df43..b36ce18 100644

> --- a/drivers/net/wireless/ti/wl18xx/event.c

> +++ b/drivers/net/wireless/ti/wl18xx/event.c

> @@ -22,6 +22,7 @@

>  #include <net/genetlink.h>

>  #include "event.h"

>  #include "scan.h"

> +#include "conf.h"

>  #include "../wlcore/cmd.h"

>  #include "../wlcore/debug.h"

>  #include "../wlcore/vendor_cmd.h"

> diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h

> index 8f28aa0..1827546 100644

> --- a/drivers/net/wireless/ti/wlcore/wlcore.h

> +++ b/drivers/net/wireless/ti/wlcore/wlcore.h

> @@ -501,6 +501,9 @@ struct wl1271 {

>  

>  	/* dynamic fw traces */

>  	u32 dynamic_fw_traces;

> +

> +	/* time sync zone master */

> +	u8 zone_master_mac_addr[ETH_ALEN];

>  };

>  

>  int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
Kalle Valo Aug. 19, 2016, 9:57 a.m. UTC | #2
"Pedersen, Thomas" <twp@qca.qualcomm.com> writes:

> On Mon, 2016-08-08 at 11:57 +0300, Guy Mishol wrote:
>> Add zone time sync support for mesh role.
>> This allows to configure the mesh peer
>> master of each zone for time synchronization.
>
> What is this? mac80211 already tries to maintain TSF sync with mesh
> peers if get/set TSF ops are supported by the driver.

Yeah, and why use debugfs?
Guy Mishol Aug. 21, 2016, 10:13 a.m. UTC | #3
Kalle/Thomas,
Thanks for your feedback.

This time sync support is different from the one that mac80211 maintains with mesh peers.
This time sync is mostly used by upper layers for several applications (like audio).
In this case we allow the user to configure for each zone who will be the synchronizer.
You can refer to the following Application Report (chapter 6) for more information: http://www.ti.com/lit/an/swaa166/swaa166.pdf

BR,

Guy Mishol
  (+972) 9-7906726
  guym@ti.com


-----Original Message-----
From: Kalle Valo [mailto:kvalo@codeaurora.org] 
Sent: Friday, August 19, 2016 12:57
To: Pedersen, Thomas
Cc: Mishol, Guy; linux-wireless@vger.kernel.org
Subject: Re: [PATCH] wlcore: mesh: add zone time sync support

"Pedersen, Thomas" <twp@qca.qualcomm.com> writes:

> On Mon, 2016-08-08 at 11:57 +0300, Guy Mishol wrote:
>> Add zone time sync support for mesh role.
>> This allows to configure the mesh peer master of each zone for time 
>> synchronization.
>
> What is this? mac80211 already tries to maintain TSF sync with mesh 
> peers if get/set TSF ops are supported by the driver.

Yeah, and why use debugfs?

--
Kalle Valo
Kalle Valo Aug. 22, 2016, 3:56 p.m. UTC | #4
"Mishol, Guy" <guym@ti.com> writes:

> Kalle/Thomas,
> Thanks for your feedback.

Please don't top most, it makes using patchwork difficult and is
annoying to the readers.

> This time sync support is different from the one that mac80211
> maintains with mesh peers. This time sync is mostly used by upper
> layers for several applications (like audio). In this case we allow
> the user to configure for each zone who will be the synchronizer. You
> can refer to the following Application Report (chapter 6) for more
> information: http://www.ti.com/lit/an/swaa166/swaa166.pdf

I didn't fully understand what this does, but debugfs doesn't sound (no
pun intended) like a suitable interface for something like this. nl80211
is more likely candidate.
Guy Mishol Aug. 23, 2016, 9:12 a.m. UTC | #5
On Mon, Aug 22, 2016 at 18:56:01, Kalle Valo wrote:
> Subject: Re: [PATCH] wlcore: mesh: add zone time sync support
> 
> "Mishol, Guy" <guym@ti.com> writes:
> 
> > Kalle/Thomas,
> > Thanks for your feedback.
> 
> Please don't top most, it makes using patchwork difficult and is 
> annoying to the readers.

OK. Understood.

> > This time sync support is different from the one that mac80211 
> > maintains with mesh peers. This time sync is mostly used by upper 
> > layers for several applications (like audio). In this case we allow 
> > the user to configure for each zone who will be the synchronizer. 
> > You can refer to the following Application Report (chapter 6) for 
> > more
> > information: http://www.ti.com/lit/an/swaa166/swaa166.pdf
> 
> I didn't fully understand what this does, but debugfs doesn't sound 
> (no pun
> intended) like a suitable interface for something like this. nl80211 
> is more likely candidate.

Agree. The debugfs part was mainly meant for demo and can be omitted. I will submit instead a different patch that only adds the necessary APIs in the wlcore.

Guy
Pedersen, Thomas Aug. 25, 2016, 6:50 p.m. UTC | #6
On Sun, 2016-08-21 at 10:13 +0000, Mishol, Guy wrote:
> Kalle/Thomas,

> Thanks for your feedback.

> 

> This time sync support is different from the one that mac80211 maintains with mesh peers.

> This time sync is mostly used by upper layers for several applications (like audio).

> In this case we allow the user to configure for each zone who will be the synchronizer.

> You can refer to the following Application Report (chapter 6) for more information: http://www.ti.com/lit/an/swaa166/swaa166.pdf


So it breaks regular mesh synchronization? Power Save, and in the future
possibly DFS and MCCA rely on this to work.

It sounds like you want some absolute TSF time synchronized within 20us.
Mesh TSF synchronization can provide this, it's just a little more
complicated as you'll need to compute at the application level using the
per-sta offsets. Mesh synchronization accuracy was pretty good IIRC,
unfortunately I don't have any test data to share :(

thomas
Guy Mishol Aug. 28, 2016, 7:34 a.m. UTC | #7
On Thu, Aug 25, 2016 at 21:50:59, Pedersen, Thomas wrote:
> Subject: Re: [PATCH] wlcore: mesh: add zone time sync support

> 

> On Sun, 2016-08-21 at 10:13 +0000, Mishol, Guy wrote:

> > Kalle/Thomas,

> > Thanks for your feedback.

> >

> > This time sync support is different from the one that mac80211 

> > maintains

> with mesh peers.

> > This time sync is mostly used by upper layers for several 

> > applications (like

> audio).

> > In this case we allow the user to configure for each zone who will 

> > be the

> synchronizer.

> > You can refer to the following Application Report (chapter 6) for 

> > more

> > information: http://www.ti.com/lit/an/swaa166/swaa166.pdf

> 

> So it breaks regular mesh synchronization? Power Save, and in the 

> future possibly DFS and MCCA rely on this to work.

> 

> It sounds like you want some absolute TSF time synchronized within 20us.

> Mesh TSF synchronization can provide this, it's just a little more 

> complicated as you'll need to compute at the application level using the per-sta offsets.

> Mesh synchronization accuracy was pretty good IIRC, unfortunately I 

> don't have any test data to share :(


Yes. This feature can hit time accuracy of less than 20us when using wl18xx devices.
It is not built for mesh role specifically but for STA and AP as well.
Unlike STA and AP modes where the topology is well defined when running mesh
you have several zones that can be treated as STA-AP topology.
This patch just add the API for configuring which mesh peer will act as AP on its zone
For the time synchronization matter.
It has nothing to do with Mesh TSF synchronization specifically so it shouldn’t break anything.

Guy
diff mbox

Patch

diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c
index 4be0409..b5525a3 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.c
+++ b/drivers/net/wireless/ti/wl18xx/acx.c
@@ -309,3 +309,32 @@  out:
 	kfree(acx);
 	return ret;
 }
+
+int wl18xx_acx_time_sync_cfg(struct wl1271 *wl)
+{
+	struct acx_time_sync_cfg *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx time sync cfg: mode %d, addr: %pM",
+		     wl->conf.sg.params[WL18XX_CONF_SG_TIME_SYNC],
+		     wl->zone_master_mac_addr);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->sync_mode = wl->conf.sg.params[WL18XX_CONF_SG_TIME_SYNC];
+	memcpy(acx->zone_mac_addr, wl->zone_master_mac_addr, ETH_ALEN);
+
+	ret = wl1271_cmd_configure(wl, ACX_TIME_SYNC_CFG,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx time sync cfg failed: %d", ret);
+		goto out;
+	}
+out:
+	kfree(acx);
+	return ret;
+}
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index 342a299..2edbbbf 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -37,6 +37,7 @@  enum {
 	ACX_RX_BA_FILTER		 = 0x0058,
 	ACX_AP_SLEEP_CFG                 = 0x0059,
 	ACX_DYNAMIC_TRACES_CFG		 = 0x005A,
+	ACX_TIME_SYNC_CFG		 = 0x005B,
 };
 
 /* numbers of bits the length field takes (add 1 for the actual number) */
@@ -388,6 +389,17 @@  struct acx_dynamic_fw_traces_cfg {
 	__le32 dynamic_fw_traces;
 } __packed;
 
+/*
+ * ACX_TIME_SYNC_CFG
+ * configure the time sync parameters
+ */
+struct acx_time_sync_cfg {
+	struct acx_header header;
+	u8 sync_mode;
+	u8 zone_mac_addr[ETH_ALEN];
+	u8 padding[1];
+} __packed;
+
 int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
 				  u32 sdio_blk_size, u32 extra_mem_blks,
 				  u32 len_field_size);
@@ -402,5 +414,6 @@  int wl18xx_acx_interrupt_notify_config(struct wl1271 *wl, bool action);
 int wl18xx_acx_rx_ba_filter(struct wl1271 *wl, bool action);
 int wl18xx_acx_ap_sleep(struct wl1271 *wl);
 int wl18xx_acx_dynamic_fw_traces(struct wl1271 *wl);
+int wl18xx_acx_time_sync_cfg(struct wl1271 *wl);
 
 #endif /* __WL18XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c
index 86ccf84..9e28748 100644
--- a/drivers/net/wireless/ti/wl18xx/debugfs.c
+++ b/drivers/net/wireless/ti/wl18xx/debugfs.c
@@ -408,6 +408,64 @@  static const struct file_operations radar_debug_mode_ops = {
 };
 #endif /* CFG80211_CERTIFICATION_ONUS */
 
+static ssize_t time_sync_zone_addr_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos) {
+	struct wl1271 *wl = file->private_data;
+	char buf[(ETH_ALEN * 2)];
+	int ret;
+
+	if (count < (ETH_ALEN * 2 + 1)) {
+		wl1271_warning("Illegal MAC address: wrong size");
+		return -EINVAL;
+	}
+
+	ret = copy_from_user(buf, user_buf, (ETH_ALEN * 2));
+	if (ret < 0)
+		return ret;
+
+	ret = hex2bin(wl->zone_master_mac_addr, buf, ETH_ALEN);
+	if (ret < 0) {
+		wl1271_warning("Illegal MAC address: invalid characters");
+		return ret;
+	}
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state != WLCORE_STATE_ON))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl18xx_acx_time_sync_cfg(wl);
+	if (ret < 0)
+		count = ret;
+
+	wl1271_ps_elp_sleep(wl);
+out:
+	mutex_unlock(&wl->mutex);
+	return count;
+}
+
+static ssize_t time_sync_zone_addr_read(struct file *file,
+					char __user *userbuf,
+					size_t count, loff_t *ppos)
+{
+	struct wl1271 *wl = file->private_data;
+
+	return wl1271_format_buffer(userbuf, count, ppos,
+				    "%pM\n", wl->zone_master_mac_addr);
+}
+
+static const struct file_operations time_sync_zone_addr_ops = {
+	.write  = time_sync_zone_addr_write,
+	.read = time_sync_zone_addr_read,
+	.open   = simple_open,
+	.llseek = default_llseek,
+};
+
 int wl18xx_debugfs_add_files(struct wl1271 *wl,
 			     struct dentry *rootdir)
 {
@@ -576,6 +634,7 @@  int wl18xx_debugfs_add_files(struct wl1271 *wl,
 #ifdef CONFIG_CFG80211_CERTIFICATION_ONUS
 	DEBUGFS_ADD(radar_debug_mode, moddir);
 #endif
+	DEBUGFS_ADD(time_sync_zone_addr, moddir);
 	DEBUGFS_ADD(dynamic_fw_traces, moddir);
 
 	return 0;
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
index 2c5df43..b36ce18 100644
--- a/drivers/net/wireless/ti/wl18xx/event.c
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -22,6 +22,7 @@ 
 #include <net/genetlink.h>
 #include "event.h"
 #include "scan.h"
+#include "conf.h"
 #include "../wlcore/cmd.h"
 #include "../wlcore/debug.h"
 #include "../wlcore/vendor_cmd.h"
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 8f28aa0..1827546 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -501,6 +501,9 @@  struct wl1271 {
 
 	/* dynamic fw traces */
 	u32 dynamic_fw_traces;
+
+	/* time sync zone master */
+	u8 zone_master_mac_addr[ETH_ALEN];
 };
 
 int wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);