Commit 2603d315 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'wireless-2024-09-04' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless

Kalle Valo says:

====================
wireless fixes for v6.11

Hopefully final fixes for v6.11 and this time only fixes to ath11k
driver. We need to revert hibernation support due to reported
regressions and we have a fix for kernel crash introduced in
v6.11-rc1.

* tag 'wireless-2024-09-04' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless:
  MAINTAINERS: wifi: cw1200: add net-cw1200.h
  Revert "wifi: ath11k: support hibernation"
  Revert "wifi: ath11k: restore country code during resume"
  wifi: ath11k: fix NULL pointer dereference in ath11k_mac_get_eirp_power()
====================

Link: https://patch.msgid.link/20240904135906.5986EC4CECA@smtp.kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 858430db 5872b47c
...@@ -5953,6 +5953,7 @@ F: Documentation/process/cve.rst ...@@ -5953,6 +5953,7 @@ F: Documentation/process/cve.rst
CW1200 WLAN driver CW1200 WLAN driver
S: Orphan S: Orphan
F: drivers/net/wireless/st/cw1200/ F: drivers/net/wireless/st/cw1200/
F: include/linux/platform_data/net-cw1200.h
CX18 VIDEO4LINUX DRIVER CX18 VIDEO4LINUX DRIVER
M: Andy Walls <awalls@md.metrocast.net> M: Andy Walls <awalls@md.metrocast.net>
......
...@@ -413,7 +413,7 @@ static int ath11k_ahb_power_up(struct ath11k_base *ab) ...@@ -413,7 +413,7 @@ static int ath11k_ahb_power_up(struct ath11k_base *ab)
return ret; return ret;
} }
static void ath11k_ahb_power_down(struct ath11k_base *ab, bool is_suspend) static void ath11k_ahb_power_down(struct ath11k_base *ab)
{ {
struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
...@@ -1280,7 +1280,7 @@ static void ath11k_ahb_remove(struct platform_device *pdev) ...@@ -1280,7 +1280,7 @@ static void ath11k_ahb_remove(struct platform_device *pdev)
struct ath11k_base *ab = platform_get_drvdata(pdev); struct ath11k_base *ab = platform_get_drvdata(pdev);
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
ath11k_ahb_power_down(ab, false); ath11k_ahb_power_down(ab);
ath11k_debugfs_soc_destroy(ab); ath11k_debugfs_soc_destroy(ab);
ath11k_qmi_deinit_service(ab); ath11k_qmi_deinit_service(ab);
goto qmi_fail; goto qmi_fail;
......
...@@ -906,6 +906,12 @@ int ath11k_core_suspend(struct ath11k_base *ab) ...@@ -906,6 +906,12 @@ int ath11k_core_suspend(struct ath11k_base *ab)
return ret; return ret;
} }
ret = ath11k_wow_enable(ab);
if (ret) {
ath11k_warn(ab, "failed to enable wow during suspend: %d\n", ret);
return ret;
}
ret = ath11k_dp_rx_pktlog_stop(ab, false); ret = ath11k_dp_rx_pktlog_stop(ab, false);
if (ret) { if (ret) {
ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n", ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
...@@ -916,85 +922,29 @@ int ath11k_core_suspend(struct ath11k_base *ab) ...@@ -916,85 +922,29 @@ int ath11k_core_suspend(struct ath11k_base *ab)
ath11k_ce_stop_shadow_timers(ab); ath11k_ce_stop_shadow_timers(ab);
ath11k_dp_stop_shadow_timers(ab); ath11k_dp_stop_shadow_timers(ab);
/* PM framework skips suspend_late/resume_early callbacks
* if other devices report errors in their suspend callbacks.
* However ath11k_core_resume() would still be called because
* here we return success thus kernel put us on dpm_suspended_list.
* Since we won't go through a power down/up cycle, there is
* no chance to call complete(&ab->restart_completed) in
* ath11k_core_restart(), making ath11k_core_resume() timeout.
* So call it here to avoid this issue. This also works in case
* no error happens thus suspend_late/resume_early get called,
* because it will be reinitialized in ath11k_core_resume_early().
*/
complete(&ab->restart_completed);
return 0;
}
EXPORT_SYMBOL(ath11k_core_suspend);
int ath11k_core_suspend_late(struct ath11k_base *ab)
{
struct ath11k_pdev *pdev;
struct ath11k *ar;
if (!ab->hw_params.supports_suspend)
return -EOPNOTSUPP;
/* so far single_pdev_only chips have supports_suspend as true
* and only the first pdev is valid.
*/
pdev = ath11k_core_get_single_pdev(ab);
ar = pdev->ar;
if (!ar || ar->state != ATH11K_STATE_OFF)
return 0;
ath11k_hif_irq_disable(ab); ath11k_hif_irq_disable(ab);
ath11k_hif_ce_irq_disable(ab); ath11k_hif_ce_irq_disable(ab);
ath11k_hif_power_down(ab, true); ret = ath11k_hif_suspend(ab);
if (ret) {
ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
return ret;
}
return 0; return 0;
} }
EXPORT_SYMBOL(ath11k_core_suspend_late); EXPORT_SYMBOL(ath11k_core_suspend);
int ath11k_core_resume_early(struct ath11k_base *ab)
{
int ret;
struct ath11k_pdev *pdev;
struct ath11k *ar;
if (!ab->hw_params.supports_suspend)
return -EOPNOTSUPP;
/* so far single_pdev_only chips have supports_suspend as true
* and only the first pdev is valid.
*/
pdev = ath11k_core_get_single_pdev(ab);
ar = pdev->ar;
if (!ar || ar->state != ATH11K_STATE_OFF)
return 0;
reinit_completion(&ab->restart_completed);
ret = ath11k_hif_power_up(ab);
if (ret)
ath11k_warn(ab, "failed to power up hif during resume: %d\n", ret);
return ret;
}
EXPORT_SYMBOL(ath11k_core_resume_early);
int ath11k_core_resume(struct ath11k_base *ab) int ath11k_core_resume(struct ath11k_base *ab)
{ {
int ret; int ret;
struct ath11k_pdev *pdev; struct ath11k_pdev *pdev;
struct ath11k *ar; struct ath11k *ar;
long time_left;
if (!ab->hw_params.supports_suspend) if (!ab->hw_params.supports_suspend)
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* so far single_pdev_only chips have supports_suspend as true /* so far signle_pdev_only chips have supports_suspend as true
* and only the first pdev is valid. * and only the first pdev is valid.
*/ */
pdev = ath11k_core_get_single_pdev(ab); pdev = ath11k_core_get_single_pdev(ab);
...@@ -1002,29 +952,29 @@ int ath11k_core_resume(struct ath11k_base *ab) ...@@ -1002,29 +952,29 @@ int ath11k_core_resume(struct ath11k_base *ab)
if (!ar || ar->state != ATH11K_STATE_OFF) if (!ar || ar->state != ATH11K_STATE_OFF)
return 0; return 0;
time_left = wait_for_completion_timeout(&ab->restart_completed, ret = ath11k_hif_resume(ab);
ATH11K_RESET_TIMEOUT_HZ); if (ret) {
if (time_left == 0) { ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
ath11k_warn(ab, "timeout while waiting for restart complete"); return ret;
return -ETIMEDOUT;
} }
if (ab->hw_params.current_cc_support && ath11k_hif_ce_irq_enable(ab);
ar->alpha2[0] != 0 && ar->alpha2[1] != 0) { ath11k_hif_irq_enable(ab);
ret = ath11k_reg_set_cc(ar);
if (ret) {
ath11k_warn(ab, "failed to set country code during resume: %d\n",
ret);
return ret;
}
}
ret = ath11k_dp_rx_pktlog_start(ab); ret = ath11k_dp_rx_pktlog_start(ab);
if (ret) if (ret) {
ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n", ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",
ret); ret);
return ret;
}
return ret; ret = ath11k_wow_wakeup(ab);
if (ret) {
ath11k_warn(ab, "failed to wakeup wow during resume: %d\n", ret);
return ret;
}
return 0;
} }
EXPORT_SYMBOL(ath11k_core_resume); EXPORT_SYMBOL(ath11k_core_resume);
...@@ -2119,8 +2069,6 @@ static void ath11k_core_restart(struct work_struct *work) ...@@ -2119,8 +2069,6 @@ static void ath11k_core_restart(struct work_struct *work)
if (!ab->is_reset) if (!ab->is_reset)
ath11k_core_post_reconfigure_recovery(ab); ath11k_core_post_reconfigure_recovery(ab);
complete(&ab->restart_completed);
} }
static void ath11k_core_reset(struct work_struct *work) static void ath11k_core_reset(struct work_struct *work)
...@@ -2190,7 +2138,7 @@ static void ath11k_core_reset(struct work_struct *work) ...@@ -2190,7 +2138,7 @@ static void ath11k_core_reset(struct work_struct *work)
ath11k_hif_irq_disable(ab); ath11k_hif_irq_disable(ab);
ath11k_hif_ce_irq_disable(ab); ath11k_hif_ce_irq_disable(ab);
ath11k_hif_power_down(ab, false); ath11k_hif_power_down(ab);
ath11k_hif_power_up(ab); ath11k_hif_power_up(ab);
ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n"); ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
...@@ -2263,7 +2211,7 @@ void ath11k_core_deinit(struct ath11k_base *ab) ...@@ -2263,7 +2211,7 @@ void ath11k_core_deinit(struct ath11k_base *ab)
mutex_unlock(&ab->core_lock); mutex_unlock(&ab->core_lock);
ath11k_hif_power_down(ab, false); ath11k_hif_power_down(ab);
ath11k_mac_destroy(ab); ath11k_mac_destroy(ab);
ath11k_core_soc_destroy(ab); ath11k_core_soc_destroy(ab);
ath11k_fw_destroy(ab); ath11k_fw_destroy(ab);
...@@ -2316,7 +2264,6 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, ...@@ -2316,7 +2264,6 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0); timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
init_completion(&ab->htc_suspend); init_completion(&ab->htc_suspend);
init_completion(&ab->wow.wakeup_completed); init_completion(&ab->wow.wakeup_completed);
init_completion(&ab->restart_completed);
ab->dev = dev; ab->dev = dev;
ab->hif.bus = bus; ab->hif.bus = bus;
......
...@@ -1036,8 +1036,6 @@ struct ath11k_base { ...@@ -1036,8 +1036,6 @@ struct ath11k_base {
DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT); DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT);
} fw; } fw;
struct completion restart_completed;
#ifdef CONFIG_NL80211_TESTMODE #ifdef CONFIG_NL80211_TESTMODE
struct { struct {
u32 data_pos; u32 data_pos;
...@@ -1237,10 +1235,8 @@ void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd); ...@@ -1237,10 +1235,8 @@ void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
int ath11k_core_check_dt(struct ath11k_base *ath11k); int ath11k_core_check_dt(struct ath11k_base *ath11k);
int ath11k_core_check_smbios(struct ath11k_base *ab); int ath11k_core_check_smbios(struct ath11k_base *ab);
void ath11k_core_halt(struct ath11k *ar); void ath11k_core_halt(struct ath11k *ar);
int ath11k_core_resume_early(struct ath11k_base *ab);
int ath11k_core_resume(struct ath11k_base *ab); int ath11k_core_resume(struct ath11k_base *ab);
int ath11k_core_suspend(struct ath11k_base *ab); int ath11k_core_suspend(struct ath11k_base *ab);
int ath11k_core_suspend_late(struct ath11k_base *ab);
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab); void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab); bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab);
......
...@@ -18,7 +18,7 @@ struct ath11k_hif_ops { ...@@ -18,7 +18,7 @@ struct ath11k_hif_ops {
int (*start)(struct ath11k_base *ab); int (*start)(struct ath11k_base *ab);
void (*stop)(struct ath11k_base *ab); void (*stop)(struct ath11k_base *ab);
int (*power_up)(struct ath11k_base *ab); int (*power_up)(struct ath11k_base *ab);
void (*power_down)(struct ath11k_base *ab, bool is_suspend); void (*power_down)(struct ath11k_base *ab);
int (*suspend)(struct ath11k_base *ab); int (*suspend)(struct ath11k_base *ab);
int (*resume)(struct ath11k_base *ab); int (*resume)(struct ath11k_base *ab);
int (*map_service_to_pipe)(struct ath11k_base *ab, u16 service_id, int (*map_service_to_pipe)(struct ath11k_base *ab, u16 service_id,
...@@ -67,18 +67,12 @@ static inline void ath11k_hif_irq_disable(struct ath11k_base *ab) ...@@ -67,18 +67,12 @@ static inline void ath11k_hif_irq_disable(struct ath11k_base *ab)
static inline int ath11k_hif_power_up(struct ath11k_base *ab) static inline int ath11k_hif_power_up(struct ath11k_base *ab)
{ {
if (!ab->hif.ops->power_up)
return -EOPNOTSUPP;
return ab->hif.ops->power_up(ab); return ab->hif.ops->power_up(ab);
} }
static inline void ath11k_hif_power_down(struct ath11k_base *ab, bool is_suspend) static inline void ath11k_hif_power_down(struct ath11k_base *ab)
{ {
if (!ab->hif.ops->power_down) ab->hif.ops->power_down(ab);
return;
ab->hif.ops->power_down(ab, is_suspend);
} }
static inline int ath11k_hif_suspend(struct ath11k_base *ab) static inline int ath11k_hif_suspend(struct ath11k_base *ab)
......
...@@ -7900,6 +7900,7 @@ static void ath11k_mac_parse_tx_pwr_env(struct ath11k *ar, ...@@ -7900,6 +7900,7 @@ static void ath11k_mac_parse_tx_pwr_env(struct ath11k *ar,
} }
if (psd) { if (psd) {
arvif->reg_tpc_info.is_psd_power = true;
arvif->reg_tpc_info.num_pwr_levels = psd->count; arvif->reg_tpc_info.num_pwr_levels = psd->count;
for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++) { for (i = 0; i < arvif->reg_tpc_info.num_pwr_levels; i++) {
......
...@@ -453,17 +453,9 @@ int ath11k_mhi_start(struct ath11k_pci *ab_pci) ...@@ -453,17 +453,9 @@ int ath11k_mhi_start(struct ath11k_pci *ab_pci)
return 0; return 0;
} }
void ath11k_mhi_stop(struct ath11k_pci *ab_pci, bool is_suspend) void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
{ {
/* During suspend we need to use mhi_power_down_keep_dev() mhi_power_down(ab_pci->mhi_ctrl, true);
* workaround, otherwise ath11k_core_resume() will timeout
* during resume.
*/
if (is_suspend)
mhi_power_down_keep_dev(ab_pci->mhi_ctrl, true);
else
mhi_power_down(ab_pci->mhi_ctrl, true);
mhi_unprepare_after_power_down(ab_pci->mhi_ctrl); mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#define MHICTRL_RESET_MASK 0x2 #define MHICTRL_RESET_MASK 0x2
int ath11k_mhi_start(struct ath11k_pci *ar_pci); int ath11k_mhi_start(struct ath11k_pci *ar_pci);
void ath11k_mhi_stop(struct ath11k_pci *ar_pci, bool is_suspend); void ath11k_mhi_stop(struct ath11k_pci *ar_pci);
int ath11k_mhi_register(struct ath11k_pci *ar_pci); int ath11k_mhi_register(struct ath11k_pci *ar_pci);
void ath11k_mhi_unregister(struct ath11k_pci *ar_pci); void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);
void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab); void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab);
...@@ -26,4 +26,5 @@ void ath11k_mhi_clear_vector(struct ath11k_base *ab); ...@@ -26,4 +26,5 @@ void ath11k_mhi_clear_vector(struct ath11k_base *ab);
int ath11k_mhi_suspend(struct ath11k_pci *ar_pci); int ath11k_mhi_suspend(struct ath11k_pci *ar_pci);
int ath11k_mhi_resume(struct ath11k_pci *ar_pci); int ath11k_mhi_resume(struct ath11k_pci *ar_pci);
#endif #endif
...@@ -638,7 +638,7 @@ static int ath11k_pci_power_up(struct ath11k_base *ab) ...@@ -638,7 +638,7 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
return 0; return 0;
} }
static void ath11k_pci_power_down(struct ath11k_base *ab, bool is_suspend) static void ath11k_pci_power_down(struct ath11k_base *ab)
{ {
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
...@@ -649,7 +649,7 @@ static void ath11k_pci_power_down(struct ath11k_base *ab, bool is_suspend) ...@@ -649,7 +649,7 @@ static void ath11k_pci_power_down(struct ath11k_base *ab, bool is_suspend)
ath11k_pci_msi_disable(ab_pci); ath11k_pci_msi_disable(ab_pci);
ath11k_mhi_stop(ab_pci, is_suspend); ath11k_mhi_stop(ab_pci);
clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags); clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, &ab->dev_flags);
ath11k_pci_sw_reset(ab_pci->ab, false); ath11k_pci_sw_reset(ab_pci->ab, false);
} }
...@@ -970,7 +970,7 @@ static void ath11k_pci_remove(struct pci_dev *pdev) ...@@ -970,7 +970,7 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) {
ath11k_pci_power_down(ab, false); ath11k_pci_power_down(ab);
ath11k_debugfs_soc_destroy(ab); ath11k_debugfs_soc_destroy(ab);
ath11k_qmi_deinit_service(ab); ath11k_qmi_deinit_service(ab);
goto qmi_fail; goto qmi_fail;
...@@ -998,7 +998,7 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev) ...@@ -998,7 +998,7 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL); ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
ath11k_pci_power_down(ab, false); ath11k_pci_power_down(ab);
} }
static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev) static __maybe_unused int ath11k_pci_pm_suspend(struct device *dev)
...@@ -1035,39 +1035,9 @@ static __maybe_unused int ath11k_pci_pm_resume(struct device *dev) ...@@ -1035,39 +1035,9 @@ static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
return ret; return ret;
} }
static __maybe_unused int ath11k_pci_pm_suspend_late(struct device *dev) static SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
{ ath11k_pci_pm_suspend,
struct ath11k_base *ab = dev_get_drvdata(dev); ath11k_pci_pm_resume);
int ret;
ret = ath11k_core_suspend_late(ab);
if (ret)
ath11k_warn(ab, "failed to late suspend core: %d\n", ret);
/* Similar to ath11k_pci_pm_suspend(), we return success here
* even error happens, to allow system suspend/hibernation survive.
*/
return 0;
}
static __maybe_unused int ath11k_pci_pm_resume_early(struct device *dev)
{
struct ath11k_base *ab = dev_get_drvdata(dev);
int ret;
ret = ath11k_core_resume_early(ab);
if (ret)
ath11k_warn(ab, "failed to early resume core: %d\n", ret);
return ret;
}
static const struct dev_pm_ops __maybe_unused ath11k_pci_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ath11k_pci_pm_suspend,
ath11k_pci_pm_resume)
SET_LATE_SYSTEM_SLEEP_PM_OPS(ath11k_pci_pm_suspend_late,
ath11k_pci_pm_resume_early)
};
static struct pci_driver ath11k_pci_driver = { static struct pci_driver ath11k_pci_driver = {
.name = "ath11k_pci", .name = "ath11k_pci",
......
...@@ -2877,7 +2877,7 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab) ...@@ -2877,7 +2877,7 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
} }
/* reset the firmware */ /* reset the firmware */
ath11k_hif_power_down(ab, false); ath11k_hif_power_down(ab);
ath11k_hif_power_up(ab); ath11k_hif_power_up(ab);
ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n"); ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n");
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment