mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 05:32:00 +00:00
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. -----BEGIN PGP SIGNATURE----- iQFFBAABCgAvFiEEiBjanGPFTz4PRfLobhckVSbrbZsFAmbYZsIRHGt2YWxvQGtl cm5lbC5vcmcACgkQbhckVSbrbZvwbAf/XhgO7uKuZnGfq6NBfyLIaXQjHRe6OSc0 /EJ+c9J3DK5vQUHcw2ALrBYtKPJIrgLIzMG+u4N/4klxLwWCzZpsMLTqNvUV4VRe eKdD9v/0dZnrKrpmQxgtEoImc028gC5c2K9jDK4e9MU/kBMln9PpH3xyasnV9aLj 2ajkO7xdLooTJ4cdZtdDL9fd5px7IdghNgHiY+24lfuPY2AZV5AUK/AUHZw3CG6K nXk6+PEO1Xr2P3SAc5yRYg4vXJIy7g8ELAGUj8f3XznvYKpcO+afce8By+H6GecQ ofsWSLO86ajgu3wMMxyWhXFs8TAsyeE8fLJgNBqIfC05i1IkGfYwBg== =C23H -----END PGP SIGNATURE----- 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.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
2603d3152b
@ -5953,6 +5953,7 @@ F: Documentation/process/cve.rst
|
||||
CW1200 WLAN driver
|
||||
S: Orphan
|
||||
F: drivers/net/wireless/st/cw1200/
|
||||
F: include/linux/platform_data/net-cw1200.h
|
||||
|
||||
CX18 VIDEO4LINUX DRIVER
|
||||
M: Andy Walls <awalls@md.metrocast.net>
|
||||
|
@ -413,7 +413,7 @@ static int ath11k_ahb_power_up(struct ath11k_base *ab)
|
||||
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);
|
||||
|
||||
@ -1280,7 +1280,7 @@ static void ath11k_ahb_remove(struct platform_device *pdev)
|
||||
struct ath11k_base *ab = platform_get_drvdata(pdev);
|
||||
|
||||
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_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
|
@ -906,6 +906,12 @@ int ath11k_core_suspend(struct ath11k_base *ab)
|
||||
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);
|
||||
if (ret) {
|
||||
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)
|
||||
ath11k_ce_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);
|
||||
ath11k_hif_irq_disable(ab);
|
||||
ath11k_hif_ce_irq_disable(ab);
|
||||
|
||||
ret = ath11k_hif_suspend(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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_ce_irq_disable(ab);
|
||||
|
||||
ath11k_hif_power_down(ab, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_suspend_late);
|
||||
|
||||
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 ret;
|
||||
struct ath11k_pdev *pdev;
|
||||
struct ath11k *ar;
|
||||
long time_left;
|
||||
|
||||
if (!ab->hw_params.supports_suspend)
|
||||
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.
|
||||
*/
|
||||
pdev = ath11k_core_get_single_pdev(ab);
|
||||
@ -1002,29 +952,29 @@ int ath11k_core_resume(struct ath11k_base *ab)
|
||||
if (!ar || ar->state != ATH11K_STATE_OFF)
|
||||
return 0;
|
||||
|
||||
time_left = wait_for_completion_timeout(&ab->restart_completed,
|
||||
ATH11K_RESET_TIMEOUT_HZ);
|
||||
if (time_left == 0) {
|
||||
ath11k_warn(ab, "timeout while waiting for restart complete");
|
||||
return -ETIMEDOUT;
|
||||
ret = ath11k_hif_resume(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ab->hw_params.current_cc_support &&
|
||||
ar->alpha2[0] != 0 && ar->alpha2[1] != 0) {
|
||||
ret = ath11k_reg_set_cc(ar);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set country code during resume: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ath11k_hif_ce_irq_enable(ab);
|
||||
ath11k_hif_irq_enable(ab);
|
||||
|
||||
ret = ath11k_dp_rx_pktlog_start(ab);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",
|
||||
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);
|
||||
|
||||
@ -2119,8 +2069,6 @@ static void ath11k_core_restart(struct work_struct *work)
|
||||
|
||||
if (!ab->is_reset)
|
||||
ath11k_core_post_reconfigure_recovery(ab);
|
||||
|
||||
complete(&ab->restart_completed);
|
||||
}
|
||||
|
||||
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_ce_irq_disable(ab);
|
||||
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_up(ab);
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");
|
||||
@ -2263,7 +2211,7 @@ void ath11k_core_deinit(struct ath11k_base *ab)
|
||||
|
||||
mutex_unlock(&ab->core_lock);
|
||||
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_mac_destroy(ab);
|
||||
ath11k_core_soc_destroy(ab);
|
||||
ath11k_fw_destroy(ab);
|
||||
@ -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);
|
||||
init_completion(&ab->htc_suspend);
|
||||
init_completion(&ab->wow.wakeup_completed);
|
||||
init_completion(&ab->restart_completed);
|
||||
|
||||
ab->dev = dev;
|
||||
ab->hif.bus = bus;
|
||||
|
@ -1036,8 +1036,6 @@ struct ath11k_base {
|
||||
DECLARE_BITMAP(fw_features, ATH11K_FW_FEATURE_COUNT);
|
||||
} fw;
|
||||
|
||||
struct completion restart_completed;
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
struct {
|
||||
u32 data_pos;
|
||||
@ -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_smbios(struct ath11k_base *ab);
|
||||
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_suspend(struct ath11k_base *ab);
|
||||
int ath11k_core_suspend_late(struct ath11k_base *ab);
|
||||
void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab);
|
||||
bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab);
|
||||
|
||||
|
@ -18,7 +18,7 @@ struct ath11k_hif_ops {
|
||||
int (*start)(struct ath11k_base *ab);
|
||||
void (*stop)(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 (*resume)(struct ath11k_base *ab);
|
||||
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)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
ab->hif.ops->power_down(ab, is_suspend);
|
||||
ab->hif.ops->power_down(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,
|
||||
}
|
||||
|
||||
if (psd) {
|
||||
arvif->reg_tpc_info.is_psd_power = true;
|
||||
arvif->reg_tpc_info.num_pwr_levels = psd->count;
|
||||
|
||||
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)
|
||||
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()
|
||||
* 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_power_down(ab_pci->mhi_ctrl, true);
|
||||
mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#define MHICTRL_RESET_MASK 0x2
|
||||
|
||||
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);
|
||||
void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);
|
||||
void ath11k_mhi_set_mhictrl_reset(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_resume(struct ath11k_pci *ar_pci);
|
||||
|
||||
#endif
|
||||
|
@ -638,7 +638,7 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
|
||||
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);
|
||||
|
||||
@ -649,7 +649,7 @@ static void ath11k_pci_power_down(struct ath11k_base *ab, bool is_suspend)
|
||||
|
||||
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);
|
||||
ath11k_pci_sw_reset(ab_pci->ab, false);
|
||||
}
|
||||
@ -970,7 +970,7 @@ static void ath11k_pci_remove(struct pci_dev *pdev)
|
||||
ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
|
||||
|
||||
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_qmi_deinit_service(ab);
|
||||
goto qmi_fail;
|
||||
@ -998,7 +998,7 @@ static void ath11k_pci_shutdown(struct pci_dev *pdev)
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
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)
|
||||
@ -1035,39 +1035,9 @@ static __maybe_unused int ath11k_pci_pm_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __maybe_unused int ath11k_pci_pm_suspend_late(struct device *dev)
|
||||
{
|
||||
struct ath11k_base *ab = dev_get_drvdata(dev);
|
||||
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 SIMPLE_DEV_PM_OPS(ath11k_pci_pm_ops,
|
||||
ath11k_pci_pm_suspend,
|
||||
ath11k_pci_pm_resume);
|
||||
|
||||
static struct pci_driver ath11k_pci_driver = {
|
||||
.name = "ath11k_pci",
|
||||
|
@ -2877,7 +2877,7 @@ int ath11k_qmi_fwreset_from_cold_boot(struct ath11k_base *ab)
|
||||
}
|
||||
|
||||
/* reset the firmware */
|
||||
ath11k_hif_power_down(ab, false);
|
||||
ath11k_hif_power_down(ab);
|
||||
ath11k_hif_power_up(ab);
|
||||
ath11k_dbg(ab, ATH11K_DBG_QMI, "exit wait for cold boot done\n");
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user