wifi: iwlwifi: mei: make sure ownership confirmed message is sent

[ Upstream commit 5aa7ce31bd ]

It is possible that CSME will try to take ownership while the driver
is stopping. In this case, if the CSME takes ownership message arrives
after the driver started unregistering, the iwl_mei_cache->ops is
already invalid, so the host will not answer with the ownership
confirmed message.
Similarly, if the take ownership message arrived after the mac was
stopped or when iwl_mvm_up() failed, setting rfkill will not trigger
sending the confirm message. As a result, CSME will not take
ownership, which will result in a disconnection.

Fix it by sending the ownership confirmed message immediately in such
cases.

Fixes: 2da4366f9e ("iwlwifi: mei: add the driver to allow cooperation with CSME")
Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20221030191011.b2a4c009e3e6.I7f931b7ee8b168e8ac88b11f23bff98b7ed3cb19@changeid
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Avraham Stern
2022-10-30 19:17:41 +02:00
committed by Greg Kroah-Hartman
parent 61dd45b01b
commit 39138cee7a
5 changed files with 29 additions and 16 deletions

View File

@@ -446,9 +446,10 @@ void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_info,
void iwl_mei_host_disassociated(void);
/**
* iwl_mei_device_down() - must be called when the device is down
* iwl_mei_device_state() - must be called when the device changes up/down state
* @up: true if the device is up, false otherwise.
*/
void iwl_mei_device_down(void);
void iwl_mei_device_state(bool up);
#else
@@ -497,7 +498,7 @@ static inline void iwl_mei_host_associated(const struct iwl_mei_conn_info *conn_
static inline void iwl_mei_host_disassociated(void)
{}
static inline void iwl_mei_device_down(void)
static inline void iwl_mei_device_state(bool up)
{}
#endif /* CONFIG_IWLMEI */

View File

@@ -147,6 +147,8 @@ struct iwl_mei_filters {
* to send CSME_OWNERSHIP_CONFIRMED when the driver completes its down
* flow.
* @link_prot_state: true when we are in link protection PASSIVE
* @device_down: true if the device is down. Used to remember to send
* CSME_OWNERSHIP_CONFIRMED when the driver is already down.
* @csa_throttle_end_wk: used when &csa_throttled is true
* @data_q_lock: protects the access to the data queues which are
* accessed without the mutex.
@@ -167,6 +169,7 @@ struct iwl_mei {
bool csa_throttled;
bool csme_taking_ownership;
bool link_prot_state;
bool device_down;
struct delayed_work csa_throttle_end_wk;
spinlock_t data_q_lock;
@@ -798,14 +801,18 @@ static void iwl_mei_handle_csme_taking_ownership(struct mei_cl_device *cldev,
mei->got_ownership = false;
/*
* Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi driver
* is finished taking the device down.
*/
mei->csme_taking_ownership = true;
if (iwl_mei_cache.ops && !mei->device_down) {
/*
* Remember to send CSME_OWNERSHIP_CONFIRMED when the wifi
* driver is finished taking the device down.
*/
mei->csme_taking_ownership = true;
if (iwl_mei_cache.ops)
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true);
iwl_mei_cache.ops->rfkill(iwl_mei_cache.priv, true, true);
} else {
iwl_mei_send_sap_msg(cldev,
SAP_MSG_NOTIF_CSME_OWNERSHIP_CONFIRMED);
}
}
static void iwl_mei_handle_nvm(struct mei_cl_device *cldev,
@@ -1616,7 +1623,7 @@ out:
}
EXPORT_SYMBOL_GPL(iwl_mei_set_netdev);
void iwl_mei_device_down(void)
void iwl_mei_device_state(bool up)
{
struct iwl_mei *mei;
@@ -1630,7 +1637,9 @@ void iwl_mei_device_down(void)
if (!mei)
goto out;
if (!mei->csme_taking_ownership)
mei->device_down = !up;
if (up || !mei->csme_taking_ownership)
goto out;
iwl_mei_send_sap_msg(mei->cldev,
@@ -1639,7 +1648,7 @@ void iwl_mei_device_down(void)
out:
mutex_unlock(&iwl_mei_mutex);
}
EXPORT_SYMBOL_GPL(iwl_mei_device_down);
EXPORT_SYMBOL_GPL(iwl_mei_device_state);
int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops)
{
@@ -1821,6 +1830,7 @@ static int iwl_mei_probe(struct mei_cl_device *cldev,
mei_cldev_set_drvdata(cldev, mei);
mei->cldev = cldev;
mei->device_down = true;
do {
ret = iwl_mei_alloc_shared_mem(cldev);

View File

@@ -1665,6 +1665,8 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
iwl_rfi_send_config_cmd(mvm, NULL);
}
iwl_mvm_mei_device_state(mvm, true);
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
return 0;
error:

View File

@@ -2201,10 +2201,10 @@ static inline void iwl_mvm_mei_host_disassociated(struct iwl_mvm *mvm)
iwl_mei_host_disassociated();
}
static inline void iwl_mvm_mei_device_down(struct iwl_mvm *mvm)
static inline void iwl_mvm_mei_device_state(struct iwl_mvm *mvm, bool up)
{
if (mvm->mei_registered)
iwl_mei_device_down();
iwl_mei_device_state(up);
}
static inline void iwl_mvm_mei_set_sw_rfkill_state(struct iwl_mvm *mvm)

View File

@@ -1375,7 +1375,7 @@ void iwl_mvm_stop_device(struct iwl_mvm *mvm)
iwl_trans_stop_device(mvm->trans);
iwl_free_fw_paging(&mvm->fwrt);
iwl_fw_dump_conf_clear(&mvm->fwrt);
iwl_mvm_mei_device_down(mvm);
iwl_mvm_mei_device_state(mvm, false);
}
static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)