* [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 @ 2009-10-01 3:04 Bing Zhao 2009-10-01 7:42 ` Holger Schurig 2009-10-01 18:27 ` Dan Williams 0 siblings, 2 replies; 7+ messages in thread From: Bing Zhao @ 2009-10-01 3:04 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: 32842 bytes --] From: Amitkumar Karwar <akarwar@marvell.com> Add timer based auto deep sleep feature in libertas driver which can be configured using iwconfig command. 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 | 26 ++++- drivers/net/wireless/libertas/cmd.c | 72 ++++++++++++- drivers/net/wireless/libertas/cmdresp.c | 12 ++ drivers/net/wireless/libertas/debugfs.c | 46 ++++++++ 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 | 185 ++++++++++++++++++++++++++++++- 15 files changed, 533 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index ab6a2d5..635002d 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,28 @@ 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. +======================== +IWCONFIG COMMANDS +======================== +power period + + This command is used to configure the station in deep sleep mode / + auto deep sleep mode. + + The timer is implemented to monitor the activities (command, event, + 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 deep sleep mode is entered + automatically. + + Note: this command is for SDIO interface only. + + Usage: + To enable deep sleep mode do: + iwconfig wlan0 power period 0 + To enable auto deep sleep mode with idle time period 5 seconds do: + iwconfig wlan0 power period 5 + To disable deep sleep/auto deep sleep mode do: + iwconfig wlan0 power period -1 + ============================================================================== 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..8a7e931 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; @@ -223,6 +233,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 +288,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 +460,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 +517,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 +558,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 +616,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 +657,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 +715,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; 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..38a451e 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) { @@ -709,6 +776,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { struct lbs_private *priv = dev->ml_priv; + int ret = 0; lbs_deb_enter(LBS_DEB_WEXT); @@ -737,8 +805,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, "setting power timeout is not supported\n"); return -EINVAL; } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { - lbs_deb_wext("setting power period not supported\n"); - return -EINVAL; + vwrq->value = vwrq->value / 1000; + if (!priv->enter_deep_sleep) { + lbs_pr_err("deep sleep feature is not implemented " + "for this interface driver\n"); + return -EINVAL; + } + + if (priv->connect_status == LBS_CONNECTED) { + if ((priv->is_auto_deep_sleep_enabled) && + (vwrq->value == -1000)) { + lbs_exit_auto_deep_sleep(priv); + return 0; + } else { + lbs_pr_err("can't use deep sleep cmd in " + "connected state\n"); + return -EINVAL; + } + } + + if ((vwrq->value < 0) && (vwrq->value != -1000)) { + lbs_pr_err("unknown option\n"); + return -EINVAL; + } + + if (vwrq->value > 0) { + if (!priv->is_auto_deep_sleep_enabled) { + priv->is_activity_detected = 0; + priv->auto_deep_sleep_timeout = vwrq->value; + lbs_enter_auto_deep_sleep(priv); + } else { + priv->auto_deep_sleep_timeout = vwrq->value; + lbs_deb_debugfs("auto deep sleep: " + "already enabled\n"); + } + return 0; + } else { + if (priv->is_auto_deep_sleep_enabled) { + lbs_exit_auto_deep_sleep(priv); + /* Try to exit deep sleep if auto */ + /*deep sleep disabled */ + ret = lbs_set_deep_sleep(priv, 0); + } + if (vwrq->value == 0) + ret = lbs_set_deep_sleep(priv, 1); + else if (vwrq->value == -1000) + ret = lbs_set_deep_sleep(priv, 0); + return ret; + } } if (priv->psmode != LBS802_11POWERMODECAM) { @@ -752,6 +866,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, } lbs_deb_leave(LBS_DEB_WEXT); + return 0; } @@ -792,6 +907,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 +1010,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 +1124,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 +1188,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 +1219,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 +1465,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 +1654,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 +1872,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 +1980,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 +2028,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 +2152,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 +2285,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] 7+ messages in thread
* Re: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-10-01 3:04 [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 Bing Zhao @ 2009-10-01 7:42 ` Holger Schurig 2009-10-06 21:44 ` Bing Zhao 2009-10-01 18:27 ` Dan Williams 1 sibling, 1 reply; 7+ messages in thread From: Holger Schurig @ 2009-10-01 7:42 UTC (permalink / raw) To: Bing Zhao; +Cc: libertas-dev, linux-wireless, Amitkumar Karwar > Tests have been done for USB/CS cards to make sure that the patch > won't break USB/CS code. Side question: which firmware are you using on CS cards? -- http://www.holgerschurig.de ^ permalink raw reply [flat|nested] 7+ messages in thread
* RE: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-10-01 7:42 ` Holger Schurig @ 2009-10-06 21:44 ` Bing Zhao 2009-10-20 6:43 ` Holger Schurig 0 siblings, 1 reply; 7+ messages in thread From: Bing Zhao @ 2009-10-06 21:44 UTC (permalink / raw) To: Holger Schurig Cc: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar Hi Holger, Sorry for the late response. > -----Original Message----- > From: Holger Schurig [mailto:hs4233@mail.mn-solutions.de] > Sent: Thursday, October 01, 2009 12:43 AM > To: Bing Zhao > Cc: libertas-dev@lists.infradead.org; linux-wireless@vger.kernel.org; Amitkumar Karwar > Subject: Re: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 > > > Tests have been done for USB/CS cards to make sure that the patch > > won't break USB/CS code. > > > Side question: which firmware are you using on CS cards? firmware version for Marvell CF8385 card: 5.101.13p1 Regards, Bing > > -- > http://www.holgerschurig.de ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-10-06 21:44 ` Bing Zhao @ 2009-10-20 6:43 ` Holger Schurig 0 siblings, 0 replies; 7+ messages in thread From: Holger Schurig @ 2009-10-20 6:43 UTC (permalink / raw) To: Bing Zhao Cc: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Amitkumar Karwar > > Side question: which firmware are you using on CS cards? > > firmware version for Marvell CF8385 card: 5.101.13p1 Can you provide this firmware to me? Or can you say me where I can download it? I still have 5.0.16p0, which seems to not understand CMD_802_11_MONITOR_MODE and CMD_802_11_TX_RATE_QUERY. -- http://www.holgerschurig.de ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-10-01 3:04 [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 Bing Zhao 2009-10-01 7:42 ` Holger Schurig @ 2009-10-01 18:27 ` Dan Williams 2009-10-05 18:47 ` Bing Zhao 1 sibling, 1 reply; 7+ messages in thread From: Dan Williams @ 2009-10-01 18:27 UTC (permalink / raw) To: Bing Zhao; +Cc: libertas-dev, Amitkumar Karwar, linux-wireless On Wed, 2009-09-30 at 20:04 -0700, Bing Zhao wrote: > From: Amitkumar Karwar <akarwar@marvell.com> > > Add timer based auto deep sleep feature in libertas driver which can be > configured using iwconfig command. 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> Acked-by: Dan Williams <dcbw@redhat.com> Though I wonder if we could just put the lbs_is_cmd_allowed() check into the actual command handling routines instead of sprinkling it around. We did move away from the 'one-huge-switch' command submission model, which makes it a bit harder to gate commands based on device state, but I can't think of anything off the top of my head that would hurt by doing it like that. i.e. would putting the check in both __lbs_cmd_async() and lbs_prepare_and_send_command() around where the priv->surprise_removed check is work too? Dan > --- > drivers/net/wireless/libertas/README | 26 ++++- > drivers/net/wireless/libertas/cmd.c | 72 ++++++++++++- > drivers/net/wireless/libertas/cmdresp.c | 12 ++ > drivers/net/wireless/libertas/debugfs.c | 46 ++++++++ > 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 | 185 ++++++++++++++++++++++++++++++- > 15 files changed, 533 insertions(+), 21 deletions(-) > > diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README > index ab6a2d5..635002d 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,28 @@ 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. > > +======================== > +IWCONFIG COMMANDS > +======================== > +power period > + > + This command is used to configure the station in deep sleep mode / > + auto deep sleep mode. > + > + The timer is implemented to monitor the activities (command, event, > + 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 deep sleep mode is entered > + automatically. > + > + Note: this command is for SDIO interface only. > + > + Usage: > + To enable deep sleep mode do: > + iwconfig wlan0 power period 0 > + To enable auto deep sleep mode with idle time period 5 seconds do: > + iwconfig wlan0 power period 5 > + To disable deep sleep/auto deep sleep mode do: > + iwconfig wlan0 power period -1 > + > ============================================================================== > 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..8a7e931 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; > @@ -223,6 +233,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 +288,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 +460,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 +517,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 +558,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 +616,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 +657,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 +715,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; > 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..38a451e 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) { > @@ -709,6 +776,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > struct iw_param *vwrq, char *extra) > { > struct lbs_private *priv = dev->ml_priv; > + int ret = 0; > > lbs_deb_enter(LBS_DEB_WEXT); > > @@ -737,8 +805,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > "setting power timeout is not supported\n"); > return -EINVAL; > } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { > - lbs_deb_wext("setting power period not supported\n"); > - return -EINVAL; > + vwrq->value = vwrq->value / 1000; > + if (!priv->enter_deep_sleep) { > + lbs_pr_err("deep sleep feature is not implemented " > + "for this interface driver\n"); > + return -EINVAL; > + } > + > + if (priv->connect_status == LBS_CONNECTED) { > + if ((priv->is_auto_deep_sleep_enabled) && > + (vwrq->value == -1000)) { > + lbs_exit_auto_deep_sleep(priv); > + return 0; > + } else { > + lbs_pr_err("can't use deep sleep cmd in " > + "connected state\n"); > + return -EINVAL; > + } > + } > + > + if ((vwrq->value < 0) && (vwrq->value != -1000)) { > + lbs_pr_err("unknown option\n"); > + return -EINVAL; > + } > + > + if (vwrq->value > 0) { > + if (!priv->is_auto_deep_sleep_enabled) { > + priv->is_activity_detected = 0; > + priv->auto_deep_sleep_timeout = vwrq->value; > + lbs_enter_auto_deep_sleep(priv); > + } else { > + priv->auto_deep_sleep_timeout = vwrq->value; > + lbs_deb_debugfs("auto deep sleep: " > + "already enabled\n"); > + } > + return 0; > + } else { > + if (priv->is_auto_deep_sleep_enabled) { > + lbs_exit_auto_deep_sleep(priv); > + /* Try to exit deep sleep if auto */ > + /*deep sleep disabled */ > + ret = lbs_set_deep_sleep(priv, 0); > + } > + if (vwrq->value == 0) > + ret = lbs_set_deep_sleep(priv, 1); > + else if (vwrq->value == -1000) > + ret = lbs_set_deep_sleep(priv, 0); > + return ret; > + } > } > > if (priv->psmode != LBS802_11POWERMODECAM) { > @@ -752,6 +866,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > } > > lbs_deb_leave(LBS_DEB_WEXT); > + > return 0; > } > > @@ -792,6 +907,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 +1010,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 +1124,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 +1188,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 +1219,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 +1465,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 +1654,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 +1872,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 +1980,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 +2028,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 +2152,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 +2285,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; > > _______________________________________________ > libertas-dev mailing list > libertas-dev@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/libertas-dev ^ permalink raw reply [flat|nested] 7+ messages in thread
* RE: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-10-01 18:27 ` Dan Williams @ 2009-10-05 18:47 ` Bing Zhao 2009-10-05 18:59 ` Dan Williams 0 siblings, 1 reply; 7+ messages in thread From: Bing Zhao @ 2009-10-05 18:47 UTC (permalink / raw) To: Dan Williams Cc: libertas-dev@lists.infradead.org, Amitkumar Karwar, linux-wireless@vger.kernel.org SGkgRGFuLA0KDQo+IC0tLS0tT3JpZ2luYWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IERhbiBXaWxs aWFtcyBbbWFpbHRvOmRjYndAcmVkaGF0LmNvbV0NCj4gU2VudDogVGh1cnNkYXksIE9jdG9iZXIg MDEsIDIwMDkgMTE6MjcgQU0NCj4gVG86IEJpbmcgWmhhbw0KPiBDYzogbGliZXJ0YXMtZGV2QGxp c3RzLmluZnJhZGVhZC5vcmc7IEFtaXRrdW1hciBLYXJ3YXI7IGxpbnV4LXdpcmVsZXNzQHZnZXIu a2VybmVsLm9yZw0KPiBTdWJqZWN0OiBSZTogW1BBVENIIHYyXSBsaWJlcnRhczogQWRkIGF1dG8g ZGVlcCBzbGVlcCBzdXBwb3J0IGZvciBTRDgzODUvU0Q4Njg2L1NEODY4OA0KPg0KPiBPbiBXZWQs IDIwMDktMDktMzAgYXQgMjA6MDQgLTA3MDAsIEJpbmcgWmhhbyB3cm90ZToNCj4gPiBGcm9tOiBB bWl0a3VtYXIgS2Fyd2FyIDxha2Fyd2FyQG1hcnZlbGwuY29tPg0KPiA+DQo+ID4gQWRkIHRpbWVy IGJhc2VkIGF1dG8gZGVlcCBzbGVlcCBmZWF0dXJlIGluIGxpYmVydGFzIGRyaXZlciB3aGljaCBj YW4gYmUNCj4gPiBjb25maWd1cmVkIHVzaW5nIGl3Y29uZmlnIGNvbW1hbmQuIFRoaXMgaXMgdGVz dGVkIG9uIFNEODY4OCwgU0Q4Njg2IGNhcmRzDQo+ID4gd2l0aCBmaXJtd2FyZSB2ZXJzaW9ucyAx MC4zOC4xLnAyNSwgOS43MC40LnAwIHJlc3BlY3RpdmVseSBvbiAzMi1iaXQgYW5kIDY0LWJpdA0K PiA+IHBsYXRmb3Jtcy4gVGVzdHMgaGF2ZSBiZWVuIGRvbmUgZm9yIFVTQi9DUyBjYXJkcyB0byBt YWtlIHN1cmUgdGhhdCB0aGUgcGF0Y2gNCj4gPiB3b24ndCBicmVhayBVU0IvQ1MgY29kZS4gV2Ug ZGlkbid0IHRlc3QgdGhlIGlmX3NwaSBkcml2ZXIuDQo+ID4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBB bWl0a3VtYXIgS2Fyd2FyIDxha2Fyd2FyQG1hcnZlbGwuY29tPg0KPiA+IFNpZ25lZC1vZmYtYnk6 IEJpbmcgWmhhbyA8YnpoYW9AbWFydmVsbC5jb20+DQo+DQo+IEFja2VkLWJ5OiBEYW4gV2lsbGlh bXMgPGRjYndAcmVkaGF0LmNvbT4NCj4NCj4gVGhvdWdoIEkgd29uZGVyIGlmIHdlIGNvdWxkIGp1 c3QgcHV0IHRoZSBsYnNfaXNfY21kX2FsbG93ZWQoKSBjaGVjayBpbnRvDQo+IHRoZSBhY3R1YWwg Y29tbWFuZCBoYW5kbGluZyByb3V0aW5lcyBpbnN0ZWFkIG9mIHNwcmlua2xpbmcgaXQgYXJvdW5k Lg0KDQpZZXMsIHdlIGNhbiBkbyB0aGF0Lg0KDQo+IFdlIGRpZCBtb3ZlIGF3YXkgZnJvbSB0aGUg J29uZS1odWdlLXN3aXRjaCcgY29tbWFuZCBzdWJtaXNzaW9uIG1vZGVsLA0KPiB3aGljaCBtYWtl cyBpdCBhIGJpdCBoYXJkZXIgdG8gZ2F0ZSBjb21tYW5kcyBiYXNlZCBvbiBkZXZpY2Ugc3RhdGUs IGJ1dA0KPiBJIGNhbid0IHRoaW5rIG9mIGFueXRoaW5nIG9mZiB0aGUgdG9wIG9mIG15IGhlYWQg dGhhdCB3b3VsZCBodXJ0IGJ5DQo+IGRvaW5nIGl0IGxpa2UgdGhhdC4NCj4NCj4gaS5lLiB3b3Vs ZCBwdXR0aW5nIHRoZSBjaGVjayBpbiBib3RoIF9fbGJzX2NtZF9hc3luYygpIGFuZA0KPiBsYnNf cHJlcGFyZV9hbmRfc2VuZF9jb21tYW5kKCkgYXJvdW5kIHdoZXJlIHRoZSBwcml2LT5zdXJwcmlz ZV9yZW1vdmVkDQo+IGNoZWNrIGlzIHdvcmsgdG9vPw0KDQpXZSB3aWxsIHN1Ym1pdCBhIG5ldyBw YXRjaCBmb3IgdGhpcy4NCg0KUmVnYXJkcywNCg0KQmluZw0KDQo+DQo+IERhbg0KPg0KPiA+IC0t LQ0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9SRUFETUUgICAgfCAgIDI2ICsr KystDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2NtZC5jICAgICB8ICAgNzIg KysrKysrKysrKysrLQ0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWRyZXNw LmMgfCAgIDEyICsrDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2RlYnVnZnMu YyB8ICAgNDYgKysrKysrKysNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGVj bC5oICAgIHwgICAgNCArDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2Rldi5o ICAgICB8ICAgMTggKysrDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2hvc3Qu aCAgICB8ICAgIDEgKw0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9jcy5j ICAgfCAgICAzICsNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc2Rpby5j IHwgICA1NiArKysrKysrKysNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZf c2Rpby5oIHwgICAgMyArLQ0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9z cGkuYyAgfCAgICAzICsNCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfdXNi LmMgIHwgICAgMyArDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL21haW4uYyAg ICB8ICAxMTEgKysrKysrKysrKysrKysrKy0tLQ0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9s aWJlcnRhcy9zY2FuLmMgICAgfCAgIDExICsrDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL2xp YmVydGFzL3dleHQuYyAgICB8ICAxODUgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrLQ0K PiA+ICAxNSBmaWxlcyBjaGFuZ2VkLCA1MzMgaW5zZXJ0aW9ucygrKSwgMjEgZGVsZXRpb25zKC0p DQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvUkVB RE1FIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvUkVBRE1FDQo+ID4gaW5kZXggYWI2 YTJkNS4uNjM1MDAyZCAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJl cnRhcy9SRUFETUUNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9SRUFE TUUNCj4gPiBAQCAtMSw1ICsxLDUgQEANCj4gPiAgPT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCj4g PiAtICAgICAgICAgICAgICAgICAgIFJFQURNRSBmb3IgVVNCODM4OA0KPiA+ICsgICAgICAgICAg ICAgICAgICAgUkVBRE1FIGZvciBMaWJlcnRhcw0KPiA+DQo+ID4gICAoYykgQ29weXJpZ2h0IMKp IDIwMDMtMjAwNiwgTWFydmVsbCBJbnRlcm5hdGlvbmFsIEx0ZC4NCj4gPiAgIEFsbCBSaWdodHMg UmVzZXJ2ZWQNCj4gPiBAQCAtMjI2LDQgKzIyNiwyOCBAQCBzZXR1c2Vyc2Nhbg0KPiA+ICAgICAg QWxsIGVudHJpZXMgaW4gdGhlIHNjYW4gdGFibGUgKG5vdCBqdXN0IHRoZSBuZXcgc2NhbiBkYXRh IHdoZW4ga2VlcD0xKQ0KPiA+ICAgICAgd2lsbCBiZSBkaXNwbGF5ZWQgdXBvbiBjb21wbGV0aW9u IGJ5IHVzZSBvZiB0aGUgZ2V0c2NhbnRhYmxlIGlvY3RsLg0KPiA+DQo+ID4gKz09PT09PT09PT09 PT09PT09PT09PT09PQ0KPiA+ICtJV0NPTkZJRyBDT01NQU5EUw0KPiA+ICs9PT09PT09PT09PT09 PT09PT09PT09PT0NCj4gPiArcG93ZXIgcGVyaW9kDQo+ID4gKw0KPiA+ICsgICBUaGlzIGNvbW1h bmQgaXMgdXNlZCB0byBjb25maWd1cmUgdGhlIHN0YXRpb24gaW4gZGVlcCBzbGVlcCBtb2RlIC8N Cj4gPiArICAgYXV0byBkZWVwIHNsZWVwIG1vZGUuDQo+ID4gKw0KPiA+ICsgICBUaGUgdGltZXIg aXMgaW1wbGVtZW50ZWQgdG8gbW9uaXRvciB0aGUgYWN0aXZpdGllcyAoY29tbWFuZCwgZXZlbnQs DQo+ID4gKyAgIGV0Yy4pLiBXaGVuIGFuIGFjdGl2aXR5IGlzIGRldGVjdGVkIHN0YXRpb24gd2ls bCBleGl0IGZyb20gZGVlcA0KPiA+ICsgICBzbGVlcCBtb2RlIGF1dG9tYXRpY2FsbHkgYW5kIHJl c3RhcnQgdGhlIHRpbWVyLiBBdCB0aW1lciBleHBpcnkNCj4gPiArICAgKG5vIGFjdGl2aXR5IGZv ciBkZWZpbmVkIHRpbWUgcGVyaW9kKSB0aGUgZGVlcCBzbGVlcCBtb2RlIGlzIGVudGVyZWQNCj4g PiArICAgYXV0b21hdGljYWxseS4NCj4gPiArDQo+ID4gKyAgIE5vdGU6IHRoaXMgY29tbWFuZCBp cyBmb3IgU0RJTyBpbnRlcmZhY2Ugb25seS4NCj4gPiArDQo+ID4gKyAgIFVzYWdlOg0KPiA+ICsg ICBUbyBlbmFibGUgZGVlcCBzbGVlcCBtb2RlIGRvOg0KPiA+ICsgICAgICAgICAgIGl3Y29uZmln IHdsYW4wIHBvd2VyIHBlcmlvZCAwDQo+ID4gKyAgIFRvIGVuYWJsZSBhdXRvIGRlZXAgc2xlZXAg bW9kZSB3aXRoIGlkbGUgdGltZSBwZXJpb2QgNSBzZWNvbmRzIGRvOg0KPiA+ICsgICAgICAgICAg IGl3Y29uZmlnIHdsYW4wIHBvd2VyIHBlcmlvZCA1DQo+ID4gKyAgIFRvIGRpc2FibGUgZGVlcCBz bGVlcC9hdXRvIGRlZXAgc2xlZXAgbW9kZSBkbzoNCj4gPiArICAgICAgICAgICBpd2NvbmZpZyB3 bGFuMCBwb3dlciBwZXJpb2QgLTENCj4gPiArDQo+ID4gID09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0K PiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWQuYyBiL2Ry aXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2NtZC5jDQo+ID4gaW5kZXggNjg1MDk4MS4uM2Ez ZTg5NCAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWQu Yw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2NtZC5jDQo+ID4gQEAg LTE3LDcgKzE3LDYgQEANCj4gPg0KPiA+ICBzdGF0aWMgc3RydWN0IGNtZF9jdHJsX25vZGUgKmxi c19nZXRfY21kX2N0cmxfbm9kZShzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYpOw0KPiA+DQo+ID4g LQ0KPiA+ICAvKioNCj4gPiAgICogIEBicmllZiBTaW1wbGUgY2FsbGJhY2sgdGhhdCBjb3BpZXMg cmVzcG9uc2UgYmFjayBpbnRvIGNvbW1hbmQNCj4gPiAgICoNCj4gPiBAQCAtMzE5LDYgKzMxOCw2 MCBAQCBpbnQgbGJzX2NtZF84MDJfMTFfc2xlZXBfcGFyYW1zKHN0cnVjdCBsYnNfcHJpdmF0ZSAq cHJpdiwgdWludDE2X3QgY21kX2FjdGlvbiwNCj4gPiAgICAgcmV0dXJuIDA7DQo+ID4gIH0NCj4g Pg0KPiA+ICtzdGF0aWMgaW50IGxic193YWl0X2Zvcl9kc19hd2FrZShzdHJ1Y3QgbGJzX3ByaXZh dGUgKnByaXYpDQo+ID4gK3sNCj4gPiArICAgaW50IHJldCA9IDA7DQo+ID4gKw0KPiA+ICsgICBs YnNfZGViX2VudGVyKExCU19ERUJfQ01EKTsNCj4gPiArDQo+ID4gKyAgIGlmIChwcml2LT5pc19k ZWVwX3NsZWVwKSB7DQo+ID4gKyAgICAgICAgICAgaWYgKCF3YWl0X2V2ZW50X2ludGVycnVwdGli bGVfdGltZW91dChwcml2LT5kc19hd2FrZV9xLA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICFwcml2LT5pc19kZWVwX3NsZWVwLCAoMTAgKiBIWikpKSB7DQo+ID4gKyAg ICAgICAgICAgICAgICAgICBsYnNfcHJfZXJyKCJkc19hd2FrZV9xOiB0aW1lciBleHBpcmVkXG4i KTsNCj4gPiArICAgICAgICAgICAgICAgICAgIHJldCA9IC0xOw0KPiA+ICsgICAgICAgICAgIH0N Cj4gPiArICAgfQ0KPiA+ICsNCj4gPiArICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfQ01E LCAicmV0ICVkIiwgcmV0KTsNCj4gPiArICAgcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4g PiAraW50IGxic19zZXRfZGVlcF9zbGVlcChzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYsIGludCBk ZWVwX3NsZWVwKQ0KPiA+ICt7DQo+ID4gKyAgIGludCByZXQgPSAgMDsNCj4gPiArDQo+ID4gKyAg IGxic19kZWJfZW50ZXIoTEJTX0RFQl9DTUQpOw0KPiA+ICsNCj4gPiArICAgaWYgKGRlZXBfc2xl ZXApIHsNCj4gPiArICAgICAgICAgICBpZiAocHJpdi0+aXNfZGVlcF9zbGVlcCAhPSAxKSB7DQo+ ID4gKyAgICAgICAgICAgICAgICAgICBsYnNfZGViX2NtZCgiZGVlcCBzbGVlcDogc2xlZXBcbiIp Ow0KPiA+ICsgICAgICAgICAgICAgICAgICAgQlVHX09OKCFwcml2LT5lbnRlcl9kZWVwX3NsZWVw KTsNCj4gPiArICAgICAgICAgICAgICAgICAgIHJldCA9IHByaXYtPmVudGVyX2RlZXBfc2xlZXAo cHJpdik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBpZiAoIXJldCkgew0KPiA+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICBuZXRpZl9zdG9wX3F1ZXVlKHByaXYtPmRldik7DQo+ID4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgIG5ldGlmX2NhcnJpZXJfb2ZmKHByaXYtPmRldik7DQo+ ID4gKyAgICAgICAgICAgICAgICAgICB9DQo+ID4gKyAgICAgICAgICAgfSBlbHNlIHsNCj4gPiAr ICAgICAgICAgICAgICAgICAgIGxic19wcl9lcnIoImRlZXAgc2xlZXA6IGFscmVhZHkgZW5hYmxl ZFxuIik7DQo+ID4gKyAgICAgICAgICAgfQ0KPiA+ICsgICB9IGVsc2Ugew0KPiA+ICsgICAgICAg ICAgIGlmIChwcml2LT5pc19kZWVwX3NsZWVwKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBs YnNfZGViX2NtZCgiZGVlcCBzbGVlcDogd2FrZXVwXG4iKTsNCj4gPiArICAgICAgICAgICAgICAg ICAgIEJVR19PTighcHJpdi0+ZXhpdF9kZWVwX3NsZWVwKTsNCj4gPiArICAgICAgICAgICAgICAg ICAgIHJldCA9IHByaXYtPmV4aXRfZGVlcF9zbGVlcChwcml2KTsNCj4gPiArICAgICAgICAgICAg ICAgICAgIGlmICghcmV0KSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldCA9 IGxic193YWl0X2Zvcl9kc19hd2FrZShwcml2KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAg ICAgICAgaWYgKHJldCkNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBs YnNfcHJfZXJyKCJkZWVwIHNsZWVwOiB3YWtldXAiDQo+ID4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmYWlsZWRcbiIpOw0KPiA+ICsgICAgICAg ICAgICAgICAgICAgfQ0KPiA+ICsgICAgICAgICAgIH0NCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAr ICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfQ01ELCAicmV0ICVkIiwgcmV0KTsNCj4gPiAr ICAgcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiAgaW50IGxic19jbWRfODAyXzExX3Nl dF93ZXAoc3RydWN0IGxic19wcml2YXRlICpwcml2LCB1aW50MTZfdCBjbWRfYWN0aW9uLA0KPiA+ ICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGFzc29jX3JlcXVlc3QgKmFzc29jKQ0KPiA+ ICB7DQo+ID4gQEAgLTEyNDIsOCArMTI5NSwxNyBAQCBzdGF0aWMgdm9pZCBsYnNfc3VibWl0X2Nv bW1hbmQoc3RydWN0IGxic19wcml2YXRlICpwcml2LA0KPiA+ICAgICAgICAgICAgIHRpbWVvID0g SFovNDsNCj4gPiAgICAgfQ0KPiA+DQo+ID4gLSAgIC8qIFNldHVwIHRoZSB0aW1lciBhZnRlciB0 cmFuc21pdCBjb21tYW5kICovDQo+ID4gLSAgIG1vZF90aW1lcigmcHJpdi0+Y29tbWFuZF90aW1l ciwgamlmZmllcyArIHRpbWVvKTsNCj4gPiArICAgaWYgKGNvbW1hbmQgPT0gQ01EXzgwMl8xMV9E RUVQX1NMRUVQKSB7DQo+ID4gKyAgICAgICAgICAgaWYgKHByaXYtPmlzX2F1dG9fZGVlcF9zbGVl cF9lbmFibGVkKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBwcml2LT53YWtldXBfZGV2X3Jl cXVpcmVkID0gMTsNCj4gPiArICAgICAgICAgICAgICAgICAgIHByaXYtPmRubGRfc2VudCA9IDA7 DQo+ID4gKyAgICAgICAgICAgfQ0KPiA+ICsgICAgICAgICAgIHByaXYtPmlzX2RlZXBfc2xlZXAg PSAxOw0KPiA+ICsgICAgICAgICAgIGxic19jb21wbGV0ZV9jb21tYW5kKHByaXYsIGNtZG5vZGUs IDApOw0KPiA+ICsgICB9IGVsc2Ugew0KPiA+ICsgICAgICAgICAgIC8qIFNldHVwIHRoZSB0aW1l ciBhZnRlciB0cmFuc21pdCBjb21tYW5kICovDQo+ID4gKyAgICAgICAgICAgbW9kX3RpbWVyKCZw cml2LT5jb21tYW5kX3RpbWVyLCBqaWZmaWVzICsgdGltZW8pOw0KPiA+ICsgICB9DQo+ID4NCj4g PiAgICAgbGJzX2RlYl9sZWF2ZShMQlNfREVCX0hPU1QpOw0KPiA+ICB9DQo+ID4gQEAgLTE1MDUs NiArMTU2NywxMCBAQCBpbnQgbGJzX3ByZXBhcmVfYW5kX3NlbmRfY29tbWFuZChzdHJ1Y3QgbGJz X3ByaXZhdGUgKnByaXYsDQo+ID4gICAgIGNhc2UgQ01EXzgwMl8xMV9CRUFDT05fQ1RSTDoNCj4g PiAgICAgICAgICAgICByZXQgPSBsYnNfY21kX2Jjbl9jdHJsKHByaXYsIGNtZHB0ciwgY21kX2Fj dGlvbik7DQo+ID4gICAgICAgICAgICAgYnJlYWs7DQo+ID4gKyAgIGNhc2UgQ01EXzgwMl8xMV9E RUVQX1NMRUVQOg0KPiA+ICsgICAgICAgICAgIGNtZHB0ci0+Y29tbWFuZCA9IGNwdV90b19sZTE2 KENNRF84MDJfMTFfREVFUF9TTEVFUCk7DQo+ID4gKyAgICAgICAgICAgY21kcHRyLT5zaXplID0g Y3B1X3RvX2xlMTYoU19EU19HRU4pOw0KPiA+ICsgICAgICAgICAgIGJyZWFrOw0KPiA+ICAgICBk ZWZhdWx0Og0KPiA+ICAgICAgICAgICAgIGxic19wcl9lcnIoIlBSRVBfQ01EOiB1bmtub3duIGNv bW1hbmQgMHglMDR4XG4iLCBjbWRfbm8pOw0KPiA+ICAgICAgICAgICAgIHJldCA9IC0xOw0KPiA+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWRyZXNwLmMgYi9k cml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9jbWRyZXNwLmMNCj4gPiBpbmRleCBjNDJkM2Zh Li40N2QyYjE5IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFz L2NtZHJlc3AuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2NtZHJl c3AuYw0KPiA+IEBAIC01MDQsOSArNTA0LDIxIEBAIGludCBsYnNfcHJvY2Vzc19ldmVudChzdHJ1 Y3QgbGJzX3ByaXZhdGUgKnByaXYsIHUzMiBldmVudCkNCj4gPg0KPiA+ICAgICBjYXNlIE1BQ1JF R19JTlRfQ09ERV9IT1NUX0FXQUtFOg0KPiA+ICAgICAgICAgICAgIGxic19kZWJfY21kKCJFVkVO VDogaG9zdCBhd2FrZVxuIik7DQo+ID4gKyAgICAgICAgICAgaWYgKHByaXYtPnJlc2V0X2RlZXBf c2xlZXBfd2FrZXVwKQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgcHJpdi0+cmVzZXRfZGVlcF9z bGVlcF93YWtldXAocHJpdik7DQo+ID4gKyAgICAgICAgICAgcHJpdi0+aXNfZGVlcF9zbGVlcCA9 IDA7DQo+ID4gICAgICAgICAgICAgbGJzX3NlbmRfY29uZmlybXdha2UocHJpdik7DQo+ID4gICAg ICAgICAgICAgYnJlYWs7DQo+ID4NCj4gPiArICAgY2FzZSBNQUNSRUdfSU5UX0NPREVfREVFUF9T TEVFUF9BV0FLRToNCj4gPiArICAgICAgICAgICBpZiAocHJpdi0+cmVzZXRfZGVlcF9zbGVlcF93 YWtldXApDQo+ID4gKyAgICAgICAgICAgICAgICAgICBwcml2LT5yZXNldF9kZWVwX3NsZWVwX3dh a2V1cChwcml2KTsNCj4gPiArICAgICAgICAgICBsYnNfZGViX2NtZCgiRVZFTlQ6IGRzIGF3YWtl XG4iKTsNCj4gPiArICAgICAgICAgICBwcml2LT5pc19kZWVwX3NsZWVwID0gMDsNCj4gPiArICAg ICAgICAgICBwcml2LT53YWtldXBfZGV2X3JlcXVpcmVkID0gMDsNCj4gPiArICAgICAgICAgICB3 YWtlX3VwX2ludGVycnVwdGlibGUoJnByaXYtPmRzX2F3YWtlX3EpOw0KPiA+ICsgICAgICAgICAg IGJyZWFrOw0KPiA+ICsNCj4gPiAgICAgY2FzZSBNQUNSRUdfSU5UX0NPREVfUFNfQVdBS0U6DQo+ ID4gICAgICAgICAgICAgbGJzX2RlYl9jbWQoIkVWRU5UOiBwcyBhd2FrZVxuIik7DQo+ID4gICAg ICAgICAgICAgLyogaGFuZGxlIHVuZXhwZWN0ZWQgUFMgQVdBS0UgZXZlbnQgKi8NCj4gPiBkaWZm IC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGVidWdmcy5jIGIvZHJpdmVy cy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGVidWdmcy5jDQo+ID4gaW5kZXggODkzYTU1Yy4uOGE3 ZTkzMSAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9kZWJ1 Z2ZzLmMNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9kZWJ1Z2ZzLmMN Cj4gPiBAQCAtMTE3LDYgKzExNywxMSBAQCBzdGF0aWMgc3NpemVfdCBsYnNfc2xlZXBwYXJhbXNf d3JpdGUoc3RydWN0IGZpbGUgKmZpbGUsDQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ICAgICAgICAg ICAgIHJldHVybiAtRU5PTUVNOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2Vk KHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAg IGdvdG8gb3V0X3VubG9jazsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgYnVmX3NpemUgPSBt aW4oY291bnQsIGxlbiAtIDEpOw0KPiA+ICAgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2Vy X2J1ZiwgYnVmX3NpemUpKSB7DQo+ID4gICAgICAgICAgICAgcmV0ID0gLUVGQVVMVDsNCj4gPiBA QCAtMTU3LDYgKzE2MiwxMSBAQCBzdGF0aWMgc3NpemVfdCBsYnNfc2xlZXBwYXJhbXNfcmVhZChz dHJ1Y3QgZmlsZSAqZmlsZSwgY2hhciBfX3VzZXIgKnVzZXJidWYsDQo+ID4gICAgIGlmICghYnVm KQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOw0KPiA+DQo+ID4gKyAgIGlmICghbGJz X2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0K PiA+ICsgICAgICAgICAgIGdvdG8gb3V0X3VubG9jazsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAg ICAgcmV0ID0gbGJzX2NtZF84MDJfMTFfc2xlZXBfcGFyYW1zKHByaXYsIENNRF9BQ1RfR0VULCAm c3ApOw0KPiA+ICAgICBpZiAocmV0KQ0KPiA+ICAgICAgICAgICAgIGdvdG8gb3V0X3VubG9jazsN Cj4gPiBAQCAtMjIzLDYgKzIzMyw5IEBAIHN0YXRpYyBzc2l6ZV90IGxic190aHJlc2hvbGRfcmVh ZCh1aW50MTZfdCB0bHZfdHlwZSwgdWludDE2X3QgZXZlbnRfbWFzaywNCj4gPiAgICAgdTggZnJl cTsNCj4gPiAgICAgaW50IGV2ZW50cyA9IDA7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21k X2FsbG93ZWQocHJpdikpDQo+ID4gKyAgICAgICAgICAgcmV0dXJuIC1FQlVTWTsNCj4gPiArDQo+ ID4gICAgIGJ1ZiA9IChjaGFyICopZ2V0X3plcm9lZF9wYWdlKEdGUF9LRVJORUwpOw0KPiA+ICAg ICBpZiAoIWJ1ZikNCj4gPiAgICAgICAgICAgICByZXR1cm4gLUVOT01FTTsNCj4gPiBAQCAtMjc1 LDYgKzI4OCw5IEBAIHN0YXRpYyBzc2l6ZV90IGxic190aHJlc2hvbGRfd3JpdGUodWludDE2X3Qg dGx2X3R5cGUsIHVpbnQxNl90IGV2ZW50X21hc2ssDQo+ID4gICAgIGNoYXIgKmJ1ZjsNCj4gPiAg ICAgaW50IHJldDsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkN Cj4gPiArICAgICAgICAgICByZXR1cm4gLUVCVVNZOw0KPiA+ICsNCj4gPiAgICAgYnVmID0gKGNo YXIgKilnZXRfemVyb2VkX3BhZ2UoR0ZQX0tFUk5FTCk7DQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ ICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOw0KPiA+IEBAIC00NDQsNiArNDYwLDExIEBAIHN0 YXRpYyBzc2l6ZV90IGxic19yZG1hY19yZWFkKHN0cnVjdCBmaWxlICpmaWxlLCBjaGFyIF9fdXNl ciAqdXNlcmJ1ZiwNCj4gPiAgICAgaWYgKCFidWYpDQo+ID4gICAgICAgICAgICAgcmV0dXJuIC1F Tk9NRU07DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4g PiArICAgICAgICAgICBmcmVlX3BhZ2UoYWRkcik7DQo+ID4gKyAgICAgICAgICAgcmV0dXJuIC1F QlVTWTsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgb2ZmdmFsLm9mZnNldCA9IHByaXYtPm1h Y19vZmZzZXQ7DQo+ID4gICAgIG9mZnZhbC52YWx1ZSA9IDA7DQo+ID4NCj4gPiBAQCAtNDk2LDYg KzUxNywxMSBAQCBzdGF0aWMgc3NpemVfdCBsYnNfd3JtYWNfd3JpdGUoc3RydWN0IGZpbGUgKmZp bGUsDQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOw0K PiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAg ICAgICAgcmVzID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0X3VubG9jazsNCj4g PiArICAgfQ0KPiA+ICsNCj4gPiAgICAgYnVmX3NpemUgPSBtaW4oY291bnQsIGxlbiAtIDEpOw0K PiA+ICAgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2VyYnVmLCBidWZfc2l6ZSkpIHsNCj4g PiAgICAgICAgICAgICByZXMgPSAtRUZBVUxUOw0KPiA+IEBAIC01MzIsNiArNTU4LDExIEBAIHN0 YXRpYyBzc2l6ZV90IGxic19yZGJicF9yZWFkKHN0cnVjdCBmaWxlICpmaWxlLCBjaGFyIF9fdXNl ciAqdXNlcmJ1ZiwNCj4gPiAgICAgaWYgKCFidWYpDQo+ID4gICAgICAgICAgICAgcmV0dXJuIC1F Tk9NRU07DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4g PiArICAgICAgICAgICBmcmVlX3BhZ2UoYWRkcik7DQo+ID4gKyAgICAgICAgICAgcmV0dXJuIC1F QlVTWTsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgb2ZmdmFsLm9mZnNldCA9IHByaXYtPmJi cF9vZmZzZXQ7DQo+ID4gICAgIG9mZnZhbC52YWx1ZSA9IDA7DQo+ID4NCj4gPiBAQCAtNTg1LDYg KzYxNiwxMSBAQCBzdGF0aWMgc3NpemVfdCBsYnNfd3JiYnBfd3JpdGUoc3RydWN0IGZpbGUgKmZp bGUsDQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOw0K PiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAg ICAgICAgcmVzID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0X3VubG9jazsNCj4g PiArICAgfQ0KPiA+ICsNCj4gPiAgICAgYnVmX3NpemUgPSBtaW4oY291bnQsIGxlbiAtIDEpOw0K PiA+ICAgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2VyYnVmLCBidWZfc2l6ZSkpIHsNCj4g PiAgICAgICAgICAgICByZXMgPSAtRUZBVUxUOw0KPiA+IEBAIC02MjEsNiArNjU3LDExIEBAIHN0 YXRpYyBzc2l6ZV90IGxic19yZHJmX3JlYWQoc3RydWN0IGZpbGUgKmZpbGUsIGNoYXIgX191c2Vy ICp1c2VyYnVmLA0KPiA+ICAgICBpZiAoIWJ1ZikNCj4gPiAgICAgICAgICAgICByZXR1cm4gLUVO T01FTTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ ICsgICAgICAgICAgIGZyZWVfcGFnZShhZGRyKTsNCj4gPiArICAgICAgICAgICByZXR1cm4gLUVC VVNZOw0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBvZmZ2YWwub2Zmc2V0ID0gcHJpdi0+cmZf b2Zmc2V0Ow0KPiA+ICAgICBvZmZ2YWwudmFsdWUgPSAwOw0KPiA+DQo+ID4gQEAgLTY3NCw2ICs3 MTUsMTEgQEAgc3RhdGljIHNzaXplX3QgbGJzX3dycmZfd3JpdGUoc3RydWN0IGZpbGUgKmZpbGUs DQo+ID4gICAgIGlmICghYnVmKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOw0KPiA+ DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAg ICAgcmVzID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0X3VubG9jazsNCj4gPiAr ICAgfQ0KPiA+ICsNCj4gPiAgICAgYnVmX3NpemUgPSBtaW4oY291bnQsIGxlbiAtIDEpOw0KPiA+ ICAgICBpZiAoY29weV9mcm9tX3VzZXIoYnVmLCB1c2VyYnVmLCBidWZfc2l6ZSkpIHsNCj4gPiAg ICAgICAgICAgICByZXMgPSAtRUZBVUxUOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93 aXJlbGVzcy9saWJlcnRhcy9kZWNsLmggYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9k ZWNsLmgNCj4gPiBpbmRleCAwYjg0YmRjLi4zNGI0NzVmIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZl cnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2RlY2wuaA0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dp cmVsZXNzL2xpYmVydGFzL2RlY2wuaA0KPiA+IEBAIC0zMyw2ICszMywxMCBAQCBpbnQgbGJzX2V4 ZWN1dGVfbmV4dF9jb21tYW5kKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdik7DQo+ID4gIGludCBs YnNfcHJvY2Vzc19ldmVudChzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYsIHUzMiBldmVudCk7DQo+ ID4gIHZvaWQgbGJzX3F1ZXVlX2V2ZW50KHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdiwgdTMyIGV2 ZW50KTsNCj4gPiAgdm9pZCBsYnNfbm90aWZ5X2NvbW1hbmRfcmVzcG9uc2Uoc3RydWN0IGxic19w cml2YXRlICpwcml2LCB1OCByZXNwX2lkeCk7DQo+ID4gK2ludCBsYnNfc2V0X2RlZXBfc2xlZXAo c3RydWN0IGxic19wcml2YXRlICpwcml2LCBpbnQgZGVlcF9zbGVlcCk7DQo+ID4gK2ludCBsYnNf aXNfY21kX2FsbG93ZWQoc3RydWN0IGxic19wcml2YXRlICpwcml2KTsNCj4gPiAraW50IGxic19l bnRlcl9hdXRvX2RlZXBfc2xlZXAoc3RydWN0IGxic19wcml2YXRlICpwcml2KTsNCj4gPiAraW50 IGxic19leGl0X2F1dG9fZGVlcF9zbGVlcChzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYpOw0KPiA+ DQo+ID4gIHUzMiBsYnNfZndfaW5kZXhfdG9fZGF0YV9yYXRlKHU4IGluZGV4KTsNCj4gPiAgdTgg bGJzX2RhdGFfcmF0ZV90b19md19pbmRleCh1MzIgcmF0ZSk7DQo+ID4gZGlmZiAtLWdpdCBhL2Ry aXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2Rldi5oIGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mv bGliZXJ0YXMvZGV2LmgNCj4gPiBpbmRleCA1NzhjNjk3Li5lMmI0ZWYyIDEwMDY0NA0KPiA+IC0t LSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2Rldi5oDQo+ID4gKysrIGIvZHJpdmVy cy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvZGV2LmgNCj4gPiBAQCAtMTI5LDYgKzEyOSwyMCBAQCBz dHJ1Y3QgbGJzX3ByaXZhdGUgew0KPiA+ICAgICB1MzIgYmJwX29mZnNldDsNCj4gPiAgICAgdTMy IHJmX29mZnNldDsNCj4gPg0KPiA+ICsgICAvKiogRGVlcCBzbGVlcCBmbGFnICovDQo+ID4gKyAg IGludCBpc19kZWVwX3NsZWVwOw0KPiA+ICsgICAvKiogQXV0byBkZWVwIHNsZWVwIGVuYWJsZWQg ZmxhZyAqLw0KPiA+ICsgICBpbnQgaXNfYXV0b19kZWVwX3NsZWVwX2VuYWJsZWQ7DQo+ID4gKyAg IC8qKiBEZXZpY2Ugd2FrZXVwIHJlcXVpcmVkIGZsYWcgKi8NCj4gPiArICAgaW50IHdha2V1cF9k ZXZfcmVxdWlyZWQ7DQo+ID4gKyAgIC8qKiBBdXRvIGRlZXAgc2xlZXAgZmxhZyovDQo+ID4gKyAg IGludCBpc19hY3Rpdml0eV9kZXRlY3RlZDsNCj4gPiArICAgLyoqIEF1dG8gZGVlcCBzbGVlcCB0 aW1lb3V0IChpbiBtaWxpc2Vjb25kcykgKi8NCj4gPiArICAgaW50IGF1dG9fZGVlcF9zbGVlcF90 aW1lb3V0Ow0KPiA+ICsNCj4gPiArICAgLyoqIERlZXAgc2xlZXAgd2FpdCBxdWV1ZSAqLw0KPiA+ ICsgICB3YWl0X3F1ZXVlX2hlYWRfdCAgICAgICBkc19hd2FrZV9xOw0KPiA+ICsNCj4gPiAgICAg LyogRG93bmxvYWQgc2VudDoNCj4gPiAgICAgICAgYml0MCAxLzA9ZGF0YV9zZW50L2RhdGFfdHhf ZG9uZSwNCj4gPiAgICAgICAgYml0MSAxLzA9Y21kX3NlbnQvY21kX3R4X2RvbmUsDQo+ID4gQEAg LTE1NCw2ICsxNjgsOSBAQCBzdHJ1Y3QgbGJzX3ByaXZhdGUgew0KPiA+ICAgICAvKiogSGFyZHdh cmUgYWNjZXNzICovDQo+ID4gICAgIGludCAoKmh3X2hvc3RfdG9fY2FyZCkgKHN0cnVjdCBsYnNf cHJpdmF0ZSAqcHJpdiwgdTggdHlwZSwgdTggKnBheWxvYWQsIHUxNiBuYik7DQo+ID4gICAgIHZv aWQgKCpyZXNldF9jYXJkKSAoc3RydWN0IGxic19wcml2YXRlICpwcml2KTsNCj4gPiArICAgaW50 ICgqZW50ZXJfZGVlcF9zbGVlcCkgKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdik7DQo+ID4gKyAg IGludCAoKmV4aXRfZGVlcF9zbGVlcCkgKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdik7DQo+ID4g KyAgIGludCAoKnJlc2V0X2RlZXBfc2xlZXBfd2FrZXVwKSAoc3RydWN0IGxic19wcml2YXRlICpw cml2KTsNCj4gPg0KPiA+ICAgICAvKiBXYWtlIE9uIExBTiAqLw0KPiA+ICAgICB1aW50MzJfdCB3 b2xfY3JpdGVyaWE7DQo+ID4gQEAgLTIwNCw2ICsyMjEsNyBAQCBzdHJ1Y3QgbGJzX3ByaXZhdGUg ew0KPiA+DQo+ID4gICAgIC8qKiBUaW1lcnMgKi8NCj4gPiAgICAgc3RydWN0IHRpbWVyX2xpc3Qg Y29tbWFuZF90aW1lcjsNCj4gPiArICAgc3RydWN0IHRpbWVyX2xpc3QgYXV0b19kZWVwc2xlZXBf dGltZXI7DQo+ID4gICAgIGludCBucl9yZXRyaWVzOw0KPiA+ICAgICBpbnQgY21kX3RpbWVkX291 dDsNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9o b3N0LmggYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9ob3N0LmgNCj4gPiBpbmRleCBm ZThmMGNiLi5jMDU1ZGFhIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xp YmVydGFzL2hvc3QuaA0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2hv c3QuaA0KPiA+IEBAIC01Nyw2ICs1Nyw3IEBADQo+ID4gICNkZWZpbmUgQ01EXzgwMl8xMV9FTkFC TEVfUlNOICAgICAgICAgICAgICAgICAgICAgIDB4MDAyZg0KPiA+ICAjZGVmaW5lIENNRF84MDJf MTFfU0VUX0FGQyAgICAgICAgICAgICAgICAgMHgwMDNjDQo+ID4gICNkZWZpbmUgQ01EXzgwMl8x MV9HRVRfQUZDICAgICAgICAgICAgICAgICAweDAwM2QNCj4gPiArI2RlZmluZSBDTURfODAyXzEx X0RFRVBfU0xFRVAgICAgICAgICAgICAgICAgICAweDAwM2UNCj4gPiAgI2RlZmluZSBDTURfODAy XzExX0FEX0hPQ19TVE9QICAgICAgICAgICAgICAgICAgICAgMHgwMDQwDQo+ID4gICNkZWZpbmUg Q01EXzgwMl8xMV9IT1NUX1NMRUVQX0NGRyAgICAgICAgICAweDAwNDMNCj4gPiAgI2RlZmluZSBD TURfODAyXzExX1dBS0VVUF9DT05GSVJNICAgICAgICAgIDB4MDA0NA0KPiA+IGRpZmYgLS1naXQg YS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9jcy5jIGIvZHJpdmVycy9uZXQvd2ly ZWxlc3MvbGliZXJ0YXMvaWZfY3MuYw0KPiA+IGluZGV4IDYyMzgxNzYuLjQ2NTc0MmYgMTAwNjQ0 DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfY3MuYw0KPiA+ICsr KyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX2NzLmMNCj4gPiBAQCAtOTQ2LDYg Kzk0Niw5IEBAIHN0YXRpYyBpbnQgaWZfY3NfcHJvYmUoc3RydWN0IHBjbWNpYV9kZXZpY2UgKnBf ZGV2KQ0KPiA+ICAgICBjYXJkLT5wcml2ID0gcHJpdjsNCj4gPiAgICAgcHJpdi0+Y2FyZCA9IGNh cmQ7DQo+ID4gICAgIHByaXYtPmh3X2hvc3RfdG9fY2FyZCA9IGlmX2NzX2hvc3RfdG9fY2FyZDsN Cj4gPiArICAgcHJpdi0+ZW50ZXJfZGVlcF9zbGVlcCA9IE5VTEw7DQo+ID4gKyAgIHByaXYtPmV4 aXRfZGVlcF9zbGVlcCA9IE5VTEw7DQo+ID4gKyAgIHByaXYtPnJlc2V0X2RlZXBfc2xlZXBfd2Fr ZXVwID0gTlVMTDsNCj4gPiAgICAgcHJpdi0+ZndfcmVhZHkgPSAxOw0KPiA+DQo+ID4gICAgIC8q IE5vdyBhY3R1YWxseSBnZXQgdGhlIElSUSAqLw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25l dC93aXJlbGVzcy9saWJlcnRhcy9pZl9zZGlvLmMgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJl cnRhcy9pZl9zZGlvLmMNCj4gPiBpbmRleCA0ODVhOGQ0Li45NzE2NzI4IDEwMDY0NA0KPiA+IC0t LSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3NkaW8uYw0KPiA+ICsrKyBiL2Ry aXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3NkaW8uYw0KPiA+IEBAIC04MzEsNiArODMx LDU4IEBAIG91dDoNCj4gPiAgICAgcmV0dXJuIHJldDsNCj4gPiAgfQ0KPiA+DQo+ID4gK3N0YXRp YyBpbnQgaWZfc2Rpb19lbnRlcl9kZWVwX3NsZWVwKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdikN Cj4gPiArew0KPiA+ICsgICBpbnQgcmV0ID0gLTE7DQo+ID4gKyAgIHN0cnVjdCBjbWRfaGVhZGVy IGNtZDsNCj4gPiArDQo+ID4gKyAgIG1lbXNldCgmY21kLCAwLCBzaXplb2YoY21kKSk7DQo+ID4g Kw0KPiA+ICsgICBsYnNfZGViX3NkaW8oInNlbmQgREVFUF9TTEVFUCBjb21tYW5kXG4iKTsNCj4g PiArICAgcmV0ID0gX19sYnNfY21kKHByaXYsIENNRF84MDJfMTFfREVFUF9TTEVFUCwgJmNtZCwg c2l6ZW9mKGNtZCksDQo+ID4gKyAgICAgICAgICAgICAgICAgICBsYnNfY21kX2NvcHliYWNrLCAo dW5zaWduZWQgbG9uZykgJmNtZCk7DQo+ID4gKyAgIGlmIChyZXQpDQo+ID4gKyAgICAgICAgICAg bGJzX3ByX2VycigiREVFUF9TTEVFUCBjbWQgZmFpbGVkXG4iKTsNCj4gPiArDQo+ID4gKyAgIG1k ZWxheSgyMDApOw0KPiA+ICsgICByZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0 aWMgaW50IGlmX3NkaW9fZXhpdF9kZWVwX3NsZWVwKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdikN Cj4gPiArew0KPiA+ICsgICBzdHJ1Y3QgaWZfc2Rpb19jYXJkICpjYXJkID0gcHJpdi0+Y2FyZDsN Cj4gPiArICAgaW50IHJldCA9IC0xOw0KPiA+ICsNCj4gPiArICAgbGJzX2RlYl9lbnRlcihMQlNf REVCX1NESU8pOw0KPiA+ICsgICBzZGlvX2NsYWltX2hvc3QoY2FyZC0+ZnVuYyk7DQo+ID4gKw0K PiA+ICsgICBzZGlvX3dyaXRlYihjYXJkLT5mdW5jLCBIT1NUX1BPV0VSX1VQLCBDT05GSUdVUkFU SU9OX1JFRywgJnJldCk7DQo+ID4gKyAgIGlmIChyZXQpDQo+ID4gKyAgICAgICAgICAgbGJzX3By X2Vycigic2Rpb193cml0ZWIgZmFpbGVkIVxuIik7DQo+ID4gKw0KPiA+ICsgICBzZGlvX3JlbGVh c2VfaG9zdChjYXJkLT5mdW5jKTsNCj4gPiArICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJf U0RJTywgInJldCAlZCIsIHJldCk7DQo+ID4gKyAgIHJldHVybiByZXQ7DQo+ID4gK30NCj4gPiAr DQo+ID4gK3N0YXRpYyBpbnQgaWZfc2Rpb19yZXNldF9kZWVwX3NsZWVwX3dha2V1cChzdHJ1Y3Qg bGJzX3ByaXZhdGUgKnByaXYpDQo+ID4gK3sNCj4gPiArICAgc3RydWN0IGlmX3NkaW9fY2FyZCAq Y2FyZCA9IHByaXYtPmNhcmQ7DQo+ID4gKyAgIGludCByZXQgPSAtMTsNCj4gPiArDQo+ID4gKyAg IGxic19kZWJfZW50ZXIoTEJTX0RFQl9TRElPKTsNCj4gPiArICAgc2Rpb19jbGFpbV9ob3N0KGNh cmQtPmZ1bmMpOw0KPiA+ICsNCj4gPiArICAgc2Rpb193cml0ZWIoY2FyZC0+ZnVuYywgMCwgQ09O RklHVVJBVElPTl9SRUcsICZyZXQpOw0KPiA+ICsgICBpZiAocmV0KQ0KPiA+ICsgICAgICAgICAg IGxic19wcl9lcnIoInNkaW9fd3JpdGViIGZhaWxlZCFcbiIpOw0KPiA+ICsNCj4gPiArICAgc2Rp b19yZWxlYXNlX2hvc3QoY2FyZC0+ZnVuYyk7DQo+ID4gKyAgIGxic19kZWJfbGVhdmVfYXJncyhM QlNfREVCX1NESU8sICJyZXQgJWQiLCByZXQpOw0KPiA+ICsgICByZXR1cm4gcmV0Ow0KPiA+ICsN Cj4gPiArfQ0KPiA+ICsNCj4gPiAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovDQo+ID4gIC8qIFNESU8gY2FsbGJhY2tz ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqLw0KPiA+ ICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKi8NCj4gPiBAQCAtODU5LDYgKzkxMSw3IEBAIHN0YXRpYyB2b2lkIGlmX3Nk aW9faW50ZXJydXB0KHN0cnVjdCBzZGlvX2Z1bmMgKmZ1bmMpDQo+ID4gICAgICAqIElnbm9yZSB0 aGUgZGVmaW5lIG5hbWUsIHRoaXMgcmVhbGx5IG1lYW5zIHRoZSBjYXJkIGhhcw0KPiA+ICAgICAg KiBzdWNjZXNzZnVsbHkgcmVjZWl2ZWQgdGhlIGNvbW1hbmQuDQo+ID4gICAgICAqLw0KPiA+ICsg ICBjYXJkLT5wcml2LT5pc19hY3Rpdml0eV9kZXRlY3RlZCA9IDE7DQo+ID4gICAgIGlmIChjYXVz ZSAmIElGX1NESU9fSF9JTlRfRE5MRCkNCj4gPiAgICAgICAgICAgICBsYnNfaG9zdF90b19jYXJk X2RvbmUoY2FyZC0+cHJpdik7DQo+ID4NCj4gPiBAQCAtOTk4LDYgKzEwNTEsOSBAQCBzdGF0aWMg aW50IGlmX3NkaW9fcHJvYmUoc3RydWN0IHNkaW9fZnVuYyAqZnVuYywNCj4gPg0KPiA+ICAgICBw cml2LT5jYXJkID0gY2FyZDsNCj4gPiAgICAgcHJpdi0+aHdfaG9zdF90b19jYXJkID0gaWZfc2Rp b19ob3N0X3RvX2NhcmQ7DQo+ID4gKyAgIHByaXYtPmVudGVyX2RlZXBfc2xlZXAgPSBpZl9zZGlv X2VudGVyX2RlZXBfc2xlZXA7DQo+ID4gKyAgIHByaXYtPmV4aXRfZGVlcF9zbGVlcCA9IGlmX3Nk aW9fZXhpdF9kZWVwX3NsZWVwOw0KPiA+ICsgICBwcml2LT5yZXNldF9kZWVwX3NsZWVwX3dha2V1 cCA9IGlmX3NkaW9fcmVzZXRfZGVlcF9zbGVlcF93YWtldXA7DQo+ID4NCj4gPiAgICAgcHJpdi0+ ZndfcmVhZHkgPSAxOw0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNz L2xpYmVydGFzL2lmX3NkaW8uaCBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3Nk aW8uaA0KPiA+IGluZGV4IDYwYzliMmYuLjEyMTc5YzEgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVy cy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc2Rpby5oDQo+ID4gKysrIGIvZHJpdmVycy9uZXQv d2lyZWxlc3MvbGliZXJ0YXMvaWZfc2Rpby5oDQo+ID4gQEAgLTUxLDUgKzUxLDYgQEANCj4gPiAg I2RlZmluZSBJRl9TRElPX0VWRU5UICAgICAgICAgICAweDgwZmMNCj4gPg0KPiA+ICAjZGVmaW5l IElGX1NESU9fQkxPQ0tfU0laRSAyNTYNCj4gPiAtDQo+ID4gKyNkZWZpbmUgQ09ORklHVVJBVElP Tl9SRUcgICAgICAgICAgICAgICAweDAzDQo+ID4gKyNkZWZpbmUgSE9TVF9QT1dFUl9VUCAgICAg ICAgICAgICAgICAgICAoMHgxVSA8PCAxKQ0KPiA+ICAjZW5kaWYNCj4gPiBkaWZmIC0tZ2l0IGEv ZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc3BpLmMgYi9kcml2ZXJzL25ldC93aXJl bGVzcy9saWJlcnRhcy9pZl9zcGkuYw0KPiA+IGluZGV4IDQ0NmUzMjcuLmUyZmE2NTcgMTAwNjQ0 DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfc3BpLmMNCj4gPiAr KysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9pZl9zcGkuYw0KPiA+IEBAIC0xMTE3 LDYgKzExMTcsOSBAQCBzdGF0aWMgaW50IF9fZGV2aW5pdCBpZl9zcGlfcHJvYmUoc3RydWN0IHNw aV9kZXZpY2UgKnNwaSkNCj4gPiAgICAgY2FyZC0+cHJpdiA9IHByaXY7DQo+ID4gICAgIHByaXYt PmNhcmQgPSBjYXJkOw0KPiA+ICAgICBwcml2LT5od19ob3N0X3RvX2NhcmQgPSBpZl9zcGlfaG9z dF90b19jYXJkOw0KPiA+ICsgICBwcml2LT5lbnRlcl9kZWVwX3NsZWVwID0gTlVMTDsNCj4gPiAr ICAgcHJpdi0+ZXhpdF9kZWVwX3NsZWVwID0gTlVMTDsNCj4gPiArICAgcHJpdi0+cmVzZXRfZGVl cF9zbGVlcF93YWtldXAgPSBOVUxMOw0KPiA+ICAgICBwcml2LT5md19yZWFkeSA9IDE7DQo+ID4N Cj4gPiAgICAgLyogSW5pdGlhbGl6ZSBpbnRlcnJ1cHQgaGFuZGxpbmcgc3R1ZmYuICovDQo+ID4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lmX3VzYi5jIGIvZHJp dmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfdXNiLmMNCj4gPiBpbmRleCA5MmJjOGM1Li5h ODI2MmRlIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL2lm X3VzYi5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGliZXJ0YXMvaWZfdXNiLmMN Cj4gPiBAQCAtMzAwLDYgKzMwMCw5IEBAIHN0YXRpYyBpbnQgaWZfdXNiX3Byb2JlKHN0cnVjdCB1 c2JfaW50ZXJmYWNlICppbnRmLA0KPiA+ICAgICBjYXJkcC0+cHJpdi0+ZndfcmVhZHkgPSAxOw0K PiA+DQo+ID4gICAgIHByaXYtPmh3X2hvc3RfdG9fY2FyZCA9IGlmX3VzYl9ob3N0X3RvX2NhcmQ7 DQo+ID4gKyAgIHByaXYtPmVudGVyX2RlZXBfc2xlZXAgPSBOVUxMOw0KPiA+ICsgICBwcml2LT5l eGl0X2RlZXBfc2xlZXAgPSBOVUxMOw0KPiA+ICsgICBwcml2LT5yZXNldF9kZWVwX3NsZWVwX3dh a2V1cCA9IE5VTEw7DQo+ID4gICNpZmRlZiBDT05GSUdfT0xQQw0KPiA+ICAgICBpZiAobWFjaGlu ZV9pc19vbHBjKCkpDQo+ID4gICAgICAgICAgICAgcHJpdi0+cmVzZXRfY2FyZCA9IGlmX3VzYl9y ZXNldF9vbHBjX2NhcmQ7DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xp YmVydGFzL21haW4uYyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL21haW4uYw0KPiA+ IGluZGV4IDhkZjFjZmQuLjNiMTRmY2MgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2ly ZWxlc3MvbGliZXJ0YXMvbWFpbi5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3MvbGli ZXJ0YXMvbWFpbi5jDQo+ID4gQEAgLTU3NCw4ICs1NzQsMTAgQEAgdm9pZCBsYnNfaG9zdF90b19j YXJkX2RvbmUoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0KPiA+ICAgICBwcml2LT5kbmxkX3Nl bnQgPSBETkxEX1JFU19SRUNFSVZFRDsNCj4gPg0KPiA+ICAgICAvKiBXYWtlIG1haW4gdGhyZWFk IGlmIGNvbW1hbmRzIGFyZSBwZW5kaW5nICovDQo+ID4gLSAgIGlmICghcHJpdi0+Y3VyX2NtZCB8 fCBwcml2LT50eF9wZW5kaW5nX2xlbiA+IDApDQo+ID4gLSAgICAgICAgICAgd2FrZV91cF9pbnRl cnJ1cHRpYmxlKCZwcml2LT53YWl0cSk7DQo+ID4gKyAgIGlmICghcHJpdi0+Y3VyX2NtZCB8fCBw cml2LT50eF9wZW5kaW5nX2xlbiA+IDApIHsNCj4gPiArICAgICAgICAgICBpZiAoIXByaXYtPndh a2V1cF9kZXZfcmVxdWlyZWQpDQo+ID4gKyAgICAgICAgICAgICAgICAgICB3YWtlX3VwX2ludGVy cnVwdGlibGUoJnByaXYtPndhaXRxKTsNCj4gPiArICAgfQ0KPiA+DQo+ID4gICAgIHNwaW5fdW5s b2NrX2lycXJlc3RvcmUoJnByaXYtPmRyaXZlcl9sb2NrLCBmbGFncyk7DQo+ID4gICAgIGxic19k ZWJfbGVhdmUoTEJTX0RFQl9USFJFQUQpOw0KPiA+IEBAIC03NzAsNyArNzcyLDggQEAgc3RhdGlj IGludCBsYnNfdGhyZWFkKHZvaWQgKmRhdGEpDQo+ID4gICAgICAgICAgICAgICAgICAgICBzaG91 bGRzbGVlcCA9IDA7ICAgICAgICAvKiBXZSBoYXZlIGEgY29tbWFuZCByZXNwb25zZSAqLw0KPiA+ ICAgICAgICAgICAgIGVsc2UgaWYgKHByaXYtPmN1cl9jbWQpDQo+ID4gICAgICAgICAgICAgICAg ICAgICBzaG91bGRzbGVlcCA9IDE7ICAgICAgICAvKiBDYW4ndCBzZW5kIGEgY29tbWFuZDsgb25l IGFscmVhZHkgcnVubmluZyAqLw0KPiA+IC0gICAgICAgICAgIGVsc2UgaWYgKCFsaXN0X2VtcHR5 KCZwcml2LT5jbWRwZW5kaW5ncSkpDQo+ID4gKyAgICAgICAgICAgZWxzZSBpZiAoIWxpc3RfZW1w dHkoJnByaXYtPmNtZHBlbmRpbmdxKSAmJg0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICEocHJpdi0+d2FrZXVwX2Rldl9yZXF1aXJlZCkpDQo+ID4gICAgICAgICAgICAg ICAgICAgICBzaG91bGRzbGVlcCA9IDA7ICAgICAgICAvKiBXZSBoYXZlIGEgY29tbWFuZCB0byBz ZW5kICovDQo+ID4gICAgICAgICAgICAgZWxzZSBpZiAoX19rZmlmb19sZW4ocHJpdi0+ZXZlbnRf ZmlmbykpDQo+ID4gICAgICAgICAgICAgICAgICAgICBzaG91bGRzbGVlcCA9IDA7ICAgICAgICAv KiBXZSBoYXZlIGFuIGV2ZW50IHRvIHByb2Nlc3MgKi8NCj4gPiBAQCAtODIyLDYgKzgyNSwyNiBA QCBzdGF0aWMgaW50IGxic190aHJlYWQodm9pZCAqZGF0YSkNCj4gPiAgICAgICAgICAgICB9DQo+ ID4gICAgICAgICAgICAgc3Bpbl91bmxvY2tfaXJxKCZwcml2LT5kcml2ZXJfbG9jayk7DQo+ID4N Cj4gPiArICAgICAgICAgICAvKiBQcm9jZXNzIGhhcmR3YXJlIGV2ZW50cywgZS5nLiBjYXJkIHJl bW92ZWQsIGxpbmsgbG9zdCAqLw0KPiA+ICsgICAgICAgICAgIHNwaW5fbG9ja19pcnEoJnByaXYt PmRyaXZlcl9sb2NrKTsNCj4gPiArICAgICAgICAgICB3aGlsZSAoX19rZmlmb19sZW4ocHJpdi0+ ZXZlbnRfZmlmbykpIHsNCj4gPiArICAgICAgICAgICAgICAgICAgIHUzMiBldmVudDsNCj4gPiAr ICAgICAgICAgICAgICAgICAgIF9fa2ZpZm9fZ2V0KHByaXYtPmV2ZW50X2ZpZm8sICh1bnNpZ25l ZCBjaGFyICopICZldmVudCwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZW9m KGV2ZW50KSk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBzcGluX3VubG9ja19pcnEoJnByaXYt PmRyaXZlcl9sb2NrKTsNCj4gPiArICAgICAgICAgICAgICAgICAgIGxic19wcm9jZXNzX2V2ZW50 KHByaXYsIGV2ZW50KTsNCj4gPiArICAgICAgICAgICAgICAgICAgIHNwaW5fbG9ja19pcnEoJnBy aXYtPmRyaXZlcl9sb2NrKTsNCj4gPiArICAgICAgICAgICB9DQo+ID4gKyAgICAgICAgICAgc3Bp bl91bmxvY2tfaXJxKCZwcml2LT5kcml2ZXJfbG9jayk7DQo+ID4gKw0KPiA+ICsgICAgICAgICAg IGlmIChwcml2LT53YWtldXBfZGV2X3JlcXVpcmVkKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAg ICBsYnNfZGViX3RocmVhZCgiV2FraW5nIHVwIGRldmljZS4uLlxuIik7DQo+ID4gKyAgICAgICAg ICAgICAgICAgICAvKiBXYWtlIHVwIGRldmljZSAqLw0KPiA+ICsgICAgICAgICAgICAgICAgICAg aWYgKHByaXYtPmV4aXRfZGVlcF9zbGVlcChwcml2KSkNCj4gPiArICAgICAgICAgICAgICAgICAg ICAgICAgICAgbGJzX2RlYl90aHJlYWQoIldha2V1cCBkZXZpY2UgZmFpbGVkXG4iKTsNCj4gPiAr ICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOw0KPiA+ICsgICAgICAgICAgIH0NCj4gPiArDQo+ ID4gICAgICAgICAgICAgLyogY29tbWFuZCB0aW1lb3V0IHN0dWZmICovDQo+ID4gICAgICAgICAg ICAgaWYgKHByaXYtPmNtZF90aW1lZF9vdXQgJiYgcHJpdi0+Y3VyX2NtZCkgew0KPiA+ICAgICAg ICAgICAgICAgICAgICAgc3RydWN0IGNtZF9jdHJsX25vZGUgKmNtZG5vZGUgPSBwcml2LT5jdXJf Y21kOw0KPiA+IEBAIC04NDksMTggKzg3Miw3IEBAIHN0YXRpYyBpbnQgbGJzX3RocmVhZCh2b2lk ICpkYXRhKQ0KPiA+ICAgICAgICAgICAgIH0NCj4gPiAgICAgICAgICAgICBwcml2LT5jbWRfdGlt ZWRfb3V0ID0gMDsNCj4gPg0KPiA+IC0gICAgICAgICAgIC8qIFByb2Nlc3MgaGFyZHdhcmUgZXZl bnRzLCBlLmcuIGNhcmQgcmVtb3ZlZCwgbGluayBsb3N0ICovDQo+ID4gLSAgICAgICAgICAgc3Bp bl9sb2NrX2lycSgmcHJpdi0+ZHJpdmVyX2xvY2spOw0KPiA+IC0gICAgICAgICAgIHdoaWxlIChf X2tmaWZvX2xlbihwcml2LT5ldmVudF9maWZvKSkgew0KPiA+IC0gICAgICAgICAgICAgICAgICAg dTMyIGV2ZW50Ow0KPiA+DQo+ID4gLSAgICAgICAgICAgICAgICAgICBfX2tmaWZvX2dldChwcml2 LT5ldmVudF9maWZvLCAodW5zaWduZWQgY2hhciAqKSAmZXZlbnQsDQo+ID4gLSAgICAgICAgICAg ICAgICAgICAgICAgICAgIHNpemVvZihldmVudCkpOw0KPiA+IC0gICAgICAgICAgICAgICAgICAg c3Bpbl91bmxvY2tfaXJxKCZwcml2LT5kcml2ZXJfbG9jayk7DQo+ID4gLSAgICAgICAgICAgICAg ICAgICBsYnNfcHJvY2Vzc19ldmVudChwcml2LCBldmVudCk7DQo+ID4gLSAgICAgICAgICAgICAg ICAgICBzcGluX2xvY2tfaXJxKCZwcml2LT5kcml2ZXJfbG9jayk7DQo+ID4gLSAgICAgICAgICAg fQ0KPiA+IC0gICAgICAgICAgIHNwaW5fdW5sb2NrX2lycSgmcHJpdi0+ZHJpdmVyX2xvY2spOw0K PiA+DQo+ID4gICAgICAgICAgICAgaWYgKCFwcml2LT5md19yZWFkeSkNCj4gPiAgICAgICAgICAg ICAgICAgICAgIGNvbnRpbnVlOw0KPiA+IEBAIC04OTQsNiArOTA2LDkgQEAgc3RhdGljIGludCBs YnNfdGhyZWFkKHZvaWQgKmRhdGEpDQo+ID4gICAgICAgICAgICAgICAgIChwcml2LT5wc3N0YXRl ID09IFBTX1NUQVRFX1BSRV9TTEVFUCkpDQo+ID4gICAgICAgICAgICAgICAgICAgICBjb250aW51 ZTsNCj4gPg0KPiA+ICsgICAgICAgICAgIGlmIChwcml2LT5pc19kZWVwX3NsZWVwKQ0KPiA+ICsg ICAgICAgICAgICAgICAgICAgY29udGludWU7DQo+ID4gKw0KPiA+ICAgICAgICAgICAgIC8qIEV4 ZWN1dGUgdGhlIG5leHQgY29tbWFuZCAqLw0KPiA+ICAgICAgICAgICAgIGlmICghcHJpdi0+ZG5s ZF9zZW50ICYmICFwcml2LT5jdXJfY21kKQ0KPiA+ICAgICAgICAgICAgICAgICAgICAgbGJzX2V4 ZWN1dGVfbmV4dF9jb21tYW5kKHByaXYpOw0KPiA+IEBAIC05MjgsNiArOTQzLDcgQEAgc3RhdGlj IGludCBsYnNfdGhyZWFkKHZvaWQgKmRhdGEpDQo+ID4gICAgIH0NCj4gPg0KPiA+ICAgICBkZWxf dGltZXIoJnByaXYtPmNvbW1hbmRfdGltZXIpOw0KPiA+ICsgICBkZWxfdGltZXIoJnByaXYtPmF1 dG9fZGVlcHNsZWVwX3RpbWVyKTsNCj4gPiAgICAgd2FrZV91cF9hbGwoJnByaXYtPmNtZF9wZW5k aW5nKTsNCj4gPg0KPiA+ICAgICBsYnNfZGViX2xlYXZlKExCU19ERUJfVEhSRUFEKTsNCj4gPiBA QCAtMTA1MCw2ICsxMDY2LDYwIEBAIG91dDoNCj4gPiAgICAgbGJzX2RlYl9sZWF2ZShMQlNfREVC X0NNRCk7DQo+ID4gIH0NCj4gPg0KPiA+ICsvKioNCj4gPiArICogIFRoaXMgZnVuY3Rpb24gcHV0 IHRoZSBkZXZpY2UgYmFjayB0byBkZWVwIHNsZWVwIG1vZGUgd2hlbiB0aW1lciBleHBpcmVzDQo+ ID4gKyAqICBhbmQgbm8gYWN0aXZpdHkgKGNvbW1hbmQsIGV2ZW50LCBkYXRhIGV0Yy4pIGlzIGRl dGVjdGVkLg0KPiA+ICsgKi8NCj4gPiArc3RhdGljIHZvaWQgYXV0b19kZWVwc2xlZXBfdGltZXJf Zm4odW5zaWduZWQgbG9uZyBkYXRhKQ0KPiA+ICt7DQo+ID4gKyAgIHN0cnVjdCBsYnNfcHJpdmF0 ZSAqcHJpdiA9IChzdHJ1Y3QgbGJzX3ByaXZhdGUgKilkYXRhOw0KPiA+ICsgICBpbnQgcmV0Ow0K PiA+ICsNCj4gPiArICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX0NNRCk7DQo+ID4gKw0KPiA+ICsg ICBpZiAocHJpdi0+aXNfYWN0aXZpdHlfZGV0ZWN0ZWQpIHsNCj4gPiArICAgICAgICAgICBwcml2 LT5pc19hY3Rpdml0eV9kZXRlY3RlZCA9IDA7DQo+ID4gKyAgIH0gZWxzZSB7DQo+ID4gKyAgICAg ICAgICAgaWYgKHByaXYtPmlzX2F1dG9fZGVlcF9zbGVlcF9lbmFibGVkICYmDQo+ID4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICghcHJpdi0+d2FrZXVwX2Rldl9yZXF1aXJlZCkgJiYNCj4g PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgKHByaXYtPmNvbm5lY3Rfc3RhdHVzICE9IExC U19DT05ORUNURUQpKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBsYnNfZGViX21haW4oIkVu dGVyaW5nIGF1dG8gZGVlcCBzbGVlcCBtb2RlLi4uXG4iKTsNCj4gPiArICAgICAgICAgICAgICAg ICAgIHJldCA9IGxic19wcmVwYXJlX2FuZF9zZW5kX2NvbW1hbmQocHJpdiwNCj4gPiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDTURfODAyXzExX0RFRVBfU0xFRVAsIDAsDQo+ ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMCwgMCwgTlVMTCk7DQo+ID4g KyAgICAgICAgICAgfQ0KPiA+ICsgICB9DQo+ID4gKyAgIG1vZF90aW1lcigmcHJpdi0+YXV0b19k ZWVwc2xlZXBfdGltZXIgLCBqaWZmaWVzICsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAg ICAgKHByaXYtPmF1dG9fZGVlcF9zbGVlcF90aW1lb3V0ICogSFopLzEwMDApOw0KPiA+ICsgICBs YnNfZGViX2xlYXZlKExCU19ERUJfQ01EKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiAraW50IGxic19l bnRlcl9hdXRvX2RlZXBfc2xlZXAoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0KPiA+ICt7DQo+ ID4gKyAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9TRElPKTsNCj4gPiArDQo+ID4gKyAgIHByaXYt PmlzX2F1dG9fZGVlcF9zbGVlcF9lbmFibGVkID0gMTsNCj4gPiArICAgaWYgKHByaXYtPmlzX2Rl ZXBfc2xlZXApDQo+ID4gKyAgICAgICAgICAgcHJpdi0+d2FrZXVwX2Rldl9yZXF1aXJlZCA9IDE7 DQo+ID4gKyAgIG1vZF90aW1lcigmcHJpdi0+YXV0b19kZWVwc2xlZXBfdGltZXIgLA0KPiA+ICsg ICAgICAgICAgICAgICAgICAgamlmZmllcyArIChwcml2LT5hdXRvX2RlZXBfc2xlZXBfdGltZW91 dCAqIEhaKS8xMDAwKTsNCj4gPiArDQo+ID4gKyAgIGxic19kZWJfbGVhdmUoTEJTX0RFQl9TRElP KTsNCj4gPiArICAgcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK2ludCBsYnNfZXhpdF9h dXRvX2RlZXBfc2xlZXAoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0KPiA+ICt7DQo+ID4gKyAg IGxic19kZWJfZW50ZXIoTEJTX0RFQl9TRElPKTsNCj4gPiArDQo+ID4gKyAgIHByaXYtPmlzX2F1 dG9fZGVlcF9zbGVlcF9lbmFibGVkID0gMDsNCj4gPiArICAgcHJpdi0+YXV0b19kZWVwX3NsZWVw X3RpbWVvdXQgPSAwOw0KPiA+ICsgICBkZWxfdGltZXIoJnByaXYtPmF1dG9fZGVlcHNsZWVwX3Rp bWVyKTsNCj4gPiArDQo+ID4gKyAgIGxic19kZWJfbGVhdmUoTEJTX0RFQl9TRElPKTsNCj4gPiAr ICAgcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gIHN0YXRpYyB2b2lkIGxic19zeW5jX2No YW5uZWxfd29ya2VyKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykNCj4gPiAgew0KPiA+ICAgICBz dHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYgPSBjb250YWluZXJfb2Yod29yaywgc3RydWN0IGxic19w cml2YXRlLA0KPiA+IEBAIC0xMDk5LDExICsxMTY5LDE3IEBAIHN0YXRpYyBpbnQgbGJzX2luaXRf YWRhcHRlcihzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYpDQo+ID4gICAgIHByaXYtPmNhcGFiaWxp dHkgPSBXTEFOX0NBUEFCSUxJVFlfU0hPUlRfUFJFQU1CTEU7DQo+ID4gICAgIHByaXYtPnBzbW9k ZSA9IExCUzgwMl8xMVBPV0VSTU9ERUNBTTsNCj4gPiAgICAgcHJpdi0+cHNzdGF0ZSA9IFBTX1NU QVRFX0ZVTExfUE9XRVI7DQo+ID4gKyAgIHByaXYtPmlzX2RlZXBfc2xlZXAgPSAwOw0KPiA+ICsg ICBwcml2LT5pc19hdXRvX2RlZXBfc2xlZXBfZW5hYmxlZCA9IDA7DQo+ID4gKyAgIHByaXYtPndh a2V1cF9kZXZfcmVxdWlyZWQgPSAwOw0KPiA+ICsgICBpbml0X3dhaXRxdWV1ZV9oZWFkKCZwcml2 LT5kc19hd2FrZV9xKTsNCj4gPg0KPiA+ICAgICBtdXRleF9pbml0KCZwcml2LT5sb2NrKTsNCj4g Pg0KPiA+ICAgICBzZXR1cF90aW1lcigmcHJpdi0+Y29tbWFuZF90aW1lciwgY29tbWFuZF90aW1l cl9mbiwNCj4gPiAgICAgICAgICAgICAodW5zaWduZWQgbG9uZylwcml2KTsNCj4gPiArICAgc2V0 dXBfdGltZXIoJnByaXYtPmF1dG9fZGVlcHNsZWVwX3RpbWVyLCBhdXRvX2RlZXBzbGVlcF90aW1l cl9mbiwNCj4gPiArICAgICAgICAgICAgICAgICAgICh1bnNpZ25lZCBsb25nKXByaXYpOw0KPiA+ DQo+ID4gICAgIElOSVRfTElTVF9IRUFEKCZwcml2LT5jbWRmcmVlcSk7DQo+ID4gICAgIElOSVRf TElTVF9IRUFEKCZwcml2LT5jbWRwZW5kaW5ncSk7DQo+ID4gQEAgLTExNDIsNiArMTIxOCw3IEBA IHN0YXRpYyB2b2lkIGxic19mcmVlX2FkYXB0ZXIoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0K PiA+ICAgICBpZiAocHJpdi0+ZXZlbnRfZmlmbykNCj4gPiAgICAgICAgICAgICBrZmlmb19mcmVl KHByaXYtPmV2ZW50X2ZpZm8pOw0KPiA+ICAgICBkZWxfdGltZXIoJnByaXYtPmNvbW1hbmRfdGlt ZXIpOw0KPiA+ICsgICBkZWxfdGltZXIoJnByaXYtPmF1dG9fZGVlcHNsZWVwX3RpbWVyKTsNCj4g PiAgICAga2ZyZWUocHJpdi0+bmV0d29ya3MpOw0KPiA+ICAgICBwcml2LT5uZXR3b3JrcyA9IE5V TEw7DQo+ID4NCj4gPiBAQCAtMTI3Miw2ICsxMzQ5LDExIEBAIHZvaWQgbGJzX3JlbW92ZV9jYXJk KHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdikNCj4gPiAgICAgd3JxdS5hcF9hZGRyLnNhX2ZhbWls eSA9IEFSUEhSRF9FVEhFUjsNCj4gPiAgICAgd2lyZWxlc3Nfc2VuZF9ldmVudChwcml2LT5kZXYs IFNJT0NHSVdBUCwgJndycXUsIE5VTEwpOw0KPiA+DQo+ID4gKyAgIGlmIChwcml2LT5pc19kZWVw X3NsZWVwKSB7DQo+ID4gKyAgICAgICAgICAgcHJpdi0+aXNfZGVlcF9zbGVlcCA9IDA7DQo+ID4g KyAgICAgICAgICAgd2FrZV91cF9pbnRlcnJ1cHRpYmxlKCZwcml2LT5kc19hd2FrZV9xKTsNCj4g PiArICAgfQ0KPiA+ICsNCj4gPiAgICAgLyogU3RvcCB0aGUgdGhyZWFkIHNlcnZpY2luZyB0aGUg aW50ZXJydXB0cyAqLw0KPiA+ICAgICBwcml2LT5zdXJwcmlzZXJlbW92ZWQgPSAxOw0KPiA+ICAg ICBrdGhyZWFkX3N0b3AocHJpdi0+bWFpbl90aHJlYWQpOw0KPiA+IEBAIC0xMzkyLDYgKzE0NzQs NyBAQCB2b2lkIGxic19zdG9wX2NhcmQoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0KPiA+DQo+ ID4gICAgIC8qIERlbGV0ZSB0aGUgdGltZW91dCBvZiB0aGUgY3VycmVudGx5IHByb2Nlc3Npbmcg Y29tbWFuZCAqLw0KPiA+ICAgICBkZWxfdGltZXJfc3luYygmcHJpdi0+Y29tbWFuZF90aW1lcik7 DQo+ID4gKyAgIGRlbF90aW1lcl9zeW5jKCZwcml2LT5hdXRvX2RlZXBzbGVlcF90aW1lcik7DQo+ ID4NCj4gPiAgICAgLyogRmx1c2ggcGVuZGluZyBjb21tYW5kIG5vZGVzICovDQo+ID4gICAgIHNw aW5fbG9ja19pcnFzYXZlKCZwcml2LT5kcml2ZXJfbG9jaywgZmxhZ3MpOw0KPiA+IGRpZmYgLS1n aXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy9zY2FuLmMgYi9kcml2ZXJzL25ldC93 aXJlbGVzcy9saWJlcnRhcy9zY2FuLmMNCj4gPiBpbmRleCA2Yzk1YWYzLi5lNDY4ZTE1IDEwMDY0 NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL3NjYW4uYw0KPiA+ICsr KyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL3NjYW4uYw0KPiA+IEBAIC05NTAsNiAr OTUwLDExIEBAIGludCBsYnNfc2V0X3NjYW4oc3RydWN0IG5ldF9kZXZpY2UgKmRldiwgc3RydWN0 IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4gPg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19E RUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsN Cj4gPiArICAgICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4gKyAgICAgICAgICAgZ290byBvdXQ7 DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIGlmICghcHJpdi0+cmFkaW9fb24pIHsNCj4gPiAg ICAgICAgICAgICByZXQgPSAtRUlOVkFMOw0KPiA+ICAgICAgICAgICAgIGdvdG8gb3V0Ow0KPiA+ IEBAIC0xMDE3LDYgKzEwMjIsMTIgQEAgaW50IGxic19nZXRfc2NhbihzdHJ1Y3QgbmV0X2Rldmlj ZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZvLA0KPiA+DQo+ID4gICAgIGxic19k ZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxs b3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIGVyciA9IC1FQlVTWTsNCj4gPiArICAgICAg ICAgICBsYnNfZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9XRVhULCAicmV0ICVkIiwgZXJyKTsNCj4g PiArICAgICAgICAgICByZXR1cm4gZXJyOw0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICAvKiBp d2xpc3Qgc2hvdWxkIHdhaXQgdW50aWwgdGhlIGN1cnJlbnQgc2NhbiBpcyBmaW5pc2hlZCAqLw0K PiA+ICAgICBpZiAocHJpdi0+c2Nhbl9jaGFubmVsKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAt RUFHQUlOOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy93 ZXh0LmMgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9saWJlcnRhcy93ZXh0LmMNCj4gPiBpbmRleCBi ZTgzN2EwLi4zOGE0NTFlIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xp YmVydGFzL3dleHQuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL2xpYmVydGFzL3dl eHQuYw0KPiA+IEBAIC00NSw2ICs0NSwzMSBAQCBzdGF0aWMgaW5saW5lIHZvaWQgbGJzX2NhbmNl bF9hc3NvY2lhdGlvbl93b3JrKHN0cnVjdCBsYnNfcHJpdmF0ZSAqcHJpdikNCj4gPiAgICAgcHJp di0+cGVuZGluZ19hc3NvY19yZXEgPSBOVUxMOw0KPiA+ICB9DQo+ID4NCj4gPiArLyoqDQo+ID4g KyAqICBAYnJpZWYgVGhpcyBmdW5jdGlvbiBjaGVja3MgaWYgdGhlIGNvbW1hbmQgaXMgYWxsb3dl ZC4NCj4gPiArICoNCj4gPiArICogIEBwYXJhbSBwcml2ICAgICAgICAgQSBwb2ludGVyIHRvIGxi c19wcml2YXRlIHN0cnVjdHVyZQ0KPiA+ICsgKiAgQHJldHVybiAgICAgICAgICAgICBhbGxvd2Vk IG9yIG5vdCBhbGxvd2VkLg0KPiA+ICsgKi8NCj4gPiArDQo+ID4gK2ludCBsYnNfaXNfY21kX2Fs bG93ZWQoc3RydWN0IGxic19wcml2YXRlICpwcml2KQ0KPiA+ICt7DQo+ID4gKyAgIGludCAgICAg ICAgIHJldCA9IDE7DQo+ID4gKw0KPiA+ICsgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7 DQo+ID4gKw0KPiA+ICsgICBpZiAoIXByaXYtPmlzX2F1dG9fZGVlcF9zbGVlcF9lbmFibGVkKSB7 DQo+ID4gKyAgICAgICAgICAgaWYgKHByaXYtPmlzX2RlZXBfc2xlZXApIHsNCj4gPiArICAgICAg ICAgICAgICAgICAgIGxic19kZWJfd2V4dCgiSU9DVExTIGNhbGxlZCB3aGVuIHN0YXRpb24iDQo+ ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImlzIGluIGRlZXAgc2xlZXBc biIpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgcmV0ID0gMDsNCj4gPiArICAgICAgICAgICB9 DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gKyAgIGxic19kZWJfbGVhdmUoTEJTX0RFQl9XRVhUKTsN Cj4gPiArICAgcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPg0KPiA+ICAvKioNCj4gPiAg ICogIEBicmllZiBGaW5kIHRoZSBjaGFubmVsIGZyZXF1ZW5jeSBwb3dlciBpbmZvIHdpdGggc3Bl Y2lmaWMgY2hhbm5lbA0KPiA+IEBAIC0xNjgsNiArMTkzLDExIEBAIHN0YXRpYyBpbnQgbGJzX2dl dF9mcmVxKHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1ZXN0X2luZm8gKmlu Zm8sDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4g KyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgbGJz X2RlYl9sZWF2ZShMQlNfREVCX1dFWFQpOw0KPiA+ICsgICAgICAgICAgIHJldHVybiAtRUJVU1k7 DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIGNmcCA9IGxic19maW5kX2NmcF9ieV9iYW5kX2Fu ZF9jaGFubmVsKHByaXYsIDAsDQo+ID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgcHJpdi0+Y3VyYnNzcGFyYW1zLmNoYW5uZWwpOw0KPiA+DQo+ID4gQEAgLTI3OCw2ICsz MDgsMTIgQEAgc3RhdGljIGludCBsYnNfc2V0X3J0cyhzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBz dHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZvLA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIo TEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2 KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBsYnNf ZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9XRVhULCAicmV0ICVkIiwgcmV0KTsNCj4gPiArICAgICAg ICAgICByZXR1cm4gcmV0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAodndycS0+ZGlz YWJsZWQpDQo+ID4gICAgICAgICAgICAgdmFsID0gTVJWRFJWX1JUU19NQVhfVkFMVUU7DQo+ID4N Cj4gPiBAQCAtMjk5LDYgKzMzNSwxMSBAQCBzdGF0aWMgaW50IGxic19nZXRfcnRzKHN0cnVjdCBu ZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1ZXN0X2luZm8gKmluZm8sDQo+ID4NCj4gPiAg ICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lz X2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ ICsgICAgICAgICAgIGdvdG8gb3V0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICByZXQgPSBs YnNfZ2V0X3NubXBfbWliKHByaXYsIFNOTVBfTUlCX09JRF9SVFNfVEhSRVNIT0xELCAmdmFsKTsN Cj4gPiAgICAgaWYgKHJldCkNCj4gPiAgICAgICAgICAgICBnb3RvIG91dDsNCj4gPiBAQCAtMzIx LDYgKzM2MiwxMiBAQCBzdGF0aWMgaW50IGxic19zZXRfZnJhZyhzdHJ1Y3QgbmV0X2RldmljZSAq ZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZvLA0KPiA+DQo+ID4gICAgIGxic19kZWJf ZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dl ZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAg ICBsYnNfZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9XRVhULCAicmV0ICVkIiwgcmV0KTsNCj4gPiAr ICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAodndy cS0+ZGlzYWJsZWQpDQo+ID4gICAgICAgICAgICAgdmFsID0gTVJWRFJWX0ZSQUdfTUFYX1ZBTFVF Ow0KPiA+DQo+ID4gQEAgLTM0Miw2ICszODksMTEgQEAgc3RhdGljIGludCBsYnNfZ2V0X2ZyYWco c3RydWN0IG5ldF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4g Pg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYg KCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJV U1k7DQo+ID4gKyAgICAgICAgICAgZ290byBvdXQ7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAg IHJldCA9IGxic19nZXRfc25tcF9taWIocHJpdiwgU05NUF9NSUJfT0lEX0ZSQUdfVEhSRVNIT0xE LCAmdmFsKTsNCj4gPiAgICAgaWYgKHJldCkNCj4gPiAgICAgICAgICAgICBnb3RvIG91dDsNCj4g PiBAQCAtMzkxLDYgKzQ0MywxMSBAQCBzdGF0aWMgaW50IGxic19nZXRfdHhwb3coc3RydWN0IG5l dF9kZXZpY2UgKmRldiwNCj4gPg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7 DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAg ICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4gKyAgICAgICAgICAgZ290byBvdXQ7DQo+ID4gKyAg IH0NCj4gPiArDQo+ID4gICAgIGlmICghcHJpdi0+cmFkaW9fb24pIHsNCj4gPiAgICAgICAgICAg ICBsYnNfZGViX3dleHQoInR4IHBvd2VyIG9mZlxuIik7DQo+ID4gICAgICAgICAgICAgdndycS0+ dmFsdWUgPSAwOw0KPiA+IEBAIC00MjQsNiArNDgxLDExIEBAIHN0YXRpYyBpbnQgbGJzX3NldF9y ZXRyeShzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZv LA0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsg ICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9 IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBnb3RvIG91dDsNCj4gPiArICAgfQ0KPiA+ICsNCj4g PiAgICAgICAgICBpZiAoKHZ3cnEtPmZsYWdzICYgSVdfUkVUUllfVFlQRSkgIT0gSVdfUkVUUllf TElNSVQpDQo+ID4gICAgICAgICAgICAgICAgICByZXR1cm4gLUVPUE5PVFNVUFA7DQo+ID4NCj4g PiBAQCAtNDcyLDYgKzUzNCwxMSBAQCBzdGF0aWMgaW50IGxic19nZXRfcmV0cnkoc3RydWN0IG5l dF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4gPg0KPiA+ICAg ICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNf Y21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4g KyAgICAgICAgICAgZ290byBvdXQ7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIHZ3cnEtPmRp c2FibGVkID0gMDsNCj4gPg0KPiA+ICAgICBpZiAodndycS0+ZmxhZ3MgJiBJV19SRVRSWV9MT05H KSB7DQo+ID4gQEAgLTcwOSw2ICs3NzYsNyBAQCBzdGF0aWMgaW50IGxic19zZXRfcG93ZXIoc3Ry dWN0IG5ldF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3JlcXVlc3RfaW5mbyAqaW5mbywNCj4gPiAg ICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGl3X3BhcmFtICp2d3JxLCBjaGFyICpleHRyYSkN Cj4gPiAgew0KPiA+ICAgICBzdHJ1Y3QgbGJzX3ByaXZhdGUgKnByaXYgPSBkZXYtPm1sX3ByaXY7 DQo+ID4gKyAgIGludCByZXQgPSAwOw0KPiA+DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RF Ql9XRVhUKTsNCj4gPg0KPiA+IEBAIC03MzcsOCArODA1LDU0IEBAIHN0YXRpYyBpbnQgbGJzX3Nl dF9wb3dlcihzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICpp bmZvLA0KPiA+ICAgICAgICAgICAgICAgICAgICAic2V0dGluZyBwb3dlciB0aW1lb3V0IGlzIG5v dCBzdXBwb3J0ZWRcbiIpOw0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRUlOVkFMOw0KPiA+ICAg ICB9IGVsc2UgaWYgKCh2d3JxLT5mbGFncyAmIElXX1BPV0VSX1RZUEUpID09IElXX1BPV0VSX1BF UklPRCkgew0KPiA+IC0gICAgICAgICAgIGxic19kZWJfd2V4dCgic2V0dGluZyBwb3dlciBwZXJp b2Qgbm90IHN1cHBvcnRlZFxuIik7DQo+ID4gLSAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7DQo+ ID4gKyAgICAgICAgICAgdndycS0+dmFsdWUgPSB2d3JxLT52YWx1ZSAvIDEwMDA7DQo+ID4gKyAg ICAgICAgICAgaWYgKCFwcml2LT5lbnRlcl9kZWVwX3NsZWVwKSB7DQo+ID4gKyAgICAgICAgICAg ICAgICAgICBsYnNfcHJfZXJyKCJkZWVwIHNsZWVwIGZlYXR1cmUgaXMgbm90IGltcGxlbWVudGVk ICINCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm9yIHRoaXMgaW50 ZXJmYWNlIGRyaXZlclxuIik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZB TDsNCj4gPiArICAgICAgICAgICB9DQo+ID4gKw0KPiA+ICsgICAgICAgICAgIGlmIChwcml2LT5j b25uZWN0X3N0YXR1cyA9PSBMQlNfQ09OTkVDVEVEKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAg ICBpZiAoKHByaXYtPmlzX2F1dG9fZGVlcF9zbGVlcF9lbmFibGVkKSAmJg0KPiA+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZ3cnEtPnZhbHVlID09IC0xMDAw KSkgew0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICBsYnNfZXhpdF9hdXRvX2RlZXBf c2xlZXAocHJpdik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAwOw0K PiA+ICsgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAgICAgICAgICAg ICAgICAgICAgbGJzX3ByX2VycigiY2FuJ3QgdXNlIGRlZXAgc2xlZXAgY21kIGluICINCj4gPiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb25uZWN0ZWQgc3Rh dGVcbiIpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsN Cj4gPiArICAgICAgICAgICAgICAgICAgIH0NCj4gPiArICAgICAgICAgICB9DQo+ID4gKw0KPiA+ ICsgICAgICAgICAgIGlmICgodndycS0+dmFsdWUgPCAwKSAmJiAodndycS0+dmFsdWUgIT0gLTEw MDApKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICBsYnNfcHJfZXJyKCJ1bmtub3duIG9wdGlv blxuIik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsNCj4gPiArICAg ICAgICAgICB9DQo+ID4gKw0KPiA+ICsgICAgICAgICAgIGlmICh2d3JxLT52YWx1ZSA+IDApIHsN Cj4gPiArICAgICAgICAgICAgICAgICAgIGlmICghcHJpdi0+aXNfYXV0b19kZWVwX3NsZWVwX2Vu YWJsZWQpIHsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpdi0+aXNfYWN0aXZp dHlfZGV0ZWN0ZWQgPSAwOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICBwcml2LT5h dXRvX2RlZXBfc2xlZXBfdGltZW91dCA9IHZ3cnEtPnZhbHVlOw0KPiA+ICsgICAgICAgICAgICAg ICAgICAgICAgICAgICBsYnNfZW50ZXJfYXV0b19kZWVwX3NsZWVwKHByaXYpOw0KPiA+ICsgICAg ICAgICAgICAgICAgICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAg cHJpdi0+YXV0b19kZWVwX3NsZWVwX3RpbWVvdXQgPSB2d3JxLT52YWx1ZTsNCj4gPiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgbGJzX2RlYl9kZWJ1Z2ZzKCJhdXRvIGRlZXAgc2xlZXA6ICIN Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhbHJlYWR5 IGVuYWJsZWRcbiIpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgfQ0KPiA+ICsgICAgICAgICAg ICAgICAgICAgcmV0dXJuIDA7DQo+ID4gKyAgICAgICAgICAgfSBlbHNlIHsNCj4gPiArICAgICAg ICAgICAgICAgICAgIGlmIChwcml2LT5pc19hdXRvX2RlZXBfc2xlZXBfZW5hYmxlZCkgew0KPiA+ ICsgICAgICAgICAgICAgICAgICAgICAgICAgICBsYnNfZXhpdF9hdXRvX2RlZXBfc2xlZXAocHJp dik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIFRyeSB0byBleGl0IGRlZXAg c2xlZXAgaWYgYXV0byAqLw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAvKmRlZXAg c2xlZXAgZGlzYWJsZWQgKi8NCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0ID0g bGJzX3NldF9kZWVwX3NsZWVwKHByaXYsIDApOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgfQ0K PiA+ICsgICAgICAgICAgICAgICAgICAgaWYgKHZ3cnEtPnZhbHVlID09IDApDQo+ID4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgIHJldCA9IGxic19zZXRfZGVlcF9zbGVlcChwcml2LCAxKTsN Cj4gPiArICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHZ3cnEtPnZhbHVlID09IC0xMDAwKQ0K PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICByZXQgPSBsYnNfc2V0X2RlZXBfc2xlZXAo cHJpdiwgMCk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiA+ICsgICAg ICAgICAgIH0NCj4gPiAgICAgfQ0KPiA+DQo+ID4gICAgIGlmIChwcml2LT5wc21vZGUgIT0gTEJT ODAyXzExUE9XRVJNT0RFQ0FNKSB7DQo+ID4gQEAgLTc1Miw2ICs4NjYsNyBAQCBzdGF0aWMgaW50 IGxic19zZXRfcG93ZXIoc3RydWN0IG5ldF9kZXZpY2UgKmRldiwgc3RydWN0IGl3X3JlcXVlc3Rf aW5mbyAqaW5mbywNCj4gPiAgICAgfQ0KPiA+DQo+ID4gICAgIGxic19kZWJfbGVhdmUoTEJTX0RF Ql9XRVhUKTsNCj4gPiArDQo+ID4gICAgIHJldHVybiAwOw0KPiA+ICB9DQo+ID4NCj4gPiBAQCAt NzkyLDYgKzkwNyw5IEBAIHN0YXRpYyBzdHJ1Y3QgaXdfc3RhdGlzdGljcyAqbGJzX2dldF93aXJl bGVzc19zdGF0cyhzdHJ1Y3QgbmV0X2RldmljZSAqZGV2KQ0KPiA+DQo+ID4gICAgIGxic19kZWJf ZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dl ZChwcml2KSkNCj4gPiArICAgICAgICAgICByZXR1cm4gTlVMTDsNCj4gPiArDQo+ID4gICAgIHBy aXYtPndzdGF0cy5zdGF0dXMgPSBwcml2LT5tb2RlOw0KPiA+DQo+ID4gICAgIC8qIElmIHdlJ3Jl IG5vdCBhc3NvY2lhdGVkLCBhbGwgcXVhbGl0eSB2YWx1ZXMgYXJlIG1lYW5pbmdsZXNzICovDQo+ ID4gQEAgLTg5Miw2ICsxMDEwLDEyIEBAIHN0YXRpYyBpbnQgbGJzX3NldF9mcmVxKHN0cnVjdCBu ZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1ZXN0X2luZm8gKmluZm8sDQo+ID4NCj4gPiAg ICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lz X2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ ICsgICAgICAgICAgIGxic19kZWJfbGVhdmVfYXJncyhMQlNfREVCX1dFWFQsICJyZXQgJWQiLCBy ZXQpOw0KPiA+ICsgICAgICAgICAgIHJldHVybiByZXQ7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4g ICAgIG11dGV4X2xvY2soJnByaXYtPmxvY2spOw0KPiA+ICAgICBhc3NvY19yZXEgPSBsYnNfZ2V0 X2Fzc29jaWF0aW9uX3JlcXVlc3QocHJpdik7DQo+ID4gICAgIGlmICghYXNzb2NfcmVxKSB7DQo+ ID4gQEAgLTEwMDAsNiArMTEyNCwxMiBAQCBzdGF0aWMgaW50IGxic19zZXRfcmF0ZShzdHJ1Y3Qg bmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZvLA0KPiA+ICAgICB1 OCByYXRlc1tNQVhfUkFURVMgKyAxXTsNCj4gPg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19E RUJfV0VYVCk7DQo+ID4gKw0KPiA+ICsgICBpZiAoIWxic19pc19jbWRfYWxsb3dlZChwcml2KSkg ew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVTWTsNCj4gPiArICAgICAgICAgICBnb3RvIG91 dDsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgbGJzX2RlYl93ZXh0KCJ2d3JxLT52YWx1ZSAl ZFxuIiwgdndycS0+dmFsdWUpOw0KPiA+ICAgICBsYnNfZGViX3dleHQoInZ3cnEtPmZpeGVkICVk XG4iLCB2d3JxLT5maXhlZCk7DQo+ID4NCj4gPiBAQCAtMTA1OCw2ICsxMTg4LDExIEBAIHN0YXRp YyBpbnQgbGJzX2dldF9yYXRlKHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1 ZXN0X2luZm8gKmluZm8sDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQp Ow0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAg ICAgICAgICAgbGJzX2RlYl9sZWF2ZShMQlNfREVCX1dFWFQpOw0KPiA+ICsgICAgICAgICAgIHJl dHVybiAtRUJVU1k7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIGlmIChwcml2LT5jb25uZWN0 X3N0YXR1cyA9PSBMQlNfQ09OTkVDVEVEKSB7DQo+ID4gICAgICAgICAgICAgdndycS0+dmFsdWUg PSBwcml2LT5jdXJfcmF0ZSAqIDUwMDAwMDsNCj4gPg0KPiA+IEBAIC0xMDg0LDYgKzEyMTksMTEg QEAgc3RhdGljIGludCBsYnNfc2V0X21vZGUoc3RydWN0IG5ldF9kZXZpY2UgKmRldiwNCj4gPg0K PiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFs YnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJVU1k7 DQo+ID4gKyAgICAgICAgICAgZ290byBvdXQ7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIGlm ICggICAoKnV3cnEgIT0gSVdfTU9ERV9BREhPQykNCj4gPiAgICAgICAgICYmICgqdXdycSAhPSBJ V19NT0RFX0lORlJBKQ0KPiA+ICAgICAgICAgJiYgKCp1d3JxICE9IElXX01PREVfQVVUTykpIHsN Cj4gPiBAQCAtMTMyNSw2ICsxNDY1LDEyIEBAIHN0YXRpYyBpbnQgbGJzX3NldF9lbmNvZGUoc3Ry dWN0IG5ldF9kZXZpY2UgKmRldiwNCj4gPg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJf V0VYVCk7DQo+ID4NCj4gPiArICAgaWYgKCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4g PiArICAgICAgICAgICByZXQgPSAtRUJVU1k7DQo+ID4gKyAgICAgICAgICAgbGJzX2RlYl9sZWF2 ZV9hcmdzKExCU19ERUJfV0VYVCwgInJldCAlZCIsIHJldCk7DQo+ID4gKyAgICAgICAgICAgcmV0 dXJuIHJldDsNCj4gPiArICAgfQ0KPiA+ICsNCj4gPiAgICAgbXV0ZXhfbG9jaygmcHJpdi0+bG9j ayk7DQo+ID4gICAgIGFzc29jX3JlcSA9IGxic19nZXRfYXNzb2NpYXRpb25fcmVxdWVzdChwcml2 KTsNCj4gPiAgICAgaWYgKCFhc3NvY19yZXEpIHsNCj4gPiBAQCAtMTUwOCw2ICsxNjU0LDEyIEBA IHN0YXRpYyBpbnQgbGJzX3NldF9lbmNvZGVleHQoc3RydWN0IG5ldF9kZXZpY2UgKmRldiwNCj4g Pg0KPiA+ICAgICBsYnNfZGViX2VudGVyKExCU19ERUJfV0VYVCk7DQo+ID4NCj4gPiArICAgaWYg KCFsYnNfaXNfY21kX2FsbG93ZWQocHJpdikpIHsNCj4gPiArICAgICAgICAgICByZXQgPSAtRUJV U1k7DQo+ID4gKyAgICAgICAgICAgbGJzX2RlYl9sZWF2ZV9hcmdzKExCU19ERUJfV0VYVCwgInJl dCAlZCIsIHJldCk7DQo+ID4gKyAgICAgICAgICAgcmV0dXJuIHJldDsNCj4gPiArICAgfQ0KPiA+ ICsNCj4gPiAgICAgbXV0ZXhfbG9jaygmcHJpdi0+bG9jayk7DQo+ID4gICAgIGFzc29jX3JlcSA9 IGxic19nZXRfYXNzb2NpYXRpb25fcmVxdWVzdChwcml2KTsNCj4gPiAgICAgaWYgKCFhc3NvY19y ZXEpIHsNCj4gPiBAQCAtMTcyMCw2ICsxODcyLDEyIEBAIHN0YXRpYyBpbnQgbGJzX3NldF9hdXRo KHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNf REVCX1dFWFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7 DQo+ID4gKyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGxic19kZWJf bGVhdmVfYXJncyhMQlNfREVCX1dFWFQsICJyZXQgJWQiLCByZXQpOw0KPiA+ICsgICAgICAgICAg IHJldHVybiByZXQ7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIG11dGV4X2xvY2soJnByaXYt PmxvY2spOw0KPiA+ICAgICBhc3NvY19yZXEgPSBsYnNfZ2V0X2Fzc29jaWF0aW9uX3JlcXVlc3Qo cHJpdik7DQo+ID4gICAgIGlmICghYXNzb2NfcmVxKSB7DQo+ID4gQEAgLTE4MjIsNiArMTk4MCwx MiBAQCBzdGF0aWMgaW50IGxic19nZXRfYXV0aChzdHJ1Y3QgbmV0X2RldmljZSAqZGV2LA0KPiA+ DQo+ID4gICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsgICBpZiAo IWxic19pc19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVT WTsNCj4gPiArICAgICAgICAgICBsYnNfZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9XRVhULCAicmV0 ICVkIiwgcmV0KTsNCj4gPiArICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiA+ICsgICB9DQo+ID4g Kw0KPiA+ICAgICBzd2l0Y2ggKGR3cnEtPmZsYWdzICYgSVdfQVVUSF9JTkRFWCkgew0KPiA+ICAg ICBjYXNlIElXX0FVVEhfS0VZX01HTVQ6DQo+ID4gICAgICAgICAgICAgZHdycS0+dmFsdWUgPSBw cml2LT5zZWNpbmZvLmtleV9tZ210Ow0KPiA+IEBAIC0xODY0LDYgKzIwMjgsMTEgQEAgc3RhdGlj IGludCBsYnNfc2V0X3R4cG93KHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1 ZXN0X2luZm8NCj4gKmluZm8sDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dF WFQpOw0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4g KyAgICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGdvdG8gb3V0Ow0KPiA+ ICsgICB9DQo+ID4gKw0KPiA+ICAgICBpZiAodndycS0+ZGlzYWJsZWQpIHsNCj4gPiAgICAgICAg ICAgICBsYnNfc2V0X3JhZGlvKHByaXYsIFJBRElPX1BSRUFNQkxFX0FVVE8sIDApOw0KPiA+ICAg ICAgICAgICAgIGdvdG8gb3V0Ow0KPiA+IEBAIC0xOTgzLDYgKzIxNTIsMTIgQEAgc3RhdGljIGlu dCBsYnNfc2V0X2Vzc2lkKHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsIHN0cnVjdCBpd19yZXF1ZXN0 X2luZm8NCj4gKmluZm8sDQo+ID4NCj4gPiAgICAgbGJzX2RlYl9lbnRlcihMQlNfREVCX1dFWFQp Ow0KPiA+DQo+ID4gKyAgIGlmICghbGJzX2lzX2NtZF9hbGxvd2VkKHByaXYpKSB7DQo+ID4gKyAg ICAgICAgICAgcmV0ID0gLUVCVVNZOw0KPiA+ICsgICAgICAgICAgIGxic19kZWJfbGVhdmVfYXJn cyhMQlNfREVCX1dFWFQsICJyZXQgJWQiLCByZXQpOw0KPiA+ICsgICAgICAgICAgIHJldHVybiBy ZXQ7DQo+ID4gKyAgIH0NCj4gPiArDQo+ID4gICAgIGlmICghcHJpdi0+cmFkaW9fb24pIHsNCj4g PiAgICAgICAgICAgICByZXQgPSAtRUlOVkFMOw0KPiA+ICAgICAgICAgICAgIGdvdG8gb3V0Ow0K PiA+IEBAIC0yMTEwLDYgKzIyODUsMTIgQEAgc3RhdGljIGludCBsYnNfc2V0X3dhcChzdHJ1Y3Qg bmV0X2RldmljZSAqZGV2LCBzdHJ1Y3QgaXdfcmVxdWVzdF9pbmZvICppbmZvLA0KPiA+DQo+ID4g ICAgIGxic19kZWJfZW50ZXIoTEJTX0RFQl9XRVhUKTsNCj4gPg0KPiA+ICsgICBpZiAoIWxic19p c19jbWRfYWxsb3dlZChwcml2KSkgew0KPiA+ICsgICAgICAgICAgIHJldCA9IC1FQlVTWTsNCj4g PiArICAgICAgICAgICBsYnNfZGViX2xlYXZlX2FyZ3MoTEJTX0RFQl9XRVhULCAicmV0ICVkIiwg cmV0KTsNCj4gPiArICAgICAgICAgICByZXR1cm4gcmV0Ow0KPiA+ICsgICB9DQo+ID4gKw0KPiA+ ICAgICBpZiAoIXByaXYtPnJhZGlvX29uKQ0KPiA+ICAgICAgICAgICAgIHJldHVybiAtRUlOVkFM Ow0KPiA+DQo+ID4gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X18NCj4gPiBsaWJlcnRhcy1kZXYgbWFpbGluZyBsaXN0DQo+ID4gbGliZXJ0YXMtZGV2QGxpc3Rz LmluZnJhZGVhZC5vcmcNCj4gPiBodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xp c3RpbmZvL2xpYmVydGFzLWRldg0KDQo= ^ permalink raw reply [flat|nested] 7+ messages in thread
* RE: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 2009-10-05 18:47 ` Bing Zhao @ 2009-10-05 18:59 ` Dan Williams 0 siblings, 0 replies; 7+ messages in thread From: Dan Williams @ 2009-10-05 18:59 UTC (permalink / raw) To: Bing Zhao Cc: libertas-dev@lists.infradead.org, Amitkumar Karwar, linux-wireless@vger.kernel.org On Mon, 2009-10-05 at 11:47 -0700, Bing Zhao wrote: > Hi Dan, > > > -----Original Message----- > > From: Dan Williams [mailto:dcbw@redhat.com] > > Sent: Thursday, October 01, 2009 11:27 AM > > To: Bing Zhao > > Cc: libertas-dev@lists.infradead.org; Amitkumar Karwar; linux-wireless@vger.kernel.org > > Subject: Re: [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 > > > > On Wed, 2009-09-30 at 20:04 -0700, Bing Zhao wrote: > > > From: Amitkumar Karwar <akarwar@marvell.com> > > > > > > Add timer based auto deep sleep feature in libertas driver which can be > > > configured using iwconfig command. 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> > > > > Acked-by: Dan Williams <dcbw@redhat.com> > > > > Though I wonder if we could just put the lbs_is_cmd_allowed() check into > > the actual command handling routines instead of sprinkling it around. > > Yes, we can do that. > > > We did move away from the 'one-huge-switch' command submission model, > > which makes it a bit harder to gate commands based on device state, but > > I can't think of anything off the top of my head that would hurt by > > doing it like that. > > > > i.e. would putting the check in both __lbs_cmd_async() and > > lbs_prepare_and_send_command() around where the priv->surprise_removed > > check is work too? > > We will submit a new patch for this. John may have already applied, so I think it's OK to base the new patch on top of this one. Dan > Regards, > > Bing > > > > > Dan > > > > > --- > > > drivers/net/wireless/libertas/README | 26 ++++- > > > drivers/net/wireless/libertas/cmd.c | 72 ++++++++++++- > > > drivers/net/wireless/libertas/cmdresp.c | 12 ++ > > > drivers/net/wireless/libertas/debugfs.c | 46 ++++++++ > > > 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 | 185 ++++++++++++++++++++++++++++++- > > > 15 files changed, 533 insertions(+), 21 deletions(-) > > > > > > diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README > > > index ab6a2d5..635002d 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,28 @@ 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. > > > > > > +======================== > > > +IWCONFIG COMMANDS > > > +======================== > > > +power period > > > + > > > + This command is used to configure the station in deep sleep mode / > > > + auto deep sleep mode. > > > + > > > + The timer is implemented to monitor the activities (command, event, > > > + 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 deep sleep mode is entered > > > + automatically. > > > + > > > + Note: this command is for SDIO interface only. > > > + > > > + Usage: > > > + To enable deep sleep mode do: > > > + iwconfig wlan0 power period 0 > > > + To enable auto deep sleep mode with idle time period 5 seconds do: > > > + iwconfig wlan0 power period 5 > > > + To disable deep sleep/auto deep sleep mode do: > > > + iwconfig wlan0 power period -1 > > > + > > > ============================================================================== > > > 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..8a7e931 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; > > > @@ -223,6 +233,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 +288,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 +460,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 +517,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 +558,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 +616,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 +657,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 +715,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; > > > 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..38a451e 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) { > > > @@ -709,6 +776,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > > > struct iw_param *vwrq, char *extra) > > > { > > > struct lbs_private *priv = dev->ml_priv; > > > + int ret = 0; > > > > > > lbs_deb_enter(LBS_DEB_WEXT); > > > > > > @@ -737,8 +805,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > > > "setting power timeout is not supported\n"); > > > return -EINVAL; > > > } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { > > > - lbs_deb_wext("setting power period not supported\n"); > > > - return -EINVAL; > > > + vwrq->value = vwrq->value / 1000; > > > + if (!priv->enter_deep_sleep) { > > > + lbs_pr_err("deep sleep feature is not implemented " > > > + "for this interface driver\n"); > > > + return -EINVAL; > > > + } > > > + > > > + if (priv->connect_status == LBS_CONNECTED) { > > > + if ((priv->is_auto_deep_sleep_enabled) && > > > + (vwrq->value == -1000)) { > > > + lbs_exit_auto_deep_sleep(priv); > > > + return 0; > > > + } else { > > > + lbs_pr_err("can't use deep sleep cmd in " > > > + "connected state\n"); > > > + return -EINVAL; > > > + } > > > + } > > > + > > > + if ((vwrq->value < 0) && (vwrq->value != -1000)) { > > > + lbs_pr_err("unknown option\n"); > > > + return -EINVAL; > > > + } > > > + > > > + if (vwrq->value > 0) { > > > + if (!priv->is_auto_deep_sleep_enabled) { > > > + priv->is_activity_detected = 0; > > > + priv->auto_deep_sleep_timeout = vwrq->value; > > > + lbs_enter_auto_deep_sleep(priv); > > > + } else { > > > + priv->auto_deep_sleep_timeout = vwrq->value; > > > + lbs_deb_debugfs("auto deep sleep: " > > > + "already enabled\n"); > > > + } > > > + return 0; > > > + } else { > > > + if (priv->is_auto_deep_sleep_enabled) { > > > + lbs_exit_auto_deep_sleep(priv); > > > + /* Try to exit deep sleep if auto */ > > > + /*deep sleep disabled */ > > > + ret = lbs_set_deep_sleep(priv, 0); > > > + } > > > + if (vwrq->value == 0) > > > + ret = lbs_set_deep_sleep(priv, 1); > > > + else if (vwrq->value == -1000) > > > + ret = lbs_set_deep_sleep(priv, 0); > > > + return ret; > > > + } > > > } > > > > > > if (priv->psmode != LBS802_11POWERMODECAM) { > > > @@ -752,6 +866,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, > > > } > > > > > > lbs_deb_leave(LBS_DEB_WEXT); > > > + > > > return 0; > > > } > > > > > > @@ -792,6 +907,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 +1010,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 +1124,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 +1188,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 +1219,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 +1465,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 +1654,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 +1872,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 +1980,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 +2028,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 +2152,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 +2285,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; > > > > > > _______________________________________________ > > > libertas-dev mailing list > > > libertas-dev@lists.infradead.org > > > http://lists.infradead.org/mailman/listinfo/libertas-dev > > NrybXǧv^){.n+{*ޕ,{ay\x1dʇڙ,j\afhz\x1ew\fj:+vwjm\azZ+ݢj"! ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-10-20 6:43 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-10-01 3:04 [PATCH v2] libertas: Add auto deep sleep support for SD8385/SD8686/SD8688 Bing Zhao 2009-10-01 7:42 ` Holger Schurig 2009-10-06 21:44 ` Bing Zhao 2009-10-20 6:43 ` Holger Schurig 2009-10-01 18:27 ` Dan Williams 2009-10-05 18:47 ` Bing Zhao 2009-10-05 18:59 ` Dan Williams
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox