Loading drivers/net/wireless/iwlwifi/dvm/mac80211.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -430,7 +430,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); iwl_trans_d3_suspend(priv->trans); iwl_trans_d3_suspend(priv->trans, false); goto out; goto out; Loading Loading @@ -504,7 +504,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; vif = ctx->vif; ret = iwl_trans_d3_resume(priv->trans, &d3_status); ret = iwl_trans_d3_resume(priv->trans, &d3_status, false); if (ret) if (ret) goto out_unlock; goto out_unlock; Loading drivers/net/wireless/iwlwifi/iwl-trans.h +8 −6 Original line number Original line Diff line number Diff line Loading @@ -428,8 +428,9 @@ struct iwl_trans_ops { void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*stop_device)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); void (*d3_suspend)(struct iwl_trans *trans); void (*d3_suspend)(struct iwl_trans *trans, bool test); int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status); int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, bool test); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); Loading Loading @@ -588,17 +589,18 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) trans->state = IWL_TRANS_NO_FW; trans->state = IWL_TRANS_NO_FW; } } static inline void iwl_trans_d3_suspend(struct iwl_trans *trans) static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test) { { might_sleep(); might_sleep(); trans->ops->d3_suspend(trans); trans->ops->d3_suspend(trans, test); } } static inline int iwl_trans_d3_resume(struct iwl_trans *trans, static inline int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status) enum iwl_d3_status *status, bool test) { { might_sleep(); might_sleep(); return trans->ops->d3_resume(trans, status); return trans->ops->d3_resume(trans, status, test); } } static inline int iwl_trans_send_cmd(struct iwl_trans *trans, static inline int iwl_trans_send_cmd(struct iwl_trans *trans, Loading drivers/net/wireless/iwlwifi/mvm/bt-coex.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -174,7 +174,7 @@ static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaeaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xcc00ff28), cpu_to_le32(0xcc00ff28), cpu_to_le32(0x0000aaaa), cpu_to_le32(0x0000aaaa), Loading drivers/net/wireless/iwlwifi/mvm/d3.c +139 −10 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,7 @@ #include <linux/etherdevice.h> #include <linux/etherdevice.h> #include <linux/ip.h> #include <linux/ip.h> #include <linux/fs.h> #include <net/cfg80211.h> #include <net/cfg80211.h> #include <net/ipv6.h> #include <net/ipv6.h> #include <net/tcp.h> #include <net/tcp.h> Loading Loading @@ -756,7 +757,9 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return 0; return 0; } } int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) static int __iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan, bool test) { { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_d3_iter_data suspend_iter_data = { struct iwl_d3_iter_data suspend_iter_data = { Loading @@ -769,7 +772,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; struct iwl_d3_manager_config d3_cfg_cmd = { struct iwl_d3_manager_config d3_cfg_cmd_data = { /* /* * Program the minimum sleep time to 10 seconds, as many * Program the minimum sleep time to 10 seconds, as many * platforms have issues processing a wakeup signal while * platforms have issues processing a wakeup signal while Loading @@ -777,17 +780,30 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) */ */ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), }; }; struct iwl_host_cmd d3_cfg_cmd = { .id = D3_CONFIG_CMD, .flags = CMD_SYNC | CMD_WANT_SKB, .data[0] = &d3_cfg_cmd_data, .len[0] = sizeof(d3_cfg_cmd_data), }; struct wowlan_key_data key_data = { struct wowlan_key_data key_data = { .use_rsc_tsc = false, .use_rsc_tsc = false, .tkip = &tkip_cmd, .tkip = &tkip_cmd, .use_tkip = false, .use_tkip = false, }; }; int ret, i; int ret, i; int len __maybe_unused; u16 seq; u16 seq; u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; if (WARN_ON(!wowlan)) if (!wowlan) { /* * mac80211 shouldn't get here, but for D3 test * it doesn't warrant a warning */ WARN_ON(!test); return -EINVAL; return -EINVAL; } key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); if (!key_data.rsc_tsc) if (!key_data.rsc_tsc) Loading Loading @@ -1012,14 +1028,26 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) goto out; goto out; /* must be last -- this switches firmware state */ /* must be last -- this switches firmware state */ ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); sizeof(d3_cfg_cmd), &d3_cfg_cmd); if (ret) if (ret) goto out; goto out; #ifdef CONFIG_IWLWIFI_DEBUGFS len = le32_to_cpu(d3_cfg_cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; if (len >= sizeof(u32) * 2) { mvm->d3_test_pme_ptr = le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); } else if (test) { /* in test mode we require the pointer */ ret = -EIO; goto out; } #endif iwl_free_resp(&d3_cfg_cmd); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); iwl_trans_d3_suspend(mvm->trans); iwl_trans_d3_suspend(mvm->trans, test); out: out: mvm->aux_sta.sta_id = old_aux_sta_id; mvm->aux_sta.sta_id = old_aux_sta_id; mvm_ap_sta->sta_id = old_ap_sta_id; mvm_ap_sta->sta_id = old_ap_sta_id; Loading @@ -1034,6 +1062,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) return ret; return ret; } } int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { return __iwl_mvm_suspend(hw, wowlan, false); } static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, struct ieee80211_vif *vif) struct ieee80211_vif *vif) { { Loading Loading @@ -1238,9 +1271,8 @@ static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) #endif #endif } } int iwl_mvm_resume(struct ieee80211_hw *hw) static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) { { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_d3_iter_data resume_iter_data = { struct iwl_d3_iter_data resume_iter_data = { .mvm = mvm, .mvm = mvm, }; }; Loading @@ -1260,7 +1292,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) vif = resume_iter_data.vif; vif = resume_iter_data.vif; ret = iwl_trans_d3_resume(mvm->trans, &d3_status); ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); if (ret) if (ret) goto out_unlock; goto out_unlock; Loading @@ -1277,7 +1309,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) out_unlock: out_unlock: mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex); if (vif) if (!test && vif) ieee80211_resume_disconnect(vif); ieee80211_resume_disconnect(vif); /* return 1 to reconfigure the device */ /* return 1 to reconfigure the device */ Loading @@ -1285,9 +1317,106 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) return 1; return 1; } } int iwl_mvm_resume(struct ieee80211_hw *hw) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); return __iwl_mvm_resume(mvm, false); } void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled) void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled) { { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); device_set_wakeup_enable(mvm->trans->dev, enabled); device_set_wakeup_enable(mvm->trans->dev, enabled); } } #ifdef CONFIG_IWLWIFI_DEBUGFS static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) { struct iwl_mvm *mvm = inode->i_private; int err; if (mvm->d3_test_active) return -EBUSY; file->private_data = inode->i_private; ieee80211_stop_queues(mvm->hw); synchronize_net(); /* start pseudo D3 */ rtnl_lock(); err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); rtnl_unlock(); if (err > 0) err = -EINVAL; if (err) { ieee80211_wake_queues(mvm->hw); return err; } mvm->d3_test_active = true; return 0; } static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_mvm *mvm = file->private_data; u32 pme_asserted; while (true) { pme_asserted = iwl_trans_read_mem32(mvm->trans, mvm->d3_test_pme_ptr); if (pme_asserted) break; if (msleep_interruptible(100)) break; } return 0; } static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { if (vif->type == NL80211_IFTYPE_STATION) ieee80211_connection_loss(vif); } static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) { struct iwl_mvm *mvm = inode->i_private; int remaining_time = 10; mvm->d3_test_active = false; __iwl_mvm_resume(mvm, true); iwl_abort_notification_waits(&mvm->notif_wait); ieee80211_restart_hw(mvm->hw); /* wait for restart and disconnect all interfaces */ while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && remaining_time > 0) { remaining_time--; msleep(1000); } if (remaining_time == 0) IWL_ERR(mvm, "Timed out waiting for HW restart to finish!\n"); ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_d3_test_disconn_work_iter, NULL); ieee80211_wake_queues(mvm->hw); return 0; } const struct file_operations iwl_dbgfs_d3_test_ops = { .llseek = no_llseek, .open = iwl_mvm_d3_test_open, .read = iwl_mvm_d3_test_read, .release = iwl_mvm_d3_test_release, }; #endif drivers/net/wireless/iwlwifi/mvm/debugfs.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -938,6 +938,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); #ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); #endif #endif /* /* Loading Loading
drivers/net/wireless/iwlwifi/dvm/mac80211.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -430,7 +430,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); iwl_trans_d3_suspend(priv->trans); iwl_trans_d3_suspend(priv->trans, false); goto out; goto out; Loading Loading @@ -504,7 +504,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; vif = ctx->vif; ret = iwl_trans_d3_resume(priv->trans, &d3_status); ret = iwl_trans_d3_resume(priv->trans, &d3_status, false); if (ret) if (ret) goto out_unlock; goto out_unlock; Loading
drivers/net/wireless/iwlwifi/iwl-trans.h +8 −6 Original line number Original line Diff line number Diff line Loading @@ -428,8 +428,9 @@ struct iwl_trans_ops { void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*stop_device)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans); void (*d3_suspend)(struct iwl_trans *trans); void (*d3_suspend)(struct iwl_trans *trans, bool test); int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status); int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, bool test); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); Loading Loading @@ -588,17 +589,18 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) trans->state = IWL_TRANS_NO_FW; trans->state = IWL_TRANS_NO_FW; } } static inline void iwl_trans_d3_suspend(struct iwl_trans *trans) static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test) { { might_sleep(); might_sleep(); trans->ops->d3_suspend(trans); trans->ops->d3_suspend(trans, test); } } static inline int iwl_trans_d3_resume(struct iwl_trans *trans, static inline int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status) enum iwl_d3_status *status, bool test) { { might_sleep(); might_sleep(); return trans->ops->d3_resume(trans, status); return trans->ops->d3_resume(trans, status, test); } } static inline int iwl_trans_send_cmd(struct iwl_trans *trans, static inline int iwl_trans_send_cmd(struct iwl_trans *trans, Loading
drivers/net/wireless/iwlwifi/mvm/bt-coex.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -174,7 +174,7 @@ static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaeaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xcc00ff28), cpu_to_le32(0xcc00ff28), cpu_to_le32(0x0000aaaa), cpu_to_le32(0x0000aaaa), Loading
drivers/net/wireless/iwlwifi/mvm/d3.c +139 −10 Original line number Original line Diff line number Diff line Loading @@ -63,6 +63,7 @@ #include <linux/etherdevice.h> #include <linux/etherdevice.h> #include <linux/ip.h> #include <linux/ip.h> #include <linux/fs.h> #include <net/cfg80211.h> #include <net/cfg80211.h> #include <net/ipv6.h> #include <net/ipv6.h> #include <net/tcp.h> #include <net/tcp.h> Loading Loading @@ -756,7 +757,9 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return 0; return 0; } } int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) static int __iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan, bool test) { { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_d3_iter_data suspend_iter_data = { struct iwl_d3_iter_data suspend_iter_data = { Loading @@ -769,7 +772,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; struct iwl_d3_manager_config d3_cfg_cmd = { struct iwl_d3_manager_config d3_cfg_cmd_data = { /* /* * Program the minimum sleep time to 10 seconds, as many * Program the minimum sleep time to 10 seconds, as many * platforms have issues processing a wakeup signal while * platforms have issues processing a wakeup signal while Loading @@ -777,17 +780,30 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) */ */ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), }; }; struct iwl_host_cmd d3_cfg_cmd = { .id = D3_CONFIG_CMD, .flags = CMD_SYNC | CMD_WANT_SKB, .data[0] = &d3_cfg_cmd_data, .len[0] = sizeof(d3_cfg_cmd_data), }; struct wowlan_key_data key_data = { struct wowlan_key_data key_data = { .use_rsc_tsc = false, .use_rsc_tsc = false, .tkip = &tkip_cmd, .tkip = &tkip_cmd, .use_tkip = false, .use_tkip = false, }; }; int ret, i; int ret, i; int len __maybe_unused; u16 seq; u16 seq; u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; u8 old_aux_sta_id, old_ap_sta_id = IWL_MVM_STATION_COUNT; if (WARN_ON(!wowlan)) if (!wowlan) { /* * mac80211 shouldn't get here, but for D3 test * it doesn't warrant a warning */ WARN_ON(!test); return -EINVAL; return -EINVAL; } key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); if (!key_data.rsc_tsc) if (!key_data.rsc_tsc) Loading Loading @@ -1012,14 +1028,26 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) goto out; goto out; /* must be last -- this switches firmware state */ /* must be last -- this switches firmware state */ ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SYNC, ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd); sizeof(d3_cfg_cmd), &d3_cfg_cmd); if (ret) if (ret) goto out; goto out; #ifdef CONFIG_IWLWIFI_DEBUGFS len = le32_to_cpu(d3_cfg_cmd.resp_pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; if (len >= sizeof(u32) * 2) { mvm->d3_test_pme_ptr = le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data); } else if (test) { /* in test mode we require the pointer */ ret = -EIO; goto out; } #endif iwl_free_resp(&d3_cfg_cmd); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); iwl_trans_d3_suspend(mvm->trans); iwl_trans_d3_suspend(mvm->trans, test); out: out: mvm->aux_sta.sta_id = old_aux_sta_id; mvm->aux_sta.sta_id = old_aux_sta_id; mvm_ap_sta->sta_id = old_ap_sta_id; mvm_ap_sta->sta_id = old_ap_sta_id; Loading @@ -1034,6 +1062,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) return ret; return ret; } } int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { return __iwl_mvm_suspend(hw, wowlan, false); } static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, struct ieee80211_vif *vif) struct ieee80211_vif *vif) { { Loading Loading @@ -1238,9 +1271,8 @@ static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm) #endif #endif } } int iwl_mvm_resume(struct ieee80211_hw *hw) static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) { { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_d3_iter_data resume_iter_data = { struct iwl_d3_iter_data resume_iter_data = { .mvm = mvm, .mvm = mvm, }; }; Loading @@ -1260,7 +1292,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) vif = resume_iter_data.vif; vif = resume_iter_data.vif; ret = iwl_trans_d3_resume(mvm->trans, &d3_status); ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); if (ret) if (ret) goto out_unlock; goto out_unlock; Loading @@ -1277,7 +1309,7 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) out_unlock: out_unlock: mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex); if (vif) if (!test && vif) ieee80211_resume_disconnect(vif); ieee80211_resume_disconnect(vif); /* return 1 to reconfigure the device */ /* return 1 to reconfigure the device */ Loading @@ -1285,9 +1317,106 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) return 1; return 1; } } int iwl_mvm_resume(struct ieee80211_hw *hw) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); return __iwl_mvm_resume(mvm, false); } void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled) void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled) { { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); device_set_wakeup_enable(mvm->trans->dev, enabled); device_set_wakeup_enable(mvm->trans->dev, enabled); } } #ifdef CONFIG_IWLWIFI_DEBUGFS static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) { struct iwl_mvm *mvm = inode->i_private; int err; if (mvm->d3_test_active) return -EBUSY; file->private_data = inode->i_private; ieee80211_stop_queues(mvm->hw); synchronize_net(); /* start pseudo D3 */ rtnl_lock(); err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); rtnl_unlock(); if (err > 0) err = -EINVAL; if (err) { ieee80211_wake_queues(mvm->hw); return err; } mvm->d3_test_active = true; return 0; } static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct iwl_mvm *mvm = file->private_data; u32 pme_asserted; while (true) { pme_asserted = iwl_trans_read_mem32(mvm->trans, mvm->d3_test_pme_ptr); if (pme_asserted) break; if (msleep_interruptible(100)) break; } return 0; } static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac, struct ieee80211_vif *vif) { if (vif->type == NL80211_IFTYPE_STATION) ieee80211_connection_loss(vif); } static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) { struct iwl_mvm *mvm = inode->i_private; int remaining_time = 10; mvm->d3_test_active = false; __iwl_mvm_resume(mvm, true); iwl_abort_notification_waits(&mvm->notif_wait); ieee80211_restart_hw(mvm->hw); /* wait for restart and disconnect all interfaces */ while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && remaining_time > 0) { remaining_time--; msleep(1000); } if (remaining_time == 0) IWL_ERR(mvm, "Timed out waiting for HW restart to finish!\n"); ieee80211_iterate_active_interfaces_atomic( mvm->hw, IEEE80211_IFACE_ITER_NORMAL, iwl_mvm_d3_test_disconn_work_iter, NULL); ieee80211_wake_queues(mvm->hw); return 0; } const struct file_operations iwl_dbgfs_d3_test_ops = { .llseek = no_llseek, .open = iwl_mvm_d3_test_open, .read = iwl_mvm_d3_test_read, .release = iwl_mvm_d3_test_release, }; #endif
drivers/net/wireless/iwlwifi/mvm/debugfs.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -938,6 +938,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, S_IWUSR); #ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(d3_sram, mvm->debugfs_dir, S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, S_IRUSR); #endif #endif /* /* Loading