From 4a8e85bc08381510af7df836fde8d9643578df6f Mon Sep 17 00:00:00 2001 From: Ahmad Masri Date: Wed, 4 Dec 2019 12:48:48 +0200 Subject: [PATCH 1/4] wil6210: enable AP/PCP power save New FW has power save capability in AP/PCP mode. FW reports this to driver with WMI_FW_CAPABILITY_AP_POWER_MANAGEMENT. AP/PCP mode power save in FW is disabled by default. It can be enabled by sending WMI_PS_DEV_PROFILE_CFG_CMD to FW as part of start_ap sequence. Several pre-conditions must be met for driver to enable this: 1. power save enabled from cfg80211 2. AP power save enabled from platform driver. This is reported from platform driver with a new WIL_PLATFORM_CAPA_AP_PS AP power save can be controlled via "ap_ps" debugfs. Change-Id: I328fdbfe5382e60688c9f4a67aa9378197e01987 Signed-off-by: Ahmad Masri Signed-off-by: Alexei Avshalom Lazar --- drivers/net/wireless/ath/wil6210/cfg80211.c | 11 ++++++++++- drivers/net/wireless/ath/wil6210/debugfs.c | 1 + drivers/net/wireless/ath/wil6210/main.c | 2 ++ drivers/net/wireless/ath/wil6210/wil6210.h | 1 + drivers/net/wireless/ath/wil6210/wil_platform.h | 1 + drivers/net/wireless/ath/wil6210/wmi.h | 1 + 6 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index f1bf54031901..9a7ab837b4d6 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -2155,7 +2155,8 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, if (pbss) wmi_nettype = WMI_NETTYPE_P2P; - wil_dbg_misc(wil, "start_ap: mid=%d, is_go=%d\n", vif->mid, is_go); + wil_dbg_misc(wil, "start_ap: mid=%d, is_go=%d ap_ps=%d\n", vif->mid, + is_go, wil->ap_ps); if (is_go && !pbss) { wil_err(wil, "P2P GO must be in PBSS\n"); return -ENOTSUPP; @@ -2247,6 +2248,14 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, if (rc) goto err_bcast; + if (test_bit(WMI_FW_CAPABILITY_AP_POWER_MANAGEMENT, + wil->fw_capabilities)) { + enum wmi_ps_profile_type ps_profile = wil->ap_ps ? + wil->ps_profile : WMI_PS_PROFILE_TYPE_PS_DISABLED; + + wil_ps_update(wil, ps_profile); + } + goto out; /* success */ err_bcast: diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index f603bf60ea45..7207a879e45d 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -2460,6 +2460,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(rx_buff_id_count, 0644, doff_u32), WIL_FIELD(amsdu_en, 0644, doff_u8), WIL_FIELD(force_edmg_channel, 0644, doff_u8), + WIL_FIELD(ap_ps, 0644, doff_u8), {}, }; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index b3d60bdf9c1b..88b6ff9d4948 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1309,6 +1309,8 @@ void wil_refresh_fw_capabilities(struct wil6210_priv *wil) } update_supported_bands(wil); + + wil->ap_ps = test_bit(WIL_PLATFORM_CAPA_AP_PS, wil->platform_capa); } void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 8d7b8ce2d554..c01c3afb949d 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1047,6 +1047,7 @@ struct wil6210_priv { void *platform_handle; struct wil_platform_ops platform_ops; bool keep_radio_on_during_sleep; + u8 ap_ps; /* AP mode power save enabled */ struct pmc_ctx pmc; diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h index d3816498c2dc..e6730afe8a46 100644 --- a/drivers/net/wireless/ath/wil6210/wil_platform.h +++ b/drivers/net/wireless/ath/wil6210/wil_platform.h @@ -32,6 +32,7 @@ enum wil_platform_capa { WIL_PLATFORM_CAPA_T_PWR_ON_0 = 1, WIL_PLATFORM_CAPA_EXT_CLK = 2, WIL_PLATFORM_CAPA_SMMU = 3, + WIL_PLATFORM_CAPA_AP_PS = 4, WIL_PLATFORM_CAPA_MAX, }; diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index c2d4eac96fb3..39029bc45d93 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -100,6 +100,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_IPA = 27, WMI_FW_CAPABILITY_TEMPERATURE_ALL_RF = 30, WMI_FW_CAPABILITY_SPLIT_REKEY = 31, + WMI_FW_CAPABILITY_AP_POWER_MANAGEMENT = 32, WMI_FW_CAPABILITY_MAX, }; From 68aa288faa8004382f7f20a6884459eaffa6a3de Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Thu, 29 Aug 2019 15:15:58 +0300 Subject: [PATCH 2/4] wil6210: minimize the time that mem_lock is held mem_lock is taken for the entire wil_reset(). Optimize this by taking mem_lock just before device is being reset and release the lock after FW download. Change-Id: Icf3430e355acc2c33dc37c6a38a18c47de03a2cf Signed-off-by: Alexei Avshalom Lazar --- drivers/net/wireless/ath/wil6210/cfg80211.c | 2 -- drivers/net/wireless/ath/wil6210/main.c | 10 ++++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 9a7ab837b4d6..dd0bdae7b3e2 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -3792,9 +3792,7 @@ static int wil_nl_60g_handle_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, "NL_60G_GEN_FW_RESET, resetting...\n"); mutex_lock(&wil->mutex); - down_write(&wil->mem_lock); rc = wil_reset(wil, true); - up_write(&wil->mem_lock); mutex_unlock(&wil->mutex); break; diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 88b6ff9d4948..c5120d8c8455 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1753,6 +1753,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) /* Disable device led before reset*/ wmi_led_cfg(wil, false); + down_write(&wil->mem_lock); + /* prevent NAPI from being scheduled and prevent wmi commands */ mutex_lock(&wil->wmi_mutex); if (test_bit(wil_status_suspending, wil->status)) @@ -1808,6 +1810,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) if (wil->secured_boot) { wil_err(wil, "secured boot is not supported\n"); + up_write(&wil->mem_lock); return -ENOTSUPP; } @@ -1838,6 +1841,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) clear_bit(wil_status_resetting, wil->status); + up_write(&wil->mem_lock); + if (load_fw) { wil_unmask_irq(wil); @@ -1905,6 +1910,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) return rc; out: + up_write(&wil->mem_lock); clear_bit(wil_status_resetting, wil->status); return rc; } @@ -1930,9 +1936,7 @@ int __wil_up(struct wil6210_priv *wil) WARN_ON(!mutex_is_locked(&wil->mutex)); - down_write(&wil->mem_lock); rc = wil_reset(wil, true); - up_write(&wil->mem_lock); if (rc) return rc; @@ -2025,9 +2029,7 @@ int __wil_down(struct wil6210_priv *wil) wil_abort_scan_all_vifs(wil, false); mutex_unlock(&wil->vif_mutex); - down_write(&wil->mem_lock); rc = wil_reset(wil, false); - up_write(&wil->mem_lock); return rc; } From ff02bf9483fc4efa43a83e58aec509cfbf387a06 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Thu, 22 Aug 2019 16:11:03 +0300 Subject: [PATCH 3/4] wil6210: take mem_lock for writing in crash dump collection On some crash dump cases mem_lock is already taken, error returns and crash dump copy fails. In this case wait until mem_lock available instead of failing the operation. Also take the mem_lock for writing to prevent other threads from altering the state of the device while collecting crash dump. Change-Id: I2ae74fba77e39161e33a7c5302916d1c9254fa05 Signed-off-by: Alexei Avshalom Lazar --- .../net/wireless/ath/wil6210/wil_crash_dump.c | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c index 772cb00c2002..89c12cb2aaab 100644 --- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c @@ -1,18 +1,7 @@ +// SPDX-License-Identifier: ISC /* * Copyright (c) 2015,2017 Qualcomm Atheros, Inc. * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "wil6210.h" @@ -57,7 +46,7 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil, int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) { - int i, rc; + int i; const struct fw_map *map; void *data; u32 host_min, dump_size, offset, len; @@ -73,9 +62,15 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) return -EINVAL; } - rc = wil_mem_access_lock(wil); - if (rc) - return rc; + down_write(&wil->mem_lock); + + if (test_bit(wil_status_suspending, wil->status) || + test_bit(wil_status_suspended, wil->status)) { + wil_err(wil, + "suspend/resume in progress. cannot copy crash dump\n"); + up_write(&wil->mem_lock); + return -EBUSY; + } /* copy to crash dump area */ for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { @@ -95,7 +90,8 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) wil_memcpy_fromio_32((void * __force)(dest + offset), (const void __iomem * __force)data, len); } - wil_mem_access_unlock(wil); + + up_write(&wil->mem_lock); return 0; } From 5f44d3caa745dfb5ed432d1f9e13337f1eafd519 Mon Sep 17 00:00:00 2001 From: Alexei Avshalom Lazar Date: Wed, 4 Dec 2019 12:52:55 +0200 Subject: [PATCH 4/4] wil6210: add verification for cid upper bound max_assoc_sta can receive values (from the user or from the FW) that are higher than WIL6210_MAX_CID. Verify that cid doesn't exceed the upper bound of WIL6210_MAX_CID. Change-Id: Id00b69a128d2c4df4a3ef85583bbe44590ff557c Signed-off-by: Alexei Avshalom Lazar --- drivers/net/wireless/ath/wil6210/wil6210.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index c01c3afb949d..f04887033199 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1199,7 +1199,7 @@ static inline void wil_c(struct wil6210_priv *wil, u32 reg, u32 val) */ static inline bool wil_cid_valid(struct wil6210_priv *wil, int cid) { - return (cid >= 0 && cid < wil->max_assoc_sta); + return (cid >= 0 && cid < wil->max_assoc_sta && cid < WIL6210_MAX_CID); } void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len);