This is unused and I'm not really sure in what context it was designed to
be used.
Signed-off-by: Daniel Drake <[email protected]>
---
drivers/net/wireless/libertas/cmd.c | 14 ++-----
drivers/net/wireless/libertas/decl.h | 3 --
drivers/net/wireless/libertas/dev.h | 3 --
drivers/net/wireless/libertas/main.c | 64 ----------------------------------
4 files changed, 4 insertions(+), 80 deletions(-)
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index dbd24a4..627bdf4 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1024,10 +1024,6 @@ static void lbs_submit_command(struct lbs_private *priv,
}
if (command == CMD_802_11_DEEP_SLEEP) {
- if (priv->is_auto_deep_sleep_enabled) {
- priv->wakeup_dev_required = 1;
- priv->dnld_sent = 0;
- }
priv->is_deep_sleep = 1;
lbs_complete_command(priv, cmdnode, 0);
} else {
@@ -1614,12 +1610,10 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
/* No commands are allowed in Deep Sleep until we toggle the GPIO
* to wake up the card and it has signaled that it's ready.
*/
- if (!priv->is_auto_deep_sleep_enabled) {
- if (priv->is_deep_sleep) {
- lbs_deb_cmd("command not allowed in deep sleep\n");
- cmdnode = ERR_PTR(-EBUSY);
- goto done;
- }
+ if (priv->is_deep_sleep) {
+ lbs_deb_cmd("command not allowed in deep sleep\n");
+ cmdnode = ERR_PTR(-EBUSY);
+ goto done;
}
cmdnode = lbs_get_free_cmd_node(priv);
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index da0b05b..cfe3272 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -54,9 +54,6 @@ int lbs_resume(struct lbs_private *priv);
void lbs_queue_event(struct lbs_private *priv, u32 event);
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
-int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
-int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
-
u32 lbs_fw_index_to_data_rate(u8 index);
u8 lbs_data_rate_to_fw_index(u32 rate);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 76d018b..094e1f2 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -74,12 +74,9 @@ struct lbs_private {
/* Deep sleep */
int is_deep_sleep;
int deep_sleep_required;
- int is_auto_deep_sleep_enabled;
int wakeup_dev_required;
int is_activity_detected;
- int auto_deep_sleep_timeout; /* in ms */
wait_queue_head_t ds_awake_q;
- struct timer_list auto_deepsleep_timer;
/* Host sleep*/
int is_host_sleep_configured;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index c79aac4..4b086cd 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -520,7 +520,6 @@ static int lbs_thread(void *data)
}
del_timer(&priv->command_timer);
- del_timer(&priv->auto_deepsleep_timer);
lbs_deb_leave(LBS_DEB_THREAD);
return 0;
@@ -653,64 +652,6 @@ out:
lbs_deb_leave(LBS_DEB_CMD);
}
-/**
- * auto_deepsleep_timer_fn - put the device back to deep sleep mode when
- * timer expires and no activity (command, event, data etc.) is detected.
- * @data: &struct lbs_private pointer
- * returns: N/A
- */
-static void auto_deepsleep_timer_fn(unsigned long data)
-{
- struct lbs_private *priv = (struct lbs_private *)data;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (priv->is_activity_detected) {
- priv->is_activity_detected = 0;
- } else {
- if (priv->is_auto_deep_sleep_enabled &&
- (!priv->wakeup_dev_required) &&
- (priv->connect_status != LBS_CONNECTED)) {
- struct cmd_header cmd;
-
- lbs_deb_main("Entering auto deep sleep mode...\n");
- memset(&cmd, 0, sizeof(cmd));
- cmd.size = cpu_to_le16(sizeof(cmd));
- lbs_cmd_async(priv, CMD_802_11_DEEP_SLEEP, &cmd,
- sizeof(cmd));
- }
- }
- mod_timer(&priv->auto_deepsleep_timer , jiffies +
- (priv->auto_deep_sleep_timeout * HZ)/1000);
- lbs_deb_leave(LBS_DEB_CMD);
-}
-
-int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_SDIO);
-
- priv->is_auto_deep_sleep_enabled = 1;
- if (priv->is_deep_sleep)
- priv->wakeup_dev_required = 1;
- mod_timer(&priv->auto_deepsleep_timer ,
- jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
-
- lbs_deb_leave(LBS_DEB_SDIO);
- return 0;
-}
-
-int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_SDIO);
-
- priv->is_auto_deep_sleep_enabled = 0;
- priv->auto_deep_sleep_timeout = 0;
- del_timer(&priv->auto_deepsleep_timer);
-
- lbs_deb_leave(LBS_DEB_SDIO);
- return 0;
-}
-
static int lbs_init_adapter(struct lbs_private *priv)
{
int ret;
@@ -726,7 +667,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
priv->psmode = LBS802_11POWERMODECAM;
priv->psstate = PS_STATE_FULL_POWER;
priv->is_deep_sleep = 0;
- priv->is_auto_deep_sleep_enabled = 0;
priv->deep_sleep_required = 0;
priv->wakeup_dev_required = 0;
init_waitqueue_head(&priv->ds_awake_q);
@@ -739,8 +679,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
(unsigned long)priv);
- setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
- (unsigned long)priv);
INIT_LIST_HEAD(&priv->cmdfreeq);
INIT_LIST_HEAD(&priv->cmdpendingq);
@@ -776,7 +714,6 @@ static void lbs_free_adapter(struct lbs_private *priv)
lbs_free_cmd_buffer(priv);
kfifo_free(&priv->event_fifo);
del_timer(&priv->command_timer);
- del_timer(&priv->auto_deepsleep_timer);
lbs_deb_leave(LBS_DEB_MAIN);
}
@@ -995,7 +932,6 @@ void lbs_stop_card(struct lbs_private *priv)
/* Delete the timeout of the currently processing command */
del_timer_sync(&priv->command_timer);
- del_timer_sync(&priv->auto_deepsleep_timer);
/* Flush pending command nodes */
spin_lock_irqsave(&priv->driver_lock, flags);
--
1.7.6
Hi Daniel,
> > Anyway, for users who need this feature we can add a module parameter to enable it with the patch
> below. Please let me know what you think.
>
> That seems reasonable, but it would probably be preferable to
> implement it as before. Does the cfg80211 wrapper not allow for the
> power command to be implemented by drivers? Is there a
> cfg80211-friendly way of doing it exposed with the iw command?
I will check cfg80211 API for auto deep sleep configuration.
Thanks,
Bing
On 18 July 2011 20:25, Bing Zhao <[email protected]> wrote:
> As the auto deep sleep feature for SD8385/SD8686/SD8688 cards is very useful for many embedded platforms to handle enter/exit deep sleep mode automatically, please do not remove it from libertas driver. If you have any particular issue with this feature enabled, we can work on it and solve the problem.
The problem is that it can't actually be enabled. This is dead code.
Or if it can, please point out what I'm missing.
Or is this a work in progress?
Thanks,
Daniel
Hi Daniel,
> > As the auto deep sleep feature for SD8385/SD8686/SD8688 cards is very useful for many embedded
> platforms to handle enter/exit deep sleep mode automatically, please do not remove it from libertas
> driver. If you have any particular issue with this feature enabled, we can work on it and solve the
> problem.
>
> The problem is that it can't actually be enabled. This is dead code.
> Or if it can, please point out what I'm missing.
To enable deep sleep mode:
iwconfig wlan0 power period 0
To enable auto deep sleep mode with idle time period set to 5 seconds:
iwconfig wlan0 power period 5
To disable deep sleep/auto deep sleep mode:
iwconfig wlan0 power period -1
The iwconfig (from Wireless Tools version 30pre8 beta or newer) supports "power period" command.
Thanks,
Bing
Hi Daniel,
> > To enable deep sleep mode:
> > iwconfig wlan0 power period 0
> >
> > To enable auto deep sleep mode with idle time period set to 5 seconds:
> > iwconfig wlan0 power period 5
> >
> > To disable deep sleep/auto deep sleep mode:
> > iwconfig wlan0 power period -1
>
> Paul pointed out that indeed, in old kernels, this functionality was
> hooked up to the power wireless extension.
>
> In recent kernels, this is not the case - its not hooked up to
> anything. The commands you write above will fail.
Yeah. I didn't know that the entire wext has been removed from libertas.
Anyway, for users who need this feature we can add a module parameter to enable it with the patch below. Please let me know what you think.
Thanks,
Bing
---
drivers/net/wireless/libertas/dev.h | 2 +-
drivers/net/wireless/libertas/main.c | 50 +++++++++++++++-------------------
2 files changed, 23 insertions(+), 29 deletions(-)
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 76d018b..472a5e3 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -77,7 +77,7 @@ struct lbs_private {
int is_auto_deep_sleep_enabled;
int wakeup_dev_required;
int is_activity_detected;
- int auto_deep_sleep_timeout; /* in ms */
+ int auto_deep_sleep_timeout; /* in seconds */
wait_queue_head_t ds_awake_q;
struct timer_list auto_deepsleep_timer;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index a839de0..cc8c1b5 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -40,6 +40,11 @@ unsigned int lbs_disablemesh;
EXPORT_SYMBOL_GPL(lbs_disablemesh);
module_param_named(libertas_disablemesh, lbs_disablemesh, int, 0644);
+static unsigned int lbs_auto_deep_sleep; /* in seconds */
+module_param_named(libertas_auto_deep_sleep, lbs_auto_deep_sleep, int, 0644);
+MODULE_PARM_DESC(libertas_auto_deep_sleep,
+ "timeout value for auto deep sleep timer (default 0: disabled");
+
/*
* This global structure is used to send the confirm_sleep command as
@@ -680,36 +685,10 @@ static void auto_deepsleep_timer_fn(unsigned long data)
}
}
mod_timer(&priv->auto_deepsleep_timer , jiffies +
- (priv->auto_deep_sleep_timeout * HZ)/1000);
+ priv->auto_deep_sleep_timeout * HZ);
lbs_deb_leave(LBS_DEB_CMD);
}
-int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_SDIO);
-
- priv->is_auto_deep_sleep_enabled = 1;
- if (priv->is_deep_sleep)
- priv->wakeup_dev_required = 1;
- mod_timer(&priv->auto_deepsleep_timer ,
- jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
-
- lbs_deb_leave(LBS_DEB_SDIO);
- return 0;
-}
-
-int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
-{
- lbs_deb_enter(LBS_DEB_SDIO);
-
- priv->is_auto_deep_sleep_enabled = 0;
- priv->auto_deep_sleep_timeout = 0;
- del_timer(&priv->auto_deepsleep_timer);
-
- lbs_deb_leave(LBS_DEB_SDIO);
- return 0;
-}
-
static int lbs_init_adapter(struct lbs_private *priv)
{
int ret;
@@ -725,7 +704,15 @@ static int lbs_init_adapter(struct lbs_private *priv)
priv->psmode = LBS802_11POWERMODECAM;
priv->psstate = PS_STATE_FULL_POWER;
priv->is_deep_sleep = 0;
- priv->is_auto_deep_sleep_enabled = 0;
+
+ if (lbs_auto_deep_sleep > 0) {
+ priv->is_auto_deep_sleep_enabled = 1;
+ priv->auto_deep_sleep_timeout = lbs_auto_deep_sleep;
+ } else {
+ priv->is_auto_deep_sleep_enabled = 0;
+ priv->auto_deep_sleep_timeout = 0;
+ }
+
priv->deep_sleep_required = 0;
priv->wakeup_dev_required = 0;
init_waitqueue_head(&priv->ds_awake_q);
@@ -963,6 +950,13 @@ int lbs_start_card(struct lbs_private *priv)
lbs_debugfs_init_one(priv, dev);
+ /* Start the timer if auto deep sleep is enabled */
+ if (priv->is_auto_deep_sleep_enabled && priv->auto_deep_sleep_timeout) {
+ priv->is_activity_detected = 0;
+ mod_timer(&priv->auto_deepsleep_timer,
+ jiffies + priv->auto_deep_sleep_timeout * HZ);
+ }
+
netdev_info(dev, "Marvell WLAN 802.11 adapter\n");
ret = 0;
---
On 19 July 2011 19:23, Bing Zhao <[email protected]> wrote:
> To enable deep sleep mode:
> iwconfig wlan0 power period 0
>
> To enable auto deep sleep mode with idle time period set to 5 seconds:
> iwconfig wlan0 power period 5
>
> To disable deep sleep/auto deep sleep mode:
> iwconfig wlan0 power period -1
Paul pointed out that indeed, in old kernels, this functionality was
hooked up to the power wireless extension.
In recent kernels, this is not the case - its not hooked up to
anything. The commands you write above will fail.
Daniel
On Tue, 2011-07-19 at 19:33 -0700, Bing Zhao wrote:
> Hi Daniel,
>
> > > To enable deep sleep mode:
> > > iwconfig wlan0 power period 0
> > >
> > > To enable auto deep sleep mode with idle time period set to 5 seconds:
> > > iwconfig wlan0 power period 5
> > >
> > > To disable deep sleep/auto deep sleep mode:
> > > iwconfig wlan0 power period -1
> >
> > Paul pointed out that indeed, in old kernels, this functionality was
> > hooked up to the power wireless extension.
> >
> > In recent kernels, this is not the case - its not hooked up to
> > anything. The commands you write above will fail.
>
> Yeah. I didn't know that the entire wext has been removed from libertas.
>
> Anyway, for users who need this feature we can add a module parameter to enable it with the patch below. Please let me know what you think.
I'd rather we figure out some nl80211/cfg80211 knob for this rather than
a module parameter; we can certainly add calls and attributes to nl80211
if we need to.
Dan
> Thanks,
> Bing
>
> ---
> drivers/net/wireless/libertas/dev.h | 2 +-
> drivers/net/wireless/libertas/main.c | 50 +++++++++++++++-------------------
> 2 files changed, 23 insertions(+), 29 deletions(-)
>
> diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
> index 76d018b..472a5e3 100644
> --- a/drivers/net/wireless/libertas/dev.h
> +++ b/drivers/net/wireless/libertas/dev.h
> @@ -77,7 +77,7 @@ struct lbs_private {
> int is_auto_deep_sleep_enabled;
> int wakeup_dev_required;
> int is_activity_detected;
> - int auto_deep_sleep_timeout; /* in ms */
> + int auto_deep_sleep_timeout; /* in seconds */
> wait_queue_head_t ds_awake_q;
> struct timer_list auto_deepsleep_timer;
>
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index a839de0..cc8c1b5 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -40,6 +40,11 @@ unsigned int lbs_disablemesh;
> EXPORT_SYMBOL_GPL(lbs_disablemesh);
> module_param_named(libertas_disablemesh, lbs_disablemesh, int, 0644);
>
> +static unsigned int lbs_auto_deep_sleep; /* in seconds */
> +module_param_named(libertas_auto_deep_sleep, lbs_auto_deep_sleep, int, 0644);
> +MODULE_PARM_DESC(libertas_auto_deep_sleep,
> + "timeout value for auto deep sleep timer (default 0: disabled");
> +
>
> /*
> * This global structure is used to send the confirm_sleep command as
> @@ -680,36 +685,10 @@ static void auto_deepsleep_timer_fn(unsigned long data)
> }
> }
> mod_timer(&priv->auto_deepsleep_timer , jiffies +
> - (priv->auto_deep_sleep_timeout * HZ)/1000);
> + priv->auto_deep_sleep_timeout * HZ);
> lbs_deb_leave(LBS_DEB_CMD);
> }
>
> -int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
> -{
> - lbs_deb_enter(LBS_DEB_SDIO);
> -
> - priv->is_auto_deep_sleep_enabled = 1;
> - if (priv->is_deep_sleep)
> - priv->wakeup_dev_required = 1;
> - mod_timer(&priv->auto_deepsleep_timer ,
> - jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
> -
> - lbs_deb_leave(LBS_DEB_SDIO);
> - return 0;
> -}
> -
> -int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
> -{
> - lbs_deb_enter(LBS_DEB_SDIO);
> -
> - priv->is_auto_deep_sleep_enabled = 0;
> - priv->auto_deep_sleep_timeout = 0;
> - del_timer(&priv->auto_deepsleep_timer);
> -
> - lbs_deb_leave(LBS_DEB_SDIO);
> - return 0;
> -}
> -
> static int lbs_init_adapter(struct lbs_private *priv)
> {
> int ret;
> @@ -725,7 +704,15 @@ static int lbs_init_adapter(struct lbs_private *priv)
> priv->psmode = LBS802_11POWERMODECAM;
> priv->psstate = PS_STATE_FULL_POWER;
> priv->is_deep_sleep = 0;
> - priv->is_auto_deep_sleep_enabled = 0;
> +
> + if (lbs_auto_deep_sleep > 0) {
> + priv->is_auto_deep_sleep_enabled = 1;
> + priv->auto_deep_sleep_timeout = lbs_auto_deep_sleep;
> + } else {
> + priv->is_auto_deep_sleep_enabled = 0;
> + priv->auto_deep_sleep_timeout = 0;
> + }
> +
> priv->deep_sleep_required = 0;
> priv->wakeup_dev_required = 0;
> init_waitqueue_head(&priv->ds_awake_q);
> @@ -963,6 +950,13 @@ int lbs_start_card(struct lbs_private *priv)
>
> lbs_debugfs_init_one(priv, dev);
>
> + /* Start the timer if auto deep sleep is enabled */
> + if (priv->is_auto_deep_sleep_enabled && priv->auto_deep_sleep_timeout) {
> + priv->is_activity_detected = 0;
> + mod_timer(&priv->auto_deepsleep_timer,
> + jiffies + priv->auto_deep_sleep_timeout * HZ);
> + }
> +
> netdev_info(dev, "Marvell WLAN 802.11 adapter\n");
>
> ret = 0;
> ---
>
On 20 July 2011 03:33, Bing Zhao <[email protected]> wrote:
> Yeah. I didn't know that the entire wext has been removed from libertas.
>
> Anyway, for users who need this feature we can add a module parameter to enable it with the patch below. Please let me know what you think.
That seems reasonable, but it would probably be preferable to
implement it as before. Does the cfg80211 wrapper not allow for the
power command to be implemented by drivers? Is there a
cfg80211-friendly way of doing it exposed with the iw command?
John, please drop this patch (looks like this functionality will be
revived soon). Also, I've resent the other patches in this series with
minor changes.
Thanks,
Daniel
Hi Daniel,
> Subject: [PATCH 1/4] libertas: remove auto_deep_sleep functionality
>
> This is unused and I'm not really sure in what context it was designed to
> be used.
The auto deep sleep feature was added with commit 4912545:
libertas: Add auto deep sleep support for SD8385/SD8686/SD8688
When auto deep sleep is enabled a timer will be started to monitor the activities. At timer expiry (no activity for configured time period) an enter_deep_sleep command will be sent to the card automatically to save power. Once an activity is detected station will exit from deep sleep mode for processing and restart the timer. After the event is processed and there is no new activity the timer will expire and then the deep sleep mode is entered automatically again.
As the auto deep sleep feature for SD8385/SD8686/SD8688 cards is very useful for many embedded platforms to handle enter/exit deep sleep mode automatically, please do not remove it from libertas driver. If you have any particular issue with this feature enabled, we can work on it and solve the problem.
Thanks,
Bing
SGkgRGFuLA0KDQo+ID4gPiA+IFRvIGVuYWJsZSBkZWVwIHNsZWVwIG1vZGU6DQo+ID4gPiA+IGl3
Y29uZmlnIHdsYW4wIHBvd2VyIHBlcmlvZCAwDQo+ID4gPiA+DQo+ID4gPiA+IFRvIGVuYWJsZSBh
dXRvIGRlZXAgc2xlZXAgbW9kZSB3aXRoIGlkbGUgdGltZSBwZXJpb2Qgc2V0IHRvIDUgc2Vjb25k
czoNCj4gPiA+ID4gaXdjb25maWcgd2xhbjAgcG93ZXIgcGVyaW9kIDUNCj4gPiA+ID4NCj4gPiA+
ID4gVG8gZGlzYWJsZSBkZWVwIHNsZWVwL2F1dG8gZGVlcCBzbGVlcCBtb2RlOg0KPiA+ID4gPiBp
d2NvbmZpZyB3bGFuMCBwb3dlciBwZXJpb2QgLTENCj4gPiA+DQo+ID4gPiBQYXVsIHBvaW50ZWQg
b3V0IHRoYXQgaW5kZWVkLCBpbiBvbGQga2VybmVscywgdGhpcyBmdW5jdGlvbmFsaXR5IHdhcw0K
PiA+ID4gaG9va2VkIHVwIHRvIHRoZSBwb3dlciB3aXJlbGVzcyBleHRlbnNpb24uDQo+ID4gPg0K
PiA+ID4gSW4gcmVjZW50IGtlcm5lbHMsIHRoaXMgaXMgbm90IHRoZSBjYXNlIC0gaXRzIG5vdCBo
b29rZWQgdXAgdG8NCj4gPiA+IGFueXRoaW5nLiBUaGUgY29tbWFuZHMgeW91IHdyaXRlIGFib3Zl
IHdpbGwgZmFpbC4NCj4gPg0KPiA+IFllYWguIEkgZGlkbid0IGtub3cgdGhhdCB0aGUgZW50aXJl
IHdleHQgaGFzIGJlZW4gcmVtb3ZlZCBmcm9tIGxpYmVydGFzLg0KPiA+DQo+ID4gQW55d2F5LCBm
b3IgdXNlcnMgd2hvIG5lZWQgdGhpcyBmZWF0dXJlIHdlIGNhbiBhZGQgYSBtb2R1bGUgcGFyYW1l
dGVyIHRvIGVuYWJsZSBpdCB3aXRoIHRoZSBwYXRjaA0KPiBiZWxvdy4gUGxlYXNlIGxldCBtZSBr
bm93IHdoYXQgeW91IHRoaW5rLg0KPiANCj4gSSdkIHJhdGhlciB3ZSBmaWd1cmUgb3V0IHNvbWUg
bmw4MDIxMS9jZmc4MDIxMSBrbm9iIGZvciB0aGlzIHJhdGhlciB0aGFuDQo+IGEgbW9kdWxlIHBh
cmFtZXRlcjsgd2UgY2FuIGNlcnRhaW5seSBhZGQgY2FsbHMgYW5kIGF0dHJpYnV0ZXMgdG8gbmw4
MDIxMQ0KPiBpZiB3ZSBuZWVkIHRvLg0KDQpBZ3JlZS4gQ29uZmlndXJhdGlvbiB2aWEgbmw4MDIx
MS9jZmc4MDIxMSBBUEkgaXMgdGhlIGJlc3Qgc29sdXRpb24uIEknbGwgY2hlY2sgb24gdGhhdC4N
Cg0KVGhhbmtzLA0KQmluZw0K
PiA+IEFueXdheSwgZm9yIHVzZXJzIHdobyBuZWVkIHRoaXMgZmVhdHVyZSB3ZSBjYW4gYWRkIGEg
bW9kdWxlIHBhcmFtZXRlciB0byBlbmFibGUgaXQgd2l0aCB0aGUgcGF0Y2gNCj4gYmVsb3cuIFBs
ZWFzZSBsZXQgbWUga25vdyB3aGF0IHlvdSB0aGluay4NCj4gDQo+IEknZCByYXRoZXIgd2UgZmln
dXJlIG91dCBzb21lIG5sODAyMTEvY2ZnODAyMTEga25vYiBmb3IgdGhpcyByYXRoZXIgdGhhbg0K
PiBhIG1vZHVsZSBwYXJhbWV0ZXI7IHdlIGNhbiBjZXJ0YWlubHkgYWRkIGNhbGxzIGFuZCBhdHRy
aWJ1dGVzIHRvIG5sODAyMTENCj4gaWYgd2UgbmVlZCB0by4NCj4gDQo+IERhbg0KDQpIaSBEYW4s
DQoNCkluICJzdHJ1Y3QgY2ZnODAyMTFfb3BzIiAoY2ZnODAyMTEuaCkgYSAic2V0X3Bvd2VyX21n
bXQiIGhhbmRsZXIgaXMgZGVmaW5lZCBmb3IgSUVFRSBQb3dlciBTYXZlLg0KDQotLS0NCiAqIEBz
ZXRfcG93ZXJfbWdtdDogQ29uZmlndXJlIFdMQU4gcG93ZXIgbWFuYWdlbWVudC4gQSB0aW1lb3V0
IHZhbHVlIG9mIC0xDQogKiAgICAgIGFsbG93cyB0aGUgZHJpdmVyIHRvIGFkanVzdCB0aGUgZHlu
YW1pYyBwcyB0aW1lb3V0IHZhbHVlLg0KDQogICAgICAgIGludCAgICAgKCpzZXRfcG93ZXJfbWdt
dCkoc3RydWN0IHdpcGh5ICp3aXBoeSwgc3RydWN0IG5ldF9kZXZpY2UgKmRldiwNCiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICBib29sIGVuYWJsZWQsIGludCB0aW1lb3V0KTsNCi0t
LQ0KDQpBbmQgdGhlIGNvcnJlc3BvbmRpbmcgaXcgY29tbWFuZCBpcyAic2V0IHBvd2VyX3NhdmUg
b258b2ZmIi4NCg0KQ3VycmVudGx5ICdhdGg2a2wnLCAnaXdtYzMyMDB3aWZpJywgJ3JuZGlzX3ds
YW4nLCBhbmQgJ213aWZpZXgnIGRyaXZlcnMgaGF2ZSBpbXBsZW1lbnRlZCB0aGUgc2V0X3Bvd2Vy
X21nbXQgY2FsbGJhY2sgZnVuY3Rpb24gZm9yIHBvd2VyIHNhdmluZyBoYW5kbGluZy4NCg0KRG8g
eW91IHRoaW5rIGlmIHdlIHNob3VsZCBhZGQgbmV3IG9wcyBmb3IgYXV0byBkZWVwIHNsZWVwPw0K
DQpUaGFua3MsDQpCaW5nDQoNCg==