Our binding handling for P2P-Device can run into the following
scenario, as observed by our testing:
- a station interface is connected on some channel
- the P2P-Device does a remain-on-channel (ROC) on that channel
- the ROC ends, and the P2P-Device is removed from the binding,
but the phy_ctxt pointer is left around as a PHY cache so we
don't need to recalibrate to the channel again and again in
case it's not shared
- a binding update by the station interface, even a removal,
will re-add the P2P-Device to the binding
- the P2P-Device is removed, which removes the PHY context, but
it's still in the binding so the firmware crashes
Since the P2P device is removed from the binding and only re-
added by unrelated code, but we want to keep the phy_ctxt around
as a cache for future ROC usage, fix it by adding a boolean that
indicates whether or not the P2P-Device should be added to the
binding, and handle that in the binding iterator. That way, the
station interface cannot re-add the P2P-Device to the binding
when that isn't active.
Assisted-by: Github Copilot:claude-opus-4-6
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20260527230313.07f94335ae06.I384238b0859343c4a9a9dda20682be1aad89cc9d@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
/*
* Copyright (C) 2012-2014, 2020 Intel Corporation
* Copyright (C) 2016 Intel Deutschland GmbH
- * Copyright (C) 2022, 2024 Intel Corporation
+ * Copyright (C) 2022, 2024, 2026 Intel Corporation
*/
#include <net/mac80211.h>
#include "fw-api.h"
if (vif == data->ignore_vif)
return;
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE && !mvmvif->p2p_in_binding)
+ return;
+
if (mvmvif->deflink.phy_ctxt != data->phyctxt)
return;
spin_unlock_bh(&mvm->time_event_lock);
mvmvif->roc_activity = ROC_NUM_ACTIVITIES;
+ mvmvif->p2p_in_binding = false;
mvmvif->bf_enabled = false;
mvmvif->ba_enabled = false;
static int iwl_mvm_roc_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
lockdep_assert_held(&mvm->mutex);
if (WARN(ret, "Failed binding P2P_DEVICE\n"))
return ret;
+ mvmvif->p2p_in_binding = true;
+
/* The station and queue allocation must be done only after the binding
* is done, as otherwise the FW might incorrectly configure its state.
*/
- return iwl_mvm_add_p2p_bcast_sta(mvm, vif);
+ ret = iwl_mvm_add_p2p_bcast_sta(mvm, vif);
+ if (ret) {
+ iwl_mvm_binding_remove_vif(mvm, vif);
+ mvmvif->p2p_in_binding = false;
+ }
+
+ return ret;
}
static int iwl_mvm_roc(struct ieee80211_hw *hw,
* @pm_enabled: indicates powersave is enabled
* @roc_activity: currently running ROC activity for this vif (or
* ROC_NUM_ACTIVITIES if no activity is running).
+ * @p2p_in_binding: indicates that this P2P-Device interface should be
+ * added to the binding, i.e. is running ROC right now
* @session_prot_connection_loss: the connection was lost due to session
* protection ending without receiving a beacon, so we need to now
* protect the deauth separately
struct iwl_mvm_time_event_data time_event_data;
struct iwl_mvm_time_event_data hs_time_event_data;
enum iwl_roc_activity roc_activity;
+ bool p2p_in_binding;
/* TCP Checksum Offload */
netdev_features_t features;
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2012-2014, 2018-2025 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
*/
} else {
iwl_mvm_rm_p2p_bcast_sta(mvm, vif);
iwl_mvm_binding_remove_vif(mvm, vif);
+ mvmvif->p2p_in_binding = false;
}
/* Do not remove the PHY context as removing and adding