From patchwork Wed Oct 25 13:44:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amitkumar Karwar X-Patchwork-Id: 10026749 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6B7EE60375 for ; Wed, 25 Oct 2017 13:51:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 565C728BBC for ; Wed, 25 Oct 2017 13:51:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4B32D28BAB; Wed, 25 Oct 2017 13:51:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6B97828BBC for ; Wed, 25 Oct 2017 13:51:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751686AbdJYNvN (ORCPT ); Wed, 25 Oct 2017 09:51:13 -0400 Received: from mail-pg0-f66.google.com ([74.125.83.66]:48346 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750823AbdJYNvM (ORCPT ); Wed, 25 Oct 2017 09:51:12 -0400 Received: by mail-pg0-f66.google.com with SMTP id v78so33044pgb.5 for ; Wed, 25 Oct 2017 06:51:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=+BMjo1pYCiZaRXX1VZybOqARCFUxFxG3nv5PSdZK/js=; b=WkWzZSS67SfiRGQm8pMGWI2l6oo6XZjsHrpezlIGuHHGPQiPlV0urUvT6qz8sryUTF dcLd83f0Uy3b2Z3I46q1265ra6YrAUv0TNsP3cA9v9qtlW1vNUadYK94n324QDaR76Jv zVM4m6udsdNS8wNpKHvYVUJ5EmAhMraJG0K/cWR3JKvh0VmRkIZ2cc9ffw3Gkme0OrUO Ps8WH//Lrbr7tLeu/0X3ugVroPTkgmVUZ34hOIZ/Aa2QuHC+ogkax/4hh1Ub0DEk8PpF UAPuwsgAO9bu20XEJp+3Q+Z4qZDJVOP541EOMhbU0sfWTPbTr52bVnLhMSHjh4STjTBy 5v9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=+BMjo1pYCiZaRXX1VZybOqARCFUxFxG3nv5PSdZK/js=; b=TI5EfrNVluRP5O3rre5ts4QazSNhhVfSuRJPy4lb0+605kbWEE5fngMUmrUj45cYqz URW8o6L5IXexhb2RSZGtutlnpSH3E55lHX67yMa4y7nhJkA5XQz6eYPl83ieHWXFbe6W maHHoNDSq3c0kohqPZGDij+CqHUOMQ8me9O0QNqeG0XeYHMUHIPOH3tR+7GEEVuLc1mA Pq5nfV9pGrps9KfE2JVH9qUMwalIVIUs9VPOuLfl6br7mGdW2B6JhOicsMM5b2KntCAN 7AE05kGe2Yv+Oa9LsbUdrM8/FsxoLmSWdp2/87GbI6sel9dVviXiF/h/LxDAdbj0TlRZ kSKg== X-Gm-Message-State: AMCzsaUZTsurq7BJfFvoFEcyNUFdbH/D7QXNzZ0Yn18XaYmEb8QbvW+v zGc/jXwIU5sFhOuanpZU+mW8Qg== X-Google-Smtp-Source: ABhQp+T1NTwH0+kugMNMdw8+wKI3a91w1SUnL8JRGU48pNMcsxWZgq5a5nzSzD6XgRe1MrTncqhRhw== X-Received: by 10.101.74.193 with SMTP id c1mr2105816pgu.260.1508939471398; Wed, 25 Oct 2017 06:51:11 -0700 (PDT) Received: from cpu185.redpinesignals.com ([203.196.161.90]) by smtp.gmail.com with ESMTPSA id v22sm5025517pgb.65.2017.10.25.06.51.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 25 Oct 2017 06:51:10 -0700 (PDT) From: Amitkumar Karwar To: Kalle Valo Cc: linux-wireless@vger.kernel.org, Amitkumar Karwar , Prameela Rani Garnepudi , Karun Eagalapati Subject: [v2 2/3] rsi: sdio: Add WOWLAN support for S4 hibernate state Date: Wed, 25 Oct 2017 19:14:33 +0530 Message-Id: <1508939073-16237-1-git-send-email-amitkarwar@gmail.com> X-Mailer: git-send-email 2.7.4 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Karun Eagalapati We are disabling of interrupts from firmware in freeze handler. Also setting power management capability KEEP_MMC_POWER to make device wakeup for WoWLAN trigger. At restore, we observed a device reset on some platforms. Hence reloading of firmware and device initialization is performed. Signed-off-by: Karun Eagalapati Signed-off-by: Amitkumar Karwar --- drivers/net/wireless/rsi/rsi_91x_core.c | 2 + drivers/net/wireless/rsi/rsi_91x_mac80211.c | 9 +++ drivers/net/wireless/rsi/rsi_91x_main.c | 1 + drivers/net/wireless/rsi/rsi_91x_mgmt.c | 7 +- drivers/net/wireless/rsi/rsi_91x_sdio.c | 111 ++++++++++++++++++++++++++++ drivers/net/wireless/rsi/rsi_main.h | 4 + drivers/net/wireless/rsi/rsi_sdio.h | 1 + 7 files changed, 134 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c index 87e023d..d0d2201 100644 --- a/drivers/net/wireless/rsi/rsi_91x_core.c +++ b/drivers/net/wireless/rsi/rsi_91x_core.c @@ -276,6 +276,8 @@ void rsi_core_qos_processor(struct rsi_common *common) rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__); break; } + if (common->hibernate_resume) + break; mutex_lock(&common->tx_lock); diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 2bcf412..8be24b1 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -17,6 +17,7 @@ #include #include "rsi_debugfs.h" #include "rsi_mgmt.h" +#include "rsi_sdio.h" #include "rsi_common.h" #include "rsi_ps.h" @@ -325,6 +326,11 @@ static int rsi_mac80211_start(struct ieee80211_hw *hw) rsi_dbg(ERR_ZONE, "===> Interface UP <===\n"); mutex_lock(&common->mutex); + if (common->hibernate_resume) { + common->reinit_hw = true; + adapter->host_intf_ops->reinit_device(adapter); + wait_for_completion(&adapter->priv->wlan_init_completion); + } common->iface_down = false; wiphy_rfkill_start_polling(hw->wiphy); rsi_send_rx_filter_frame(common, 0); @@ -1846,6 +1852,9 @@ static int rsi_mac80211_resume(struct ieee80211_hw *hw) rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__); + if (common->hibernate_resume) + return 0; + mutex_lock(&common->mutex); rsi_send_wowlan_request(common, 0, 0); diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c index 71b8cfb..2d19733 100644 --- a/drivers/net/wireless/rsi/rsi_91x_main.c +++ b/drivers/net/wireless/rsi/rsi_91x_main.c @@ -265,6 +265,7 @@ struct rsi_hw *rsi_91x_init(void) common->roc_timer.data = (unsigned long)common; common->roc_timer.function = (void *)&rsi_roc_timeout; init_timer(&common->roc_timer); + init_completion(&common->wlan_init_completion); common->init_done = true; return adapter; diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 1446ee3..d38a09f 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -1761,7 +1761,11 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, common->bb_rf_prog_count--; if (!common->bb_rf_prog_count) { common->fsm_state = FSM_MAC_INIT_DONE; - return rsi_mac80211_attach(common); + if (common->reinit_hw) { + complete(&common->wlan_init_completion); + } else { + return rsi_mac80211_attach(common); + } } } else { rsi_dbg(INFO_ZONE, @@ -1839,6 +1843,7 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg) case TA_CONFIRM_TYPE: return rsi_handle_ta_confirm_type(common, msg); case CARD_READY_IND: + common->hibernate_resume = false; rsi_dbg(FSM_ZONE, "%s: Card ready indication received\n", __func__); return rsi_handle_card_ready(common, msg); diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index fa6af7b..3f683d8 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -880,6 +880,7 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = { .master_reg_read = rsi_sdio_master_reg_read, .master_reg_write = rsi_sdio_master_reg_write, .load_data_master_write = rsi_sdio_load_data_master_write, + .reinit_device = rsi_sdio_reinit_device, }; /** @@ -936,6 +937,8 @@ static int rsi_probe(struct sdio_func *pfunction, return -EIO; } + adapter->priv->hibernate_resume = false; + adapter->priv->reinit_hw = false; return 0; fail: rsi_91x_deinit(adapter); @@ -1198,9 +1201,117 @@ static int rsi_resume(struct device *dev) return 0; } +static int rsi_freeze(struct device *dev) +{ + int ret; + struct sdio_func *pfunction = dev_to_sdio_func(dev); + struct rsi_hw *adapter = sdio_get_drvdata(pfunction); + struct rsi_common *common; + struct rsi_91x_sdiodev *sdev; + + rsi_dbg(INFO_ZONE, "SDIO Bus freeze ===>\n"); + + if (!adapter) { + rsi_dbg(ERR_ZONE, "Device is not ready\n"); + return -ENODEV; + } + common = adapter->priv; + sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev; + +#ifdef CONFIG_RSI_WOW + if ((common->wow_flags & RSI_WOW_ENABLED) && + (common->wow_flags & RSI_WOW_NO_CONNECTION)) + rsi_dbg(ERR_ZONE, + "##### Device can not wake up through WLAN\n"); +#endif + ret = rsi_sdio_disable_interrupts(pfunction); + + if (sdev->write_fail) + rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n"); + + ret = rsi_set_sdio_pm_caps(adapter); + if (ret) + rsi_dbg(INFO_ZONE, "Setting power management caps failed\n"); + + rsi_dbg(INFO_ZONE, "***** RSI module freezed *****\n"); + + return 0; +} + +static int rsi_thaw(struct device *dev) +{ + struct sdio_func *pfunction = dev_to_sdio_func(dev); + struct rsi_hw *adapter = sdio_get_drvdata(pfunction); + struct rsi_common *common = adapter->priv; + + rsi_dbg(ERR_ZONE, "SDIO Bus thaw =====>\n"); + + common->hibernate_resume = true; + common->fsm_state = FSM_CARD_NOT_READY; + common->iface_down = true; + + rsi_sdio_enable_interrupts(pfunction); + + rsi_dbg(INFO_ZONE, "***** RSI module thaw done *****\n"); + + return 0; +} + +int rsi_sdio_reinit_device(struct rsi_hw *adapter) +{ + struct rsi_91x_sdiodev *sdev = adapter->rsi_dev; + struct sdio_func *pfunction = sdev->pfunction; + int ii; + + for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) + skb_queue_purge(&adapter->priv->tx_queue[ii]); + + /* Initialize device again */ + sdio_claim_host(pfunction); + + sdio_release_irq(pfunction); + rsi_reset_card(pfunction); + + sdio_enable_func(pfunction); + rsi_setupcard(adapter); + rsi_init_sdio_slave_regs(adapter); + sdio_claim_irq(pfunction, rsi_handle_interrupt); + rsi_hal_device_init(adapter); + + sdio_release_host(pfunction); + + return 0; +} + +static int rsi_restore(struct device *dev) +{ + struct sdio_func *pfunction = dev_to_sdio_func(dev); + struct rsi_hw *adapter = sdio_get_drvdata(pfunction); + struct rsi_common *common = adapter->priv; + + rsi_dbg(INFO_ZONE, "SDIO Bus restore ======>\n"); + common->hibernate_resume = true; + common->fsm_state = FSM_FW_NOT_LOADED; + common->iface_down = true; + + adapter->sc_nvifs = 0; + ieee80211_restart_hw(adapter->hw); + +#ifdef CONFIG_RSI_WOW + common->wow_flags = 0; +#endif + common->iface_down = false; + + rsi_dbg(INFO_ZONE, "RSI module restored\n"); + + return 0; +} static const struct dev_pm_ops rsi_pm_ops = { .suspend = rsi_suspend, .resume = rsi_resume, + .freeze = rsi_freeze, + .thaw = rsi_thaw, + .restore = rsi_restore, }; #endif diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 44a199f..8cab630 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -214,6 +214,7 @@ struct rsi_common { struct rsi_thread tx_thread; struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 2]; + struct completion wlan_init_completion; /* Mutex declaration */ struct mutex mutex; /* Mutex used for tx thread */ @@ -272,6 +273,8 @@ struct rsi_common { u8 obm_ant_sel_val; int tx_power; u8 ant_in_use; + bool hibernate_resume; + bool reinit_hw; u8 wow_flags; u16 beacon_interval; u8 dtim_cnt; @@ -362,5 +365,6 @@ struct rsi_host_intf_ops { int (*load_data_master_write)(struct rsi_hw *adapter, u32 addr, u32 instructions_size, u16 block_size, u8 *fw); + int (*reinit_device)(struct rsi_hw *adapter); }; #endif diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h index 49c549b..8fbf90e 100644 --- a/drivers/net/wireless/rsi/rsi_sdio.h +++ b/drivers/net/wireless/rsi/rsi_sdio.h @@ -131,4 +131,5 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word); void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit); int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter); int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num); +int rsi_sdio_reinit_device(struct rsi_hw *adapter); #endif