Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4082843 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Emmanuel Grumbach
Browse files

iwlwifi: trans: divide stop_hw into stop_device/op_mode_leave



The stop_hw trans callback is not well defined. It is missing in many
cleanup flows and the division of labor between stop_device/stop_hw
is cumbersome. Remove stop_hw and use stop_device to perform both.
Implement this for all current transports.

PCIE needs some extra configuration the op-mode is leaving to configure
RF kill. Expose this explicitly as a new op_mode_leave trans callback.
Take the call to stop_device outside iwl_run_mvm_init_ucode, this
makes more sense and WARN when we want to run the INIT firmware while
it has run already.

Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 8b206d19
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -322,12 +322,6 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)

	flush_workqueue(priv->workqueue);

	/* User space software may expect getting rfkill changes
	 * even if interface is down, trans->down will leave the RF
	 * kill interrupt enabled
	 */
	iwl_trans_stop_hw(priv->trans, false);

	IWL_DEBUG_MAC80211(priv, "leave\n");
}

+2 −2
Original line number Diff line number Diff line
@@ -1313,7 +1313,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
	}

	/* Reset chip to save power until we load uCode during "up". */
	iwl_trans_stop_hw(priv->trans, false);
	iwl_trans_stop_device(priv->trans);

	priv->nvm_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
						  priv->eeprom_blob,
@@ -1458,7 +1458,7 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)

	dev_kfree_skb(priv->beacon_skb);

	iwl_trans_stop_hw(priv->trans, true);
	iwl_trans_op_mode_leave(priv->trans);
	ieee80211_free_hw(priv->hw);
}

+12 −13
Original line number Diff line number Diff line
@@ -100,8 +100,7 @@
 *	   start_fw
 *
 *	5) Then when finished (or reset):
 *	   stop_fw (a.k.a. stop device for the moment)
 *	   stop_hw
 *	   stop_device
 *
 *	6) Eventually, the free function will be called.
 */
@@ -361,9 +360,7 @@ struct iwl_trans;
 *
 * @start_hw: starts the HW- from that point on, the HW can send interrupts
 *	May sleep
 * @stop_hw: stops the HW- from that point on, the HW will be in low power but
 *	will still issue interrupt if the HW RF kill is triggered unless
 *	op_mode_leaving is true.
 * @op_mode_leave: Turn off the HW RF kill indication if on
 *	May sleep
 * @start_fw: allocates and inits all the resources for the transport
 *	layer. Also kick a fw image.
@@ -371,8 +368,11 @@ struct iwl_trans;
 * @fw_alive: called when the fw sends alive notification. If the fw provides
 *	the SCD base address in SRAM, then provide it here, or 0 otherwise.
 *	May sleep
 * @stop_device:stops the whole device (embedded CPU put to reset)
 *	May sleep
 * @stop_device: stops the whole device (embedded CPU put to reset) and stops
 *	the HW. From that point on, the HW will be in low power but will still
 *	issue interrupt if the HW RF kill is triggered. This callback must do
 *	the right thing and not crash even if start_hw() was called but not
 *	start_fw(). May sleep
 * @d3_suspend: put the device into the correct mode for WoWLAN during
 *	suspend. This is optional, if not implemented WoWLAN will not be
 *	supported. This callback may sleep.
@@ -418,7 +418,7 @@ struct iwl_trans;
struct iwl_trans_ops {

	int (*start_hw)(struct iwl_trans *iwl_trans);
	void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
	void (*op_mode_leave)(struct iwl_trans *iwl_trans);
	int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
			bool run_in_rfkill);
	void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
@@ -540,14 +540,13 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans)
	return trans->ops->start_hw(trans);
}

static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
				     bool op_mode_leaving)
static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans)
{
	might_sleep();

	trans->ops->stop_hw(trans, op_mode_leaving);
	if (trans->ops->op_mode_leave)
		trans->ops->op_mode_leave(trans);

	if (op_mode_leaving)
	trans->op_mode = NULL;

	trans->state = IWL_TRANS_NO_FW;
+14 −10
Original line number Diff line number Diff line
@@ -241,7 +241,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)

	lockdep_assert_held(&mvm->mutex);

	if (mvm->init_ucode_complete)
	if (WARN_ON_ONCE(mvm->init_ucode_complete))
		return 0;

	iwl_init_notification_wait(&mvm->notif_wait,
@@ -287,7 +287,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
		IWL_DEBUG_RF_KILL(mvm,
				  "jump over all phy activities due to RF kill\n");
		iwl_remove_notification(&mvm->notif_wait, &calib_wait);
		return 1;
		ret = 1;
		goto out;
	}

	/* Send TX valid antennas before triggering calibrations */
@@ -319,9 +320,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
error:
	iwl_remove_notification(&mvm->notif_wait, &calib_wait);
out:
	if (!iwlmvm_mod_params.init_dbg) {
		iwl_trans_stop_device(mvm->trans);
	} else if (!mvm->nvm_data) {
	if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
		/* we want to debug INIT and we have no NVM - fake */
		mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
					sizeof(struct ieee80211_channel) +
@@ -370,12 +369,17 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
				ret = -ERFKILL;
			goto error;
		}
		/* should stop & start HW since that INIT image just loaded */
		iwl_trans_stop_hw(mvm->trans, false);
		if (!iwlmvm_mod_params.init_dbg) {
			/*
			 * should stop and start HW since that INIT
			 * image just loaded
			 */
			iwl_trans_stop_device(mvm->trans);
			ret = iwl_trans_start_hw(mvm->trans);
			if (ret)
				return ret;
		}
	}

	if (iwlmvm_mod_params.init_dbg)
		return 0;
+0 −2
Original line number Diff line number Diff line
@@ -405,7 +405,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
	iwl_trans_stop_device(mvm->trans);
	iwl_trans_stop_hw(mvm->trans, false);

	mvm->scan_status = IWL_MVM_SCAN_NONE;

@@ -477,7 +476,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
	cancel_work_sync(&mvm->roc_done_wk);

	iwl_trans_stop_device(mvm->trans);
	iwl_trans_stop_hw(mvm->trans, false);

	iwl_mvm_async_handlers_purge(mvm);
	/* async_handlers_list is empty and will stay empty: HW is stopped */
Loading