From 8ff6f12fa7093981493e63b56830bd22f634750c Mon Sep 17 00:00:00 2001 From: kitakar5525 <34676735+kitakar5525@users.noreply.github.com> Date: Thu, 20 Feb 2020 16:51:11 +0900 Subject: [PATCH 2/6] wifi --- .../net/wireless/marvell/mwifiex/cfg80211.c | 26 ++++++ drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- drivers/net/wireless/marvell/mwifiex/pcie.c | 84 +++++++++++-------- .../net/wireless/marvell/mwifiex/sta_cmd.c | 31 ++----- .../wireless/marvell/mwifiex/sta_cmdresp.c | 4 +- 5 files changed, 87 insertions(+), 60 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 12bfd653a4052..68404a1767945 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -25,6 +25,11 @@ static char *reg_alpha2; module_param(reg_alpha2, charp, 0); +static bool allow_ps_mode; +module_param(allow_ps_mode, bool, 0444); +MODULE_PARM_DESC(allow_ps_mode, + "allow WiFi power management to be enabled. (default: disallowed)"); + static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { { .max = 3, .types = BIT(NL80211_IFTYPE_STATION) | @@ -439,6 +444,27 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, ps_mode = enabled; + /* Allow ps_mode to be enabled only when allow_ps_mode is set + * (but always allow ps_mode to be disabled in case it gets enabled + * for unknown reason and you want to disable it) */ + if (ps_mode && !allow_ps_mode) { + dev_info(priv->adapter->dev, + "Request to enable ps_mode received but it's disallowed " + "by module parameter. Rejecting the request.\n"); + + /* Return negative value to inform userspace tools that setting + * power_save to be enabled is not permitted. */ + return -1; + } + + if (ps_mode) + dev_warn(priv->adapter->dev, + "WARN: Request to enable ps_mode received. Enabling it. " + "Disable it if you encounter connection instability.\n"); + else + dev_info(priv->adapter->dev, + "Request to disable ps_mode received. Disabling it.\n"); + return mwifiex_drv_set_power(priv, &ps_mode); } diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index a415d73a73e62..d55e70a411d77 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -953,7 +953,7 @@ struct mwifiex_tkip_param { struct mwifiex_aes_param { u8 pn[WPA_PN_SIZE]; __le16 key_len; - u8 key[WLAN_KEY_LEN_CCMP]; + u8 key[WLAN_KEY_LEN_CCMP_256]; } __packed; struct mwifiex_wapi_param { diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 87b4ccca4b9a2..3bdad5e80ecbb 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -146,38 +146,45 @@ static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) * * If already not suspended, this function allocates and sends a host * sleep activate request to the firmware and turns off the traffic. + * + * XXX: ignoring all the above comment and just removes the card to + * fix S0ix and "AP scanning (sometimes) not working after suspend". + * Required code is extracted from mwifiex_pcie_remove(). */ static int mwifiex_pcie_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); + struct pcie_service_card *card = pci_get_drvdata(pdev); struct mwifiex_adapter *adapter; - struct pcie_service_card *card = dev_get_drvdata(dev); - + struct mwifiex_private *priv; + const struct mwifiex_pcie_card_reg *reg; + u32 fw_status; + int ret; /* Might still be loading firmware */ wait_for_completion(&card->fw_done); adapter = card->adapter; - if (!adapter) { - dev_err(dev, "adapter is not valid\n"); + if (!adapter || !adapter->priv_num) return 0; - } - mwifiex_enable_wake(adapter); + reg = card->pcie.reg; + if (reg) + ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status); + else + fw_status = -1; - /* Enable the Host Sleep */ - if (!mwifiex_enable_hs(adapter)) { - mwifiex_dbg(adapter, ERROR, - "cmd: failed to suspend\n"); - clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags); - mwifiex_disable_wake(adapter); - return -EFAULT; - } + if (fw_status == FIRMWARE_READY_PCIE && !adapter->mfg_mode) { + mwifiex_deauthenticate_all(adapter); - flush_workqueue(adapter->workqueue); + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); + + mwifiex_disable_auto_ds(priv); - /* Indicate device suspended */ - set_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags); - clear_bit(MWIFIEX_IS_HS_ENABLING, &adapter->work_flags); + mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN); + } + + mwifiex_remove_card(adapter); return 0; } @@ -189,31 +196,35 @@ static int mwifiex_pcie_suspend(struct device *dev) * * If already not resumed, this function turns on the traffic and * sends a host sleep cancel request to the firmware. + * + * XXX: ignoring all the above comment and probes the card that was + * removed on suspend. Required code is extracted from mwifiex_pcie_probe(). */ static int mwifiex_pcie_resume(struct device *dev) { - struct mwifiex_adapter *adapter; - struct pcie_service_card *card = dev_get_drvdata(dev); + struct pci_dev *pdev = to_pci_dev(dev); + struct pcie_service_card *card = pci_get_drvdata(pdev); + int ret; + pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n", + pdev->vendor, pdev->device, pdev->revision); - if (!card->adapter) { - dev_err(dev, "adapter structure is not valid\n"); - return 0; - } + init_completion(&card->fw_done); - adapter = card->adapter; + card->dev = pdev; - if (!test_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags)) { - mwifiex_dbg(adapter, WARN, - "Device already resumed\n"); - return 0; + /* device tree node parsing and platform specific configuration */ + if (pdev->dev.of_node) { + ret = mwifiex_pcie_probe_of(&pdev->dev); + if (ret) + return ret; } - clear_bit(MWIFIEX_IS_SUSPENDED, &adapter->work_flags); - - mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_ASYNC_CMD); - mwifiex_disable_wake(adapter); + if (mwifiex_add_card(card, &card->fw_done, &pcie_ops, + MWIFIEX_PCIE, &pdev->dev)) { + pr_err("%s failed\n", __func__); + return -1; + } return 0; } @@ -229,8 +240,13 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct pcie_service_card *card; + struct pci_dev *parent_pdev = pci_upstream_bridge(pdev); int ret; + /* disable bridge_d3 to fix driver crashing after suspend on gen4+ + * Surface devices */ + parent_pdev->bridge_d3 = false; + pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n", pdev->vendor, pdev->device, pdev->revision); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 0bd93f26bd7f8..91b03423c09d0 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -2254,7 +2254,6 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, * - Function init (for first interface only) * - Read MAC address (for first interface only) * - Reconfigure Tx buffer size (for first interface only) - * - Enable auto deep sleep (for first interface only) * - Get Tx rate * - Get Tx power * - Set IBSS coalescing status @@ -2267,7 +2266,6 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) struct mwifiex_adapter *adapter = priv->adapter; int ret; struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; - struct mwifiex_ds_auto_ds auto_ds; enum state_11d_t state_11d; struct mwifiex_ds_11n_tx_cfg tx_cfg; u8 sdio_sp_rx_aggr_enable; @@ -2339,16 +2337,10 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) if (ret) return -1; - if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { - /* Enable IEEE PS by default */ - priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - ret = mwifiex_send_cmd(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_STA_PS, NULL, - true); - if (ret) - return -1; - } + /* Not enabling ps_mode (IEEE power_save) by default. Enabling + * this causes connection instability, especially on 5GHz APs + * and eventually causes "firmware wakeup failed". Therefore, + * the relevant code was removed from here. */ if (drcs) { adapter->drcs_enabled = true; @@ -2395,17 +2387,10 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) if (ret) return -1; - if (!disable_auto_ds && first_sta && - priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { - /* Enable auto deep sleep */ - auto_ds.auto_ds = DEEP_SLEEP_ON; - auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_AUTO_DS, - &auto_ds, true); - if (ret) - return -1; - } + /* Not enabling auto deep sleep (auto_ds) by default. Enabling + * this reportedly causes "suspend/resume fails when not connected + * to an Access Point." Therefore, the relevant code was removed + * from here. */ if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { /* Send cmd to FW to enable/disable 11D function */ diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 962d8bfe6f101..119ccacd1fcc4 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -619,7 +619,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv, key_v2 = &resp->params.key_material_v2; len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len); - if (len > WLAN_KEY_LEN_CCMP) + if (len > sizeof(key_v2->key_param_set.key_params.aes.key)) return -EINVAL; if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) { @@ -635,7 +635,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv, return 0; memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0, - WLAN_KEY_LEN_CCMP); + sizeof(key_v2->key_param_set.key_params.aes.key)); priv->aes_key_v2.key_param_set.key_params.aes.key_len = cpu_to_le16(len); memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key, -- 2.28.0