summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi
diff options
context:
space:
mode:
authorAvraham Stern <avraham.stern@intel.com>2023-04-18 11:28:13 +0200
committerJohannes Berg <johannes.berg@intel.com>2023-04-20 11:45:55 +0200
commit06ce23ad57c8e378b86ef3f439b2e08bcb5d05eb (patch)
tree4386c4040439928efbe35983124684c951da5777 /drivers/net/wireless/intel/iwlwifi
parentwifi: iwlwifi: mei: make mei filtered scan more aggressive (diff)
downloadlinux-06ce23ad57c8e378b86ef3f439b2e08bcb5d05eb.tar.xz
linux-06ce23ad57c8e378b86ef3f439b2e08bcb5d05eb.zip
wifi: iwlwifi: mei: re-ask for ownership after it was taken by CSME
When the host disconnects from the AP CSME takes ownership right away. Since the driver never asks for ownership again wifi is left in rfkill until CSME releases the NIC, although in many cases the host could re-connect shortly after the disconnection. To allow the host to recover from occasional disconnection, re-ask for ownership to let the host connect again. Allow one minute before re-asking for ownership to avoid too frequent ownership transitions. Signed-off-by: Avraham Stern <avraham.stern@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230418122405.a6c6ebc48f2d.I8a17003b86e71b3567521cc69864b9cbe9553ea9@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mei/main.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c
index 67dfb77fedf7..f1e0fe806a00 100644
--- a/drivers/net/wireless/intel/iwlwifi/mei/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c
@@ -31,6 +31,11 @@ MODULE_LICENSE("GPL");
#define MEI_WLAN_UUID UUID_LE(0x13280904, 0x7792, 0x4fcb, \
0xa1, 0xaa, 0x5e, 0x70, 0xcb, 0xb1, 0xe8, 0x65)
+/* After CSME takes ownership, it won't release it for 60 seconds to avoid
+ * frequent ownership transitions.
+ */
+#define MEI_OWNERSHIP_RETAKE_TIMEOUT_MS msecs_to_jiffies(60000)
+
/*
* Since iwlwifi calls iwlmei without any context, hold a pointer to the
* mei_cl_device structure here.
@@ -156,6 +161,8 @@ struct iwl_mei_filters {
* accessed without the mutex.
* @netdev_work: used to defer registering and unregistering of the netdev to
* avoid taking the rtnl lock in the SAP messages handlers.
+ * @ownership_dwork: used to re-ask for NIC ownership after ownership was taken
+ * by CSME or when a previous ownership request failed.
* @sap_seq_no: the sequence number for the SAP messages
* @seq_no: the sequence number for the SAP messages
* @dbgfs_dir: the debugfs dir entry
@@ -179,6 +186,7 @@ struct iwl_mei {
bool pldr_active;
spinlock_t data_q_lock;
struct work_struct netdev_work;
+ struct delayed_work ownership_dwork;
atomic_t sap_seq_no;
atomic_t seq_no;
@@ -833,6 +841,8 @@ static void iwl_mei_handle_csme_taking_ownership(struct mei_cl_device *cldev,
} else {
iwl_mei_send_sap_msg(cldev,
SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED);
+ schedule_delayed_work(&mei->ownership_dwork,
+ MEI_OWNERSHIP_RETAKE_TIMEOUT_MS);
}
}
@@ -1447,7 +1457,13 @@ int iwl_mei_get_ownership(void)
ret = wait_event_timeout(mei->get_ownership_wq,
mei->got_ownership, HZ / 2);
- return (!ret) ? -ETIMEDOUT : 0;
+ if (!ret) {
+ schedule_delayed_work(&mei->ownership_dwork,
+ MEI_OWNERSHIP_RETAKE_TIMEOUT_MS);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
out:
mutex_unlock(&iwl_mei_mutex);
return ret;
@@ -1738,6 +1754,8 @@ void iwl_mei_device_state(bool up)
iwl_mei_send_sap_msg(mei->cldev,
SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED);
mei->csme_taking_ownership = false;
+ schedule_delayed_work(&mei->ownership_dwork,
+ MEI_OWNERSHIP_RETAKE_TIMEOUT_MS);
out:
mutex_unlock(&iwl_mei_mutex);
}
@@ -1894,6 +1912,11 @@ static void iwl_mei_dbgfs_unregister(struct iwl_mei *mei) {}
#endif /* CONFIG_DEBUG_FS */
+static void iwl_mei_ownership_dwork(struct work_struct *wk)
+{
+ iwl_mei_get_ownership();
+}
+
#define ALLOC_SHARED_MEM_RETRY_MAX_NUM 3
/*
@@ -1923,6 +1946,7 @@ static int iwl_mei_probe(struct mei_cl_device *cldev,
init_waitqueue_head(&mei->pldr_wq);
spin_lock_init(&mei->data_q_lock);
INIT_WORK(&mei->netdev_work, iwl_mei_netdev_work);
+ INIT_DELAYED_WORK(&mei->ownership_dwork, iwl_mei_ownership_dwork);
mei_cldev_set_drvdata(cldev, mei);
mei->cldev = cldev;
@@ -2105,6 +2129,7 @@ static void iwl_mei_remove(struct mei_cl_device *cldev)
cancel_work_sync(&mei->send_csa_msg_wk);
cancel_delayed_work_sync(&mei->csa_throttle_end_wk);
cancel_work_sync(&mei->netdev_work);
+ cancel_delayed_work_sync(&mei->ownership_dwork);
/*
* If someone waits for the ownership, let him know that we are going