diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index f1bf54031901..dd0bdae7b3e2 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: @@ -3783,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/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..c5120d8c8455 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) @@ -1751,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)) @@ -1806,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; } @@ -1836,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); @@ -1903,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; } @@ -1928,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; @@ -2023,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; } diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 8d7b8ce2d554..f04887033199 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; @@ -1198,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); 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; } 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, };