* [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 @ 2009-09-15 23:45 Bing Zhao 2009-09-15 23:41 ` Andrey Yurovsky 2009-09-20 14:58 ` Dan Williams 0 siblings, 2 replies; 14+ messages in thread From: Bing Zhao @ 2009-09-15 23:45 UTC (permalink / raw) To: libertas-dev; +Cc: linux-wireless, Bing Zhao, Amitkumar Karwar [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 34601 bytes --] From: Amitkumar Karwar <akarwar@marvell.com> Add timer based auto deep sleep feature in libertas driver which can be configured through debugfs interface. This is tested on SD8688, SD8686 cards with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit platforms. Tests have been done for USB/CS cards to make sure that the patch won't break USB/CS code. We didn't test the if_spi driver. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> --- drivers/net/wireless/libertas/README | 28 +++++- drivers/net/wireless/libertas/cmd.c | 72 +++++++++++++- drivers/net/wireless/libertas/cmdresp.c | 12 +++ drivers/net/wireless/libertas/debugfs.c | 160 +++++++++++++++++++++++++++++++ drivers/net/wireless/libertas/decl.h | 4 + drivers/net/wireless/libertas/dev.h | 18 ++++ drivers/net/wireless/libertas/host.h | 1 + drivers/net/wireless/libertas/if_cs.c | 3 + drivers/net/wireless/libertas/if_sdio.c | 56 +++++++++++ drivers/net/wireless/libertas/if_sdio.h | 3 +- drivers/net/wireless/libertas/if_spi.c | 3 + drivers/net/wireless/libertas/if_usb.c | 3 + drivers/net/wireless/libertas/main.c | 111 +++++++++++++++++++--- drivers/net/wireless/libertas/scan.c | 11 ++ drivers/net/wireless/libertas/wext.c | 138 ++++++++++++++++++++++++++ 15 files changed, 604 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index ab6a2d5..059ce8c 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README @@ -1,5 +1,5 @@ ================================================================================ - README for USB8388 + README for Libertas (c) Copyright © 2003-2006, Marvell International Ltd. All Rights Reserved @@ -226,4 +226,30 @@ setuserscan All entries in the scan table (not just the new scan data when keep=1) will be displayed upon completion by use of the getscantable ioctl. +deepsleep + + This command is used to configure the station in deep sleep mode/auto + deep sleep mode. Command expects two parameters: + 'state' 'idle time period' + + The timer is implemented to monitor the activities (command, event, + data, etc.). When an activity is detected station will exit from deep + sleep mode automatically and restart the timer. At timer expiry (no + activity for defined time period) the deepsleep mode is entered + automatically. + + Note: this command is for SDIO interface only. + + Path: /sys/kernel/debug/libertas_wireless/ethX/ + + Usage: + To read the current status of deep sleep do: + cat deepsleep + To enable deep sleep mode do: + echo '1 0' > deepsleep + To enable auto deep sleep mode with idle time period 5 seconds do: + echo '1 5000' > deepsleep + To disable deep sleep/auto deep sleep mode do: + echo '0 0' > deepsleep + ============================================================================== diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 6850981..3a3e894 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -17,7 +17,6 @@ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); - /** * @brief Simple callback that copies response back into command * @@ -319,6 +318,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, return 0; } +static int lbs_wait_for_ds_awake(struct lbs_private *priv) +{ + int ret = 0; + + lbs_deb_enter(LBS_DEB_CMD); + + if (priv->is_deep_sleep) { + if (!wait_event_interruptible_timeout(priv->ds_awake_q, + !priv->is_deep_sleep, (10 * HZ))) { + lbs_pr_err("ds_awake_q: timer expired\n"); + ret = -1; + } + } + + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} + +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) +{ + int ret = 0; + + lbs_deb_enter(LBS_DEB_CMD); + + if (deep_sleep) { + if (priv->is_deep_sleep != 1) { + lbs_deb_cmd("deep sleep: sleep\n"); + BUG_ON(!priv->enter_deep_sleep); + ret = priv->enter_deep_sleep(priv); + if (!ret) { + netif_stop_queue(priv->dev); + netif_carrier_off(priv->dev); + } + } else { + lbs_pr_err("deep sleep: already enabled\n"); + } + } else { + if (priv->is_deep_sleep) { + lbs_deb_cmd("deep sleep: wakeup\n"); + BUG_ON(!priv->exit_deep_sleep); + ret = priv->exit_deep_sleep(priv); + if (!ret) { + ret = lbs_wait_for_ds_awake(priv); + if (ret) + lbs_pr_err("deep sleep: wakeup" + "failed\n"); + } + } + } + + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); + return ret; +} + int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, struct assoc_request *assoc) { @@ -1242,8 +1295,17 @@ static void lbs_submit_command(struct lbs_private *priv, timeo = HZ/4; } - /* Setup the timer after transmit command */ - mod_timer(&priv->command_timer, jiffies + timeo); + 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 { + /* Setup the timer after transmit command */ + mod_timer(&priv->command_timer, jiffies + timeo); + } lbs_deb_leave(LBS_DEB_HOST); } @@ -1505,6 +1567,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, case CMD_802_11_BEACON_CTRL: ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); break; + case CMD_802_11_DEEP_SLEEP: + cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); + cmdptr->size = cpu_to_le16(S_DS_GEN); + break; default: lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); ret = -1; diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index c42d3fa..47d2b19 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event) case MACREG_INT_CODE_HOST_AWAKE: lbs_deb_cmd("EVENT: host awake\n"); + if (priv->reset_deep_sleep_wakeup) + priv->reset_deep_sleep_wakeup(priv); + priv->is_deep_sleep = 0; lbs_send_confirmwake(priv); break; + case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: + if (priv->reset_deep_sleep_wakeup) + priv->reset_deep_sleep_wakeup(priv); + lbs_deb_cmd("EVENT: ds awake\n"); + priv->is_deep_sleep = 0; + priv->wakeup_dev_required = 0; + wake_up_interruptible(&priv->ds_awake_q); + break; + case MACREG_INT_CODE_PS_AWAKE: lbs_deb_cmd("EVENT: ps awake\n"); /* handle unexpected PS AWAKE event */ diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 893a55c..624a438 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -117,6 +117,11 @@ static ssize_t lbs_sleepparams_write(struct file *file, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out_unlock; + } + buf_size = min(count, len - 1); if (copy_from_user(buf, user_buf, buf_size)) { ret = -EFAULT; @@ -157,6 +162,11 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out_unlock; + } + ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp); if (ret) goto out_unlock; @@ -173,6 +183,118 @@ out_unlock: return ret; } +static ssize_t lbs_deepsleep_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct lbs_private *priv = file->private_data; + ssize_t pos = 0; + int ret; + unsigned long addr = get_zeroed_page(GFP_KERNEL); + char *buf = (char *)addr; + + if (!buf) + return -ENOMEM; + + if (!priv->enter_deep_sleep) { + lbs_pr_err("deep sleep feature is not implemented " + "for this interface driver\n"); + ret = -EINVAL; + goto out_ds; + } + + if (priv->is_auto_deep_sleep_enabled) + pos += snprintf(buf, len, "%d %d\n", + priv->is_auto_deep_sleep_enabled, + priv->auto_deep_sleep_timeout); + else if (priv->is_deep_sleep) + pos += snprintf(buf, len, "%d %d\n", + priv->is_deep_sleep, + priv->auto_deep_sleep_timeout); + else + pos += snprintf(buf, len, "%d %d\n", + priv->is_deep_sleep, + priv->auto_deep_sleep_timeout); + + ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); + +out_ds: + free_page(addr); + return ret; +} + +static ssize_t lbs_deepsleep_write(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct lbs_private *priv = file->private_data; + ssize_t res, buf_size; + int is_deep_sleep, auto_deep_sleep_timeout; + unsigned long addr = get_zeroed_page(GFP_KERNEL); + char *buf = (char *)addr; + + if (!buf) + return -ENOMEM; + + if (!priv->enter_deep_sleep) { + lbs_pr_err("deep sleep feature is not implemented " + "for this interface driver\n"); + res = -EINVAL; + goto out_ds; + } + + if (priv->connect_status == LBS_CONNECTED) { + lbs_pr_err("can't use deep sleep cmd in connected " + "state\n"); + res = -EINVAL; + goto out_ds; + } + + buf_size = min(count, len - 1); + if (copy_from_user(buf, userbuf, buf_size)) { + res = -EFAULT; + goto out_ds; + } + + res = sscanf(buf, "%d %d", &is_deep_sleep, &auto_deep_sleep_timeout); + if ((res != 2) || (!is_deep_sleep && auto_deep_sleep_timeout) || + !((is_deep_sleep == 1) || + (is_deep_sleep == 0))) { + lbs_pr_err("unknown option\n"); + res = -EINVAL; + goto out_ds; + } + + if (auto_deep_sleep_timeout) { + if (!priv->is_auto_deep_sleep_enabled) { + priv->is_activity_detected = 0; + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout; + lbs_enter_auto_deep_sleep(priv); + } else { + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout; + lbs_deb_debugfs("auto deep sleep: already enabled\n"); + } + } else { + if (priv->is_auto_deep_sleep_enabled) { + lbs_exit_auto_deep_sleep(priv); + /* Try to exit deep sleep if auto deep sleep disabled */ + res = lbs_set_deep_sleep(priv, 0); + if (res) + goto out_ds; + } + if ((is_deep_sleep == 0) || (is_deep_sleep == 1)) { + res = lbs_set_deep_sleep(priv, is_deep_sleep); + if (res) + goto out_ds; + } + } + + res = count; + +out_ds: + free_page(addr); + return res; +} + /* * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the @@ -223,6 +345,9 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask, u8 freq; int events = 0; + if (!lbs_is_cmd_allowed(priv)) + return -EBUSY; + buf = (char *)get_zeroed_page(GFP_KERNEL); if (!buf) return -ENOMEM; @@ -275,6 +400,9 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, char *buf; int ret; + if (!lbs_is_cmd_allowed(priv)) + return -EBUSY; + buf = (char *)get_zeroed_page(GFP_KERNEL); if (!buf) return -ENOMEM; @@ -444,6 +572,11 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + free_page(addr); + return -EBUSY; + } + offval.offset = priv->mac_offset; offval.value = 0; @@ -496,6 +629,11 @@ static ssize_t lbs_wrmac_write(struct file *file, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + res = -EBUSY; + goto out_unlock; + } + buf_size = min(count, len - 1); if (copy_from_user(buf, userbuf, buf_size)) { res = -EFAULT; @@ -532,6 +670,11 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + free_page(addr); + return -EBUSY; + } + offval.offset = priv->bbp_offset; offval.value = 0; @@ -585,6 +728,11 @@ static ssize_t lbs_wrbbp_write(struct file *file, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + res = -EBUSY; + goto out_unlock; + } + buf_size = min(count, len - 1); if (copy_from_user(buf, userbuf, buf_size)) { res = -EFAULT; @@ -621,6 +769,11 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + free_page(addr); + return -EBUSY; + } + offval.offset = priv->rf_offset; offval.value = 0; @@ -674,6 +827,11 @@ static ssize_t lbs_wrrf_write(struct file *file, if (!buf) return -ENOMEM; + if (!lbs_is_cmd_allowed(priv)) { + res = -EBUSY; + goto out_unlock; + } + buf_size = min(count, len - 1); if (copy_from_user(buf, userbuf, buf_size)) { res = -EFAULT; @@ -717,6 +875,8 @@ static const struct lbs_debugfs_files debugfs_files[] = { write_file_dummy), }, { "sleepparams", 0644, FOPS(lbs_sleepparams_read, lbs_sleepparams_write), }, + { "deepsleep", 0644, FOPS(lbs_deepsleep_read, + lbs_deepsleep_write), }, }; static const struct lbs_debugfs_files debugfs_events_files[] = { diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 0b84bdc..34b475f 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -33,6 +33,10 @@ int lbs_execute_next_command(struct lbs_private *priv); int lbs_process_event(struct lbs_private *priv, u32 event); void lbs_queue_event(struct lbs_private *priv, u32 event); void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); +int lbs_is_cmd_allowed(struct lbs_private *priv); +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 578c697..e2b4ef2 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -129,6 +129,20 @@ struct lbs_private { u32 bbp_offset; u32 rf_offset; + /** Deep sleep flag */ + int is_deep_sleep; + /** Auto deep sleep enabled flag */ + int is_auto_deep_sleep_enabled; + /** Device wakeup required flag */ + int wakeup_dev_required; + /** Auto deep sleep flag*/ + int is_activity_detected; + /** Auto deep sleep timeout (in miliseconds) */ + int auto_deep_sleep_timeout; + + /** Deep sleep wait queue */ + wait_queue_head_t ds_awake_q; + /* Download sent: bit0 1/0=data_sent/data_tx_done, bit1 1/0=cmd_sent/cmd_tx_done, @@ -154,6 +168,9 @@ struct lbs_private { /** Hardware access */ int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); void (*reset_card) (struct lbs_private *priv); + int (*enter_deep_sleep) (struct lbs_private *priv); + int (*exit_deep_sleep) (struct lbs_private *priv); + int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); /* Wake On LAN */ uint32_t wol_criteria; @@ -204,6 +221,7 @@ struct lbs_private { /** Timers */ struct timer_list command_timer; + struct timer_list auto_deepsleep_timer; int nr_retries; int cmd_timed_out; diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index fe8f0cb..c055daa 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -57,6 +57,7 @@ #define CMD_802_11_ENABLE_RSN 0x002f #define CMD_802_11_SET_AFC 0x003c #define CMD_802_11_GET_AFC 0x003d +#define CMD_802_11_DEEP_SLEEP 0x003e #define CMD_802_11_AD_HOC_STOP 0x0040 #define CMD_802_11_HOST_SLEEP_CFG 0x0043 #define CMD_802_11_WAKEUP_CONFIRM 0x0044 diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 6238176..465742f 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) card->priv = priv; priv->card = card; priv->hw_host_to_card = if_cs_host_to_card; + priv->enter_deep_sleep = NULL; + priv->exit_deep_sleep = NULL; + priv->reset_deep_sleep_wakeup = NULL; priv->fw_ready = 1; /* Now actually get the IRQ */ diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 485a8d4..9716728 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -831,6 +831,58 @@ out: return ret; } +static int if_sdio_enter_deep_sleep(struct lbs_private *priv) +{ + int ret = -1; + struct cmd_header cmd; + + memset(&cmd, 0, sizeof(cmd)); + + lbs_deb_sdio("send DEEP_SLEEP command\n"); + ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), + lbs_cmd_copyback, (unsigned long) &cmd); + if (ret) + lbs_pr_err("DEEP_SLEEP cmd failed\n"); + + mdelay(200); + return ret; +} + +static int if_sdio_exit_deep_sleep(struct lbs_private *priv) +{ + struct if_sdio_card *card = priv->card; + int ret = -1; + + lbs_deb_enter(LBS_DEB_SDIO); + sdio_claim_host(card->func); + + sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); + if (ret) + lbs_pr_err("sdio_writeb failed!\n"); + + sdio_release_host(card->func); + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); + return ret; +} + +static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) +{ + struct if_sdio_card *card = priv->card; + int ret = -1; + + lbs_deb_enter(LBS_DEB_SDIO); + sdio_claim_host(card->func); + + sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); + if (ret) + lbs_pr_err("sdio_writeb failed!\n"); + + sdio_release_host(card->func); + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); + return ret; + +} + /*******************************************************************/ /* SDIO callbacks */ /*******************************************************************/ @@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func) * Ignore the define name, this really means the card has * successfully received the command. */ + card->priv->is_activity_detected = 1; if (cause & IF_SDIO_H_INT_DNLD) lbs_host_to_card_done(card->priv); @@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func, priv->card = card; priv->hw_host_to_card = if_sdio_host_to_card; + priv->enter_deep_sleep = if_sdio_enter_deep_sleep; + priv->exit_deep_sleep = if_sdio_exit_deep_sleep; + priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; priv->fw_ready = 1; diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 60c9b2f..12179c1 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h @@ -51,5 +51,6 @@ #define IF_SDIO_EVENT 0x80fc #define IF_SDIO_BLOCK_SIZE 256 - +#define CONFIGURATION_REG 0x03 +#define HOST_POWER_UP (0x1U << 1) #endif diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 446e327..e2fa657 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -1117,6 +1117,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) card->priv = priv; priv->card = card; priv->hw_host_to_card = if_spi_host_to_card; + priv->enter_deep_sleep = NULL; + priv->exit_deep_sleep = NULL; + priv->reset_deep_sleep_wakeup = NULL; priv->fw_ready = 1; /* Initialize interrupt handling stuff. */ diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 92bc8c5..a8262de 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -300,6 +300,9 @@ static int if_usb_probe(struct usb_interface *intf, cardp->priv->fw_ready = 1; priv->hw_host_to_card = if_usb_host_to_card; + priv->enter_deep_sleep = NULL; + priv->exit_deep_sleep = NULL; + priv->reset_deep_sleep_wakeup = NULL; #ifdef CONFIG_OLPC if (machine_is_olpc()) priv->reset_card = if_usb_reset_olpc_card; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 8df1cfd..3b14fcc 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -574,8 +574,10 @@ void lbs_host_to_card_done(struct lbs_private *priv) priv->dnld_sent = DNLD_RES_RECEIVED; /* Wake main thread if commands are pending */ - if (!priv->cur_cmd || priv->tx_pending_len > 0) - wake_up_interruptible(&priv->waitq); + if (!priv->cur_cmd || priv->tx_pending_len > 0) { + if (!priv->wakeup_dev_required) + wake_up_interruptible(&priv->waitq); + } spin_unlock_irqrestore(&priv->driver_lock, flags); lbs_deb_leave(LBS_DEB_THREAD); @@ -770,7 +772,8 @@ static int lbs_thread(void *data) shouldsleep = 0; /* We have a command response */ else if (priv->cur_cmd) shouldsleep = 1; /* Can't send a command; one already running */ - else if (!list_empty(&priv->cmdpendingq)) + else if (!list_empty(&priv->cmdpendingq) && + !(priv->wakeup_dev_required)) shouldsleep = 0; /* We have a command to send */ else if (__kfifo_len(priv->event_fifo)) shouldsleep = 0; /* We have an event to process */ @@ -822,6 +825,26 @@ static int lbs_thread(void *data) } spin_unlock_irq(&priv->driver_lock); + /* Process hardware events, e.g. card removed, link lost */ + spin_lock_irq(&priv->driver_lock); + while (__kfifo_len(priv->event_fifo)) { + u32 event; + __kfifo_get(priv->event_fifo, (unsigned char *) &event, + sizeof(event)); + spin_unlock_irq(&priv->driver_lock); + lbs_process_event(priv, event); + spin_lock_irq(&priv->driver_lock); + } + spin_unlock_irq(&priv->driver_lock); + + if (priv->wakeup_dev_required) { + lbs_deb_thread("Waking up device...\n"); + /* Wake up device */ + if (priv->exit_deep_sleep(priv)) + lbs_deb_thread("Wakeup device failed\n"); + continue; + } + /* command timeout stuff */ if (priv->cmd_timed_out && priv->cur_cmd) { struct cmd_ctrl_node *cmdnode = priv->cur_cmd; @@ -849,18 +872,7 @@ static int lbs_thread(void *data) } priv->cmd_timed_out = 0; - /* Process hardware events, e.g. card removed, link lost */ - spin_lock_irq(&priv->driver_lock); - while (__kfifo_len(priv->event_fifo)) { - u32 event; - __kfifo_get(priv->event_fifo, (unsigned char *) &event, - sizeof(event)); - spin_unlock_irq(&priv->driver_lock); - lbs_process_event(priv, event); - spin_lock_irq(&priv->driver_lock); - } - spin_unlock_irq(&priv->driver_lock); if (!priv->fw_ready) continue; @@ -894,6 +906,9 @@ static int lbs_thread(void *data) (priv->psstate == PS_STATE_PRE_SLEEP)) continue; + if (priv->is_deep_sleep) + continue; + /* Execute the next command */ if (!priv->dnld_sent && !priv->cur_cmd) lbs_execute_next_command(priv); @@ -928,6 +943,7 @@ static int lbs_thread(void *data) } del_timer(&priv->command_timer); + del_timer(&priv->auto_deepsleep_timer); wake_up_all(&priv->cmd_pending); lbs_deb_leave(LBS_DEB_THREAD); @@ -1050,6 +1066,60 @@ out: lbs_deb_leave(LBS_DEB_CMD); } +/** + * This function put the device back to deep sleep mode when timer expires + * and no activity (command, event, data etc.) is detected. + */ +static void auto_deepsleep_timer_fn(unsigned long data) +{ + struct lbs_private *priv = (struct lbs_private *)data; + int ret; + + 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)) { + lbs_deb_main("Entering auto deep sleep mode...\n"); + ret = lbs_prepare_and_send_command(priv, + CMD_802_11_DEEP_SLEEP, 0, + 0, 0, NULL); + } + } + 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 void lbs_sync_channel_worker(struct work_struct *work) { struct lbs_private *priv = container_of(work, struct lbs_private, @@ -1099,11 +1169,17 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; priv->psmode = LBS802_11POWERMODECAM; priv->psstate = PS_STATE_FULL_POWER; + priv->is_deep_sleep = 0; + priv->is_auto_deep_sleep_enabled = 0; + priv->wakeup_dev_required = 0; + init_waitqueue_head(&priv->ds_awake_q); mutex_init(&priv->lock); setup_timer(&priv->command_timer, command_timer_fn, (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); @@ -1142,6 +1218,7 @@ static void lbs_free_adapter(struct lbs_private *priv) if (priv->event_fifo) kfifo_free(priv->event_fifo); del_timer(&priv->command_timer); + del_timer(&priv->auto_deepsleep_timer); kfree(priv->networks); priv->networks = NULL; @@ -1272,6 +1349,11 @@ void lbs_remove_card(struct lbs_private *priv) wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + if (priv->is_deep_sleep) { + priv->is_deep_sleep = 0; + wake_up_interruptible(&priv->ds_awake_q); + } + /* Stop the thread servicing the interrupts */ priv->surpriseremoved = 1; kthread_stop(priv->main_thread); @@ -1392,6 +1474,7 @@ 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); diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 6c95af3..e468e15 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -950,6 +950,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + if (!priv->radio_on) { ret = -EINVAL; goto out; @@ -1017,6 +1022,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + err = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); + return err; + } + /* iwlist should wait until the current scan is finished */ if (priv->scan_channel) return -EAGAIN; diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index be837a0..ef2b986 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -45,6 +45,31 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv) priv->pending_assoc_req = NULL; } +/** + * @brief This function checks if the command is allowed. + * + * @param priv A pointer to lbs_private structure + * @return allowed or not allowed. + */ + +int lbs_is_cmd_allowed(struct lbs_private *priv) +{ + int ret = 1; + + lbs_deb_enter(LBS_DEB_WEXT); + + if (!priv->is_auto_deep_sleep_enabled) { + if (priv->is_deep_sleep) { + lbs_deb_wext("IOCTLS called when station" + "is in deep sleep\n"); + ret = 0; + } + } + + lbs_deb_leave(LBS_DEB_WEXT); + return ret; +} + /** * @brief Find the channel frequency power info with specific channel @@ -168,6 +193,11 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + lbs_deb_leave(LBS_DEB_WEXT); + return -EBUSY; + } + cfp = lbs_find_cfp_by_band_and_channel(priv, 0, priv->curbssparams.channel); @@ -278,6 +308,12 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + if (vwrq->disabled) val = MRVDRV_RTS_MAX_VALUE; @@ -299,6 +335,11 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val); if (ret) goto out; @@ -321,6 +362,12 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + if (vwrq->disabled) val = MRVDRV_FRAG_MAX_VALUE; @@ -342,6 +389,11 @@ static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val); if (ret) goto out; @@ -391,6 +443,11 @@ static int lbs_get_txpow(struct net_device *dev, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + if (!priv->radio_on) { lbs_deb_wext("tx power off\n"); vwrq->value = 0; @@ -424,6 +481,11 @@ static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) return -EOPNOTSUPP; @@ -472,6 +534,11 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + vwrq->disabled = 0; if (vwrq->flags & IW_RETRY_LONG) { @@ -712,6 +779,11 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + lbs_deb_leave(LBS_DEB_WEXT); + return -EBUSY; + } + if (!(priv->fwcapinfo & FW_CAPINFO_PS)) { if (vwrq->disabled) return 0; @@ -792,6 +864,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) + return NULL; + priv->wstats.status = priv->mode; /* If we're not associated, all quality values are meaningless */ @@ -892,6 +967,12 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + mutex_lock(&priv->lock); assoc_req = lbs_get_association_request(priv); if (!assoc_req) { @@ -1000,6 +1081,12 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, u8 rates[MAX_RATES + 1]; lbs_deb_enter(LBS_DEB_WEXT); + + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + lbs_deb_wext("vwrq->value %d\n", vwrq->value); lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); @@ -1058,6 +1145,11 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + lbs_deb_leave(LBS_DEB_WEXT); + return -EBUSY; + } + if (priv->connect_status == LBS_CONNECTED) { vwrq->value = priv->cur_rate * 500000; @@ -1084,6 +1176,11 @@ static int lbs_set_mode(struct net_device *dev, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + if ( (*uwrq != IW_MODE_ADHOC) && (*uwrq != IW_MODE_INFRA) && (*uwrq != IW_MODE_AUTO)) { @@ -1325,6 +1422,12 @@ static int lbs_set_encode(struct net_device *dev, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + mutex_lock(&priv->lock); assoc_req = lbs_get_association_request(priv); if (!assoc_req) { @@ -1508,6 +1611,12 @@ static int lbs_set_encodeext(struct net_device *dev, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + mutex_lock(&priv->lock); assoc_req = lbs_get_association_request(priv); if (!assoc_req) { @@ -1720,6 +1829,12 @@ static int lbs_set_auth(struct net_device *dev, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + mutex_lock(&priv->lock); assoc_req = lbs_get_association_request(priv); if (!assoc_req) { @@ -1822,6 +1937,12 @@ static int lbs_get_auth(struct net_device *dev, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + switch (dwrq->flags & IW_AUTH_INDEX) { case IW_AUTH_KEY_MGMT: dwrq->value = priv->secinfo.key_mgmt; @@ -1864,6 +1985,11 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + goto out; + } + if (vwrq->disabled) { lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0); goto out; @@ -1983,6 +2109,12 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + if (!priv->radio_on) { ret = -EINVAL; goto out; @@ -2110,6 +2242,12 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_WEXT); + if (!lbs_is_cmd_allowed(priv)) { + ret = -EBUSY; + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; + } + if (!priv->radio_on) return -EINVAL; -- 1.5.4.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-15 23:45 [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 Bing Zhao @ 2009-09-15 23:41 ` Andrey Yurovsky 2009-09-16 20:20 ` Bing Zhao 2009-09-20 14:58 ` Dan Williams 1 sibling, 1 reply; 14+ messages in thread From: Andrey Yurovsky @ 2009-09-15 23:41 UTC (permalink / raw) To: Bing Zhao; +Cc: libertas-dev, linux-wireless, Amitkumar Karwar, Dan Williams Hi Bing. This is not specific to the actual implementation of the deep sleep commands in your patch but, On Tue, Sep 15, 2009 at 4:45 PM, Bing Zhao <bzhao@marvell.com> wrote: > + Path: /sys/kernel/debug/libertas_wireless/ethX/ Is the sysfs interface really necessary? It seems like yet another non-standard configuration option to keep track of. Deep sleep seems to pretty much "turn off" the wifi card (as far as the user is concerned) so how about a simpler approach: enter deep sleep when the interface is brought down (ifconfig wlanN down) and exit deep sleep when it's brought up. Do this only when deep sleep is supported/possible. Alternately, maybe this belongs as an rfkill feature? -Andrey ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-15 23:41 ` Andrey Yurovsky @ 2009-09-16 20:20 ` Bing Zhao 2009-09-16 20:47 ` Andrey Yurovsky 0 siblings, 1 reply; 14+ messages in thread From: Bing Zhao @ 2009-09-16 20:20 UTC (permalink / raw) To: Andrey Yurovsky Cc: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar, Dan Williams Hi Andrey, > -----Original Message----- > From: Andrey Yurovsky [mailto:andrey@cozybit.com] > Sent: Tuesday, September 15, 2009 4:41 PM > To: Bing Zhao > Cc: libertas-dev@lists.infradead.org; linux-wireless@vger.kernel.org; Amitkumar Karwar; Dan Williams > Subject: Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 > > Hi Bing. This is not specific to the actual implementation of the > deep sleep commands in your patch but, > > On Tue, Sep 15, 2009 at 4:45 PM, Bing Zhao <bzhao@marvell.com> wrote: > > + Path: /sys/kernel/debug/libertas_wireless/ethX/ > > Is the sysfs interface really necessary? It seems like yet another > non-standard configuration option to keep track of. Actually the debugfs interface is used in the patch. Some information (such as the interface name and path) in README file is out of date. We just copy-and-paste it for the new deepsleep command. We need a separate patch to clean up the REAME file and keep it up to date. > > Deep sleep seems to pretty much "turn off" the wifi card (as far as > the user is concerned) so how about a simpler approach: enter deep > sleep when the interface is brought down (ifconfig wlanN down) and > exit deep sleep when it's brought up. Do this only when deep sleep is > supported/possible. Alternately, maybe this belongs as an rfkill > feature? Entering/exiting deep sleep doesn't have to depend on wlanN interface's up and down. User can still put the chip into sleep when wlanN is up. And, with auto deep sleep feature, the driver automatically wakes the chip up for sending user commands (for example, scan) and put the chip back to sleep after certain time period of inactivity. The deepsleep command through debugfs interface provides the flexibility of deep sleep options. The rfkill shuts down the RF transmitter of the device but most of other modules may be still functioning. The deep sleep shuts down most of the modules (including the RF) on the chip to save as much power as possible. Regards, Bing > > -Andrey ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-16 20:20 ` Bing Zhao @ 2009-09-16 20:47 ` Andrey Yurovsky 2009-09-17 16:11 ` Sebastian Andrzej Siewior 0 siblings, 1 reply; 14+ messages in thread From: Andrey Yurovsky @ 2009-09-16 20:47 UTC (permalink / raw) To: Bing Zhao Cc: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar, Dan Williams On Wed, Sep 16, 2009 at 1:20 PM, Bing Zhao <bzhao@marvell.com> wrote: > Hi Andrey, > >> -----Original Message----- >> From: Andrey Yurovsky [mailto:andrey@cozybit.com] >> Sent: Tuesday, September 15, 2009 4:41 PM >> To: Bing Zhao >> Cc: libertas-dev@lists.infradead.org; linux-wireless@vger.kernel.org; Amitkumar Karwar; Dan Williams >> Subject: Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 >> >> Hi Bing. This is not specific to the actual implementation of the >> deep sleep commands in your patch but, >> >> On Tue, Sep 15, 2009 at 4:45 PM, Bing Zhao <bzhao@marvell.com> wrote: >> > + Path: /sys/kernel/debug/libertas_wireless/ethX/ >> >> Is the sysfs interface really necessary? It seems like yet another >> non-standard configuration option to keep track of. > > Actually the debugfs interface is used in the patch. > > Some information (such as the interface name and path) in README file is out of date. We just copy-and-paste it for the new deepsleep command. We need a separate patch to clean up the REAME file and keep it up to date. Ok. Either way, this is another out-of-band interface (regardless of if it's debugfs or sysfs). That said, I believe that debugfs should be used for debugging, not for configuring driver/device features like these. >> Deep sleep seems to pretty much "turn off" the wifi card (as far as >> the user is concerned) so how about a simpler approach: enter deep >> sleep when the interface is brought down (ifconfig wlanN down) and >> exit deep sleep when it's brought up. Do this only when deep sleep is >> supported/possible. Alternately, maybe this belongs as an rfkill >> feature? > > Entering/exiting deep sleep doesn't have to depend on wlanN interface's up and down. User can still put the chip into sleep when wlanN is up. And, with auto deep sleep feature, the driver automatically wakes the chip up for sending user commands (for example, scan) and put the chip back to sleep after certain time period of inactivity. The deepsleep command through debugfs interface provides the flexibility of deep sleep options. > > The rfkill shuts down the RF transmitter of the device but most of other modules may be still functioning. The deep sleep shuts down most of the modules (including the RF) on the chip to save as much power as possible. It seems that when the device is in deep sleep, it's effectively "turned off" as far as the user is concerned. That seems really similar to "ifconfig down" or rfkill, does the user really care about anything beyond that? I understand that it's possible to control this feature independently of either of those functions, but is it ever necessary? If not, it would be great to just integrate it into one (or both) of these already standard network interface semantics and not introduce a whole new configuration parameter. -Andrey > Regards, > > Bing > >> >> -Andrey > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-16 20:47 ` Andrey Yurovsky @ 2009-09-17 16:11 ` Sebastian Andrzej Siewior 2009-09-18 1:47 ` Bing Zhao 2009-09-18 7:37 ` Holger Schurig 0 siblings, 2 replies; 14+ messages in thread From: Sebastian Andrzej Siewior @ 2009-09-17 16:11 UTC (permalink / raw) To: Andrey Yurovsky Cc: Bing Zhao, Dan Williams, Amitkumar Karwar, linux-wireless@vger.kernel.org, libertas-dev@lists.infradead.org * Andrey Yurovsky | 2009-09-16 13:47:48 [-0700]: >> Some information (such as the interface name and path) in README file is out of date. We just copy-and-paste it for the new deepsleep command. We need a separate patch to clean up the REAME file and keep it up to date. > >Ok. Either way, this is another out-of-band interface (regardless of >if it's debugfs or sysfs). That said, I believe that debugfs should >be used for debugging, not for configuring driver/device features like >these. I agree on this. Debugfs is for debug only and should stay that way. What do other driver in regard to this? I hardly belive that the libertas driver is the only "deep sleep" user. >>> Deep sleep seems to pretty much "turn off" the wifi card (as far as >>> the user is concerned) so how about a simpler approach: enter deep >>> sleep when the interface is brought down (ifconfig wlanN down) and >>> exit deep sleep when it's brought up. ?Do this only when deep sleep is >>> supported/possible. ?Alternately, maybe this belongs as an rfkill >>> feature? >> >> Entering/exiting deep sleep doesn't have to depend on wlanN interface's up and down. User can still put the chip into sleep when wlanN is up. And, with auto deep sleep feature, the driver automatically wakes the chip up for sending user commands (for example, scan) and put the chip back to sleep after certain time period of inactivity. The deepsleep command through debugfs interface provides the flexibility of deep sleep options. >> >> The rfkill shuts down the RF transmitter of the device but most of other modules may be still functioning. The deep sleep shuts down most of the modules (including the RF) on the chip to save as much power as possible. > >It seems that when the device is in deep sleep, it's effectively >"turned off" as far as the user is concerned. That seems really >similar to "ifconfig down" or rfkill, does the user really care about >anything beyond that? I understand that it's possible to control this >feature independently of either of those functions, but is it ever >necessary? If not, it would be great to just integrate it into one >(or both) of these already standard network interface semantics and >not introduce a whole new configuration parameter. iwconfig has an interface for this I think: |interface power {period N|timeout N|saving N|off} >From what I see in the man page it covers pretty much what you wrote in the Readme file. So it looks like like there is your flexible interface you've been looking for :) > -Andrey > >> Regards, >> >> Bing Sebastian ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-17 16:11 ` Sebastian Andrzej Siewior @ 2009-09-18 1:47 ` Bing Zhao 2009-09-18 7:37 ` Holger Schurig 1 sibling, 0 replies; 14+ messages in thread From: Bing Zhao @ 2009-09-18 1:47 UTC (permalink / raw) To: Sebastian Andrzej Siewior, Andrey Yurovsky Cc: Dan Williams, Amitkumar Karwar, linux-wireless@vger.kernel.org, libertas-dev@lists.infradead.org Hi Sebastian, > -----Original Message----- > From: Sebastian Andrzej Siewior [mailto:sebastian@breakpoint.cc] > Sent: Thursday, September 17, 2009 9:12 AM > To: Andrey Yurovsky > Cc: Bing Zhao; Dan Williams; Amitkumar Karwar; linux-wireless@vger.kernel.org; libertas- > dev@lists.infradead.org > Subject: Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 > > * Andrey Yurovsky | 2009-09-16 13:47:48 [-0700]: > > >> Some information (such as the interface name and path) in README file is out of date. We just > copy-and-paste it for the new deepsleep command. We need a separate patch to clean up the REAME file > and keep it up to date. > > > >Ok. Either way, this is another out-of-band interface (regardless of > >if it's debugfs or sysfs). That said, I believe that debugfs should > >be used for debugging, not for configuring driver/device features like > >these. > I agree on this. Debugfs is for debug only and should stay that way. > What do other driver in regard to this? I hardly belive that the > libertas driver is the only "deep sleep" user. The debugfs interface has already been used for configuring some other parameters in libertas driver. Choosing a different way for deep sleep configuration doesn't make sense to me. > > >>> Deep sleep seems to pretty much "turn off" the wifi card (as far as > >>> the user is concerned) so how about a simpler approach: enter deep > >>> sleep when the interface is brought down (ifconfig wlanN down) and > >>> exit deep sleep when it's brought up. ?Do this only when deep sleep is > >>> supported/possible. ?Alternately, maybe this belongs as an rfkill > >>> feature? > >> > >> Entering/exiting deep sleep doesn't have to depend on wlanN interface's up and down. User can > still put the chip into sleep when wlanN is up. And, with auto deep sleep feature, the driver > automatically wakes the chip up for sending user commands (for example, scan) and put the chip back > to sleep after certain time period of inactivity. The deepsleep command through debugfs interface > provides the flexibility of deep sleep options. > >> > >> The rfkill shuts down the RF transmitter of the device but most of other modules may be still > functioning. The deep sleep shuts down most of the modules (including the RF) on the chip to save as > much power as possible. > > > >It seems that when the device is in deep sleep, it's effectively > >"turned off" as far as the user is concerned. That seems really > >similar to "ifconfig down" or rfkill, does the user really care about > >anything beyond that? I understand that it's possible to control this > >feature independently of either of those functions, but is it ever > >necessary? If not, it would be great to just integrate it into one > >(or both) of these already standard network interface semantics and > >not introduce a whole new configuration parameter. > > iwconfig has an interface for this I think: > |interface power {period N|timeout N|saving N|off} > > From what I see in the man page it covers pretty much what you wrote in > the Readme file. So it looks like like there is your flexible interface > you've been looking for :) Unfortunately, the "iwconfig wlanN power" command is used for ieee power saving mode in the driver. Regards, Bing > > > -Andrey > > > >> Regards, > >> > >> Bing > > Sebastian ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-17 16:11 ` Sebastian Andrzej Siewior 2009-09-18 1:47 ` Bing Zhao @ 2009-09-18 7:37 ` Holger Schurig 2009-09-18 17:37 ` Dan Williams 1 sibling, 1 reply; 14+ messages in thread From: Holger Schurig @ 2009-09-18 7:37 UTC (permalink / raw) To: Sebastian Andrzej Siewior Cc: Andrey Yurovsky, Bing Zhao, Dan Williams, Amitkumar Karwar, linux-wireless@vger.kernel.org, libertas-dev@lists.infradead.org > I agree on this. Debugfs is for debug only and should stay > that way. What do other driver in regard to this? I see this now as an example where a Manufacturer (Marvell) starts to work with the community, has a nice feature (probably bacause of customer-request) and cannot get this into the kernel because of this issue :-) Debugfs isn't suitable for anything except debugging. It is, per definition, an interface for developers that want to debug it. The idea is that a kernel for end-user devices won't even have debugfs compiled in. If libertas currently does use debugfs for something != debugging? I don't know, but than that has been a lapse, an oversight. Let's not do that oversight again. So you can use * iwpriv * sysfs * kernel module parameters * nl80211/cfg80211 * Maybe the new "stable debugfs" proposed by Rostedt (see the Article "A stable debugfs" on http://lwn.net/Articles/350463/, but here it's not even clear that this will come). For me, iwpriv seems the best candidate as long as libertas doesn't have a cfg80211/nl80211 interface. > I hardly belive that the libertas driver is the only "deep > sleep" user. I think that ATH6K WLAN devices might be candidates for this, too. If the interface is "iwpriv XXX deepsleep 0" / "iwpriv XXX deepsleep 1" I don't see a reason they could do it similar. > iwconfig has an interface for this I think: > |interface power {period N|timeout N|saving N|off} That's something very differently. -- http://www.holgerschurig.de ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-18 7:37 ` Holger Schurig @ 2009-09-18 17:37 ` Dan Williams 0 siblings, 0 replies; 14+ messages in thread From: Dan Williams @ 2009-09-18 17:37 UTC (permalink / raw) To: Holger Schurig Cc: Sebastian Andrzej Siewior, Andrey Yurovsky, Bing Zhao, Amitkumar Karwar, linux-wireless@vger.kernel.org, libertas-dev@lists.infradead.org On Fri, 2009-09-18 at 09:37 +0200, Holger Schurig wrote: > > I agree on this. Debugfs is for debug only and should stay > > that way. What do other driver in regard to this? > > I see this now as an example where a Manufacturer (Marvell) > starts to work with the community, has a nice feature (probably > bacause of customer-request) and cannot get this into the kernel > because of this issue :-) We've been over this for a long time actually. I'm the one that removed all the private vendor ioctls in the first place back in 2006 from the vendor driver. The reasons were known then, and are still the same. But Bing probably wasn't involved then, and he doesn't need to bear the brunt of that :) I'm very happy to be getting more active contributions from Marvell and we should work this sort of thing out. The major issue then was that iwpriv is a "quick fix" that is not standardized and *is* kernel API that cannot/should not change. Thus, unless it's well-designed and generic, it probably shouldn't even go in in the first place. We (Woodhouse, I, and Marcelo Tosatti) pushed back on Michail and Marvell at the time and nobody (Michail in particular) was not willing to spend the time to _do it right_ and help out with nl80211. Getting attributes Marvell wanted into nl80211 would have been fine, and still would be fine, but there's a process to follow and it will take longer than a single iwpriv patch. > Debugfs isn't suitable for anything except debugging. It is, per > definition, an interface for developers that want to debug it. > The idea is that a kernel for end-user devices won't even have > debugfs compiled in. Correct; that's the point: if we can't find a generic API to put this into, it probably shouldn't go in, because the interface hasn't been thought out well enough. Yes, that means a little more work, but it's much more maintainable in the long run. > If libertas currently does use debugfs for something != > debugging? I don't know, but than that has been a lapse, an > oversight. Let's not do that oversight again. > > > So you can use > > * iwpriv No. > * sysfs No, it's basically the same thing as iwpriv just in a file. Slightly better (since there's the rule of one-value-per-file) but not much. > * kernel module parameters No, because they usually cannot be changed at runtime. > * nl80211/cfg80211 Yes. > * Maybe the new "stable debugfs" proposed by Rostedt (see the > Article "A stable debugfs" on http://lwn.net/Articles/350463/, > but here it's not even clear that this will come). No, if the value isn't for debugging. > For me, iwpriv seems the best candidate as long as libertas > doesn't have a cfg80211/nl80211 interface. Then maybe we should convert it to cfg80211/nl80211. We should anyway. > > > > I hardly belive that the libertas driver is the only "deep > > sleep" user. > > I think that ATH6K WLAN devices might be candidates for this, > too. If the interface is "iwpriv XXX deepsleep 0" / "iwpriv XXX > deepsleep 1" I don't see a reason they could do it similar. So if libertas isn't the only user, then we can make a more generic interface for this that uses 'iw' and cfg80211. Dan > > > iwconfig has an interface for this I think: > > |interface power {period N|timeout N|saving N|off} > > That's something very differently. > > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-15 23:45 [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 Bing Zhao 2009-09-15 23:41 ` Andrey Yurovsky @ 2009-09-20 14:58 ` Dan Williams 2009-09-28 22:42 ` Bing Zhao 1 sibling, 1 reply; 14+ messages in thread From: Dan Williams @ 2009-09-20 14:58 UTC (permalink / raw) To: Bing Zhao; +Cc: libertas-dev, linux-wireless, Amitkumar Karwar On Tue, 2009-09-15 at 16:45 -0700, Bing Zhao wrote: > From: Amitkumar Karwar <akarwar@marvell.com> > > Add timer based auto deep sleep feature in libertas driver which can be > configured through debugfs interface. This is tested on SD8688, SD8686 cards > with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit > platforms. Tests have been done for USB/CS cards to make sure that the patch > won't break USB/CS code. We didn't test the if_spi driver. So there's always: #define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/ iwconfig wlan0 power saving 10 That seems quite a bit better than a new debugfs parameter, until we can conver the driver over cfg80211 and do this properly. If the power saving mode is higher than some number X, the chip gets put into deep sleep mode, or it can be automatically placed in deep sleep mode by the driver when there is no association like you have done with the timer above. I think you should pick reasonable defaults, and perhaps if the 'saving' value is larger, the timer value in the driver gets smaller. Does that sound like an OK approach? We really should be using debugfs only for debugging stuff (obviously), and the real fix for this sort of thing is to switch over to cfg80211 where we can actually extend the configuration API instead of hacking it into debugfs/WEXT/etc. Dan > Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> > Signed-off-by: Bing Zhao <bzhao@marvell.com> > --- > drivers/net/wireless/libertas/README | 28 +++++- > drivers/net/wireless/libertas/cmd.c | 72 +++++++++++++- > drivers/net/wireless/libertas/cmdresp.c | 12 +++ > drivers/net/wireless/libertas/debugfs.c | 160 +++++++++++++++++++++++++++++++ > drivers/net/wireless/libertas/decl.h | 4 + > drivers/net/wireless/libertas/dev.h | 18 ++++ > drivers/net/wireless/libertas/host.h | 1 + > drivers/net/wireless/libertas/if_cs.c | 3 + > drivers/net/wireless/libertas/if_sdio.c | 56 +++++++++++ > drivers/net/wireless/libertas/if_sdio.h | 3 +- > drivers/net/wireless/libertas/if_spi.c | 3 + > drivers/net/wireless/libertas/if_usb.c | 3 + > drivers/net/wireless/libertas/main.c | 111 +++++++++++++++++++--- > drivers/net/wireless/libertas/scan.c | 11 ++ > drivers/net/wireless/libertas/wext.c | 138 ++++++++++++++++++++++++++ > 15 files changed, 604 insertions(+), 19 deletions(-) > > diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README > index ab6a2d5..059ce8c 100644 > --- a/drivers/net/wireless/libertas/README > +++ b/drivers/net/wireless/libertas/README > @@ -1,5 +1,5 @@ > ================================================================================ > - README for USB8388 > + README for Libertas > > (c) Copyright © 2003-2006, Marvell International Ltd. > All Rights Reserved > @@ -226,4 +226,30 @@ setuserscan > All entries in the scan table (not just the new scan data when keep=1) > will be displayed upon completion by use of the getscantable ioctl. > > +deepsleep > + > + This command is used to configure the station in deep sleep mode/auto > + deep sleep mode. Command expects two parameters: > + 'state' 'idle time period' > + > + The timer is implemented to monitor the activities (command, event, > + data, etc.). When an activity is detected station will exit from deep > + sleep mode automatically and restart the timer. At timer expiry (no > + activity for defined time period) the deepsleep mode is entered > + automatically. > + > + Note: this command is for SDIO interface only. > + > + Path: /sys/kernel/debug/libertas_wireless/ethX/ > + > + Usage: > + To read the current status of deep sleep do: > + cat deepsleep > + To enable deep sleep mode do: > + echo '1 0' > deepsleep > + To enable auto deep sleep mode with idle time period 5 seconds do: > + echo '1 5000' > deepsleep > + To disable deep sleep/auto deep sleep mode do: > + echo '0 0' > deepsleep > + > ============================================================================== > diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c > index 6850981..3a3e894 100644 > --- a/drivers/net/wireless/libertas/cmd.c > +++ b/drivers/net/wireless/libertas/cmd.c > @@ -17,7 +17,6 @@ > > static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); > > - > /** > * @brief Simple callback that copies response back into command > * > @@ -319,6 +318,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, > return 0; > } > > +static int lbs_wait_for_ds_awake(struct lbs_private *priv) > +{ > + int ret = 0; > + > + lbs_deb_enter(LBS_DEB_CMD); > + > + if (priv->is_deep_sleep) { > + if (!wait_event_interruptible_timeout(priv->ds_awake_q, > + !priv->is_deep_sleep, (10 * HZ))) { > + lbs_pr_err("ds_awake_q: timer expired\n"); > + ret = -1; > + } > + } > + > + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); > + return ret; > +} > + > +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) > +{ > + int ret = 0; > + > + lbs_deb_enter(LBS_DEB_CMD); > + > + if (deep_sleep) { > + if (priv->is_deep_sleep != 1) { > + lbs_deb_cmd("deep sleep: sleep\n"); > + BUG_ON(!priv->enter_deep_sleep); > + ret = priv->enter_deep_sleep(priv); > + if (!ret) { > + netif_stop_queue(priv->dev); > + netif_carrier_off(priv->dev); > + } > + } else { > + lbs_pr_err("deep sleep: already enabled\n"); > + } > + } else { > + if (priv->is_deep_sleep) { > + lbs_deb_cmd("deep sleep: wakeup\n"); > + BUG_ON(!priv->exit_deep_sleep); > + ret = priv->exit_deep_sleep(priv); > + if (!ret) { > + ret = lbs_wait_for_ds_awake(priv); > + if (ret) > + lbs_pr_err("deep sleep: wakeup" > + "failed\n"); > + } > + } > + } > + > + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); > + return ret; > +} > + > int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, > struct assoc_request *assoc) > { > @@ -1242,8 +1295,17 @@ static void lbs_submit_command(struct lbs_private *priv, > timeo = HZ/4; > } > > - /* Setup the timer after transmit command */ > - mod_timer(&priv->command_timer, jiffies + timeo); > + 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 { > + /* Setup the timer after transmit command */ > + mod_timer(&priv->command_timer, jiffies + timeo); > + } > > lbs_deb_leave(LBS_DEB_HOST); > } > @@ -1505,6 +1567,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, > case CMD_802_11_BEACON_CTRL: > ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); > break; > + case CMD_802_11_DEEP_SLEEP: > + cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); > + cmdptr->size = cpu_to_le16(S_DS_GEN); > + break; > default: > lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); > ret = -1; > diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c > index c42d3fa..47d2b19 100644 > --- a/drivers/net/wireless/libertas/cmdresp.c > +++ b/drivers/net/wireless/libertas/cmdresp.c > @@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event) > > case MACREG_INT_CODE_HOST_AWAKE: > lbs_deb_cmd("EVENT: host awake\n"); > + if (priv->reset_deep_sleep_wakeup) > + priv->reset_deep_sleep_wakeup(priv); > + priv->is_deep_sleep = 0; > lbs_send_confirmwake(priv); > break; > > + case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: > + if (priv->reset_deep_sleep_wakeup) > + priv->reset_deep_sleep_wakeup(priv); > + lbs_deb_cmd("EVENT: ds awake\n"); > + priv->is_deep_sleep = 0; > + priv->wakeup_dev_required = 0; > + wake_up_interruptible(&priv->ds_awake_q); > + break; > + > case MACREG_INT_CODE_PS_AWAKE: > lbs_deb_cmd("EVENT: ps awake\n"); > /* handle unexpected PS AWAKE event */ > diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c > index 893a55c..624a438 100644 > --- a/drivers/net/wireless/libertas/debugfs.c > +++ b/drivers/net/wireless/libertas/debugfs.c > @@ -117,6 +117,11 @@ static ssize_t lbs_sleepparams_write(struct file *file, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out_unlock; > + } > + > buf_size = min(count, len - 1); > if (copy_from_user(buf, user_buf, buf_size)) { > ret = -EFAULT; > @@ -157,6 +162,11 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out_unlock; > + } > + > ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp); > if (ret) > goto out_unlock; > @@ -173,6 +183,118 @@ out_unlock: > return ret; > } > > +static ssize_t lbs_deepsleep_read(struct file *file, char __user *userbuf, > + size_t count, loff_t *ppos) > +{ > + struct lbs_private *priv = file->private_data; > + ssize_t pos = 0; > + int ret; > + unsigned long addr = get_zeroed_page(GFP_KERNEL); > + char *buf = (char *)addr; > + > + if (!buf) > + return -ENOMEM; > + > + if (!priv->enter_deep_sleep) { > + lbs_pr_err("deep sleep feature is not implemented " > + "for this interface driver\n"); > + ret = -EINVAL; > + goto out_ds; > + } > + > + if (priv->is_auto_deep_sleep_enabled) > + pos += snprintf(buf, len, "%d %d\n", > + priv->is_auto_deep_sleep_enabled, > + priv->auto_deep_sleep_timeout); > + else if (priv->is_deep_sleep) > + pos += snprintf(buf, len, "%d %d\n", > + priv->is_deep_sleep, > + priv->auto_deep_sleep_timeout); > + else > + pos += snprintf(buf, len, "%d %d\n", > + priv->is_deep_sleep, > + priv->auto_deep_sleep_timeout); > + > + ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); > + > +out_ds: > + free_page(addr); > + return ret; > +} > + > +static ssize_t lbs_deepsleep_write(struct file *file, > + const char __user *userbuf, > + size_t count, loff_t *ppos) > +{ > + struct lbs_private *priv = file->private_data; > + ssize_t res, buf_size; > + int is_deep_sleep, auto_deep_sleep_timeout; > + unsigned long addr = get_zeroed_page(GFP_KERNEL); > + char *buf = (char *)addr; > + > + if (!buf) > + return -ENOMEM; > + > + if (!priv->enter_deep_sleep) { > + lbs_pr_err("deep sleep feature is not implemented " > + "for this interface driver\n"); > + res = -EINVAL; > + goto out_ds; > + } > + > + if (priv->connect_status == LBS_CONNECTED) { > + lbs_pr_err("can't use deep sleep cmd in connected " > + "state\n"); > + res = -EINVAL; > + goto out_ds; > + } > + > + buf_size = min(count, len - 1); > + if (copy_from_user(buf, userbuf, buf_size)) { > + res = -EFAULT; > + goto out_ds; > + } > + > + res = sscanf(buf, "%d %d", &is_deep_sleep, &auto_deep_sleep_timeout); > + if ((res != 2) || (!is_deep_sleep && auto_deep_sleep_timeout) || > + !((is_deep_sleep == 1) || > + (is_deep_sleep == 0))) { > + lbs_pr_err("unknown option\n"); > + res = -EINVAL; > + goto out_ds; > + } > + > + if (auto_deep_sleep_timeout) { > + if (!priv->is_auto_deep_sleep_enabled) { > + priv->is_activity_detected = 0; > + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout; > + lbs_enter_auto_deep_sleep(priv); > + } else { > + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout; > + lbs_deb_debugfs("auto deep sleep: already enabled\n"); > + } > + } else { > + if (priv->is_auto_deep_sleep_enabled) { > + lbs_exit_auto_deep_sleep(priv); > + /* Try to exit deep sleep if auto deep sleep disabled */ > + res = lbs_set_deep_sleep(priv, 0); > + if (res) > + goto out_ds; > + } > + if ((is_deep_sleep == 0) || (is_deep_sleep == 1)) { > + res = lbs_set_deep_sleep(priv, is_deep_sleep); > + if (res) > + goto out_ds; > + } > + } > + > + res = count; > + > +out_ds: > + free_page(addr); > + return res; > +} > + > /* > * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might > * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the > @@ -223,6 +345,9 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask, > u8 freq; > int events = 0; > > + if (!lbs_is_cmd_allowed(priv)) > + return -EBUSY; > + > buf = (char *)get_zeroed_page(GFP_KERNEL); > if (!buf) > return -ENOMEM; > @@ -275,6 +400,9 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, > char *buf; > int ret; > > + if (!lbs_is_cmd_allowed(priv)) > + return -EBUSY; > + > buf = (char *)get_zeroed_page(GFP_KERNEL); > if (!buf) > return -ENOMEM; > @@ -444,6 +572,11 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + free_page(addr); > + return -EBUSY; > + } > + > offval.offset = priv->mac_offset; > offval.value = 0; > > @@ -496,6 +629,11 @@ static ssize_t lbs_wrmac_write(struct file *file, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + res = -EBUSY; > + goto out_unlock; > + } > + > buf_size = min(count, len - 1); > if (copy_from_user(buf, userbuf, buf_size)) { > res = -EFAULT; > @@ -532,6 +670,11 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + free_page(addr); > + return -EBUSY; > + } > + > offval.offset = priv->bbp_offset; > offval.value = 0; > > @@ -585,6 +728,11 @@ static ssize_t lbs_wrbbp_write(struct file *file, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + res = -EBUSY; > + goto out_unlock; > + } > + > buf_size = min(count, len - 1); > if (copy_from_user(buf, userbuf, buf_size)) { > res = -EFAULT; > @@ -621,6 +769,11 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + free_page(addr); > + return -EBUSY; > + } > + > offval.offset = priv->rf_offset; > offval.value = 0; > > @@ -674,6 +827,11 @@ static ssize_t lbs_wrrf_write(struct file *file, > if (!buf) > return -ENOMEM; > > + if (!lbs_is_cmd_allowed(priv)) { > + res = -EBUSY; > + goto out_unlock; > + } > + > buf_size = min(count, len - 1); > if (copy_from_user(buf, userbuf, buf_size)) { > res = -EFAULT; > @@ -717,6 +875,8 @@ static const struct lbs_debugfs_files debugfs_files[] = { > write_file_dummy), }, > { "sleepparams", 0644, FOPS(lbs_sleepparams_read, > lbs_sleepparams_write), }, > + { "deepsleep", 0644, FOPS(lbs_deepsleep_read, > + lbs_deepsleep_write), }, > }; > > static const struct lbs_debugfs_files debugfs_events_files[] = { > diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h > index 0b84bdc..34b475f 100644 > --- a/drivers/net/wireless/libertas/decl.h > +++ b/drivers/net/wireless/libertas/decl.h > @@ -33,6 +33,10 @@ int lbs_execute_next_command(struct lbs_private *priv); > int lbs_process_event(struct lbs_private *priv, u32 event); > void lbs_queue_event(struct lbs_private *priv, u32 event); > void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); > +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); > +int lbs_is_cmd_allowed(struct lbs_private *priv); > +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 578c697..e2b4ef2 100644 > --- a/drivers/net/wireless/libertas/dev.h > +++ b/drivers/net/wireless/libertas/dev.h > @@ -129,6 +129,20 @@ struct lbs_private { > u32 bbp_offset; > u32 rf_offset; > > + /** Deep sleep flag */ > + int is_deep_sleep; > + /** Auto deep sleep enabled flag */ > + int is_auto_deep_sleep_enabled; > + /** Device wakeup required flag */ > + int wakeup_dev_required; > + /** Auto deep sleep flag*/ > + int is_activity_detected; > + /** Auto deep sleep timeout (in miliseconds) */ > + int auto_deep_sleep_timeout; > + > + /** Deep sleep wait queue */ > + wait_queue_head_t ds_awake_q; > + > /* Download sent: > bit0 1/0=data_sent/data_tx_done, > bit1 1/0=cmd_sent/cmd_tx_done, > @@ -154,6 +168,9 @@ struct lbs_private { > /** Hardware access */ > int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); > void (*reset_card) (struct lbs_private *priv); > + int (*enter_deep_sleep) (struct lbs_private *priv); > + int (*exit_deep_sleep) (struct lbs_private *priv); > + int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); > > /* Wake On LAN */ > uint32_t wol_criteria; > @@ -204,6 +221,7 @@ struct lbs_private { > > /** Timers */ > struct timer_list command_timer; > + struct timer_list auto_deepsleep_timer; > int nr_retries; > int cmd_timed_out; > > diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h > index fe8f0cb..c055daa 100644 > --- a/drivers/net/wireless/libertas/host.h > +++ b/drivers/net/wireless/libertas/host.h > @@ -57,6 +57,7 @@ > #define CMD_802_11_ENABLE_RSN 0x002f > #define CMD_802_11_SET_AFC 0x003c > #define CMD_802_11_GET_AFC 0x003d > +#define CMD_802_11_DEEP_SLEEP 0x003e > #define CMD_802_11_AD_HOC_STOP 0x0040 > #define CMD_802_11_HOST_SLEEP_CFG 0x0043 > #define CMD_802_11_WAKEUP_CONFIRM 0x0044 > diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c > index 6238176..465742f 100644 > --- a/drivers/net/wireless/libertas/if_cs.c > +++ b/drivers/net/wireless/libertas/if_cs.c > @@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) > card->priv = priv; > priv->card = card; > priv->hw_host_to_card = if_cs_host_to_card; > + priv->enter_deep_sleep = NULL; > + priv->exit_deep_sleep = NULL; > + priv->reset_deep_sleep_wakeup = NULL; > priv->fw_ready = 1; > > /* Now actually get the IRQ */ > diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c > index 485a8d4..9716728 100644 > --- a/drivers/net/wireless/libertas/if_sdio.c > +++ b/drivers/net/wireless/libertas/if_sdio.c > @@ -831,6 +831,58 @@ out: > return ret; > } > > +static int if_sdio_enter_deep_sleep(struct lbs_private *priv) > +{ > + int ret = -1; > + struct cmd_header cmd; > + > + memset(&cmd, 0, sizeof(cmd)); > + > + lbs_deb_sdio("send DEEP_SLEEP command\n"); > + ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), > + lbs_cmd_copyback, (unsigned long) &cmd); > + if (ret) > + lbs_pr_err("DEEP_SLEEP cmd failed\n"); > + > + mdelay(200); > + return ret; > +} > + > +static int if_sdio_exit_deep_sleep(struct lbs_private *priv) > +{ > + struct if_sdio_card *card = priv->card; > + int ret = -1; > + > + lbs_deb_enter(LBS_DEB_SDIO); > + sdio_claim_host(card->func); > + > + sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); > + if (ret) > + lbs_pr_err("sdio_writeb failed!\n"); > + > + sdio_release_host(card->func); > + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); > + return ret; > +} > + > +static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) > +{ > + struct if_sdio_card *card = priv->card; > + int ret = -1; > + > + lbs_deb_enter(LBS_DEB_SDIO); > + sdio_claim_host(card->func); > + > + sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); > + if (ret) > + lbs_pr_err("sdio_writeb failed!\n"); > + > + sdio_release_host(card->func); > + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); > + return ret; > + > +} > + > /*******************************************************************/ > /* SDIO callbacks */ > /*******************************************************************/ > @@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func) > * Ignore the define name, this really means the card has > * successfully received the command. > */ > + card->priv->is_activity_detected = 1; > if (cause & IF_SDIO_H_INT_DNLD) > lbs_host_to_card_done(card->priv); > > @@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func, > > priv->card = card; > priv->hw_host_to_card = if_sdio_host_to_card; > + priv->enter_deep_sleep = if_sdio_enter_deep_sleep; > + priv->exit_deep_sleep = if_sdio_exit_deep_sleep; > + priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; > > priv->fw_ready = 1; > > diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h > index 60c9b2f..12179c1 100644 > --- a/drivers/net/wireless/libertas/if_sdio.h > +++ b/drivers/net/wireless/libertas/if_sdio.h > @@ -51,5 +51,6 @@ > #define IF_SDIO_EVENT 0x80fc > > #define IF_SDIO_BLOCK_SIZE 256 > - > +#define CONFIGURATION_REG 0x03 > +#define HOST_POWER_UP (0x1U << 1) > #endif > diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c > index 446e327..e2fa657 100644 > --- a/drivers/net/wireless/libertas/if_spi.c > +++ b/drivers/net/wireless/libertas/if_spi.c > @@ -1117,6 +1117,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) > card->priv = priv; > priv->card = card; > priv->hw_host_to_card = if_spi_host_to_card; > + priv->enter_deep_sleep = NULL; > + priv->exit_deep_sleep = NULL; > + priv->reset_deep_sleep_wakeup = NULL; > priv->fw_ready = 1; > > /* Initialize interrupt handling stuff. */ > diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c > index 92bc8c5..a8262de 100644 > --- a/drivers/net/wireless/libertas/if_usb.c > +++ b/drivers/net/wireless/libertas/if_usb.c > @@ -300,6 +300,9 @@ static int if_usb_probe(struct usb_interface *intf, > cardp->priv->fw_ready = 1; > > priv->hw_host_to_card = if_usb_host_to_card; > + priv->enter_deep_sleep = NULL; > + priv->exit_deep_sleep = NULL; > + priv->reset_deep_sleep_wakeup = NULL; > #ifdef CONFIG_OLPC > if (machine_is_olpc()) > priv->reset_card = if_usb_reset_olpc_card; > diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c > index 8df1cfd..3b14fcc 100644 > --- a/drivers/net/wireless/libertas/main.c > +++ b/drivers/net/wireless/libertas/main.c > @@ -574,8 +574,10 @@ void lbs_host_to_card_done(struct lbs_private *priv) > priv->dnld_sent = DNLD_RES_RECEIVED; > > /* Wake main thread if commands are pending */ > - if (!priv->cur_cmd || priv->tx_pending_len > 0) > - wake_up_interruptible(&priv->waitq); > + if (!priv->cur_cmd || priv->tx_pending_len > 0) { > + if (!priv->wakeup_dev_required) > + wake_up_interruptible(&priv->waitq); > + } > > spin_unlock_irqrestore(&priv->driver_lock, flags); > lbs_deb_leave(LBS_DEB_THREAD); > @@ -770,7 +772,8 @@ static int lbs_thread(void *data) > shouldsleep = 0; /* We have a command response */ > else if (priv->cur_cmd) > shouldsleep = 1; /* Can't send a command; one already running */ > - else if (!list_empty(&priv->cmdpendingq)) > + else if (!list_empty(&priv->cmdpendingq) && > + !(priv->wakeup_dev_required)) > shouldsleep = 0; /* We have a command to send */ > else if (__kfifo_len(priv->event_fifo)) > shouldsleep = 0; /* We have an event to process */ > @@ -822,6 +825,26 @@ static int lbs_thread(void *data) > } > spin_unlock_irq(&priv->driver_lock); > > + /* Process hardware events, e.g. card removed, link lost */ > + spin_lock_irq(&priv->driver_lock); > + while (__kfifo_len(priv->event_fifo)) { > + u32 event; > + __kfifo_get(priv->event_fifo, (unsigned char *) &event, > + sizeof(event)); > + spin_unlock_irq(&priv->driver_lock); > + lbs_process_event(priv, event); > + spin_lock_irq(&priv->driver_lock); > + } > + spin_unlock_irq(&priv->driver_lock); > + > + if (priv->wakeup_dev_required) { > + lbs_deb_thread("Waking up device...\n"); > + /* Wake up device */ > + if (priv->exit_deep_sleep(priv)) > + lbs_deb_thread("Wakeup device failed\n"); > + continue; > + } > + > /* command timeout stuff */ > if (priv->cmd_timed_out && priv->cur_cmd) { > struct cmd_ctrl_node *cmdnode = priv->cur_cmd; > @@ -849,18 +872,7 @@ static int lbs_thread(void *data) > } > priv->cmd_timed_out = 0; > > - /* Process hardware events, e.g. card removed, link lost */ > - spin_lock_irq(&priv->driver_lock); > - while (__kfifo_len(priv->event_fifo)) { > - u32 event; > > - __kfifo_get(priv->event_fifo, (unsigned char *) &event, > - sizeof(event)); > - spin_unlock_irq(&priv->driver_lock); > - lbs_process_event(priv, event); > - spin_lock_irq(&priv->driver_lock); > - } > - spin_unlock_irq(&priv->driver_lock); > > if (!priv->fw_ready) > continue; > @@ -894,6 +906,9 @@ static int lbs_thread(void *data) > (priv->psstate == PS_STATE_PRE_SLEEP)) > continue; > > + if (priv->is_deep_sleep) > + continue; > + > /* Execute the next command */ > if (!priv->dnld_sent && !priv->cur_cmd) > lbs_execute_next_command(priv); > @@ -928,6 +943,7 @@ static int lbs_thread(void *data) > } > > del_timer(&priv->command_timer); > + del_timer(&priv->auto_deepsleep_timer); > wake_up_all(&priv->cmd_pending); > > lbs_deb_leave(LBS_DEB_THREAD); > @@ -1050,6 +1066,60 @@ out: > lbs_deb_leave(LBS_DEB_CMD); > } > > +/** > + * This function put the device back to deep sleep mode when timer expires > + * and no activity (command, event, data etc.) is detected. > + */ > +static void auto_deepsleep_timer_fn(unsigned long data) > +{ > + struct lbs_private *priv = (struct lbs_private *)data; > + int ret; > + > + 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)) { > + lbs_deb_main("Entering auto deep sleep mode...\n"); > + ret = lbs_prepare_and_send_command(priv, > + CMD_802_11_DEEP_SLEEP, 0, > + 0, 0, NULL); > + } > + } > + 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 void lbs_sync_channel_worker(struct work_struct *work) > { > struct lbs_private *priv = container_of(work, struct lbs_private, > @@ -1099,11 +1169,17 @@ static int lbs_init_adapter(struct lbs_private *priv) > priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; > priv->psmode = LBS802_11POWERMODECAM; > priv->psstate = PS_STATE_FULL_POWER; > + priv->is_deep_sleep = 0; > + priv->is_auto_deep_sleep_enabled = 0; > + priv->wakeup_dev_required = 0; > + init_waitqueue_head(&priv->ds_awake_q); > > mutex_init(&priv->lock); > > setup_timer(&priv->command_timer, command_timer_fn, > (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); > @@ -1142,6 +1218,7 @@ static void lbs_free_adapter(struct lbs_private *priv) > if (priv->event_fifo) > kfifo_free(priv->event_fifo); > del_timer(&priv->command_timer); > + del_timer(&priv->auto_deepsleep_timer); > kfree(priv->networks); > priv->networks = NULL; > > @@ -1272,6 +1349,11 @@ void lbs_remove_card(struct lbs_private *priv) > wrqu.ap_addr.sa_family = ARPHRD_ETHER; > wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); > > + if (priv->is_deep_sleep) { > + priv->is_deep_sleep = 0; > + wake_up_interruptible(&priv->ds_awake_q); > + } > + > /* Stop the thread servicing the interrupts */ > priv->surpriseremoved = 1; > kthread_stop(priv->main_thread); > @@ -1392,6 +1474,7 @@ 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); > diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c > index 6c95af3..e468e15 100644 > --- a/drivers/net/wireless/libertas/scan.c > +++ b/drivers/net/wireless/libertas/scan.c > @@ -950,6 +950,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > if (!priv->radio_on) { > ret = -EINVAL; > goto out; > @@ -1017,6 +1022,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + err = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); > + return err; > + } > + > /* iwlist should wait until the current scan is finished */ > if (priv->scan_channel) > return -EAGAIN; > diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c > index be837a0..ef2b986 100644 > --- a/drivers/net/wireless/libertas/wext.c > +++ b/drivers/net/wireless/libertas/wext.c > @@ -45,6 +45,31 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv) > priv->pending_assoc_req = NULL; > } > > +/** > + * @brief This function checks if the command is allowed. > + * > + * @param priv A pointer to lbs_private structure > + * @return allowed or not allowed. > + */ > + > +int lbs_is_cmd_allowed(struct lbs_private *priv) > +{ > + int ret = 1; > + > + lbs_deb_enter(LBS_DEB_WEXT); > + > + if (!priv->is_auto_deep_sleep_enabled) { > + if (priv->is_deep_sleep) { > + lbs_deb_wext("IOCTLS called when station" > + "is in deep sleep\n"); > + ret = 0; > + } > + } > + > + lbs_deb_leave(LBS_DEB_WEXT); > + return ret; > +} > + > > /** > * @brief Find the channel frequency power info with specific channel > @@ -168,6 +193,11 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + lbs_deb_leave(LBS_DEB_WEXT); > + return -EBUSY; > + } > + > cfp = lbs_find_cfp_by_band_and_channel(priv, 0, > priv->curbssparams.channel); > > @@ -278,6 +308,12 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > if (vwrq->disabled) > val = MRVDRV_RTS_MAX_VALUE; > > @@ -299,6 +335,11 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val); > if (ret) > goto out; > @@ -321,6 +362,12 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > if (vwrq->disabled) > val = MRVDRV_FRAG_MAX_VALUE; > > @@ -342,6 +389,11 @@ static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val); > if (ret) > goto out; > @@ -391,6 +443,11 @@ static int lbs_get_txpow(struct net_device *dev, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > if (!priv->radio_on) { > lbs_deb_wext("tx power off\n"); > vwrq->value = 0; > @@ -424,6 +481,11 @@ static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) > return -EOPNOTSUPP; > > @@ -472,6 +534,11 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > vwrq->disabled = 0; > > if (vwrq->flags & IW_RETRY_LONG) { > @@ -712,6 +779,11 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + lbs_deb_leave(LBS_DEB_WEXT); > + return -EBUSY; > + } > + > if (!(priv->fwcapinfo & FW_CAPINFO_PS)) { > if (vwrq->disabled) > return 0; > @@ -792,6 +864,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) > + return NULL; > + > priv->wstats.status = priv->mode; > > /* If we're not associated, all quality values are meaningless */ > @@ -892,6 +967,12 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > mutex_lock(&priv->lock); > assoc_req = lbs_get_association_request(priv); > if (!assoc_req) { > @@ -1000,6 +1081,12 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, > u8 rates[MAX_RATES + 1]; > > lbs_deb_enter(LBS_DEB_WEXT); > + > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > lbs_deb_wext("vwrq->value %d\n", vwrq->value); > lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); > > @@ -1058,6 +1145,11 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + lbs_deb_leave(LBS_DEB_WEXT); > + return -EBUSY; > + } > + > if (priv->connect_status == LBS_CONNECTED) { > vwrq->value = priv->cur_rate * 500000; > > @@ -1084,6 +1176,11 @@ static int lbs_set_mode(struct net_device *dev, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > if ( (*uwrq != IW_MODE_ADHOC) > && (*uwrq != IW_MODE_INFRA) > && (*uwrq != IW_MODE_AUTO)) { > @@ -1325,6 +1422,12 @@ static int lbs_set_encode(struct net_device *dev, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > mutex_lock(&priv->lock); > assoc_req = lbs_get_association_request(priv); > if (!assoc_req) { > @@ -1508,6 +1611,12 @@ static int lbs_set_encodeext(struct net_device *dev, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > mutex_lock(&priv->lock); > assoc_req = lbs_get_association_request(priv); > if (!assoc_req) { > @@ -1720,6 +1829,12 @@ static int lbs_set_auth(struct net_device *dev, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > mutex_lock(&priv->lock); > assoc_req = lbs_get_association_request(priv); > if (!assoc_req) { > @@ -1822,6 +1937,12 @@ static int lbs_get_auth(struct net_device *dev, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > switch (dwrq->flags & IW_AUTH_INDEX) { > case IW_AUTH_KEY_MGMT: > dwrq->value = priv->secinfo.key_mgmt; > @@ -1864,6 +1985,11 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + goto out; > + } > + > if (vwrq->disabled) { > lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0); > goto out; > @@ -1983,6 +2109,12 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > if (!priv->radio_on) { > ret = -EINVAL; > goto out; > @@ -2110,6 +2242,12 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, > > lbs_deb_enter(LBS_DEB_WEXT); > > + if (!lbs_is_cmd_allowed(priv)) { > + ret = -EBUSY; > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > + return ret; > + } > + > if (!priv->radio_on) > return -EINVAL; > ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-20 14:58 ` Dan Williams @ 2009-09-28 22:42 ` Bing Zhao 2009-09-29 7:04 ` Holger Schurig ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: Bing Zhao @ 2009-09-28 22:42 UTC (permalink / raw) To: Dan Williams Cc: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar SGkgRGFuLA0KDQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IERhbiBXaWxs aWFtcyBbbWFpbHRvOmRjYndAcmVkaGF0LmNvbV0NCj4gU2VudDogU3VuZGF5LCBTZXB0ZW1iZXIg MjAsIDIwMDkgNzo1OCBBTQ0KPiBUbzogQmluZyBaaGFvDQo+IENjOiBsaWJlcnRhcy1kZXZAbGlz dHMuaW5mcmFkZWFkLm9yZzsgbGludXgtd2lyZWxlc3NAdmdlci5rZXJuZWwub3JnOyBBbWl0a3Vt YXIgS2Fyd2FyDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0hdIGxpYmVydGFzOiBBZGQgYXV0byBkZWVw IHNsZWVwIHN1cHBvcnQgZm9yIFNEODM4NS9TRDg2ODYvU0Q4Njg4DQo+DQo+IE9uIFR1ZSwgMjAw OS0wOS0xNSBhdCAxNjo0NSAtMDcwMCwgQmluZyBaaGFvIHdyb3RlOg0KPiA+IEZyb206IEFtaXRr dW1hciBLYXJ3YXIgPGFrYXJ3YXJAbWFydmVsbC5jb20+DQo+ID4NCj4gPiBBZGQgdGltZXIgYmFz ZWQgYXV0byBkZWVwIHNsZWVwIGZlYXR1cmUgaW4gbGliZXJ0YXMgZHJpdmVyIHdoaWNoIGNhbiBi ZQ0KPiA+IGNvbmZpZ3VyZWQgdGhyb3VnaCBkZWJ1Z2ZzIGludGVyZmFjZS4gVGhpcyBpcyB0ZXN0 ZWQgb24gU0Q4Njg4LCBTRDg2ODYgY2FyZHMNCj4gPiB3aXRoIGZpcm13YXJlIHZlcnNpb25zIDEw LjM4LjEucDI1LCA5LjcwLjQucDAgcmVzcGVjdGl2ZWx5IG9uIDMyLWJpdCBhbmQgNjQtYml0DQo+ ID4gcGxhdGZvcm1zLiBUZXN0cyBoYXZlIGJlZW4gZG9uZSBmb3IgVVNCL0NTIGNhcmRzIHRvIG1h a2Ugc3VyZSB0aGF0IHRoZSBwYXRjaA0KPiA+IHdvbid0IGJyZWFrIFVTQi9DUyBjb2RlLiBXZSBk aWRuJ3QgdGVzdCB0aGUgaWZfc3BpIGRyaXZlci4NCj4NCj4gU28gdGhlcmUncyBhbHdheXM6DQo+ DQo+ICNkZWZpbmUgSVdfUE9XRVJfU0FWSU5HICAgICAgICAgICAgICAgMHg0MDAwICAvKiBWYWx1 ZSBpcyByZWxhdGl2ZSAoaG93IGFnZ3Jlc3NpdmUpKi8NCj4NCj4gaXdjb25maWcgd2xhbjAgcG93 ZXIgc2F2aW5nIDEwDQo+DQo+IFRoYXQgc2VlbXMgcXVpdGUgYSBiaXQgYmV0dGVyIHRoYW4gYSBu ZXcgZGVidWdmcyBwYXJhbWV0ZXIsIHVudGlsIHdlIGNhbg0KPiBjb252ZXIgdGhlIGRyaXZlciBv dmVyIGNmZzgwMjExIGFuZCBkbyB0aGlzIHByb3Blcmx5LiAgSWYgdGhlIHBvd2VyDQo+IHNhdmlu ZyBtb2RlIGlzIGhpZ2hlciB0aGFuIHNvbWUgbnVtYmVyIFgsIHRoZSBjaGlwIGdldHMgcHV0IGlu dG8gZGVlcA0KPiBzbGVlcCBtb2RlLCBvciBpdCBjYW4gYmUgYXV0b21hdGljYWxseSBwbGFjZWQg aW4gZGVlcCBzbGVlcCBtb2RlIGJ5IHRoZQ0KPiBkcml2ZXIgd2hlbiB0aGVyZSBpcyBubyBhc3Nv Y2lhdGlvbiBsaWtlIHlvdSBoYXZlIGRvbmUgd2l0aCB0aGUgdGltZXINCj4gYWJvdmUuICBJIHRo aW5rIHlvdSBzaG91bGQgcGljayByZWFzb25hYmxlIGRlZmF1bHRzLCBhbmQgcGVyaGFwcyBpZiB0 aGUNCj4gJ3NhdmluZycgdmFsdWUgaXMgbGFyZ2VyLCB0aGUgdGltZXIgdmFsdWUgaW4gdGhlIGRy aXZlciBnZXRzIHNtYWxsZXIuDQo+DQo+IERvZXMgdGhhdCBzb3VuZCBsaWtlIGFuIE9LIGFwcHJv YWNoPyAgV2UgcmVhbGx5IHNob3VsZCBiZSB1c2luZyBkZWJ1Z2ZzDQo+IG9ubHkgZm9yIGRlYnVn Z2luZyBzdHVmZiAob2J2aW91c2x5KSwgYW5kIHRoZSByZWFsIGZpeCBmb3IgdGhpcyBzb3J0IG9m DQo+IHRoaW5nIGlzIHRvIHN3aXRjaCBvdmVyIHRvIGNmZzgwMjExIHdoZXJlIHdlIGNhbiBhY3R1 YWxseSBleHRlbmQgdGhlDQo+IGNvbmZpZ3VyYXRpb24gQVBJIGluc3RlYWQgb2YgaGFja2luZyBp dCBpbnRvIGRlYnVnZnMvV0VYVC9ldGMuDQo+DQo+IERhbg0KDQpUaGFua3MgZm9yIHlvdXIgc3Vn Z2VzdGlvbi4NCg0KSW4gbGF0ZXN0IGtlcm5lbCwgSVdfUE9XRVJfU0FWSU5HIGlzIG5vdCBkZWZp bmVkIGluIGluY2x1ZGUvbGludXgvd2lyZWxlc3MuaC4NCklXX1BPV0VSX1BFUklPRCBhbmQgSVdf UE9XRVJfVElNRU9VVCBhcmUgZGVmaW5lZCB0aG91Z2guDQoNCldlIGFyZSBwbGFubmluZyB0byBy ZW1vdmUgZGVidWdmcyBmb3IgY29uZmlndXJhdGlvbnMgYW5kIHVzZSB0aGUgZm9sbG93aW5nIGNv bW1hbmRzIGluc3RlYWQuDQpQbGVhc2UgbGV0IHVzIGtub3cgaWYgdGhlcmUgaXMgYW55IGNvbmNl cm4uDQoNCml3Y29uZmlnIHdsYW4wIHBvd2VyIHBlcmlvZCAwICAgLT4gZW5hYmxlIGRlZXAgc2xl ZXAgKGVudGVyIGRlZXAgc2xlZXAgaW1tZWRpYXRlbHkpDQppd2NvbmZpZyB3bGFuMCBwb3dlciBw ZXJpb2QgNSAgIC0+IGVuYWJsZSBhdXRvIGRlZXAgc2xlZXAgKGVudGVyIGRlZXAgc2xlZXAgYXV0 b21hdGljYWxseSBhZnRlciA1cyBpZGxlIHRpbWUpDQppd2NvbmZpZyB3bGFuMCBwb3dlciBwZXJp b2QgLTEgIC0+IGRpc2FibGUgZGVlcCBzbGVlcCAvIGF1dG8gZGVlcCBzbGVlcA0KDQpCeSB0aGUg d2F5LCB0aGVyZSBpcyBhIGJ1ZyBpbiBpd2NvbmZpZyB0b29sIHYyOS4gSXQgZG9lc27igJl0IHRh a2UgYW55IHZhbHVlcyByaWdodCBhZnRlciAicGVyaW9kIiBvciAidGltZW91dCIuIFRoZSBuZXcg dmVyc2lvbiBvZiBXaXJlbGVzcyBUb29scyB2MzAtcHJlOCAobGluayBiZWxvdykgZml4ZWQgdGhl IGJ1ZzoNCg0KaHR0cDovL3d3dy5ocGwuaHAuY29tL3BlcnNvbmFsL0plYW5fVG91cnJpbGhlcy9M aW51eC93aXJlbGVzc190b29scy4zMC5wcmU4LnRhci5neg0KDQpUaGFua3MsDQoNCkJpbmcNCg0K Pg0KPiA+IFNpZ25lZC1vZmYtYnk6IEFtaXRrdW1hciBLYXJ3YXIgPGFrYXJ3YXJAbWFydmVsbC5j b20+DQo+ID4gU2lnbmVkLW9mZi1ieTogQmluZyBaaGFvIDxiemhhb0BtYXJ2ZWxsLmNvbT4NCj4g PiAtLS0NCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvUkVBRE1FICAgIHwgICAy OCArKysrKy0NCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvY21kLmMgICAgIHwg ICA3MiArKysrKysrKysrKysrLQ0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9j bWRyZXNwLmMgfCAgIDEyICsrKw0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9k ZWJ1Z2ZzLmMgfCAgMTYwICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gPiAgZHJp dmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGVjbC5oICAgIHwgICAgNCArDQo+ID4gIGRyaXZl cnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2Rldi5oICAgICB8ICAgMTggKysrKw0KPiA+ICBkcml2 ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9ob3N0LmggICAgfCAgICAxICsNCj4gPiAgZHJpdmVy cy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfY3MuYyAgIHwgICAgMyArDQo+ID4gIGRyaXZlcnMv bmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3NkaW8uYyB8ICAgNTYgKysrKysrKysrKysNCj4gPiAg ZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc2Rpby5oIHwgICAgMyArLQ0KPiA+ICBk cml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9zcGkuYyAgfCAgICAzICsNCj4gPiAgZHJp dmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfdXNiLmMgIHwgICAgMyArDQo+ID4gIGRyaXZl cnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL21haW4uYyAgICB8ICAxMTEgKysrKysrKysrKysrKysr KysrKy0tLQ0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9zY2FuLmMgICAgfCAg IDExICsrDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL3dleHQuYyAgICB8ICAx MzggKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gPiAgMTUgZmlsZXMgY2hhbmdlZCwgNjA0 IGluc2VydGlvbnMoKyksIDE5IGRlbGV0aW9ucygtKQ0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2Ry aXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL1JFQURNRSBiL2RyaXZlcnMvbmV0L3dpcmVsZXNz L2xpYmVydGFzL1JFQURNRQ0KPiA+IGluZGV4IGFiNmEyZDUuLjA1OWNlOGMgMTAwNjQ0DQo+ID4g LS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvUkVBRE1FDQo+ID4gKysrIGIvZHJp dmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvUkVBRE1FDQo+ID4gQEAgLTEsNSArMSw1IEBADQo+ ID4gID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09DQo+ID4gLSAgICAgICAgICAgICAgICAgICBSRUFE TUUgZm9yIFVTQjgzODgNCj4gPiArICAgICAgICAgICAgICAgICAgIFJFQURNRSBmb3IgTGliZXJ0 YXMNCj4gPg0KPiA+ICAgKGMpIENvcHlyaWdodCDCqSAyMDAzLTIwMDYsIE1hcnZlbGwgSW50ZXJu YXRpb25hbCBMdGQuDQo+ID4gICBBbGwgUmlnaHRzIFJlc2VydmVkDQo+ID4gQEAgLTIyNiw0ICsy MjYsMzAgQEAgc2V0dXNlcnNjYW4NCj4gPiAgICAgIEFsbCBlbnRyaWVzIGluIHRoZSBzY2FuIHRh YmxlIChub3QganVzdCB0aGUgbmV3IHNjYW4gZGF0YSB3aGVuIGtlZXA9MSkNCj4gPiAgICAgIHdp bGwgYmUgZGlzcGxheWVkIHVwb24gY29tcGxldGlvbiBieSB1c2Ugb2YgdGhlIGdldHNjYW50YWJs ZSBpb2N0bC4NCj4gPg0KPiA+ICtkZWVwc2xlZXANCj4gPiArDQo+ID4gKyAgIFRoaXMgY29tbWFu ZCBpcyB1c2VkIHRvIGNvbmZpZ3VyZSB0aGUgc3RhdGlvbiBpbiBkZWVwIHNsZWVwIG1vZGUvYXV0 bw0KPiA+ICsgICBkZWVwIHNsZWVwIG1vZGUuIENvbW1hbmQgZXhwZWN0cyB0d28gcGFyYW1ldGVy czoNCj4gPiArICAgJ3N0YXRlJyAnaWRsZSB0aW1lIHBlcmlvZCcNCj4gPiArDQo+ID4gKyAgIFRo ZSB0aW1lciBpcyBpbXBsZW1lbnRlZCB0byBtb25pdG9yIHRoZSBhY3Rpdml0aWVzIChjb21tYW5k LCBldmVudCwNCj4gPiArICAgICAgICBkYXRhLCBldGMuKS4gV2hlbiBhbiBhY3Rpdml0eSBpcyBk ZXRlY3RlZCBzdGF0aW9uIHdpbGwgZXhpdCBmcm9tIGRlZXANCj4gPiArICAgICAgICBzbGVlcCBt b2RlIGF1dG9tYXRpY2FsbHkgYW5kIHJlc3RhcnQgdGhlIHRpbWVyLiBBdCB0aW1lciBleHBpcnkg KG5vDQo+ID4gKyAgICAgICAgYWN0aXZpdHkgZm9yIGRlZmluZWQgdGltZSBwZXJpb2QpIHRoZSBk ZWVwc2xlZXAgbW9kZSBpcyBlbnRlcmVkDQo+ID4gKyAgICAgICAgYXV0b21hdGljYWxseS4NCj4g PiArDQo+ID4gKyAgIE5vdGU6IHRoaXMgY29tbWFuZCBpcyBmb3IgU0RJTyBpbnRlcmZhY2Ugb25s eS4NCj4gPiArDQo+ID4gKyAgIFBhdGg6IC9zeXMva2VybmVsL2RlYnVnL2xpYmVydGFzX3dpcmVs ZXNzL2V0aFgvDQo+ID4gKw0KPiA+ICsgICBVc2FnZToNCj4gPiArICAgVG8gcmVhZCB0aGUgY3Vy cmVudCBzdGF0dXMgb2YgZGVlcCBzbGVlcCBkbzoNCj4gPiArICAgICAgICAgICBjYXQgZGVlcHNs ZWVwDQo+ID4gKyAgIFRvIGVuYWJsZSBkZWVwIHNsZWVwIG1vZGUgZG86DQo+ID4gKyAgICAgICAg ICAgZWNobyAnMSAwJyA+IGRlZXBzbGVlcA0KPiA+ICsgICBUbyBlbmFibGUgYXV0byBkZWVwIHNs ZWVwIG1vZGUgd2l0aCBpZGxlIHRpbWUgcGVyaW9kIDUgc2Vjb25kcyBkbzoNCj4gPiArICAgICAg ICAgICBlY2hvICcxIDUwMDAnID4gZGVlcHNsZWVwDQo+ID4gKyAgIFRvIGRpc2FibGUgZGVlcCBz bGVlcC9hdXRvIGRlZXAgc2xlZXAgbW9kZSBkbzoNCj4gPiArICAgICAgICAgICBlY2hvICcwIDAn ID4gZGVlcHNsZWVwDQo+ID4gKw0KPiA+ICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCj4gPiBkaWZm IC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvY21kLmMgYi9kcml2ZXJzL25l dC93aXJlbGVzcy9saWJlcnRhcy9jbWQuYw0KPiA+IGluZGV4IDY4NTA5ODEuLjNhM2U4OTQgMTAw NjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvY21kLmMNCj4gPiAr KysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWQuYw0KPiA+IEBAIC0xNyw3ICsx Nyw2IEBADQo+ID4NCj4gPiAgc3RhdGljIHN0cnVjdCBjbWRfY3RybF9ub2RlICpsYnNfZ2V0X2Nt ZF9jdHJsX25vZGUoc3RydWN0IGxic19wcml2YXRlICpwcml2KTsNCj4gPg0KPiA+IC0NCj4gPiAg LyoqDQo+ID4gICAqICBAYnJpZWYgU2ltcGxlIGNhbGxiYWNrIHRoYXQgY29waWVzIHJlc3BvbnNl IGJhY2sgaW50byBjb21tYW5kDQo+ID4gICAqDQo+ID4gQEAgLTMxOSw2ICszMTgsNjAgQEAgaW50 IGxic19jbWRfODAyXzExX3NsZWVwX3BhcmFtcyhzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYsIHVp bnQxNl90IGNtZF9hY3Rpb24sDQo+ID4gICAgIHJldHVybiAwOw0KPiA+ICB9DQo+ID4NCj4gPiAr c3RhdGljIGludCBsYnNfd2FpdF9mb3JfZHNfYXdha2Uoc3RydWN0IGxic19wcml2YXRlICpwcml2 KQ0KPiA+ICt7DQo+ID4gKyAgIGludCByZXQgPSAwOw0KPiA+ICsNCj4gPiArICAgbGJzX2RlYl9l bnRlcihMQlNfREVCX0NNRCk7DQo+ID4gKw0KPiA+ICsgICBpZiAocHJpdi0+aXNfZGVlcF9zbGVl cCkgew0KPiA+ICsgICAgICAgICAgIGlmICghd2FpdF9ldmVudF9pbnRlcnJ1cHRpYmxlX3RpbWVv dXQocHJpdi0+ZHNfYXdha2VfcSwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAhcHJpdi0+aXNfZGVlcF9zbGVlcCwgKDEwICogSFopKSkgew0KPiA+ICsgICAgICAgICAg ICAgICAgICAgbGJzX3ByX2VycigiZHNfYXdha2VfcTogdGltZXIgZXhwaXJlZFxuIik7DQo+ID4g KyAgICAgICAgICAgICAgICAgICByZXQgPSAtMTsNCj4gPiArICAgICAgICAgICB9DQo+ID4gKyAg IH0NCj4gPiArDQo+ID4gKyAgIGxic19kZWJfbGVhdmVfYXJncyhMQlNfREVCX0NNRCwgInJldCAl ZCIsIHJldCk7DQo+ID4gKyAgIHJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK2ludCBs YnNfc2V0X2RlZXBfc2xlZXAoc3RydWN0IGxic19wcml2YXRlICpwcml2LCBpbnQgZGVlcF9zbGVl cCkNCj4gPiArew0KPiA+ICsgICBpbnQgcmV0ID0gIDA7DQo+ID4gKw0KPiA+ICsgICBsYnNfZGVi X2VudGVyKExCU19ERUJfQ01EKTsNCj4gPiArDQo+ID4gKyAgIGlmIChkZWVwX3NsZWVwKSB7DQo+ ID4gKyAgICAgICAgICAgaWYgKHByaXYtPmlzX2RlZXBfc2xlZXAgIT0gMSkgew0KPiA+ICsgICAg ICAgICAgICAgICAgICAgbGJzX2RlYl9jbWQoImRlZXAgc2xlZXA6IHNsZWVwXG4iKTsNCj4gPiAr ICAgICAgICAgICAgICAgICAgIEJVR19PTighcHJpdi0+ZW50ZXJfZGVlcF9zbGVlcCk7DQo+ID4g KyAgICAgICAgICAgICAgICAgICByZXQgPSBwcml2LT5lbnRlcl9kZWVwX3NsZWVwKHByaXYpOw0K PiA+ICsgICAgICAgICAgICAgICAgICAgaWYgKCFyZXQpIHsNCj4gPiArICAgICAgICAgICAgICAg ICAgICAgICAgICAgbmV0aWZfc3RvcF9xdWV1ZShwcml2LT5kZXYpOw0KPiA+ICsgICAgICAgICAg ICAgICAgICAgICAgICAgICBuZXRpZl9jYXJyaWVyX29mZihwcml2LT5kZXYpOw0KPiA+ICsgICAg ICAgICAgICAgICAgICAgfQ0KPiA+ICsgICAgICAgICAgIH0gZWxzZSB7DQo+ID4gKyAgICAgICAg ICAgICAgICAgICBsYnNfcHJfZXJyKCJkZWVwIHNsZWVwOiBhbHJlYWR5IGVuYWJsZWRcbiIpOw0K PiA+ICsgICAgICAgICAgIH0NCj4gPiArICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAgICBpZiAo cHJpdi0+aXNfZGVlcF9zbGVlcCkgew0KPiA+ICsgICAgICAgICAgICAgICAgICAgbGJzX2RlYl9j bWQoImRlZXAgc2xlZXA6IHdha2V1cFxuIik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBCVUdf T04oIXByaXYtPmV4aXRfZGVlcF9zbGVlcCk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICByZXQg PSBwcml2LT5leGl0X2RlZXBfc2xlZXAocHJpdik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBp ZiAoIXJldCkgew0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICByZXQgPSBsYnNfd2Fp dF9mb3JfZHNfYXdha2UocHJpdik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgIGlm IChyZXQpDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGJzX3ByX2Vy cigiZGVlcCBzbGVlcDogd2FrZXVwIg0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAiZmFpbGVkXG4iKTsNCj4gPiArICAgICAgICAgICAgICAg ICAgIH0NCj4gPiArICAgICAgICAgICB9DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gKyAgIGxic19k ZWJfbGVhdmVfYXJncyhMQlNfREVCX0NNRCwgInJldCAlZCIsIHJldCk7DQo+ID4gKyAgIHJldHVy biByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gIGludCBsYnNfY21kXzgwMl8xMV9zZXRfd2VwKHN0 cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdiwgdWludDE2X3QgY21kX2FjdGlvbiwNCj4gPiAgICAgICAg ICAgICAgICAgICAgICAgIHN0cnVjdCBhc3NvY19yZXF1ZXN0ICphc3NvYykNCj4gPiAgew0KPiA+ IEBAIC0xMjQyLDggKzEyOTUsMTcgQEAgc3RhdGljIHZvaWQgbGJzX3N1Ym1pdF9jb21tYW5kKHN0 cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdiwNCj4gPiAgICAgICAgICAgICB0aW1lbyA9IEhaLzQ7DQo+ ID4gICAgIH0NCj4gPg0KPiA+IC0gICAvKiBTZXR1cCB0aGUgdGltZXIgYWZ0ZXIgdHJhbnNtaXQg Y29tbWFuZCAqLw0KPiA+IC0gICBtb2RfdGltZXIoJnByaXYtPmNvbW1hbmRfdGltZXIsIGppZmZp ZXMgKyB0aW1lbyk7DQo+ID4gKyAgIGlmIChjb21tYW5kID09IENNRF84MDJfMTFfREVFUF9TTEVF UCkgew0KPiA+ICsgICAgICAgICAgIGlmIChwcml2LT5pc19hdXRvX2RlZXBfc2xlZXBfZW5hYmxl ZCkgew0KPiA+ICsgICAgICAgICAgICAgICAgICAgcHJpdi0+d2FrZXVwX2Rldl9yZXF1aXJlZCA9 IDE7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBwcml2LT5kbmxkX3NlbnQgPSAwOw0KPiA+ICsg ICAgICAgICAgIH0NCj4gPiArICAgICAgICAgICBwcml2LT5pc19kZWVwX3NsZWVwID0gMTsNCj4g PiArICAgICAgICAgICBsYnNfY29tcGxldGVfY29tbWFuZChwcml2LCBjbWRub2RlLCAwKTsNCj4g PiArICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAgICAvKiBTZXR1cCB0aGUgdGltZXIgYWZ0ZXIg dHJhbnNtaXQgY29tbWFuZCAqLw0KPiA+ICsgICAgICAgICAgIG1vZF90aW1lcigmcHJpdi0+Y29t bWFuZF90aW1lciwgamlmZmllcyArIHRpbWVvKTsNCj4gPiArICAgfQ0KPiA+DQo+ID4gICAgIGxi c19kZWJfbGVhdmUoTEJTX0RFQl9IT1NUKTsNCj4gPiAgfQ0KPiA+IEBAIC0xNTA1LDYgKzE1Njcs MTAgQEAgaW50IGxic19wcmVwYXJlX2FuZF9zZW5kX2NvbW1hbmQoc3RydWN0IGxic19wcml2YXRl ICpwcml2LA0KPiA+ICAgICBjYXNlIENNRF84MDJfMTFfQkVBQ09OX0NUUkw6DQo+ID4gICAgICAg ICAgICAgcmV0ID0gbGJzX2NtZF9iY25fY3RybChwcml2LCBjbWRwdHIsIGNtZF9hY3Rpb24pOw0K PiA+ICAgICAgICAgICAgIGJyZWFrOw0KPiA+ICsgICBjYXNlIENNRF84MDJfMTFfREVFUF9TTEVF UDoNCj4gPiArICAgICAgICAgICBjbWRwdHItPmNvbW1hbmQgPSBjcHVfdG9fbGUxNihDTURfODAy XzExX0RFRVBfU0xFRVApOw0KPiA+ICsgICAgICAgICAgIGNtZHB0ci0+c2l6ZSA9IGNwdV90b19s ZTE2KFNfRFNfR0VOKTsNCj4gPiArICAgICAgICAgICBicmVhazsNCj4gPiAgICAgZGVmYXVsdDoN Cj4gPiAgICAgICAgICAgICBsYnNfcHJfZXJyKCJQUkVQX0NNRDogdW5rbm93biBjb21tYW5kIDB4 JTA0eFxuIiwgY21kX25vKTsNCj4gPiAgICAgICAgICAgICByZXQgPSAtMTsNCj4gPiBkaWZmIC0t Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvY21kcmVzcC5jIGIvZHJpdmVycy9u ZXQvd2lyZWxlc3MvbGliZXJ0YXMvY21kcmVzcC5jDQo+ID4gaW5kZXggYzQyZDNmYS4uNDdkMmIx OSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWRyZXNw LmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWRyZXNwLmMNCj4g PiBAQCAtNTA0LDkgKzUwNCwyMSBAQCBpbnQgbGJzX3Byb2Nlc3NfZXZlbnQoc3RydWN0IGxic19w cml2YXRlICpwcml2LCB1MzIgZXZlbnQpDQo+ID4NCj4gPiAgICAgY2FzZSBNQUNSRUdfSU5UX0NP REVfSE9TVF9BV0FLRToNCj4gPiAgICAgICAgICAgICBsYnNfZGViX2NtZCgiRVZFTlQ6IGhvc3Qg YXdha2VcbiIpOw0KPiA+ICsgICAgICAgICAgIGlmIChwcml2LT5yZXNldF9kZWVwX3NsZWVwX3dh a2V1cCkNCj4gPiArICAgICAgICAgICAgICAgICAgIHByaXYtPnJlc2V0X2RlZXBfc2xlZXBfd2Fr ZXVwKHByaXYpOw0KPiA+ICsgICAgICAgICAgIHByaXYtPmlzX2RlZXBfc2xlZXAgPSAwOw0KPiA+ ICAgICAgICAgICAgIGxic19zZW5kX2NvbmZpcm13YWtlKHByaXYpOw0KPiA+ICAgICAgICAgICAg IGJyZWFrOw0KPiA+DQo+ID4gKyAgIGNhc2UgTUFDUkVHX0lOVF9DT0RFX0RFRVBfU0xFRVBfQVdB S0U6DQo+ID4gKyAgICAgICAgICAgaWYgKHByaXYtPnJlc2V0X2RlZXBfc2xlZXBfd2FrZXVwKQ0K PiA+ICsgICAgICAgICAgICAgICAgICAgcHJpdi0+cmVzZXRfZGVlcF9zbGVlcF93YWtldXAocHJp dik7DQo+ID4gKyAgICAgICAgICAgbGJzX2RlYl9jbWQoIkVWRU5UOiBkcyBhd2FrZVxuIik7DQo+ ID4gKyAgICAgICAgICAgcHJpdi0+aXNfZGVlcF9zbGVlcCA9IDA7DQo+ID4gKyAgICAgICAgICAg cHJpdi0+d2FrZXVwX2Rldl9yZXF1aXJlZCA9IDA7DQo+ID4gKyAgICAgICAgICAgd2FrZV91cF9p bnRlcnJ1cHRpYmxlKCZwcml2LT5kc19hd2FrZV9xKTsNCj4gPiArICAgICAgICAgICBicmVhazsN Cj4gPiArDQo+ID4gICAgIGNhc2UgTUFDUkVHX0lOVF9DT0RFX1BTX0FXQUtFOg0KPiA+ICAgICAg ICAgICAgIGxic19kZWJfY21kKCJFVkVOVDogcHMgYXdha2VcbiIpOw0KPiA+ICAgICAgICAgICAg IC8qIGhhbmRsZSB1bmV4cGVjdGVkIFBTIEFXQUtFIGV2ZW50ICovDQo+ID4gZGlmZiAtLWdpdCBh L2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2RlYnVnZnMuYyBiL2RyaXZlcnMvbmV0L3dp cmVsZXNzL2xpYmVydGFzL2RlYnVnZnMuYw0KPiA+IGluZGV4IDg5M2E1NWMuLjYyNGE0MzggMTAw NjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGVidWdmcy5jDQo+ ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGVidWdmcy5jDQo+ID4gQEAg LTExNyw2ICsxMTcsMTEgQEAgc3RhdGljIHNzaXplX3QgbGJzX3NsZWVwcGFyYW1zX3dyaXRlKHN0 cnVjdCBmaWxlICpmaWxlLA0KPiA+ICAgICBpZiAoIWJ1ZikNCj4gPiAgICAgICAgICAgICByZXR1 cm4gLUVOT01FTTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkg ew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBnb3RvIG91 dF91bmxvY2s7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIGJ1Zl9zaXplID0gbWluKGNvdW50 LCBsZW4gLSAxKTsNCj4gPiAgICAgaWYgKGNvcHlfZnJvbV91c2VyKGJ1ZiwgdXNlcl9idWYsIGJ1 Zl9zaXplKSkgew0KPiA+ICAgICAgICAgICAgIHJldCA9IC1FRkFVTFQ7DQo+ID4gQEAgLTE1Nyw2 ICsxNjIsMTEgQEAgc3RhdGljIHNzaXplX3QgbGJzX3NsZWVwcGFyYW1zX3JlYWQoc3RydWN0IGZp bGUgKmZpbGUsIGNoYXIgX191c2VyICp1c2VyYnVmLA0KPiA+ICAgICBpZiAoIWJ1ZikNCj4gPiAg ICAgICAgICAgICByZXR1cm4gLUVOT01FTTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRf YWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVTWTsNCj4gPiArICAg ICAgICAgICBnb3RvIG91dF91bmxvY2s7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIHJldCA9 IGxic19jbWRfODAyXzExX3NsZWVwX3BhcmFtcyhwcml2LCBDTURfQUNUX0dFVCwgJnNwKTsNCj4g PiAgICAgaWYgKHJldCkNCj4gPiAgICAgICAgICAgICBnb3RvIG91dF91bmxvY2s7DQo+ID4gQEAg LTE3Myw2ICsxODMsMTE4IEBAIG91dF91bmxvY2s6DQo+ID4gICAgIHJldHVybiByZXQ7DQo+ID4g IH0NCj4gPg0KPiA+ICtzdGF0aWMgc3NpemVfdCBsYnNfZGVlcHNsZWVwX3JlYWQoc3RydWN0IGZp bGUgKmZpbGUsIGNoYXIgX191c2VyICp1c2VyYnVmLA0KPiA+ICsgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIHNpemVfdCBjb3VudCwgbG9mZl90ICpwcG9zKQ0KPiA+ICt7DQo+ID4gKyAgIHN0 cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdiA9IGZpbGUtPnByaXZhdGVfZGF0YTsNCj4gPiArICAgc3Np emVfdCBwb3MgPSAwOw0KPiA+ICsgICBpbnQgcmV0Ow0KPiA+ICsgICB1bnNpZ25lZCBsb25nIGFk ZHIgPSBnZXRfemVyb2VkX3BhZ2UoR0ZQX0tFUk5FTCk7DQo+ID4gKyAgIGNoYXIgKmJ1ZiA9IChj aGFyICopYWRkcjsNCj4gPiArDQo+ID4gKyAgIGlmICghYnVmKQ0KPiA+ICsgICAgICAgICAgIHJl dHVybiAtRU5PTUVNOw0KPiA+ICsNCj4gPiArICAgaWYgKCFwcml2LT5lbnRlcl9kZWVwX3NsZWVw KSB7DQo+ID4gKyAgICAgICAgICAgbGJzX3ByX2VycigiZGVlcCBzbGVlcCBmZWF0dXJlIGlzIG5v dCBpbXBsZW1lbnRlZCAiDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3IgdGhp cyBpbnRlcmZhY2UgZHJpdmVyXG4iKTsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUlOVkFMOw0K PiA+ICsgICAgICAgICAgIGdvdG8gb3V0X2RzOw0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICsgICBp ZiAocHJpdi0+aXNfYXV0b19kZWVwX3NsZWVwX2VuYWJsZWQpDQo+ID4gKyAgICAgICAgICAgcG9z ICs9IHNucHJpbnRmKGJ1ZiwgbGVuLCAiJWQgJWRcbiIsDQo+ID4gKyAgICAgICAgICAgICAgICAg ICAgICAgICAgIHByaXYtPmlzX2F1dG9fZGVlcF9zbGVlcF9lbmFibGVkLA0KPiA+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICBwcml2LT5hdXRvX2RlZXBfc2xlZXBfdGltZW91dCk7DQo+ID4g KyAgIGVsc2UgaWYgKHByaXYtPmlzX2RlZXBfc2xlZXApDQo+ID4gKyAgICAgICAgICAgcG9zICs9 IHNucHJpbnRmKGJ1ZiwgbGVuLCAiJWQgJWRcbiIsDQo+ID4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgIHByaXYtPmlzX2RlZXBfc2xlZXAsDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgIHByaXYtPmF1dG9fZGVlcF9zbGVlcF90aW1lb3V0KTsNCj4gPiArICAgZWxzZQ0KPiA+ICsg ICAgICAgICAgIHBvcyArPSBzbnByaW50ZihidWYsIGxlbiwgIiVkICVkXG4iLA0KPiA+ICsgICAg ICAgICAgICAgICAgICAgICAgICAgICBwcml2LT5pc19kZWVwX3NsZWVwLA0KPiA+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICBwcml2LT5hdXRvX2RlZXBfc2xlZXBfdGltZW91dCk7DQo+ID4g Kw0KPiA+ICsgICByZXQgPSBzaW1wbGVfcmVhZF9mcm9tX2J1ZmZlcih1c2VyYnVmLCBjb3VudCwg cHBvcywgYnVmLCBwb3MpOw0KPiA+ICsNCj4gPiArb3V0X2RzOg0KPiA+ICsgICBmcmVlX3BhZ2Uo YWRkcik7DQo+ID4gKyAgIHJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBz c2l6ZV90IGxic19kZWVwc2xlZXBfd3JpdGUoc3RydWN0IGZpbGUgKmZpbGUsDQo+ID4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyIF9fdXNlciAqdXNlcmJ1ZiwNCj4g PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVfdCBjb3VudCwgbG9mZl90ICpw cG9zKQ0KPiA+ICt7DQo+ID4gKyAgIHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdiA9IGZpbGUtPnBy aXZhdGVfZGF0YTsNCj4gPiArICAgc3NpemVfdCByZXMsIGJ1Zl9zaXplOw0KPiA+ICsgICBpbnQg aXNfZGVlcF9zbGVlcCwgYXV0b19kZWVwX3NsZWVwX3RpbWVvdXQ7DQo+ID4gKyAgIHVuc2lnbmVk IGxvbmcgYWRkciA9IGdldF96ZXJvZWRfcGFnZShHRlBfS0VSTkVMKTsNCj4gPiArICAgY2hhciAq YnVmID0gKGNoYXIgKilhZGRyOw0KPiA+ICsNCj4gPiArICAgaWYgKCFidWYpDQo+ID4gKyAgICAg ICAgICAgcmV0dXJuIC1FTk9NRU07DQo+ID4gKw0KPiA+ICsgICBpZiAoIXByaXYtPmVudGVyX2Rl ZXBfc2xlZXApIHsNCj4gPiArICAgICAgICAgICBsYnNfcHJfZXJyKCJkZWVwIHNsZWVwIGZlYXR1 cmUgaXMgbm90IGltcGxlbWVudGVkICINCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAg ImZvciB0aGlzIGludGVyZmFjZSBkcml2ZXJcbiIpOw0KPiA+ICsgICAgICAgICAgIHJlcyA9IC1F SU5WQUw7DQo+ID4gKyAgICAgICAgICAgZ290byBvdXRfZHM7DQo+ID4gKyAgIH0NCj4gPiArDQo+ ID4gKyAgIGlmIChwcml2LT5jb25uZWN0X3N0YXR1cyA9PSBMQlNfQ09OTkVDVEVEKSB7DQo+ID4g KyAgICAgICAgICAgbGJzX3ByX2VycigiY2FuJ3QgdXNlIGRlZXAgc2xlZXAgY21kIGluIGNvbm5l Y3RlZCAiDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICJzdGF0ZVxuIik7DQo+ID4g KyAgICAgICAgICAgcmVzID0gLUVJTlZBTDsNCj4gPiArICAgICAgICAgICBnb3RvIG91dF9kczsN Cj4gPiArICAgfQ0KPiA+ICsNCj4gPiArICAgYnVmX3NpemUgPSBtaW4oY291bnQsIGxlbiAtIDEp Ow0KPiA+ICsgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2VyYnVmLCBidWZfc2l6ZSkpIHsN Cj4gPiArICAgICAgICAgICByZXMgPSAtRUZBVUxUOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0 X2RzOw0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICsgICByZXMgPSBzc2NhbmYoYnVmLCAiJWQgJWQi LCAmaXNfZGVlcF9zbGVlcCwgJmF1dG9fZGVlcF9zbGVlcF90aW1lb3V0KTsNCj4gPiArICAgaWYg KChyZXMgIT0gMikgfHwgKCFpc19kZWVwX3NsZWVwICYmIGF1dG9fZGVlcF9zbGVlcF90aW1lb3V0 KSB8fA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICEoKGlzX2RlZXBf c2xlZXAgPT0gMSkgfHwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAo aXNfZGVlcF9zbGVlcCA9PSAwKSkpIHsNCj4gPiArICAgICAgICAgICBsYnNfcHJfZXJyKCJ1bmtu b3duIG9wdGlvblxuIik7DQo+ID4gKyAgICAgICAgICAgcmVzID0gLUVJTlZBTDsNCj4gPiArICAg ICAgICAgICBnb3RvIG91dF9kczsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiArICAgaWYgKGF1dG9f ZGVlcF9zbGVlcF90aW1lb3V0KSB7DQo+ID4gKyAgICAgICAgICAgaWYgKCFwcml2LT5pc19hdXRv X2RlZXBfc2xlZXBfZW5hYmxlZCkgew0KPiA+ICsgICAgICAgICAgICAgICAgICAgcHJpdi0+aXNf YWN0aXZpdHlfZGV0ZWN0ZWQgPSAwOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgcHJpdi0+YXV0 b19kZWVwX3NsZWVwX3RpbWVvdXQgPSBhdXRvX2RlZXBfc2xlZXBfdGltZW91dDsNCj4gPiArICAg ICAgICAgICAgICAgICAgIGxic19lbnRlcl9hdXRvX2RlZXBfc2xlZXAocHJpdik7DQo+ID4gKyAg ICAgICAgICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAgICAgICAgICAgIHByaXYtPmF1dG9fZGVl cF9zbGVlcF90aW1lb3V0ID0gYXV0b19kZWVwX3NsZWVwX3RpbWVvdXQ7DQo+ID4gKyAgICAgICAg ICAgICAgICAgICBsYnNfZGViX2RlYnVnZnMoImF1dG8gZGVlcCBzbGVlcDogYWxyZWFkeSBlbmFi bGVkXG4iKTsNCj4gPiArICAgICAgICAgICB9DQo+ID4gKyAgIH0gZWxzZSB7DQo+ID4gKyAgICAg ICAgICAgaWYgKHByaXYtPmlzX2F1dG9fZGVlcF9zbGVlcF9lbmFibGVkKSB7DQo+ID4gKyAgICAg ICAgICAgICAgICAgICBsYnNfZXhpdF9hdXRvX2RlZXBfc2xlZXAocHJpdik7DQo+ID4gKyAgICAg ICAgICAgICAgICAgICAvKiBUcnkgdG8gZXhpdCBkZWVwIHNsZWVwIGlmIGF1dG8gZGVlcCBzbGVl cCBkaXNhYmxlZCAqLw0KPiA+ICsgICAgICAgICAgICAgICAgICAgcmVzID0gbGJzX3NldF9kZWVw X3NsZWVwKHByaXYsIDApOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgaWYgKHJlcykNCj4gPiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgZ290byBvdXRfZHM7DQo+ID4gKyAgICAgICAgICAg fQ0KPiA+ICsgICAgICAgICAgIGlmICgoaXNfZGVlcF9zbGVlcCA9PSAwKSB8fCAoaXNfZGVlcF9z bGVlcCA9PSAxKSkgew0KPiA+ICsgICAgICAgICAgICAgICAgICAgcmVzID0gbGJzX3NldF9kZWVw X3NsZWVwKHByaXYsIGlzX2RlZXBfc2xlZXApOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgaWYg KHJlcykNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgZ290byBvdXRfZHM7DQo+ID4g KyAgICAgICAgICAgfQ0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICsgICByZXMgPSBjb3VudDsNCj4g PiArDQo+ID4gK291dF9kczoNCj4gPiArICAgZnJlZV9wYWdlKGFkZHIpOw0KPiA+ICsgICByZXR1 cm4gcmVzOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICAvKg0KPiA+ICAgKiBXaGVuIGNhbGxpbmcgQ01E XzgwMl8xMV9TVUJTQ1JJQkVfRVZFTlQgd2l0aCBDTURfQUNUX0dFVCwgbWUgbWlnaHQNCj4gPiAg ICogZ2V0IGEgYnVuY2ggb2YgdmVuZG9yLXNwZWNpZmljIFRMVnMgKGEuay5hLiBJRXMpIGJhY2sg ZnJvbSB0aGUNCj4gPiBAQCAtMjIzLDYgKzM0NSw5IEBAIHN0YXRpYyBzc2l6ZV90IGxic190aHJl c2hvbGRfcmVhZCh1aW50MTZfdCB0bHZfdHlwZSwgdWludDE2X3QgZXZlbnRfbWFzaywNCj4gPiAg ICAgdTggZnJlcTsNCj4gPiAgICAgaW50IGV2ZW50cyA9IDA7DQo+ID4NCj4gPiArICAgaWYgKCFs YnNfaXNfY21kX2FsbG93ZWQocHJpdikpDQo+ID4gKyAgICAgICAgICAgcmV0dXJuIC1FQlVTWTsN Cj4gPiArDQo+ID4gICAgIGJ1ZiA9IChjaGFyICopZ2V0X3plcm9lZF9wYWdlKEdGUF9LRVJORUwp Ow0KPiA+ICAgICBpZiAoIWJ1ZikNCj4gPiAgICAgICAgICAgICByZXR1cm4gLUVOT01FTTsNCj4g PiBAQCAtMjc1LDYgKzQwMCw5IEBAIHN0YXRpYyBzc2l6ZV90IGxic190aHJlc2hvbGRfd3JpdGUo dWludDE2X3QgdGx2X3R5cGUsIHVpbnQxNl90IGV2ZW50X21hc2ssDQo+ID4gICAgIGNoYXIgKmJ1 ZjsNCj4gPiAgICAgaW50IHJldDsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dl ZChwcml2KSkNCj4gPiArICAgICAgICAgICByZXR1cm4gLUVCVVNZOw0KPiA+ICsNCj4gPiAgICAg YnVmID0gKGNoYXIgKilnZXRfemVyb2VkX3BhZ2UoR0ZQX0tFUk5FTCk7DQo+ID4gICAgIGlmICgh YnVmKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOw0KPiA+IEBAIC00NDQsNiArNTcy LDExIEBAIHN0YXRpYyBzc2l6ZV90IGxic19yZG1hY19yZWFkKHN0cnVjdCBmaWxlICpmaWxlLCBj aGFyIF9fdXNlciAqdXNlcmJ1ZiwNCj4gPiAgICAgaWYgKCFidWYpDQo+ID4gICAgICAgICAgICAg cmV0dXJuIC1FTk9NRU07DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJp dikpIHsNCj4gPiArICAgICAgICAgICBmcmVlX3BhZ2UoYWRkcik7DQo+ID4gKyAgICAgICAgICAg cmV0dXJuIC1FQlVTWTsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgb2ZmdmFsLm9mZnNldCA9 IHByaXYtPm1hY19vZmZzZXQ7DQo+ID4gICAgIG9mZnZhbC52YWx1ZSA9IDA7DQo+ID4NCj4gPiBA QCAtNDk2LDYgKzYyOSwxMSBAQCBzdGF0aWMgc3NpemVfdCBsYnNfd3JtYWNfd3JpdGUoc3RydWN0 IGZpbGUgKmZpbGUsDQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAt RU5PTUVNOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ ID4gKyAgICAgICAgICAgcmVzID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0X3Vu bG9jazsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgYnVmX3NpemUgPSBtaW4oY291bnQsIGxl biAtIDEpOw0KPiA+ICAgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2VyYnVmLCBidWZfc2l6 ZSkpIHsNCj4gPiAgICAgICAgICAgICByZXMgPSAtRUZBVUxUOw0KPiA+IEBAIC01MzIsNiArNjcw LDExIEBAIHN0YXRpYyBzc2l6ZV90IGxic19yZGJicF9yZWFkKHN0cnVjdCBmaWxlICpmaWxlLCBj aGFyIF9fdXNlciAqdXNlcmJ1ZiwNCj4gPiAgICAgaWYgKCFidWYpDQo+ID4gICAgICAgICAgICAg cmV0dXJuIC1FTk9NRU07DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJp dikpIHsNCj4gPiArICAgICAgICAgICBmcmVlX3BhZ2UoYWRkcik7DQo+ID4gKyAgICAgICAgICAg cmV0dXJuIC1FQlVTWTsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgb2ZmdmFsLm9mZnNldCA9 IHByaXYtPmJicF9vZmZzZXQ7DQo+ID4gICAgIG9mZnZhbC52YWx1ZSA9IDA7DQo+ID4NCj4gPiBA QCAtNTg1LDYgKzcyOCwxMSBAQCBzdGF0aWMgc3NpemVfdCBsYnNfd3JiYnBfd3JpdGUoc3RydWN0 IGZpbGUgKmZpbGUsDQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAt RU5PTUVNOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ ID4gKyAgICAgICAgICAgcmVzID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0X3Vu bG9jazsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgYnVmX3NpemUgPSBtaW4oY291bnQsIGxl biAtIDEpOw0KPiA+ICAgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2VyYnVmLCBidWZfc2l6 ZSkpIHsNCj4gPiAgICAgICAgICAgICByZXMgPSAtRUZBVUxUOw0KPiA+IEBAIC02MjEsNiArNzY5 LDExIEBAIHN0YXRpYyBzc2l6ZV90IGxic19yZHJmX3JlYWQoc3RydWN0IGZpbGUgKmZpbGUsIGNo YXIgX191c2VyICp1c2VyYnVmLA0KPiA+ICAgICBpZiAoIWJ1ZikNCj4gPiAgICAgICAgICAgICBy ZXR1cm4gLUVOT01FTTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2 KSkgew0KPiA+ICsgICAgICAgICAgIGZyZWVfcGFnZShhZGRyKTsNCj4gPiArICAgICAgICAgICBy ZXR1cm4gLUVCVVNZOw0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBvZmZ2YWwub2Zmc2V0ID0g cHJpdi0+cmZfb2Zmc2V0Ow0KPiA+ICAgICBvZmZ2YWwudmFsdWUgPSAwOw0KPiA+DQo+ID4gQEAg LTY3NCw2ICs4MjcsMTEgQEAgc3RhdGljIHNzaXplX3QgbGJzX3dycmZfd3JpdGUoc3RydWN0IGZp bGUgKmZpbGUsDQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRU5P TUVNOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4g KyAgICAgICAgICAgcmVzID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0X3VubG9j azsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgYnVmX3NpemUgPSBtaW4oY291bnQsIGxlbiAt IDEpOw0KPiA+ICAgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2VyYnVmLCBidWZfc2l6ZSkp IHsNCj4gPiAgICAgICAgICAgICByZXMgPSAtRUZBVUxUOw0KPiA+IEBAIC03MTcsNiArODc1LDgg QEAgc3RhdGljIGNvbnN0IHN0cnVjdCBsYnNfZGVidWdmc19maWxlcyBkZWJ1Z2ZzX2ZpbGVzW10g PSB7DQo+ID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVfZmlsZV9k dW1teSksIH0sDQo+ID4gICAgIHsgInNsZWVwcGFyYW1zIiwgMDY0NCwgRk9QUyhsYnNfc2xlZXBw YXJhbXNfcmVhZCwNCj4gPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGJzX3NsZWVwcGFy YW1zX3dyaXRlKSwgfSwNCj4gPiArICAgeyAiZGVlcHNsZWVwIiwgMDY0NCwgRk9QUyhsYnNfZGVl cHNsZWVwX3JlYWQsDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgIGxic19kZWVwc2xl ZXBfd3JpdGUpLCB9LA0KPiA+ICB9Ow0KPiA+DQo+ID4gIHN0YXRpYyBjb25zdCBzdHJ1Y3QgbGJz X2RlYnVnZnNfZmlsZXMgZGVidWdmc19ldmVudHNfZmlsZXNbXSA9IHsNCj4gPiBkaWZmIC0tZ2l0 IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGVjbC5oIGIvZHJpdmVycy9uZXQvd2ly ZWxlc3MvbGliZXJ0YXMvZGVjbC5oDQo+ID4gaW5kZXggMGI4NGJkYy4uMzRiNDc1ZiAxMDA2NDQN Cj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9kZWNsLmgNCj4gPiArKysg Yi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9kZWNsLmgNCj4gPiBAQCAtMzMsNiArMzMs MTAgQEAgaW50IGxic19leGVjdXRlX25leHRfY29tbWFuZChzdHJ1Y3QgbGJzX3ByaXZhdGUgKnBy aXYpOw0KPiA+ICBpbnQgbGJzX3Byb2Nlc3NfZXZlbnQoc3RydWN0IGxic19wcml2YXRlICpwcml2 LCB1MzIgZXZlbnQpOw0KPiA+ICB2b2lkIGxic19xdWV1ZV9ldmVudChzdHJ1Y3QgbGJzX3ByaXZh dGUgKnByaXYsIHUzMiBldmVudCk7DQo+ID4gIHZvaWQgbGJzX25vdGlmeV9jb21tYW5kX3Jlc3Bv bnNlKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdiwgdTggcmVzcF9pZHgpOw0KPiA+ICtpbnQgbGJz X3NldF9kZWVwX3NsZWVwKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdiwgaW50IGRlZXBfc2xlZXAp Ow0KPiA+ICtpbnQgbGJzX2lzX2NtZF9hbGxvd2VkKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdik7 DQo+ID4gK2ludCBsYnNfZW50ZXJfYXV0b19kZWVwX3NsZWVwKHN0cnVjdCBsYnNfcHJpdmF0ZSAq cHJpdik7DQo+ID4gK2ludCBsYnNfZXhpdF9hdXRvX2RlZXBfc2xlZXAoc3RydWN0IGxic19wcml2 YXRlICpwcml2KTsNCj4gPg0KPiA+ICB1MzIgbGJzX2Z3X2luZGV4X3RvX2RhdGFfcmF0ZSh1OCBp bmRleCk7DQo+ID4gIHU4IGxic19kYXRhX3JhdGVfdG9fZndfaW5kZXgodTMyIHJhdGUpOw0KPiA+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9kZXYuaCBiL2RyaXZl cnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2Rldi5oDQo+ID4gaW5kZXggNTc4YzY5Ny4uZTJiNGVm MiAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9kZXYuaA0K PiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2Rldi5oDQo+ID4gQEAgLTEy OSw2ICsxMjksMjAgQEAgc3RydWN0IGxic19wcml2YXRlIHsNCj4gPiAgICAgdTMyIGJicF9vZmZz ZXQ7DQo+ID4gICAgIHUzMiByZl9vZmZzZXQ7DQo+ID4NCj4gPiArICAgLyoqIERlZXAgc2xlZXAg ZmxhZyAqLw0KPiA+ICsgICBpbnQgaXNfZGVlcF9zbGVlcDsNCj4gPiArICAgLyoqIEF1dG8gZGVl cCBzbGVlcCBlbmFibGVkIGZsYWcgKi8NCj4gPiArICAgaW50IGlzX2F1dG9fZGVlcF9zbGVlcF9l bmFibGVkOw0KPiA+ICsgICAvKiogRGV2aWNlIHdha2V1cCByZXF1aXJlZCBmbGFnICovDQo+ID4g KyAgIGludCB3YWtldXBfZGV2X3JlcXVpcmVkOw0KPiA+ICsgICAvKiogQXV0byBkZWVwIHNsZWVw IGZsYWcqLw0KPiA+ICsgICBpbnQgaXNfYWN0aXZpdHlfZGV0ZWN0ZWQ7DQo+ID4gKyAgIC8qKiBB dXRvIGRlZXAgc2xlZXAgdGltZW91dCAoaW4gbWlsaXNlY29uZHMpICovDQo+ID4gKyAgIGludCBh dXRvX2RlZXBfc2xlZXBfdGltZW91dDsNCj4gPiArDQo+ID4gKyAgIC8qKiBEZWVwIHNsZWVwIHdh aXQgcXVldWUgKi8NCj4gPiArICAgd2FpdF9xdWV1ZV9oZWFkX3QgICAgICAgZHNfYXdha2VfcTsN Cj4gPiArDQo+ID4gICAgIC8qIERvd25sb2FkIHNlbnQ6DQo+ID4gICAgICAgIGJpdDAgMS8wPWRh dGFfc2VudC9kYXRhX3R4X2RvbmUsDQo+ID4gICAgICAgIGJpdDEgMS8wPWNtZF9zZW50L2NtZF90 eF9kb25lLA0KPiA+IEBAIC0xNTQsNiArMTY4LDkgQEAgc3RydWN0IGxic19wcml2YXRlIHsNCj4g PiAgICAgLyoqIEhhcmR3YXJlIGFjY2VzcyAqLw0KPiA+ICAgICBpbnQgKCpod19ob3N0X3RvX2Nh cmQpIChzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYsIHU4IHR5cGUsIHU4ICpwYXlsb2FkLCB1MTYg bmIpOw0KPiA+ICAgICB2b2lkICgqcmVzZXRfY2FyZCkgKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJp dik7DQo+ID4gKyAgIGludCAoKmVudGVyX2RlZXBfc2xlZXApIChzdHJ1Y3QgbGJzX3ByaXZhdGUg KnByaXYpOw0KPiA+ICsgICBpbnQgKCpleGl0X2RlZXBfc2xlZXApIChzdHJ1Y3QgbGJzX3ByaXZh dGUgKnByaXYpOw0KPiA+ICsgICBpbnQgKCpyZXNldF9kZWVwX3NsZWVwX3dha2V1cCkgKHN0cnVj dCBsYnNfcHJpdmF0ZSAqcHJpdik7DQo+ID4NCj4gPiAgICAgLyogV2FrZSBPbiBMQU4gKi8NCj4g PiAgICAgdWludDMyX3Qgd29sX2NyaXRlcmlhOw0KPiA+IEBAIC0yMDQsNiArMjIxLDcgQEAgc3Ry dWN0IGxic19wcml2YXRlIHsNCj4gPg0KPiA+ICAgICAvKiogVGltZXJzICovDQo+ID4gICAgIHN0 cnVjdCB0aW1lcl9saXN0IGNvbW1hbmRfdGltZXI7DQo+ID4gKyAgIHN0cnVjdCB0aW1lcl9saXN0 IGF1dG9fZGVlcHNsZWVwX3RpbWVyOw0KPiA+ICAgICBpbnQgbnJfcmV0cmllczsNCj4gPiAgICAg aW50IGNtZF90aW1lZF9vdXQ7DQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2ly ZWxlc3MvbGliZXJ0YXMvaG9zdC5oIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaG9z dC5oDQo+ID4gaW5kZXggZmU4ZjBjYi4uYzA1NWRhYSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJz L25ldC93aXJlbGVzcy9saWJlcnRhcy9ob3N0LmgNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJl bGVzcy9saWJlcnRhcy9ob3N0LmgNCj4gPiBAQCAtNTcsNiArNTcsNyBAQA0KPiA+ICAjZGVmaW5l IENNRF84MDJfMTFfRU5BQkxFX1JTTiAgICAgICAgICAgICAgICAgICAgICAweDAwMmYNCj4gPiAg I2RlZmluZSBDTURfODAyXzExX1NFVF9BRkMgICAgICAgICAgICAgICAgIDB4MDAzYw0KPiA+ICAj ZGVmaW5lIENNRF84MDJfMTFfR0VUX0FGQyAgICAgICAgICAgICAgICAgMHgwMDNkDQo+ID4gKyNk ZWZpbmUgQ01EXzgwMl8xMV9ERUVQX1NMRUVQICAgICAgICAgICAgICAgICAgMHgwMDNlDQo+ID4g ICNkZWZpbmUgQ01EXzgwMl8xMV9BRF9IT0NfU1RPUCAgICAgICAgICAgICAgICAgICAgIDB4MDA0 MA0KPiA+ICAjZGVmaW5lIENNRF84MDJfMTFfSE9TVF9TTEVFUF9DRkcgICAgICAgICAgMHgwMDQz DQo+ID4gICNkZWZpbmUgQ01EXzgwMl8xMV9XQUtFVVBfQ09ORklSTSAgICAgICAgICAweDAwNDQN Cj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfY3MuYyBi L2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX2NzLmMNCj4gPiBpbmRleCA2MjM4MTc2 Li40NjU3NDJmIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFz L2lmX2NzLmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9jcy5j DQo+ID4gQEAgLTk0Niw2ICs5NDYsOSBAQCBzdGF0aWMgaW50IGlmX2NzX3Byb2JlKHN0cnVjdCBw Y21jaWFfZGV2aWNlICpwX2RldikNCj4gPiAgICAgY2FyZC0+cHJpdiA9IHByaXY7DQo+ID4gICAg IHByaXYtPmNhcmQgPSBjYXJkOw0KPiA+ICAgICBwcml2LT5od19ob3N0X3RvX2NhcmQgPSBpZl9j c19ob3N0X3RvX2NhcmQ7DQo+ID4gKyAgIHByaXYtPmVudGVyX2RlZXBfc2xlZXAgPSBOVUxMOw0K PiA+ICsgICBwcml2LT5leGl0X2RlZXBfc2xlZXAgPSBOVUxMOw0KPiA+ICsgICBwcml2LT5yZXNl dF9kZWVwX3NsZWVwX3dha2V1cCA9IE5VTEw7DQo+ID4gICAgIHByaXYtPmZ3X3JlYWR5ID0gMTsN Cj4gPg0KPiA+ICAgICAvKiBOb3cgYWN0dWFsbHkgZ2V0IHRoZSBJUlEgKi8NCj4gPiBkaWZmIC0t Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc2Rpby5jIGIvZHJpdmVycy9u ZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc2Rpby5jDQo+ID4gaW5kZXggNDg1YThkNC4uOTcxNjcy OCAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9zZGlv LmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9zZGlvLmMNCj4g PiBAQCAtODMxLDYgKzgzMSw1OCBAQCBvdXQ6DQo+ID4gICAgIHJldHVybiByZXQ7DQo+ID4gIH0N Cj4gPg0KPiA+ICtzdGF0aWMgaW50IGlmX3NkaW9fZW50ZXJfZGVlcF9zbGVlcChzdHJ1Y3QgbGJz X3ByaXZhdGUgKnByaXYpDQo+ID4gK3sNCj4gPiArICAgaW50IHJldCA9IC0xOw0KPiA+ICsgICBz dHJ1Y3QgY21kX2hlYWRlciBjbWQ7DQo+ID4gKw0KPiA+ICsgICBtZW1zZXQoJmNtZCwgMCwgc2l6 ZW9mKGNtZCkpOw0KPiA+ICsNCj4gPiArICAgbGJzX2RlYl9zZGlvKCJzZW5kIERFRVBfU0xFRVAg Y29tbWFuZFxuIik7DQo+ID4gKyAgIHJldCA9IF9fbGJzX2NtZChwcml2LCBDTURfODAyXzExX0RF RVBfU0xFRVAsICZjbWQsIHNpemVvZihjbWQpLA0KPiA+ICsgICAgICAgICAgICAgICAgICAgbGJz X2NtZF9jb3B5YmFjaywgKHVuc2lnbmVkIGxvbmcpICZjbWQpOw0KPiA+ICsgICBpZiAocmV0KQ0K PiA+ICsgICAgICAgICAgIGxic19wcl9lcnIoIkRFRVBfU0xFRVAgY21kIGZhaWxlZFxuIik7DQo+ ID4gKw0KPiA+ICsgICBtZGVsYXkoMjAwKTsNCj4gPiArICAgcmV0dXJuIHJldDsNCj4gPiArfQ0K PiA+ICsNCj4gPiArc3RhdGljIGludCBpZl9zZGlvX2V4aXRfZGVlcF9zbGVlcChzdHJ1Y3QgbGJz X3ByaXZhdGUgKnByaXYpDQo+ID4gK3sNCj4gPiArICAgc3RydWN0IGlmX3NkaW9fY2FyZCAqY2Fy ZCA9IHByaXYtPmNhcmQ7DQo+ID4gKyAgIGludCByZXQgPSAtMTsNCj4gPiArDQo+ID4gKyAgIGxi c19kZWJfZW50ZXIoTEJTX0RFQl9TRElPKTsNCj4gPiArICAgc2Rpb19jbGFpbV9ob3N0KGNhcmQt PmZ1bmMpOw0KPiA+ICsNCj4gPiArICAgc2Rpb193cml0ZWIoY2FyZC0+ZnVuYywgSE9TVF9QT1dF Ul9VUCwgQ09ORklHVVJBVElPTl9SRUcsICZyZXQpOw0KPiA+ICsgICBpZiAocmV0KQ0KPiA+ICsg ICAgICAgICAgIGxic19wcl9lcnIoInNkaW9fd3JpdGViIGZhaWxlZCFcbiIpOw0KPiA+ICsNCj4g PiArICAgc2Rpb19yZWxlYXNlX2hvc3QoY2FyZC0+ZnVuYyk7DQo+ID4gKyAgIGxic19kZWJfbGVh dmVfYXJncyhMQlNfREVCX1NESU8sICJyZXQgJWQiLCByZXQpOw0KPiA+ICsgICByZXR1cm4gcmV0 Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGlmX3NkaW9fcmVzZXRfZGVlcF9zbGVl cF93YWtldXAoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0KPiA+ICt7DQo+ID4gKyAgIHN0cnVj dCBpZl9zZGlvX2NhcmQgKmNhcmQgPSBwcml2LT5jYXJkOw0KPiA+ICsgICBpbnQgcmV0ID0gLTE7 DQo+ID4gKw0KPiA+ICsgICBsYnNfZGViX2VudGVyKExCU19ERUJfU0RJTyk7DQo+ID4gKyAgIHNk aW9fY2xhaW1faG9zdChjYXJkLT5mdW5jKTsNCj4gPiArDQo+ID4gKyAgIHNkaW9fd3JpdGViKGNh cmQtPmZ1bmMsIDAsIENPTkZJR1VSQVRJT05fUkVHLCAmcmV0KTsNCj4gPiArICAgaWYgKHJldCkN Cj4gPiArICAgICAgICAgICBsYnNfcHJfZXJyKCJzZGlvX3dyaXRlYiBmYWlsZWQhXG4iKTsNCj4g PiArDQo+ID4gKyAgIHNkaW9fcmVsZWFzZV9ob3N0KGNhcmQtPmZ1bmMpOw0KPiA+ICsgICBsYnNf ZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9TRElPLCAicmV0ICVkIiwgcmV0KTsNCj4gPiArICAgcmV0 dXJuIHJldDsNCj4gPiArDQo+ID4gK30NCj4gPiArDQo+ID4gIC8qKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLw0KPiA+ICAv KiBTRElPIGNhbGxiYWNrcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgKi8NCj4gPiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKiovDQo+ID4gQEAgLTg1OSw2ICs5MTEsNyBAQCBz dGF0aWMgdm9pZCBpZl9zZGlvX2ludGVycnVwdChzdHJ1Y3Qgc2Rpb19mdW5jICpmdW5jKQ0KPiA+ ICAgICAgKiBJZ25vcmUgdGhlIGRlZmluZSBuYW1lLCB0aGlzIHJlYWxseSBtZWFucyB0aGUgY2Fy ZCBoYXMNCj4gPiAgICAgICogc3VjY2Vzc2Z1bGx5IHJlY2VpdmVkIHRoZSBjb21tYW5kLg0KPiA+ ICAgICAgKi8NCj4gPiArICAgY2FyZC0+cHJpdi0+aXNfYWN0aXZpdHlfZGV0ZWN0ZWQgPSAxOw0K PiA+ICAgICBpZiAoY2F1c2UgJiBJRl9TRElPX0hfSU5UX0ROTEQpDQo+ID4gICAgICAgICAgICAg bGJzX2hvc3RfdG9fY2FyZF9kb25lKGNhcmQtPnByaXYpOw0KPiA+DQo+ID4gQEAgLTk5OCw2ICsx MDUxLDkgQEAgc3RhdGljIGludCBpZl9zZGlvX3Byb2JlKHN0cnVjdCBzZGlvX2Z1bmMgKmZ1bmMs DQo+ID4NCj4gPiAgICAgcHJpdi0+Y2FyZCA9IGNhcmQ7DQo+ID4gICAgIHByaXYtPmh3X2hvc3Rf dG9fY2FyZCA9IGlmX3NkaW9faG9zdF90b19jYXJkOw0KPiA+ICsgICBwcml2LT5lbnRlcl9kZWVw X3NsZWVwID0gaWZfc2Rpb19lbnRlcl9kZWVwX3NsZWVwOw0KPiA+ICsgICBwcml2LT5leGl0X2Rl ZXBfc2xlZXAgPSBpZl9zZGlvX2V4aXRfZGVlcF9zbGVlcDsNCj4gPiArICAgcHJpdi0+cmVzZXRf ZGVlcF9zbGVlcF93YWtldXAgPSBpZl9zZGlvX3Jlc2V0X2RlZXBfc2xlZXBfd2FrZXVwOw0KPiA+ DQo+ID4gICAgIHByaXYtPmZ3X3JlYWR5ID0gMTsNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2 ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9zZGlvLmggYi9kcml2ZXJzL25ldC93aXJlbGVz cy9saWJlcnRhcy9pZl9zZGlvLmgNCj4gPiBpbmRleCA2MGM5YjJmLi4xMjE3OWMxIDEwMDY0NA0K PiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3NkaW8uaA0KPiA+ICsr KyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3NkaW8uaA0KPiA+IEBAIC01MSw1 ICs1MSw2IEBADQo+ID4gICNkZWZpbmUgSUZfU0RJT19FVkVOVCAgICAgICAgICAgMHg4MGZjDQo+ ID4NCj4gPiAgI2RlZmluZSBJRl9TRElPX0JMT0NLX1NJWkUgMjU2DQo+ID4gLQ0KPiA+ICsjZGVm aW5lIENPTkZJR1VSQVRJT05fUkVHICAgICAgICAgICAgICAgMHgwMw0KPiA+ICsjZGVmaW5lIEhP U1RfUE9XRVJfVVAgICAgICAgICAgICAgICAgICAgKDB4MVUgPDwgMSkNCj4gPiAgI2VuZGlmDQo+ ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3NwaS5jIGIv ZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc3BpLmMNCj4gPiBpbmRleCA0NDZlMzI3 Li5lMmZhNjU3IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFz L2lmX3NwaS5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc3Bp LmMNCj4gPiBAQCAtMTExNyw2ICsxMTE3LDkgQEAgc3RhdGljIGludCBfX2RldmluaXQgaWZfc3Bp X3Byb2JlKHN0cnVjdCBzcGlfZGV2aWNlICpzcGkpDQo+ID4gICAgIGNhcmQtPnByaXYgPSBwcml2 Ow0KPiA+ICAgICBwcml2LT5jYXJkID0gY2FyZDsNCj4gPiAgICAgcHJpdi0+aHdfaG9zdF90b19j YXJkID0gaWZfc3BpX2hvc3RfdG9fY2FyZDsNCj4gPiArICAgcHJpdi0+ZW50ZXJfZGVlcF9zbGVl cCA9IE5VTEw7DQo+ID4gKyAgIHByaXYtPmV4aXRfZGVlcF9zbGVlcCA9IE5VTEw7DQo+ID4gKyAg IHByaXYtPnJlc2V0X2RlZXBfc2xlZXBfd2FrZXVwID0gTlVMTDsNCj4gPiAgICAgcHJpdi0+Zndf cmVhZHkgPSAxOw0KPiA+DQo+ID4gICAgIC8qIEluaXRpYWxpemUgaW50ZXJydXB0IGhhbmRsaW5n IHN0dWZmLiAqLw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRh cy9pZl91c2IuYyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3VzYi5jDQo+ID4g aW5kZXggOTJiYzhjNS4uYTgyNjJkZSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJl bGVzcy9saWJlcnRhcy9pZl91c2IuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xp YmVydGFzL2lmX3VzYi5jDQo+ID4gQEAgLTMwMCw2ICszMDAsOSBAQCBzdGF0aWMgaW50IGlmX3Vz Yl9wcm9iZShzdHJ1Y3QgdXNiX2ludGVyZmFjZSAqaW50ZiwNCj4gPiAgICAgY2FyZHAtPnByaXYt PmZ3X3JlYWR5ID0gMTsNCj4gPg0KPiA+ICAgICBwcml2LT5od19ob3N0X3RvX2NhcmQgPSBpZl91 c2JfaG9zdF90b19jYXJkOw0KPiA+ICsgICBwcml2LT5lbnRlcl9kZWVwX3NsZWVwID0gTlVMTDsN Cj4gPiArICAgcHJpdi0+ZXhpdF9kZWVwX3NsZWVwID0gTlVMTDsNCj4gPiArICAgcHJpdi0+cmVz ZXRfZGVlcF9zbGVlcF93YWtldXAgPSBOVUxMOw0KPiA+ICAjaWZkZWYgQ09ORklHX09MUEMNCj4g PiAgICAgaWYgKG1hY2hpbmVfaXNfb2xwYygpKQ0KPiA+ICAgICAgICAgICAgIHByaXYtPnJlc2V0 X2NhcmQgPSBpZl91c2JfcmVzZXRfb2xwY19jYXJkOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJz L25ldC93aXJlbGVzcy9saWJlcnRhcy9tYWluLmMgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJl cnRhcy9tYWluLmMNCj4gPiBpbmRleCA4ZGYxY2ZkLi4zYjE0ZmNjIDEwMDY0NA0KPiA+IC0tLSBh L2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL21haW4uYw0KPiA+ICsrKyBiL2RyaXZlcnMv bmV0L3dpcmVsZXNzL2xpYmVydGFzL21haW4uYw0KPiA+IEBAIC01NzQsOCArNTc0LDEwIEBAIHZv aWQgbGJzX2hvc3RfdG9fY2FyZF9kb25lKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdikNCj4gPiAg ICAgcHJpdi0+ZG5sZF9zZW50ID0gRE5MRF9SRVNfUkVDRUlWRUQ7DQo+ID4NCj4gPiAgICAgLyog V2FrZSBtYWluIHRocmVhZCBpZiBjb21tYW5kcyBhcmUgcGVuZGluZyAqLw0KPiA+IC0gICBpZiAo IXByaXYtPmN1cl9jbWQgfHwgcHJpdi0+dHhfcGVuZGluZ19sZW4gPiAwKQ0KPiA+IC0gICAgICAg ICAgIHdha2VfdXBfaW50ZXJydXB0aWJsZSgmcHJpdi0+d2FpdHEpOw0KPiA+ICsgICBpZiAoIXBy aXYtPmN1cl9jbWQgfHwgcHJpdi0+dHhfcGVuZGluZ19sZW4gPiAwKSB7DQo+ID4gKyAgICAgICAg ICAgaWYgKCFwcml2LT53YWtldXBfZGV2X3JlcXVpcmVkKQ0KPiA+ICsgICAgICAgICAgICAgICAg ICAgd2FrZV91cF9pbnRlcnJ1cHRpYmxlKCZwcml2LT53YWl0cSk7DQo+ID4gKyAgIH0NCj4gPg0K PiA+ICAgICBzcGluX3VubG9ja19pcnFyZXN0b3JlKCZwcml2LT5kcml2ZXJfbG9jaywgZmxhZ3Mp Ow0KPiA+ICAgICBsYnNfZGViX2xlYXZlKExCU19ERUJfVEhSRUFEKTsNCj4gPiBAQCAtNzcwLDcg Kzc3Miw4IEBAIHN0YXRpYyBpbnQgbGJzX3RocmVhZCh2b2lkICpkYXRhKQ0KPiA+ICAgICAgICAg ICAgICAgICAgICAgc2hvdWxkc2xlZXAgPSAwOyAgICAgICAgLyogV2UgaGF2ZSBhIGNvbW1hbmQg cmVzcG9uc2UgKi8NCj4gPiAgICAgICAgICAgICBlbHNlIGlmIChwcml2LT5jdXJfY21kKQ0KPiA+ ICAgICAgICAgICAgICAgICAgICAgc2hvdWxkc2xlZXAgPSAxOyAgICAgICAgLyogQ2FuJ3Qgc2Vu ZCBhIGNvbW1hbmQ7IG9uZSBhbHJlYWR5IHJ1bm5pbmcgKi8NCj4gPiAtICAgICAgICAgICBlbHNl IGlmICghbGlzdF9lbXB0eSgmcHJpdi0+Y21kcGVuZGluZ3EpKQ0KPiA+ICsgICAgICAgICAgIGVs c2UgaWYgKCFsaXN0X2VtcHR5KCZwcml2LT5jbWRwZW5kaW5ncSkgJiYNCj4gPiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAhKHByaXYtPndha2V1cF9kZXZfcmVxdWlyZWQpKQ0K PiA+ICAgICAgICAgICAgICAgICAgICAgc2hvdWxkc2xlZXAgPSAwOyAgICAgICAgLyogV2UgaGF2 ZSBhIGNvbW1hbmQgdG8gc2VuZCAqLw0KPiA+ICAgICAgICAgICAgIGVsc2UgaWYgKF9fa2ZpZm9f bGVuKHByaXYtPmV2ZW50X2ZpZm8pKQ0KPiA+ICAgICAgICAgICAgICAgICAgICAgc2hvdWxkc2xl ZXAgPSAwOyAgICAgICAgLyogV2UgaGF2ZSBhbiBldmVudCB0byBwcm9jZXNzICovDQo+ID4gQEAg LTgyMiw2ICs4MjUsMjYgQEAgc3RhdGljIGludCBsYnNfdGhyZWFkKHZvaWQgKmRhdGEpDQo+ID4g ICAgICAgICAgICAgfQ0KPiA+ICAgICAgICAgICAgIHNwaW5fdW5sb2NrX2lycSgmcHJpdi0+ZHJp dmVyX2xvY2spOw0KPiA+DQo+ID4gKyAgICAgICAgICAgLyogUHJvY2VzcyBoYXJkd2FyZSBldmVu dHMsIGUuZy4gY2FyZCByZW1vdmVkLCBsaW5rIGxvc3QgKi8NCj4gPiArICAgICAgICAgICBzcGlu X2xvY2tfaXJxKCZwcml2LT5kcml2ZXJfbG9jayk7DQo+ID4gKyAgICAgICAgICAgd2hpbGUgKF9f a2ZpZm9fbGVuKHByaXYtPmV2ZW50X2ZpZm8pKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICB1 MzIgZXZlbnQ7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBfX2tmaWZvX2dldChwcml2LT5ldmVu dF9maWZvLCAodW5zaWduZWQgY2hhciAqKSAmZXZlbnQsDQo+ID4gKyAgICAgICAgICAgICAgICAg ICAgICAgICAgIHNpemVvZihldmVudCkpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgc3Bpbl91 bmxvY2tfaXJxKCZwcml2LT5kcml2ZXJfbG9jayk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBs YnNfcHJvY2Vzc19ldmVudChwcml2LCBldmVudCk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBz cGluX2xvY2tfaXJxKCZwcml2LT5kcml2ZXJfbG9jayk7DQo+ID4gKyAgICAgICAgICAgfQ0KPiA+ ICsgICAgICAgICAgIHNwaW5fdW5sb2NrX2lycSgmcHJpdi0+ZHJpdmVyX2xvY2spOw0KPiA+ICsN Cj4gPiArICAgICAgICAgICBpZiAocHJpdi0+d2FrZXVwX2Rldl9yZXF1aXJlZCkgew0KPiA+ICsg ICAgICAgICAgICAgICAgICAgbGJzX2RlYl90aHJlYWQoIldha2luZyB1cCBkZXZpY2UuLi5cbiIp Ow0KPiA+ICsgICAgICAgICAgICAgICAgICAgLyogV2FrZSB1cCBkZXZpY2UgKi8NCj4gPiArICAg ICAgICAgICAgICAgICAgIGlmIChwcml2LT5leGl0X2RlZXBfc2xlZXAocHJpdikpDQo+ID4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgIGxic19kZWJfdGhyZWFkKCJXYWtldXAgZGV2aWNlIGZh aWxlZFxuIik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBjb250aW51ZTsNCj4gPiArICAgICAg ICAgICB9DQo+ID4gKw0KPiA+ICAgICAgICAgICAgIC8qIGNvbW1hbmQgdGltZW91dCBzdHVmZiAq Lw0KPiA+ICAgICAgICAgICAgIGlmIChwcml2LT5jbWRfdGltZWRfb3V0ICYmIHByaXYtPmN1cl9j bWQpIHsNCj4gPiAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBjbWRfY3RybF9ub2RlICpjbWRu b2RlID0gcHJpdi0+Y3VyX2NtZDsNCj4gPiBAQCAtODQ5LDE4ICs4NzIsNyBAQCBzdGF0aWMgaW50 IGxic190aHJlYWQodm9pZCAqZGF0YSkNCj4gPiAgICAgICAgICAgICB9DQo+ID4gICAgICAgICAg ICAgcHJpdi0+Y21kX3RpbWVkX291dCA9IDA7DQo+ID4NCj4gPiAtICAgICAgICAgICAvKiBQcm9j ZXNzIGhhcmR3YXJlIGV2ZW50cywgZS5nLiBjYXJkIHJlbW92ZWQsIGxpbmsgbG9zdCAqLw0KPiA+ IC0gICAgICAgICAgIHNwaW5fbG9ja19pcnEoJnByaXYtPmRyaXZlcl9sb2NrKTsNCj4gPiAtICAg ICAgICAgICB3aGlsZSAoX19rZmlmb19sZW4ocHJpdi0+ZXZlbnRfZmlmbykpIHsNCj4gPiAtICAg ICAgICAgICAgICAgICAgIHUzMiBldmVudDsNCj4gPg0KPiA+IC0gICAgICAgICAgICAgICAgICAg X19rZmlmb19nZXQocHJpdi0+ZXZlbnRfZmlmbywgKHVuc2lnbmVkIGNoYXIgKikgJmV2ZW50LA0K PiA+IC0gICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplb2YoZXZlbnQpKTsNCj4gPiAtICAg ICAgICAgICAgICAgICAgIHNwaW5fdW5sb2NrX2lycSgmcHJpdi0+ZHJpdmVyX2xvY2spOw0KPiA+ IC0gICAgICAgICAgICAgICAgICAgbGJzX3Byb2Nlc3NfZXZlbnQocHJpdiwgZXZlbnQpOw0KPiA+ IC0gICAgICAgICAgICAgICAgICAgc3Bpbl9sb2NrX2lycSgmcHJpdi0+ZHJpdmVyX2xvY2spOw0K PiA+IC0gICAgICAgICAgIH0NCj4gPiAtICAgICAgICAgICBzcGluX3VubG9ja19pcnEoJnByaXYt PmRyaXZlcl9sb2NrKTsNCj4gPg0KPiA+ICAgICAgICAgICAgIGlmICghcHJpdi0+ZndfcmVhZHkp DQo+ID4gICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsNCj4gPiBAQCAtODk0LDYgKzkwNiw5 IEBAIHN0YXRpYyBpbnQgbGJzX3RocmVhZCh2b2lkICpkYXRhKQ0KPiA+ICAgICAgICAgICAgICAg ICAocHJpdi0+cHNzdGF0ZSA9PSBQU19TVEFURV9QUkVfU0xFRVApKQ0KPiA+ICAgICAgICAgICAg ICAgICAgICAgY29udGludWU7DQo+ID4NCj4gPiArICAgICAgICAgICBpZiAocHJpdi0+aXNfZGVl cF9zbGVlcCkNCj4gPiArICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOw0KPiA+ICsNCj4gPiAg ICAgICAgICAgICAvKiBFeGVjdXRlIHRoZSBuZXh0IGNvbW1hbmQgKi8NCj4gPiAgICAgICAgICAg ICBpZiAoIXByaXYtPmRubGRfc2VudCAmJiAhcHJpdi0+Y3VyX2NtZCkNCj4gPiAgICAgICAgICAg ICAgICAgICAgIGxic19leGVjdXRlX25leHRfY29tbWFuZChwcml2KTsNCj4gPiBAQCAtOTI4LDYg Kzk0Myw3IEBAIHN0YXRpYyBpbnQgbGJzX3RocmVhZCh2b2lkICpkYXRhKQ0KPiA+ICAgICB9DQo+ ID4NCj4gPiAgICAgZGVsX3RpbWVyKCZwcml2LT5jb21tYW5kX3RpbWVyKTsNCj4gPiArICAgZGVs X3RpbWVyKCZwcml2LT5hdXRvX2RlZXBzbGVlcF90aW1lcik7DQo+ID4gICAgIHdha2VfdXBfYWxs KCZwcml2LT5jbWRfcGVuZGluZyk7DQo+ID4NCj4gPiAgICAgbGJzX2RlYl9sZWF2ZShMQlNfREVC X1RIUkVBRCk7DQo+ID4gQEAgLTEwNTAsNiArMTA2Niw2MCBAQCBvdXQ6DQo+ID4gICAgIGxic19k ZWJfbGVhdmUoTEJTX0RFQl9DTUQpOw0KPiA+ICB9DQo+ID4NCj4gPiArLyoqDQo+ID4gKyAqICBU aGlzIGZ1bmN0aW9uIHB1dCB0aGUgZGV2aWNlIGJhY2sgdG8gZGVlcCBzbGVlcCBtb2RlIHdoZW4g dGltZXIgZXhwaXJlcw0KPiA+ICsgKiAgYW5kIG5vIGFjdGl2aXR5IChjb21tYW5kLCBldmVudCwg ZGF0YSBldGMuKSBpcyBkZXRlY3RlZC4NCj4gPiArICovDQo+ID4gK3N0YXRpYyB2b2lkIGF1dG9f ZGVlcHNsZWVwX3RpbWVyX2ZuKHVuc2lnbmVkIGxvbmcgZGF0YSkNCj4gPiArew0KPiA+ICsgICBz dHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYgPSAoc3RydWN0IGxic19wcml2YXRlICopZGF0YTsNCj4g PiArICAgaW50IHJldDsNCj4gPiArDQo+ID4gKyAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9DTUQp Ow0KPiA+ICsNCj4gPiArICAgaWYgKHByaXYtPmlzX2FjdGl2aXR5X2RldGVjdGVkKSB7DQo+ID4g KyAgICAgICAgICAgcHJpdi0+aXNfYWN0aXZpdHlfZGV0ZWN0ZWQgPSAwOw0KPiA+ICsgICB9IGVs c2Ugew0KPiA+ICsgICAgICAgICAgIGlmIChwcml2LT5pc19hdXRvX2RlZXBfc2xlZXBfZW5hYmxl ZCAmJg0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAoIXByaXYtPndha2V1cF9kZXZf cmVxdWlyZWQpICYmDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcml2LT5jb25u ZWN0X3N0YXR1cyAhPSBMQlNfQ09OTkVDVEVEKSkgew0KPiA+ICsgICAgICAgICAgICAgICAgICAg bGJzX2RlYl9tYWluKCJFbnRlcmluZyBhdXRvIGRlZXAgc2xlZXAgbW9kZS4uLlxuIik7DQo+ID4g KyAgICAgICAgICAgICAgICAgICByZXQgPSBsYnNfcHJlcGFyZV9hbmRfc2VuZF9jb21tYW5kKHBy aXYsDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ01EXzgwMl8xMV9E RUVQX1NMRUVQLCAwLA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDAs IDAsIE5VTEwpOw0KPiA+ICsgICAgICAgICAgIH0NCj4gPiArICAgfQ0KPiA+ICsgICBtb2RfdGlt ZXIoJnByaXYtPmF1dG9fZGVlcHNsZWVwX3RpbWVyICwgamlmZmllcyArDQo+ID4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgIChwcml2LT5hdXRvX2RlZXBfc2xlZXBfdGltZW91dCAqIEhaKS8x MDAwKTsNCj4gPiArICAgbGJzX2RlYl9sZWF2ZShMQlNfREVCX0NNRCk7DQo+ID4gK30NCj4gPiAr DQo+ID4gK2ludCBsYnNfZW50ZXJfYXV0b19kZWVwX3NsZWVwKHN0cnVjdCBsYnNfcHJpdmF0ZSAq cHJpdikNCj4gPiArew0KPiA+ICsgICBsYnNfZGViX2VudGVyKExCU19ERUJfU0RJTyk7DQo+ID4g Kw0KPiA+ICsgICBwcml2LT5pc19hdXRvX2RlZXBfc2xlZXBfZW5hYmxlZCA9IDE7DQo+ID4gKyAg IGlmIChwcml2LT5pc19kZWVwX3NsZWVwKQ0KPiA+ICsgICAgICAgICAgIHByaXYtPndha2V1cF9k ZXZfcmVxdWlyZWQgPSAxOw0KPiA+ICsgICBtb2RfdGltZXIoJnByaXYtPmF1dG9fZGVlcHNsZWVw X3RpbWVyICwNCj4gPiArICAgICAgICAgICAgICAgICAgIGppZmZpZXMgKyAocHJpdi0+YXV0b19k ZWVwX3NsZWVwX3RpbWVvdXQgKiBIWikvMTAwMCk7DQo+ID4gKw0KPiA+ICsgICBsYnNfZGViX2xl YXZlKExCU19ERUJfU0RJTyk7DQo+ID4gKyAgIHJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ ICtpbnQgbGJzX2V4aXRfYXV0b19kZWVwX3NsZWVwKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdikN Cj4gPiArew0KPiA+ICsgICBsYnNfZGViX2VudGVyKExCU19ERUJfU0RJTyk7DQo+ID4gKw0KPiA+ ICsgICBwcml2LT5pc19hdXRvX2RlZXBfc2xlZXBfZW5hYmxlZCA9IDA7DQo+ID4gKyAgIHByaXYt PmF1dG9fZGVlcF9zbGVlcF90aW1lb3V0ID0gMDsNCj4gPiArICAgZGVsX3RpbWVyKCZwcml2LT5h dXRvX2RlZXBzbGVlcF90aW1lcik7DQo+ID4gKw0KPiA+ICsgICBsYnNfZGViX2xlYXZlKExCU19E RUJfU0RJTyk7DQo+ID4gKyAgIHJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICBzdGF0aWMg dm9pZCBsYnNfc3luY19jaGFubmVsX3dvcmtlcihzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspDQo+ ID4gIHsNCj4gPiAgICAgc3RydWN0IGxic19wcml2YXRlICpwcml2ID0gY29udGFpbmVyX29mKHdv cmssIHN0cnVjdCBsYnNfcHJpdmF0ZSwNCj4gPiBAQCAtMTA5OSwxMSArMTE2OSwxNyBAQCBzdGF0 aWMgaW50IGxic19pbml0X2FkYXB0ZXIoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0KPiA+ICAg ICBwcml2LT5jYXBhYmlsaXR5ID0gV0xBTl9DQVBBQklMSVRZX1NIT1JUX1BSRUFNQkxFOw0KPiA+ ICAgICBwcml2LT5wc21vZGUgPSBMQlM4MDJfMTFQT1dFUk1PREVDQU07DQo+ID4gICAgIHByaXYt PnBzc3RhdGUgPSBQU19TVEFURV9GVUxMX1BPV0VSOw0KPiA+ICsgICBwcml2LT5pc19kZWVwX3Ns ZWVwID0gMDsNCj4gPiArICAgcHJpdi0+aXNfYXV0b19kZWVwX3NsZWVwX2VuYWJsZWQgPSAwOw0K PiA+ICsgICBwcml2LT53YWtldXBfZGV2X3JlcXVpcmVkID0gMDsNCj4gPiArICAgaW5pdF93YWl0 cXVldWVfaGVhZCgmcHJpdi0+ZHNfYXdha2VfcSk7DQo+ID4NCj4gPiAgICAgbXV0ZXhfaW5pdCgm cHJpdi0+bG9jayk7DQo+ID4NCj4gPiAgICAgc2V0dXBfdGltZXIoJnByaXYtPmNvbW1hbmRfdGlt ZXIsIGNvbW1hbmRfdGltZXJfZm4sDQo+ID4gICAgICAgICAgICAgKHVuc2lnbmVkIGxvbmcpcHJp dik7DQo+ID4gKyAgIHNldHVwX3RpbWVyKCZwcml2LT5hdXRvX2RlZXBzbGVlcF90aW1lciwgYXV0 b19kZWVwc2xlZXBfdGltZXJfZm4sDQo+ID4gKyAgICAgICAgICAgICAgICAgICAodW5zaWduZWQg bG9uZylwcml2KTsNCj4gPg0KPiA+ICAgICBJTklUX0xJU1RfSEVBRCgmcHJpdi0+Y21kZnJlZXEp Ow0KPiA+ICAgICBJTklUX0xJU1RfSEVBRCgmcHJpdi0+Y21kcGVuZGluZ3EpOw0KPiA+IEBAIC0x MTQyLDYgKzEyMTgsNyBAQCBzdGF0aWMgdm9pZCBsYnNfZnJlZV9hZGFwdGVyKHN0cnVjdCBsYnNf cHJpdmF0ZSAqcHJpdikNCj4gPiAgICAgaWYgKHByaXYtPmV2ZW50X2ZpZm8pDQo+ID4gICAgICAg ICAgICAga2ZpZm9fZnJlZShwcml2LT5ldmVudF9maWZvKTsNCj4gPiAgICAgZGVsX3RpbWVyKCZw cml2LT5jb21tYW5kX3RpbWVyKTsNCj4gPiArICAgZGVsX3RpbWVyKCZwcml2LT5hdXRvX2RlZXBz bGVlcF90aW1lcik7DQo+ID4gICAgIGtmcmVlKHByaXYtPm5ldHdvcmtzKTsNCj4gPiAgICAgcHJp di0+bmV0d29ya3MgPSBOVUxMOw0KPiA+DQo+ID4gQEAgLTEyNzIsNiArMTM0OSwxMSBAQCB2b2lk IGxic19yZW1vdmVfY2FyZChzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYpDQo+ID4gICAgIHdycXUu YXBfYWRkci5zYV9mYW1pbHkgPSBBUlBIUkRfRVRIRVI7DQo+ID4gICAgIHdpcmVsZXNzX3NlbmRf ZXZlbnQocHJpdi0+ZGV2LCBTSU9DR0lXQVAsICZ3cnF1LCBOVUxMKTsNCj4gPg0KPiA+ICsgICBp ZiAocHJpdi0+aXNfZGVlcF9zbGVlcCkgew0KPiA+ICsgICAgICAgICAgIHByaXYtPmlzX2RlZXBf c2xlZXAgPSAwOw0KPiA+ICsgICAgICAgICAgIHdha2VfdXBfaW50ZXJydXB0aWJsZSgmcHJpdi0+ ZHNfYXdha2VfcSk7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIC8qIFN0b3AgdGhlIHRocmVh ZCBzZXJ2aWNpbmcgdGhlIGludGVycnVwdHMgKi8NCj4gPiAgICAgcHJpdi0+c3VycHJpc2VyZW1v dmVkID0gMTsNCj4gPiAgICAga3RocmVhZF9zdG9wKHByaXYtPm1haW5fdGhyZWFkKTsNCj4gPiBA QCAtMTM5Miw2ICsxNDc0LDcgQEAgdm9pZCBsYnNfc3RvcF9jYXJkKHN0cnVjdCBsYnNfcHJpdmF0 ZSAqcHJpdikNCj4gPg0KPiA+ICAgICAvKiBEZWxldGUgdGhlIHRpbWVvdXQgb2YgdGhlIGN1cnJl bnRseSBwcm9jZXNzaW5nIGNvbW1hbmQgKi8NCj4gPiAgICAgZGVsX3RpbWVyX3N5bmMoJnByaXYt PmNvbW1hbmRfdGltZXIpOw0KPiA+ICsgICBkZWxfdGltZXJfc3luYygmcHJpdi0+YXV0b19kZWVw c2xlZXBfdGltZXIpOw0KPiA+DQo+ID4gICAgIC8qIEZsdXNoIHBlbmRpbmcgY29tbWFuZCBub2Rl cyAqLw0KPiA+ICAgICBzcGluX2xvY2tfaXJxc2F2ZSgmcHJpdi0+ZHJpdmVyX2xvY2ssIGZsYWdz KTsNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvc2Nhbi5j IGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvc2Nhbi5jDQo+ID4gaW5kZXggNmM5NWFm My4uZTQ2OGUxNSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRh cy9zY2FuLmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9zY2FuLmMN Cj4gPiBAQCAtOTUwLDYgKzk1MCwxMSBAQCBpbnQgbGJzX3NldF9zY2FuKHN0cnVjdCBuZXRfZGV2 aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1ZXN0X2luZm8gKmluZm8sDQo+ID4NCj4gPiAgICAgbGJz X2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9h bGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAg ICAgICAgIGdvdG8gb3V0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAoIXByaXYtPnJh ZGlvX29uKSB7DQo+ID4gICAgICAgICAgICAgcmV0ID0gLUVJTlZBTDsNCj4gPiAgICAgICAgICAg ICBnb3RvIG91dDsNCj4gPiBAQCAtMTAxNyw2ICsxMDIyLDEyIEBAIGludCBsYnNfZ2V0X3NjYW4o c3RydWN0IG5ldF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4g Pg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYg KCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICBlcnIgPSAtRUJV U1k7DQo+ID4gKyAgICAgICAgICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfV0VYVCwgInJl dCAlZCIsIGVycik7DQo+ID4gKyAgICAgICAgICAgcmV0dXJuIGVycjsNCj4gPiArICAgfQ0KPiA+ ICsNCj4gPiAgICAgLyogaXdsaXN0IHNob3VsZCB3YWl0IHVudGlsIHRoZSBjdXJyZW50IHNjYW4g aXMgZmluaXNoZWQgKi8NCj4gPiAgICAgaWYgKHByaXYtPnNjYW5fY2hhbm5lbCkNCj4gPiAgICAg ICAgICAgICByZXR1cm4gLUVBR0FJTjsNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2ly ZWxlc3MvbGliZXJ0YXMvd2V4dC5jIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvd2V4 dC5jDQo+ID4gaW5kZXggYmU4MzdhMC4uZWYyYjk4NiAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJz L25ldC93aXJlbGVzcy9saWJlcnRhcy93ZXh0LmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJl bGVzcy9saWJlcnRhcy93ZXh0LmMNCj4gPiBAQCAtNDUsNiArNDUsMzEgQEAgc3RhdGljIGlubGlu ZSB2b2lkIGxic19jYW5jZWxfYXNzb2NpYXRpb25fd29yayhzdHJ1Y3QgbGJzX3ByaXZhdGUgKnBy aXYpDQo+ID4gICAgIHByaXYtPnBlbmRpbmdfYXNzb2NfcmVxID0gTlVMTDsNCj4gPiAgfQ0KPiA+ DQo+ID4gKy8qKg0KPiA+ICsgKiAgQGJyaWVmIFRoaXMgZnVuY3Rpb24gY2hlY2tzIGlmIHRoZSBj b21tYW5kIGlzIGFsbG93ZWQuDQo+ID4gKyAqDQo+ID4gKyAqICBAcGFyYW0gcHJpdiAgICAgICAg IEEgcG9pbnRlciB0byBsYnNfcHJpdmF0ZSBzdHJ1Y3R1cmUNCj4gPiArICogIEByZXR1cm4gICAg ICAgICAgICAgYWxsb3dlZCBvciBub3QgYWxsb3dlZC4NCj4gPiArICovDQo+ID4gKw0KPiA+ICtp bnQgbGJzX2lzX2NtZF9hbGxvd2VkKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdikNCj4gPiArew0K PiA+ICsgICBpbnQgICAgICAgICByZXQgPSAxOw0KPiA+ICsNCj4gPiArICAgbGJzX2RlYl9lbnRl cihMQlNfREVCX1dFWFQpOw0KPiA+ICsNCj4gPiArICAgaWYgKCFwcml2LT5pc19hdXRvX2RlZXBf c2xlZXBfZW5hYmxlZCkgew0KPiA+ICsgICAgICAgICAgIGlmIChwcml2LT5pc19kZWVwX3NsZWVw KSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBsYnNfZGViX3dleHQoIklPQ1RMUyBjYWxsZWQg d2hlbiBzdGF0aW9uIg0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJp cyBpbiBkZWVwIHNsZWVwXG4iKTsNCj4gPiArICAgICAgICAgICAgICAgICAgIHJldCA9IDA7DQo+ ID4gKyAgICAgICAgICAgfQ0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICsgICBsYnNfZGViX2xlYXZl KExCU19ERUJfV0VYVCk7DQo+ID4gKyAgIHJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4N Cj4gPiAgLyoqDQo+ID4gICAqICBAYnJpZWYgRmluZCB0aGUgY2hhbm5lbCBmcmVxdWVuY3kgcG93 ZXIgaW5mbyB3aXRoIHNwZWNpZmljIGNoYW5uZWwNCj4gPiBAQCAtMTY4LDYgKzE5MywxMSBAQCBz dGF0aWMgaW50IGxic19nZXRfZnJlcShzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdf cmVxdWVzdF9pbmZvICppbmZvLA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9X RVhUKTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ ICsgICAgICAgICAgIGxic19kZWJfbGVhdmUoTEJTX0RFQl9XRVhUKTsNCj4gPiArICAgICAgICAg ICByZXR1cm4gLUVCVVNZOw0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBjZnAgPSBsYnNfZmlu ZF9jZnBfYnlfYmFuZF9hbmRfY2hhbm5lbChwcml2LCAwLA0KPiA+ICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIHByaXYtPmN1cmJzc3BhcmFtcy5jaGFubmVsKTsNCj4gPg0K PiA+IEBAIC0yNzgsNiArMzA4LDEyIEBAIHN0YXRpYyBpbnQgbGJzX3NldF9ydHMoc3RydWN0IG5l dF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4gPg0KPiA+ICAg ICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNf Y21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4g KyAgICAgICAgICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfV0VYVCwgInJldCAlZCIsIHJl dCk7DQo+ID4gKyAgICAgICAgICAgcmV0dXJuIHJldDsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAg ICAgaWYgKHZ3cnEtPmRpc2FibGVkKQ0KPiA+ICAgICAgICAgICAgIHZhbCA9IE1SVkRSVl9SVFNf TUFYX1ZBTFVFOw0KPiA+DQo+ID4gQEAgLTI5OSw2ICszMzUsMTEgQEAgc3RhdGljIGludCBsYnNf Z2V0X3J0cyhzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICpp bmZvLA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJl dCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBnb3RvIG91dDsNCj4gPiArICAgfQ0KPiA+ICsN Cj4gPiAgICAgcmV0ID0gbGJzX2dldF9zbm1wX21pYihwcml2LCBTTk1QX01JQl9PSURfUlRTX1RI UkVTSE9MRCwgJnZhbCk7DQo+ID4gICAgIGlmIChyZXQpDQo+ID4gICAgICAgICAgICAgZ290byBv dXQ7DQo+ID4gQEAgLTMyMSw2ICszNjIsMTIgQEAgc3RhdGljIGludCBsYnNfc2V0X2ZyYWcoc3Ry dWN0IG5ldF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4gPg0K PiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFs YnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJVU1k7 DQo+ID4gKyAgICAgICAgICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfV0VYVCwgInJldCAl ZCIsIHJldCk7DQo+ID4gKyAgICAgICAgICAgcmV0dXJuIHJldDsNCj4gPiArICAgfQ0KPiA+ICsN Cj4gPiAgICAgaWYgKHZ3cnEtPmRpc2FibGVkKQ0KPiA+ICAgICAgICAgICAgIHZhbCA9IE1SVkRS Vl9GUkFHX01BWF9WQUxVRTsNCj4gPg0KPiA+IEBAIC0zNDIsNiArMzg5LDExIEBAIHN0YXRpYyBp bnQgbGJzX2dldF9mcmFnKHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1ZXN0 X2luZm8gKmluZm8sDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0K PiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAg ICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0Ow0KPiA+ICsgICB9 DQo+ID4gKw0KPiA+ICAgICByZXQgPSBsYnNfZ2V0X3NubXBfbWliKHByaXYsIFNOTVBfTUlCX09J RF9GUkFHX1RIUkVTSE9MRCwgJnZhbCk7DQo+ID4gICAgIGlmIChyZXQpDQo+ID4gICAgICAgICAg ICAgZ290byBvdXQ7DQo+ID4gQEAgLTM5MSw2ICs0NDMsMTEgQEAgc3RhdGljIGludCBsYnNfZ2V0 X3R4cG93KHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRl cihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHBy aXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdv dG8gb3V0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAoIXByaXYtPnJhZGlvX29uKSB7 DQo+ID4gICAgICAgICAgICAgbGJzX2RlYl93ZXh0KCJ0eCBwb3dlciBvZmZcbiIpOw0KPiA+ICAg ICAgICAgICAgIHZ3cnEtPnZhbHVlID0gMDsNCj4gPiBAQCAtNDI0LDYgKzQ4MSwxMSBAQCBzdGF0 aWMgaW50IGxic19zZXRfcmV0cnkoc3RydWN0IG5ldF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3Jl cXVlc3RfaW5mbyAqaW5mbywNCj4gPg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VY VCk7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiAr ICAgICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4gKyAgICAgICAgICAgZ290byBvdXQ7DQo+ID4g KyAgIH0NCj4gPiArDQo+ID4gICAgICAgICAgaWYgKCh2d3JxLT5mbGFncyAmIElXX1JFVFJZX1RZ UEUpICE9IElXX1JFVFJZX0xJTUlUKQ0KPiA+ICAgICAgICAgICAgICAgICAgcmV0dXJuIC1FT1BO T1RTVVBQOw0KPiA+DQo+ID4gQEAgLTQ3Miw2ICs1MzQsMTEgQEAgc3RhdGljIGludCBsYnNfZ2V0 X3JldHJ5KHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1ZXN0X2luZm8gKmlu Zm8sDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4g KyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0 ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0Ow0KPiA+ICsgICB9DQo+ID4gKw0K PiA+ICAgICB2d3JxLT5kaXNhYmxlZCA9IDA7DQo+ID4NCj4gPiAgICAgaWYgKHZ3cnEtPmZsYWdz ICYgSVdfUkVUUllfTE9ORykgew0KPiA+IEBAIC03MTIsNiArNzc5LDExIEBAIHN0YXRpYyBpbnQg bGJzX3NldF9wb3dlcihzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9p bmZvICppbmZvLA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4g Pg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAg ICAgIGxic19kZWJfbGVhdmUoTEJTX0RFQl9XRVhUKTsNCj4gPiArICAgICAgICAgICByZXR1cm4g LUVCVVNZOw0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAoIShwcml2LT5md2NhcGluZm8g JiBGV19DQVBJTkZPX1BTKSkgew0KPiA+ICAgICAgICAgICAgIGlmICh2d3JxLT5kaXNhYmxlZCkN Cj4gPiAgICAgICAgICAgICAgICAgICAgIHJldHVybiAwOw0KPiA+IEBAIC03OTIsNiArODY0LDkg QEAgc3RhdGljIHN0cnVjdCBpd19zdGF0aXN0aWNzICpsYnNfZ2V0X3dpcmVsZXNzX3N0YXRzKHN0 cnVjdCBuZXRfZGV2aWNlICpkZXYpDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVC X1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKQ0KPiA+ ICsgICAgICAgICAgIHJldHVybiBOVUxMOw0KPiA+ICsNCj4gPiAgICAgcHJpdi0+d3N0YXRzLnN0 YXR1cyA9IHByaXYtPm1vZGU7DQo+ID4NCj4gPiAgICAgLyogSWYgd2UncmUgbm90IGFzc29jaWF0 ZWQsIGFsbCBxdWFsaXR5IHZhbHVlcyBhcmUgbWVhbmluZ2xlc3MgKi8NCj4gPiBAQCAtODkyLDYg Kzk2NywxMiBAQCBzdGF0aWMgaW50IGxic19zZXRfZnJlcShzdHJ1Y3QgbmV0X2RldmljZSAqZGV2 LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZvLA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50 ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChw cml2KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBs YnNfZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9XRVhULCAicmV0ICVkIiwgcmV0KTsNCj4gPiArICAg ICAgICAgICByZXR1cm4gcmV0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBtdXRleF9sb2Nr KCZwcml2LT5sb2NrKTsNCj4gPiAgICAgYXNzb2NfcmVxID0gbGJzX2dldF9hc3NvY2lhdGlvbl9y ZXF1ZXN0KHByaXYpOw0KPiA+ICAgICBpZiAoIWFzc29jX3JlcSkgew0KPiA+IEBAIC0xMDAwLDYg KzEwODEsMTIgQEAgc3RhdGljIGludCBsYnNfc2V0X3JhdGUoc3RydWN0IG5ldF9kZXZpY2UgKmRl diwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4gPiAgICAgdTggcmF0ZXNbTUFYX1JB VEVTICsgMV07DQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+ ICsNCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAg ICAgICByZXQgPSAtRUJVU1k7DQo+ID4gKyAgICAgICAgICAgZ290byBvdXQ7DQo+ID4gKyAgIH0N Cj4gPiArDQo+ID4gICAgIGxic19kZWJfd2V4dCgidndycS0+dmFsdWUgJWRcbiIsIHZ3cnEtPnZh bHVlKTsNCj4gPiAgICAgbGJzX2RlYl93ZXh0KCJ2d3JxLT5maXhlZCAlZFxuIiwgdndycS0+Zml4 ZWQpOw0KPiA+DQo+ID4gQEAgLTEwNTgsNiArMTE0NSwxMSBAQCBzdGF0aWMgaW50IGxic19nZXRf cmF0ZShzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZv LA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsg ICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIGxic19k ZWJfbGVhdmUoTEJTX0RFQl9XRVhUKTsNCj4gPiArICAgICAgICAgICByZXR1cm4gLUVCVVNZOw0K PiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAocHJpdi0+Y29ubmVjdF9zdGF0dXMgPT0gTEJT X0NPTk5FQ1RFRCkgew0KPiA+ICAgICAgICAgICAgIHZ3cnEtPnZhbHVlID0gcHJpdi0+Y3VyX3Jh dGUgKiA1MDAwMDA7DQo+ID4NCj4gPiBAQCAtMTA4NCw2ICsxMTc2LDExIEBAIHN0YXRpYyBpbnQg bGJzX3NldF9tb2RlKHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsDQo+ID4NCj4gPiAgICAgbGJzX2Rl Yl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxv d2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAg ICAgIGdvdG8gb3V0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAoICAgKCp1d3JxICE9 IElXX01PREVfQURIT0MpDQo+ID4gICAgICAgICAmJiAoKnV3cnEgIT0gSVdfTU9ERV9JTkZSQSkN Cj4gPiAgICAgICAgICYmICgqdXdycSAhPSBJV19NT0RFX0FVVE8pKSB7DQo+ID4gQEAgLTEzMjUs NiArMTQyMiwxMiBAQCBzdGF0aWMgaW50IGxic19zZXRfZW5jb2RlKHN0cnVjdCBuZXRfZGV2aWNl ICpkZXYsDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAg cmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGxic19kZWJfbGVhdmVfYXJncyhMQlNfREVC X1dFWFQsICJyZXQgJWQiLCByZXQpOw0KPiA+ICsgICAgICAgICAgIHJldHVybiByZXQ7DQo+ID4g KyAgIH0NCj4gPiArDQo+ID4gICAgIG11dGV4X2xvY2soJnByaXYtPmxvY2spOw0KPiA+ICAgICBh c3NvY19yZXEgPSBsYnNfZ2V0X2Fzc29jaWF0aW9uX3JlcXVlc3QocHJpdik7DQo+ID4gICAgIGlm ICghYXNzb2NfcmVxKSB7DQo+ID4gQEAgLTE1MDgsNiArMTYxMSwxMiBAQCBzdGF0aWMgaW50IGxi c19zZXRfZW5jb2RlZXh0KHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsDQo+ID4NCj4gPiAgICAgbGJz X2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9h bGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAg ICAgICAgIGxic19kZWJfbGVhdmVfYXJncyhMQlNfREVCX1dFWFQsICJyZXQgJWQiLCByZXQpOw0K PiA+ICsgICAgICAgICAgIHJldHVybiByZXQ7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIG11 dGV4X2xvY2soJnByaXYtPmxvY2spOw0KPiA+ICAgICBhc3NvY19yZXEgPSBsYnNfZ2V0X2Fzc29j aWF0aW9uX3JlcXVlc3QocHJpdik7DQo+ID4gICAgIGlmICghYXNzb2NfcmVxKSB7DQo+ID4gQEAg LTE3MjAsNiArMTgyOSwxMiBAQCBzdGF0aWMgaW50IGxic19zZXRfYXV0aChzdHJ1Y3QgbmV0X2Rl dmljZSAqZGV2LA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4g Pg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAg ICAgIHJldCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBsYnNfZGViX2xlYXZlX2FyZ3MoTEJT X0RFQl9XRVhULCAicmV0ICVkIiwgcmV0KTsNCj4gPiArICAgICAgICAgICByZXR1cm4gcmV0Ow0K PiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBtdXRleF9sb2NrKCZwcml2LT5sb2NrKTsNCj4gPiAg ICAgYXNzb2NfcmVxID0gbGJzX2dldF9hc3NvY2lhdGlvbl9yZXF1ZXN0KHByaXYpOw0KPiA+ICAg ICBpZiAoIWFzc29jX3JlcSkgew0KPiA+IEBAIC0xODIyLDYgKzE5MzcsMTIgQEAgc3RhdGljIGlu dCBsYnNfZ2V0X2F1dGgoc3RydWN0IG5ldF9kZXZpY2UgKmRldiwNCj4gPg0KPiA+ICAgICBsYnNf ZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2Fs bG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4gKyAgICAg ICAgICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfV0VYVCwgInJldCAlZCIsIHJldCk7DQo+ ID4gKyAgICAgICAgICAgcmV0dXJuIHJldDsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgc3dp dGNoIChkd3JxLT5mbGFncyAmIElXX0FVVEhfSU5ERVgpIHsNCj4gPiAgICAgY2FzZSBJV19BVVRI X0tFWV9NR01UOg0KPiA+ICAgICAgICAgICAgIGR3cnEtPnZhbHVlID0gcHJpdi0+c2VjaW5mby5r ZXlfbWdtdDsNCj4gPiBAQCAtMTg2NCw2ICsxOTg1LDExIEBAIHN0YXRpYyBpbnQgbGJzX3NldF90 eHBvdyhzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvDQo+ICpp bmZvLA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJl dCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBnb3RvIG91dDsNCj4gPiArICAgfQ0KPiA+ICsN Cj4gPiAgICAgaWYgKHZ3cnEtPmRpc2FibGVkKSB7DQo+ID4gICAgICAgICAgICAgbGJzX3NldF9y YWRpbyhwcml2LCBSQURJT19QUkVBTUJMRV9BVVRPLCAwKTsNCj4gPiAgICAgICAgICAgICBnb3Rv IG91dDsNCj4gPiBAQCAtMTk4Myw2ICsyMTA5LDEyIEBAIHN0YXRpYyBpbnQgbGJzX3NldF9lc3Np ZChzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvDQo+ICppbmZv LA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsg ICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9 IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBsYnNfZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9XRVhU LCAicmV0ICVkIiwgcmV0KTsNCj4gPiArICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiA+ICsgICB9 DQo+ID4gKw0KPiA+ICAgICBpZiAoIXByaXYtPnJhZGlvX29uKSB7DQo+ID4gICAgICAgICAgICAg cmV0ID0gLUVJTlZBTDsNCj4gPiAgICAgICAgICAgICBnb3RvIG91dDsNCj4gPiBAQCAtMjExMCw2 ICsyMjQyLDEyIEBAIHN0YXRpYyBpbnQgbGJzX3NldF93YXAoc3RydWN0IG5ldF9kZXZpY2UgKmRl diwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4gPg0KPiA+ICAgICBsYnNfZGViX2Vu dGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQo cHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4gKyAgICAgICAgICAg bGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfV0VYVCwgInJldCAlZCIsIHJldCk7DQo+ID4gKyAg ICAgICAgICAgcmV0dXJuIHJldDsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgaWYgKCFwcml2 LT5yYWRpb19vbikNCj4gPiAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsNCj4gPg0KDQo= ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-28 22:42 ` Bing Zhao @ 2009-09-29 7:04 ` Holger Schurig 2009-09-29 18:36 ` Bing Zhao 2009-09-29 7:24 ` Holger Schurig 2009-10-01 18:00 ` Dan Williams 2 siblings, 1 reply; 14+ messages in thread From: Holger Schurig @ 2009-09-29 7:04 UTC (permalink / raw) To: Bing Zhao Cc: Dan Williams, libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar Hi Bing ! Please note that I just sent an experimental patch to enable cfg80211 for libertas. Once this is polished, you can immediately start using nl80211/cfg80211 to configure such things, there's no need to have the full thingy (e.g. wpa_supplicant via -Dnl80211 working with WEP/WPA/WPA2) working, those things are not interrelated. -- http://www.holgerschurig.de ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-29 7:04 ` Holger Schurig @ 2009-09-29 18:36 ` Bing Zhao 0 siblings, 0 replies; 14+ messages in thread From: Bing Zhao @ 2009-09-29 18:36 UTC (permalink / raw) To: Holger Schurig Cc: Dan Williams, libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar Hi Holger, > From: Holger Schurig [hs4233@mail.mn-solutions.de] > Sent: Tuesday, September 29, 2009 12:04 AM > To: Bing Zhao > Cc: Dan Williams; libertas-dev@lists.infradead.org; linux-wireless@vger.kernel.org; Amitkumar Karwar > Subject: Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 > > Hi Bing ! > > Please note that I just sent an experimental patch to enable > cfg80211 for libertas. > > Once this is polished, you can immediately start using > nl80211/cfg80211 to configure such things, there's no need to > have the full thingy (e.g. wpa_supplicant via -Dnl80211 working > with WEP/WPA/WPA2) working, those things are not interrelated. Thanks for the info. I will start to use nl80211/cfg80211 to configure my parameters as soon as your patch is in libertas driver. Best regards, Bing > > > -- > http://www.holgerschurig.de ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-28 22:42 ` Bing Zhao 2009-09-29 7:04 ` Holger Schurig @ 2009-09-29 7:24 ` Holger Schurig 2009-10-01 18:00 ` Dan Williams 2 siblings, 0 replies; 14+ messages in thread From: Holger Schurig @ 2009-09-29 7:24 UTC (permalink / raw) To: Bing Zhao Cc: Dan Williams, libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar > iwconfig wlan0 power period 0 -> enable deep sleep (enter > deep sleep immediately) > iwconfig wlan0 power period 5 -> enable auto deep sleep > (enter deep sleep automatically after 5s idle time) > iwconfig wlan0 power period -1 -> disable deep sleep / auto > deep sleep ACK from my side (not that I'm the maintainer ...) -- http://www.holgerschurig.de ^ permalink raw reply [flat|nested] 14+ messages in thread
* RE: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-09-28 22:42 ` Bing Zhao 2009-09-29 7:04 ` Holger Schurig 2009-09-29 7:24 ` Holger Schurig @ 2009-10-01 18:00 ` Dan Williams 2 siblings, 0 replies; 14+ messages in thread From: Dan Williams @ 2009-10-01 18:00 UTC (permalink / raw) To: Bing Zhao Cc: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar On Mon, 2009-09-28 at 15:42 -0700, Bing Zhao wrote: > Hi Dan, > > > -----Original Message----- > > From: Dan Williams [mailto:dcbw@redhat.com] > > Sent: Sunday, September 20, 2009 7:58 AM > > To: Bing Zhao > > Cc: libertas-dev@lists.infradead.org; linux-wireless@vger.kernel.org; Amitkumar Karwar > > Subject: Re: [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 > > > > On Tue, 2009-09-15 at 16:45 -0700, Bing Zhao wrote: > > > From: Amitkumar Karwar <akarwar@marvell.com> > > > > > > Add timer based auto deep sleep feature in libertas driver which can be > > > configured through debugfs interface. This is tested on SD8688, SD8686 cards > > > with firmware versions 10.38.1.p25, 9.70.4.p0 respectively on 32-bit and 64-bit > > > platforms. Tests have been done for USB/CS cards to make sure that the patch > > > won't break USB/CS code. We didn't test the if_spi driver. > > > > So there's always: > > > > #define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/ > > > > iwconfig wlan0 power saving 10 > > > > That seems quite a bit better than a new debugfs parameter, until we can > > conver the driver over cfg80211 and do this properly. If the power > > saving mode is higher than some number X, the chip gets put into deep > > sleep mode, or it can be automatically placed in deep sleep mode by the > > driver when there is no association like you have done with the timer > > above. I think you should pick reasonable defaults, and perhaps if the > > 'saving' value is larger, the timer value in the driver gets smaller. > > > > Does that sound like an OK approach? We really should be using debugfs > > only for debugging stuff (obviously), and the real fix for this sort of > > thing is to switch over to cfg80211 where we can actually extend the > > configuration API instead of hacking it into debugfs/WEXT/etc. > > > > Dan > > Thanks for your suggestion. > > In latest kernel, IW_POWER_SAVING is not defined in include/linux/wireless.h. > IW_POWER_PERIOD and IW_POWER_TIMEOUT are defined though. You're right. wireless-tools apparently had it, but since WEXT is on life-support, John removed most of the additions before WE-21 got committed to the kernel. So it's not there. > We are planning to remove debugfs for configurations and use the following commands instead. > Please let us know if there is any concern. > > iwconfig wlan0 power period 0 -> enable deep sleep (enter deep sleep immediately) > iwconfig wlan0 power period 5 -> enable auto deep sleep (enter deep sleep automatically after 5s idle time) > iwconfig wlan0 power period -1 -> disable deep sleep / auto deep sleep Sure, that seems fine to me. dan > By the way, there is a bug in iwconfig tool v29. It doesn’t take any values right after "period" or "timeout". The new version of Wireless Tools v30-pre8 (link below) fixed the bug: > > http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/wireless_tools.30.pre8.tar.gz > > Thanks, > > Bing > > > > > > Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> > > > Signed-off-by: Bing Zhao <bzhao@marvell.com> > > > --- > > > drivers/net/wireless/libertas/README | 28 +++++- > > > drivers/net/wireless/libertas/cmd.c | 72 +++++++++++++- > > > drivers/net/wireless/libertas/cmdresp.c | 12 +++ > > > drivers/net/wireless/libertas/debugfs.c | 160 +++++++++++++++++++++++++++++++ > > > drivers/net/wireless/libertas/decl.h | 4 + > > > drivers/net/wireless/libertas/dev.h | 18 ++++ > > > drivers/net/wireless/libertas/host.h | 1 + > > > drivers/net/wireless/libertas/if_cs.c | 3 + > > > drivers/net/wireless/libertas/if_sdio.c | 56 +++++++++++ > > > drivers/net/wireless/libertas/if_sdio.h | 3 +- > > > drivers/net/wireless/libertas/if_spi.c | 3 + > > > drivers/net/wireless/libertas/if_usb.c | 3 + > > > drivers/net/wireless/libertas/main.c | 111 +++++++++++++++++++--- > > > drivers/net/wireless/libertas/scan.c | 11 ++ > > > drivers/net/wireless/libertas/wext.c | 138 ++++++++++++++++++++++++++ > > > 15 files changed, 604 insertions(+), 19 deletions(-) > > > > > > diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README > > > index ab6a2d5..059ce8c 100644 > > > --- a/drivers/net/wireless/libertas/README > > > +++ b/drivers/net/wireless/libertas/README > > > @@ -1,5 +1,5 @@ > > > ================================================================================ > > > - README for USB8388 > > > + README for Libertas > > > > > > (c) Copyright © 2003-2006, Marvell International Ltd. > > > All Rights Reserved > > > @@ -226,4 +226,30 @@ setuserscan > > > All entries in the scan table (not just the new scan data when keep=1) > > > will be displayed upon completion by use of the getscantable ioctl. > > > > > > +deepsleep > > > + > > > + This command is used to configure the station in deep sleep mode/auto > > > + deep sleep mode. Command expects two parameters: > > > + 'state' 'idle time period' > > > + > > > + The timer is implemented to monitor the activities (command, event, > > > + data, etc.). When an activity is detected station will exit from deep > > > + sleep mode automatically and restart the timer. At timer expiry (no > > > + activity for defined time period) the deepsleep mode is entered > > > + automatically. > > > + > > > + Note: this command is for SDIO interface only. > > > + > > > + Path: /sys/kernel/debug/libertas_wireless/ethX/ > > > + > > > + Usage: > > > + To read the current status of deep sleep do: > > > + cat deepsleep > > > + To enable deep sleep mode do: > > > + echo '1 0' > deepsleep > > > + To enable auto deep sleep mode with idle time period 5 seconds do: > > > + echo '1 5000' > deepsleep > > > + To disable deep sleep/auto deep sleep mode do: > > > + echo '0 0' > deepsleep > > > + > > > ============================================================================== > > > diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c > > > index 6850981..3a3e894 100644 > > > --- a/drivers/net/wireless/libertas/cmd.c > > > +++ b/drivers/net/wireless/libertas/cmd.c > > > @@ -17,7 +17,6 @@ > > > > > > static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); > > > > > > - > > > /** > > > * @brief Simple callback that copies response back into command > > > * > > > @@ -319,6 +318,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, > > > return 0; > > > } > > > > > > +static int lbs_wait_for_ds_awake(struct lbs_private *priv) > > > +{ > > > + int ret = 0; > > > + > > > + lbs_deb_enter(LBS_DEB_CMD); > > > + > > > + if (priv->is_deep_sleep) { > > > + if (!wait_event_interruptible_timeout(priv->ds_awake_q, > > > + !priv->is_deep_sleep, (10 * HZ))) { > > > + lbs_pr_err("ds_awake_q: timer expired\n"); > > > + ret = -1; > > > + } > > > + } > > > + > > > + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); > > > + return ret; > > > +} > > > + > > > +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) > > > +{ > > > + int ret = 0; > > > + > > > + lbs_deb_enter(LBS_DEB_CMD); > > > + > > > + if (deep_sleep) { > > > + if (priv->is_deep_sleep != 1) { > > > + lbs_deb_cmd("deep sleep: sleep\n"); > > > + BUG_ON(!priv->enter_deep_sleep); > > > + ret = priv->enter_deep_sleep(priv); > > > + if (!ret) { > > > + netif_stop_queue(priv->dev); > > > + netif_carrier_off(priv->dev); > > > + } > > > + } else { > > > + lbs_pr_err("deep sleep: already enabled\n"); > > > + } > > > + } else { > > > + if (priv->is_deep_sleep) { > > > + lbs_deb_cmd("deep sleep: wakeup\n"); > > > + BUG_ON(!priv->exit_deep_sleep); > > > + ret = priv->exit_deep_sleep(priv); > > > + if (!ret) { > > > + ret = lbs_wait_for_ds_awake(priv); > > > + if (ret) > > > + lbs_pr_err("deep sleep: wakeup" > > > + "failed\n"); > > > + } > > > + } > > > + } > > > + > > > + lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); > > > + return ret; > > > +} > > > + > > > int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, > > > struct assoc_request *assoc) > > > { > > > @@ -1242,8 +1295,17 @@ static void lbs_submit_command(struct lbs_private *priv, > > > timeo = HZ/4; > > > } > > > > > > - /* Setup the timer after transmit command */ > > > - mod_timer(&priv->command_timer, jiffies + timeo); > > > + 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 { > > > + /* Setup the timer after transmit command */ > > > + mod_timer(&priv->command_timer, jiffies + timeo); > > > + } > > > > > > lbs_deb_leave(LBS_DEB_HOST); > > > } > > > @@ -1505,6 +1567,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, > > > case CMD_802_11_BEACON_CTRL: > > > ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); > > > break; > > > + case CMD_802_11_DEEP_SLEEP: > > > + cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); > > > + cmdptr->size = cpu_to_le16(S_DS_GEN); > > > + break; > > > default: > > > lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); > > > ret = -1; > > > diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c > > > index c42d3fa..47d2b19 100644 > > > --- a/drivers/net/wireless/libertas/cmdresp.c > > > +++ b/drivers/net/wireless/libertas/cmdresp.c > > > @@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event) > > > > > > case MACREG_INT_CODE_HOST_AWAKE: > > > lbs_deb_cmd("EVENT: host awake\n"); > > > + if (priv->reset_deep_sleep_wakeup) > > > + priv->reset_deep_sleep_wakeup(priv); > > > + priv->is_deep_sleep = 0; > > > lbs_send_confirmwake(priv); > > > break; > > > > > > + case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: > > > + if (priv->reset_deep_sleep_wakeup) > > > + priv->reset_deep_sleep_wakeup(priv); > > > + lbs_deb_cmd("EVENT: ds awake\n"); > > > + priv->is_deep_sleep = 0; > > > + priv->wakeup_dev_required = 0; > > > + wake_up_interruptible(&priv->ds_awake_q); > > > + break; > > > + > > > case MACREG_INT_CODE_PS_AWAKE: > > > lbs_deb_cmd("EVENT: ps awake\n"); > > > /* handle unexpected PS AWAKE event */ > > > diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c > > > index 893a55c..624a438 100644 > > > --- a/drivers/net/wireless/libertas/debugfs.c > > > +++ b/drivers/net/wireless/libertas/debugfs.c > > > @@ -117,6 +117,11 @@ static ssize_t lbs_sleepparams_write(struct file *file, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out_unlock; > > > + } > > > + > > > buf_size = min(count, len - 1); > > > if (copy_from_user(buf, user_buf, buf_size)) { > > > ret = -EFAULT; > > > @@ -157,6 +162,11 @@ static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out_unlock; > > > + } > > > + > > > ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp); > > > if (ret) > > > goto out_unlock; > > > @@ -173,6 +183,118 @@ out_unlock: > > > return ret; > > > } > > > > > > +static ssize_t lbs_deepsleep_read(struct file *file, char __user *userbuf, > > > + size_t count, loff_t *ppos) > > > +{ > > > + struct lbs_private *priv = file->private_data; > > > + ssize_t pos = 0; > > > + int ret; > > > + unsigned long addr = get_zeroed_page(GFP_KERNEL); > > > + char *buf = (char *)addr; > > > + > > > + if (!buf) > > > + return -ENOMEM; > > > + > > > + if (!priv->enter_deep_sleep) { > > > + lbs_pr_err("deep sleep feature is not implemented " > > > + "for this interface driver\n"); > > > + ret = -EINVAL; > > > + goto out_ds; > > > + } > > > + > > > + if (priv->is_auto_deep_sleep_enabled) > > > + pos += snprintf(buf, len, "%d %d\n", > > > + priv->is_auto_deep_sleep_enabled, > > > + priv->auto_deep_sleep_timeout); > > > + else if (priv->is_deep_sleep) > > > + pos += snprintf(buf, len, "%d %d\n", > > > + priv->is_deep_sleep, > > > + priv->auto_deep_sleep_timeout); > > > + else > > > + pos += snprintf(buf, len, "%d %d\n", > > > + priv->is_deep_sleep, > > > + priv->auto_deep_sleep_timeout); > > > + > > > + ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); > > > + > > > +out_ds: > > > + free_page(addr); > > > + return ret; > > > +} > > > + > > > +static ssize_t lbs_deepsleep_write(struct file *file, > > > + const char __user *userbuf, > > > + size_t count, loff_t *ppos) > > > +{ > > > + struct lbs_private *priv = file->private_data; > > > + ssize_t res, buf_size; > > > + int is_deep_sleep, auto_deep_sleep_timeout; > > > + unsigned long addr = get_zeroed_page(GFP_KERNEL); > > > + char *buf = (char *)addr; > > > + > > > + if (!buf) > > > + return -ENOMEM; > > > + > > > + if (!priv->enter_deep_sleep) { > > > + lbs_pr_err("deep sleep feature is not implemented " > > > + "for this interface driver\n"); > > > + res = -EINVAL; > > > + goto out_ds; > > > + } > > > + > > > + if (priv->connect_status == LBS_CONNECTED) { > > > + lbs_pr_err("can't use deep sleep cmd in connected " > > > + "state\n"); > > > + res = -EINVAL; > > > + goto out_ds; > > > + } > > > + > > > + buf_size = min(count, len - 1); > > > + if (copy_from_user(buf, userbuf, buf_size)) { > > > + res = -EFAULT; > > > + goto out_ds; > > > + } > > > + > > > + res = sscanf(buf, "%d %d", &is_deep_sleep, &auto_deep_sleep_timeout); > > > + if ((res != 2) || (!is_deep_sleep && auto_deep_sleep_timeout) || > > > + !((is_deep_sleep == 1) || > > > + (is_deep_sleep == 0))) { > > > + lbs_pr_err("unknown option\n"); > > > + res = -EINVAL; > > > + goto out_ds; > > > + } > > > + > > > + if (auto_deep_sleep_timeout) { > > > + if (!priv->is_auto_deep_sleep_enabled) { > > > + priv->is_activity_detected = 0; > > > + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout; > > > + lbs_enter_auto_deep_sleep(priv); > > > + } else { > > > + priv->auto_deep_sleep_timeout = auto_deep_sleep_timeout; > > > + lbs_deb_debugfs("auto deep sleep: already enabled\n"); > > > + } > > > + } else { > > > + if (priv->is_auto_deep_sleep_enabled) { > > > + lbs_exit_auto_deep_sleep(priv); > > > + /* Try to exit deep sleep if auto deep sleep disabled */ > > > + res = lbs_set_deep_sleep(priv, 0); > > > + if (res) > > > + goto out_ds; > > > + } > > > + if ((is_deep_sleep == 0) || (is_deep_sleep == 1)) { > > > + res = lbs_set_deep_sleep(priv, is_deep_sleep); > > > + if (res) > > > + goto out_ds; > > > + } > > > + } > > > + > > > + res = count; > > > + > > > +out_ds: > > > + free_page(addr); > > > + return res; > > > +} > > > + > > > /* > > > * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might > > > * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the > > > @@ -223,6 +345,9 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask, > > > u8 freq; > > > int events = 0; > > > > > > + if (!lbs_is_cmd_allowed(priv)) > > > + return -EBUSY; > > > + > > > buf = (char *)get_zeroed_page(GFP_KERNEL); > > > if (!buf) > > > return -ENOMEM; > > > @@ -275,6 +400,9 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, > > > char *buf; > > > int ret; > > > > > > + if (!lbs_is_cmd_allowed(priv)) > > > + return -EBUSY; > > > + > > > buf = (char *)get_zeroed_page(GFP_KERNEL); > > > if (!buf) > > > return -ENOMEM; > > > @@ -444,6 +572,11 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + free_page(addr); > > > + return -EBUSY; > > > + } > > > + > > > offval.offset = priv->mac_offset; > > > offval.value = 0; > > > > > > @@ -496,6 +629,11 @@ static ssize_t lbs_wrmac_write(struct file *file, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + res = -EBUSY; > > > + goto out_unlock; > > > + } > > > + > > > buf_size = min(count, len - 1); > > > if (copy_from_user(buf, userbuf, buf_size)) { > > > res = -EFAULT; > > > @@ -532,6 +670,11 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + free_page(addr); > > > + return -EBUSY; > > > + } > > > + > > > offval.offset = priv->bbp_offset; > > > offval.value = 0; > > > > > > @@ -585,6 +728,11 @@ static ssize_t lbs_wrbbp_write(struct file *file, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + res = -EBUSY; > > > + goto out_unlock; > > > + } > > > + > > > buf_size = min(count, len - 1); > > > if (copy_from_user(buf, userbuf, buf_size)) { > > > res = -EFAULT; > > > @@ -621,6 +769,11 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + free_page(addr); > > > + return -EBUSY; > > > + } > > > + > > > offval.offset = priv->rf_offset; > > > offval.value = 0; > > > > > > @@ -674,6 +827,11 @@ static ssize_t lbs_wrrf_write(struct file *file, > > > if (!buf) > > > return -ENOMEM; > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + res = -EBUSY; > > > + goto out_unlock; > > > + } > > > + > > > buf_size = min(count, len - 1); > > > if (copy_from_user(buf, userbuf, buf_size)) { > > > res = -EFAULT; > > > @@ -717,6 +875,8 @@ static const struct lbs_debugfs_files debugfs_files[] = { > > > write_file_dummy), }, > > > { "sleepparams", 0644, FOPS(lbs_sleepparams_read, > > > lbs_sleepparams_write), }, > > > + { "deepsleep", 0644, FOPS(lbs_deepsleep_read, > > > + lbs_deepsleep_write), }, > > > }; > > > > > > static const struct lbs_debugfs_files debugfs_events_files[] = { > > > diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h > > > index 0b84bdc..34b475f 100644 > > > --- a/drivers/net/wireless/libertas/decl.h > > > +++ b/drivers/net/wireless/libertas/decl.h > > > @@ -33,6 +33,10 @@ int lbs_execute_next_command(struct lbs_private *priv); > > > int lbs_process_event(struct lbs_private *priv, u32 event); > > > void lbs_queue_event(struct lbs_private *priv, u32 event); > > > void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); > > > +int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); > > > +int lbs_is_cmd_allowed(struct lbs_private *priv); > > > +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 578c697..e2b4ef2 100644 > > > --- a/drivers/net/wireless/libertas/dev.h > > > +++ b/drivers/net/wireless/libertas/dev.h > > > @@ -129,6 +129,20 @@ struct lbs_private { > > > u32 bbp_offset; > > > u32 rf_offset; > > > > > > + /** Deep sleep flag */ > > > + int is_deep_sleep; > > > + /** Auto deep sleep enabled flag */ > > > + int is_auto_deep_sleep_enabled; > > > + /** Device wakeup required flag */ > > > + int wakeup_dev_required; > > > + /** Auto deep sleep flag*/ > > > + int is_activity_detected; > > > + /** Auto deep sleep timeout (in miliseconds) */ > > > + int auto_deep_sleep_timeout; > > > + > > > + /** Deep sleep wait queue */ > > > + wait_queue_head_t ds_awake_q; > > > + > > > /* Download sent: > > > bit0 1/0=data_sent/data_tx_done, > > > bit1 1/0=cmd_sent/cmd_tx_done, > > > @@ -154,6 +168,9 @@ struct lbs_private { > > > /** Hardware access */ > > > int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); > > > void (*reset_card) (struct lbs_private *priv); > > > + int (*enter_deep_sleep) (struct lbs_private *priv); > > > + int (*exit_deep_sleep) (struct lbs_private *priv); > > > + int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); > > > > > > /* Wake On LAN */ > > > uint32_t wol_criteria; > > > @@ -204,6 +221,7 @@ struct lbs_private { > > > > > > /** Timers */ > > > struct timer_list command_timer; > > > + struct timer_list auto_deepsleep_timer; > > > int nr_retries; > > > int cmd_timed_out; > > > > > > diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h > > > index fe8f0cb..c055daa 100644 > > > --- a/drivers/net/wireless/libertas/host.h > > > +++ b/drivers/net/wireless/libertas/host.h > > > @@ -57,6 +57,7 @@ > > > #define CMD_802_11_ENABLE_RSN 0x002f > > > #define CMD_802_11_SET_AFC 0x003c > > > #define CMD_802_11_GET_AFC 0x003d > > > +#define CMD_802_11_DEEP_SLEEP 0x003e > > > #define CMD_802_11_AD_HOC_STOP 0x0040 > > > #define CMD_802_11_HOST_SLEEP_CFG 0x0043 > > > #define CMD_802_11_WAKEUP_CONFIRM 0x0044 > > > diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c > > > index 6238176..465742f 100644 > > > --- a/drivers/net/wireless/libertas/if_cs.c > > > +++ b/drivers/net/wireless/libertas/if_cs.c > > > @@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) > > > card->priv = priv; > > > priv->card = card; > > > priv->hw_host_to_card = if_cs_host_to_card; > > > + priv->enter_deep_sleep = NULL; > > > + priv->exit_deep_sleep = NULL; > > > + priv->reset_deep_sleep_wakeup = NULL; > > > priv->fw_ready = 1; > > > > > > /* Now actually get the IRQ */ > > > diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c > > > index 485a8d4..9716728 100644 > > > --- a/drivers/net/wireless/libertas/if_sdio.c > > > +++ b/drivers/net/wireless/libertas/if_sdio.c > > > @@ -831,6 +831,58 @@ out: > > > return ret; > > > } > > > > > > +static int if_sdio_enter_deep_sleep(struct lbs_private *priv) > > > +{ > > > + int ret = -1; > > > + struct cmd_header cmd; > > > + > > > + memset(&cmd, 0, sizeof(cmd)); > > > + > > > + lbs_deb_sdio("send DEEP_SLEEP command\n"); > > > + ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), > > > + lbs_cmd_copyback, (unsigned long) &cmd); > > > + if (ret) > > > + lbs_pr_err("DEEP_SLEEP cmd failed\n"); > > > + > > > + mdelay(200); > > > + return ret; > > > +} > > > + > > > +static int if_sdio_exit_deep_sleep(struct lbs_private *priv) > > > +{ > > > + struct if_sdio_card *card = priv->card; > > > + int ret = -1; > > > + > > > + lbs_deb_enter(LBS_DEB_SDIO); > > > + sdio_claim_host(card->func); > > > + > > > + sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); > > > + if (ret) > > > + lbs_pr_err("sdio_writeb failed!\n"); > > > + > > > + sdio_release_host(card->func); > > > + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); > > > + return ret; > > > +} > > > + > > > +static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) > > > +{ > > > + struct if_sdio_card *card = priv->card; > > > + int ret = -1; > > > + > > > + lbs_deb_enter(LBS_DEB_SDIO); > > > + sdio_claim_host(card->func); > > > + > > > + sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); > > > + if (ret) > > > + lbs_pr_err("sdio_writeb failed!\n"); > > > + > > > + sdio_release_host(card->func); > > > + lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); > > > + return ret; > > > + > > > +} > > > + > > > /*******************************************************************/ > > > /* SDIO callbacks */ > > > /*******************************************************************/ > > > @@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func) > > > * Ignore the define name, this really means the card has > > > * successfully received the command. > > > */ > > > + card->priv->is_activity_detected = 1; > > > if (cause & IF_SDIO_H_INT_DNLD) > > > lbs_host_to_card_done(card->priv); > > > > > > @@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func, > > > > > > priv->card = card; > > > priv->hw_host_to_card = if_sdio_host_to_card; > > > + priv->enter_deep_sleep = if_sdio_enter_deep_sleep; > > > + priv->exit_deep_sleep = if_sdio_exit_deep_sleep; > > > + priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; > > > > > > priv->fw_ready = 1; > > > > > > diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h > > > index 60c9b2f..12179c1 100644 > > > --- a/drivers/net/wireless/libertas/if_sdio.h > > > +++ b/drivers/net/wireless/libertas/if_sdio.h > > > @@ -51,5 +51,6 @@ > > > #define IF_SDIO_EVENT 0x80fc > > > > > > #define IF_SDIO_BLOCK_SIZE 256 > > > - > > > +#define CONFIGURATION_REG 0x03 > > > +#define HOST_POWER_UP (0x1U << 1) > > > #endif > > > diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c > > > index 446e327..e2fa657 100644 > > > --- a/drivers/net/wireless/libertas/if_spi.c > > > +++ b/drivers/net/wireless/libertas/if_spi.c > > > @@ -1117,6 +1117,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) > > > card->priv = priv; > > > priv->card = card; > > > priv->hw_host_to_card = if_spi_host_to_card; > > > + priv->enter_deep_sleep = NULL; > > > + priv->exit_deep_sleep = NULL; > > > + priv->reset_deep_sleep_wakeup = NULL; > > > priv->fw_ready = 1; > > > > > > /* Initialize interrupt handling stuff. */ > > > diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c > > > index 92bc8c5..a8262de 100644 > > > --- a/drivers/net/wireless/libertas/if_usb.c > > > +++ b/drivers/net/wireless/libertas/if_usb.c > > > @@ -300,6 +300,9 @@ static int if_usb_probe(struct usb_interface *intf, > > > cardp->priv->fw_ready = 1; > > > > > > priv->hw_host_to_card = if_usb_host_to_card; > > > + priv->enter_deep_sleep = NULL; > > > + priv->exit_deep_sleep = NULL; > > > + priv->reset_deep_sleep_wakeup = NULL; > > > #ifdef CONFIG_OLPC > > > if (machine_is_olpc()) > > > priv->reset_card = if_usb_reset_olpc_card; > > > diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c > > > index 8df1cfd..3b14fcc 100644 > > > --- a/drivers/net/wireless/libertas/main.c > > > +++ b/drivers/net/wireless/libertas/main.c > > > @@ -574,8 +574,10 @@ void lbs_host_to_card_done(struct lbs_private *priv) > > > priv->dnld_sent = DNLD_RES_RECEIVED; > > > > > > /* Wake main thread if commands are pending */ > > > - if (!priv->cur_cmd || priv->tx_pending_len > 0) > > > - wake_up_interruptible(&priv->waitq); > > > + if (!priv->cur_cmd || priv->tx_pending_len > 0) { > > > + if (!priv->wakeup_dev_required) > > > + wake_up_interruptible(&priv->waitq); > > > + } > > > > > > spin_unlock_irqrestore(&priv->driver_lock, flags); > > > lbs_deb_leave(LBS_DEB_THREAD); > > > @@ -770,7 +772,8 @@ static int lbs_thread(void *data) > > > shouldsleep = 0; /* We have a command response */ > > > else if (priv->cur_cmd) > > > shouldsleep = 1; /* Can't send a command; one already running */ > > > - else if (!list_empty(&priv->cmdpendingq)) > > > + else if (!list_empty(&priv->cmdpendingq) && > > > + !(priv->wakeup_dev_required)) > > > shouldsleep = 0; /* We have a command to send */ > > > else if (__kfifo_len(priv->event_fifo)) > > > shouldsleep = 0; /* We have an event to process */ > > > @@ -822,6 +825,26 @@ static int lbs_thread(void *data) > > > } > > > spin_unlock_irq(&priv->driver_lock); > > > > > > + /* Process hardware events, e.g. card removed, link lost */ > > > + spin_lock_irq(&priv->driver_lock); > > > + while (__kfifo_len(priv->event_fifo)) { > > > + u32 event; > > > + __kfifo_get(priv->event_fifo, (unsigned char *) &event, > > > + sizeof(event)); > > > + spin_unlock_irq(&priv->driver_lock); > > > + lbs_process_event(priv, event); > > > + spin_lock_irq(&priv->driver_lock); > > > + } > > > + spin_unlock_irq(&priv->driver_lock); > > > + > > > + if (priv->wakeup_dev_required) { > > > + lbs_deb_thread("Waking up device...\n"); > > > + /* Wake up device */ > > > + if (priv->exit_deep_sleep(priv)) > > > + lbs_deb_thread("Wakeup device failed\n"); > > > + continue; > > > + } > > > + > > > /* command timeout stuff */ > > > if (priv->cmd_timed_out && priv->cur_cmd) { > > > struct cmd_ctrl_node *cmdnode = priv->cur_cmd; > > > @@ -849,18 +872,7 @@ static int lbs_thread(void *data) > > > } > > > priv->cmd_timed_out = 0; > > > > > > - /* Process hardware events, e.g. card removed, link lost */ > > > - spin_lock_irq(&priv->driver_lock); > > > - while (__kfifo_len(priv->event_fifo)) { > > > - u32 event; > > > > > > - __kfifo_get(priv->event_fifo, (unsigned char *) &event, > > > - sizeof(event)); > > > - spin_unlock_irq(&priv->driver_lock); > > > - lbs_process_event(priv, event); > > > - spin_lock_irq(&priv->driver_lock); > > > - } > > > - spin_unlock_irq(&priv->driver_lock); > > > > > > if (!priv->fw_ready) > > > continue; > > > @@ -894,6 +906,9 @@ static int lbs_thread(void *data) > > > (priv->psstate == PS_STATE_PRE_SLEEP)) > > > continue; > > > > > > + if (priv->is_deep_sleep) > > > + continue; > > > + > > > /* Execute the next command */ > > > if (!priv->dnld_sent && !priv->cur_cmd) > > > lbs_execute_next_command(priv); > > > @@ -928,6 +943,7 @@ static int lbs_thread(void *data) > > > } > > > > > > del_timer(&priv->command_timer); > > > + del_timer(&priv->auto_deepsleep_timer); > > > wake_up_all(&priv->cmd_pending); > > > > > > lbs_deb_leave(LBS_DEB_THREAD); > > > @@ -1050,6 +1066,60 @@ out: > > > lbs_deb_leave(LBS_DEB_CMD); > > > } > > > > > > +/** > > > + * This function put the device back to deep sleep mode when timer expires > > > + * and no activity (command, event, data etc.) is detected. > > > + */ > > > +static void auto_deepsleep_timer_fn(unsigned long data) > > > +{ > > > + struct lbs_private *priv = (struct lbs_private *)data; > > > + int ret; > > > + > > > + 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)) { > > > + lbs_deb_main("Entering auto deep sleep mode...\n"); > > > + ret = lbs_prepare_and_send_command(priv, > > > + CMD_802_11_DEEP_SLEEP, 0, > > > + 0, 0, NULL); > > > + } > > > + } > > > + 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 void lbs_sync_channel_worker(struct work_struct *work) > > > { > > > struct lbs_private *priv = container_of(work, struct lbs_private, > > > @@ -1099,11 +1169,17 @@ static int lbs_init_adapter(struct lbs_private *priv) > > > priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; > > > priv->psmode = LBS802_11POWERMODECAM; > > > priv->psstate = PS_STATE_FULL_POWER; > > > + priv->is_deep_sleep = 0; > > > + priv->is_auto_deep_sleep_enabled = 0; > > > + priv->wakeup_dev_required = 0; > > > + init_waitqueue_head(&priv->ds_awake_q); > > > > > > mutex_init(&priv->lock); > > > > > > setup_timer(&priv->command_timer, command_timer_fn, > > > (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); > > > @@ -1142,6 +1218,7 @@ static void lbs_free_adapter(struct lbs_private *priv) > > > if (priv->event_fifo) > > > kfifo_free(priv->event_fifo); > > > del_timer(&priv->command_timer); > > > + del_timer(&priv->auto_deepsleep_timer); > > > kfree(priv->networks); > > > priv->networks = NULL; > > > > > > @@ -1272,6 +1349,11 @@ void lbs_remove_card(struct lbs_private *priv) > > > wrqu.ap_addr.sa_family = ARPHRD_ETHER; > > > wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); > > > > > > + if (priv->is_deep_sleep) { > > > + priv->is_deep_sleep = 0; > > > + wake_up_interruptible(&priv->ds_awake_q); > > > + } > > > + > > > /* Stop the thread servicing the interrupts */ > > > priv->surpriseremoved = 1; > > > kthread_stop(priv->main_thread); > > > @@ -1392,6 +1474,7 @@ 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); > > > diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c > > > index 6c95af3..e468e15 100644 > > > --- a/drivers/net/wireless/libertas/scan.c > > > +++ b/drivers/net/wireless/libertas/scan.c > > > @@ -950,6 +950,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > if (!priv->radio_on) { > > > ret = -EINVAL; > > > goto out; > > > @@ -1017,6 +1022,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + err = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); > > > + return err; > > > + } > > > + > > > /* iwlist should wait until the current scan is finished */ > > > if (priv->scan_channel) > > > return -EAGAIN; > > > diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c > > > index be837a0..ef2b986 100644 > > > --- a/drivers/net/wireless/libertas/wext.c > > > +++ b/drivers/net/wireless/libertas/wext.c > > > @@ -45,6 +45,31 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv) > > > priv->pending_assoc_req = NULL; > > > } > > > > > > +/** > > > + * @brief This function checks if the command is allowed. > > > + * > > > + * @param priv A pointer to lbs_private structure > > > + * @return allowed or not allowed. > > > + */ > > > + > > > +int lbs_is_cmd_allowed(struct lbs_private *priv) > > > +{ > > > + int ret = 1; > > > + > > > + lbs_deb_enter(LBS_DEB_WEXT); > > > + > > > + if (!priv->is_auto_deep_sleep_enabled) { > > > + if (priv->is_deep_sleep) { > > > + lbs_deb_wext("IOCTLS called when station" > > > + "is in deep sleep\n"); > > > + ret = 0; > > > + } > > > + } > > > + > > > + lbs_deb_leave(LBS_DEB_WEXT); > > > + return ret; > > > +} > > > + > > > > > > /** > > > * @brief Find the channel frequency power info with specific channel > > > @@ -168,6 +193,11 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + lbs_deb_leave(LBS_DEB_WEXT); > > > + return -EBUSY; > > > + } > > > + > > > cfp = lbs_find_cfp_by_band_and_channel(priv, 0, > > > priv->curbssparams.channel); > > > > > > @@ -278,6 +308,12 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > if (vwrq->disabled) > > > val = MRVDRV_RTS_MAX_VALUE; > > > > > > @@ -299,6 +335,11 @@ static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val); > > > if (ret) > > > goto out; > > > @@ -321,6 +362,12 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > if (vwrq->disabled) > > > val = MRVDRV_FRAG_MAX_VALUE; > > > > > > @@ -342,6 +389,11 @@ static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val); > > > if (ret) > > > goto out; > > > @@ -391,6 +443,11 @@ static int lbs_get_txpow(struct net_device *dev, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > if (!priv->radio_on) { > > > lbs_deb_wext("tx power off\n"); > > > vwrq->value = 0; > > > @@ -424,6 +481,11 @@ static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) > > > return -EOPNOTSUPP; > > > > > > @@ -472,6 +534,11 @@ static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > vwrq->disabled = 0; > > > > > > if (vwrq->flags & IW_RETRY_LONG) { > > > @@ -712,6 +779,11 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + lbs_deb_leave(LBS_DEB_WEXT); > > > + return -EBUSY; > > > + } > > > + > > > if (!(priv->fwcapinfo & FW_CAPINFO_PS)) { > > > if (vwrq->disabled) > > > return 0; > > > @@ -792,6 +864,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) > > > + return NULL; > > > + > > > priv->wstats.status = priv->mode; > > > > > > /* If we're not associated, all quality values are meaningless */ > > > @@ -892,6 +967,12 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > mutex_lock(&priv->lock); > > > assoc_req = lbs_get_association_request(priv); > > > if (!assoc_req) { > > > @@ -1000,6 +1081,12 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, > > > u8 rates[MAX_RATES + 1]; > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > + > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > lbs_deb_wext("vwrq->value %d\n", vwrq->value); > > > lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); > > > > > > @@ -1058,6 +1145,11 @@ static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + lbs_deb_leave(LBS_DEB_WEXT); > > > + return -EBUSY; > > > + } > > > + > > > if (priv->connect_status == LBS_CONNECTED) { > > > vwrq->value = priv->cur_rate * 500000; > > > > > > @@ -1084,6 +1176,11 @@ static int lbs_set_mode(struct net_device *dev, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > if ( (*uwrq != IW_MODE_ADHOC) > > > && (*uwrq != IW_MODE_INFRA) > > > && (*uwrq != IW_MODE_AUTO)) { > > > @@ -1325,6 +1422,12 @@ static int lbs_set_encode(struct net_device *dev, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > mutex_lock(&priv->lock); > > > assoc_req = lbs_get_association_request(priv); > > > if (!assoc_req) { > > > @@ -1508,6 +1611,12 @@ static int lbs_set_encodeext(struct net_device *dev, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > mutex_lock(&priv->lock); > > > assoc_req = lbs_get_association_request(priv); > > > if (!assoc_req) { > > > @@ -1720,6 +1829,12 @@ static int lbs_set_auth(struct net_device *dev, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > mutex_lock(&priv->lock); > > > assoc_req = lbs_get_association_request(priv); > > > if (!assoc_req) { > > > @@ -1822,6 +1937,12 @@ static int lbs_get_auth(struct net_device *dev, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > switch (dwrq->flags & IW_AUTH_INDEX) { > > > case IW_AUTH_KEY_MGMT: > > > dwrq->value = priv->secinfo.key_mgmt; > > > @@ -1864,6 +1985,11 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info > > *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + goto out; > > > + } > > > + > > > if (vwrq->disabled) { > > > lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0); > > > goto out; > > > @@ -1983,6 +2109,12 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info > > *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > if (!priv->radio_on) { > > > ret = -EINVAL; > > > goto out; > > > @@ -2110,6 +2242,12 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > + if (!lbs_is_cmd_allowed(priv)) { > > > + ret = -EBUSY; > > > + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); > > > + return ret; > > > + } > > > + > > > if (!priv->radio_on) > > > return -EINVAL; > > > > ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2009-10-01 18:00 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-09-15 23:45 [PATCH] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 Bing Zhao 2009-09-15 23:41 ` Andrey Yurovsky 2009-09-16 20:20 ` Bing Zhao 2009-09-16 20:47 ` Andrey Yurovsky 2009-09-17 16:11 ` Sebastian Andrzej Siewior 2009-09-18 1:47 ` Bing Zhao 2009-09-18 7:37 ` Holger Schurig 2009-09-18 17:37 ` Dan Williams 2009-09-20 14:58 ` Dan Williams 2009-09-28 22:42 ` Bing Zhao 2009-09-29 7:04 ` Holger Schurig 2009-09-29 18:36 ` Bing Zhao 2009-09-29 7:24 ` Holger Schurig 2009-10-01 18:00 ` Dan Williams
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox