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

Commit 4cf677fd authored by Emmanuel Grumbach's avatar Emmanuel Grumbach
Browse files

iwlwifi: allow to define the stuck queue timer per queue



Different queue can have different behavior. While it can be
unacceptable for a certain queue to be stuck for 2 seconds
(e.g. the command queue), it can happen that another queue
will stay stuck for even longer (a queue servicing a power
saving client in GO).
The op_mode can even make the timeout be a function of the
listen interval.

Reviewed-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent ce71c2f7
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1228,7 +1228,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
	trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
	trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
	trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
	trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
	trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED;

	trans_cfg.command_names = iwl_dvm_cmd_strings;
	trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM;

+1 −1
Original line number Diff line number Diff line
@@ -715,7 +715,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
	fifo = ctx->ac_to_fifo[tid_to_ac[tid]];

	iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid,
			     buf_size, ssn);
			     buf_size, ssn, 0);

	/*
	 * If the limit is 0, then it wasn't initialised yet,
+1 −1
Original line number Diff line number Diff line
@@ -267,7 +267,7 @@ static int iwl_alive_notify(struct iwl_priv *priv)
	for (i = 0; i < n_queues; i++)
		if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED)
			iwl_trans_ac_txq_enable(priv->trans, i,
						queue_to_txf[i]);
						queue_to_txf[i], 0);

	priv->passive_no_rx = false;
	priv->transport_queue_stop = 0;
+1 −1
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ enum iwl_led_mode {

/* TX queue watchdog timeouts in mSecs */
#define IWL_WATCHDOG_DISABLED	0
#define IWL_DEF_WD_TIMEOUT	2000
#define IWL_DEF_WD_TIMEOUT	2500
#define IWL_LONG_WD_TIMEOUT	10000
#define IWL_MAX_WD_TIMEOUT	120000

+16 −13
Original line number Diff line number Diff line
@@ -368,6 +368,7 @@ enum iwl_trans_status {
 * @cmd_queue: the index of the command queue.
 *	Must be set before start_fw.
 * @cmd_fifo: the fifo for host commands
 * @cmd_q_wdg_timeout: the timeout of the watchdog timer for the command queue.
 * @no_reclaim_cmds: Some devices erroneously don't set the
 *	SEQ_RX_FRAME bit on some notifications, this is the
 *	list of such notifications to filter. Max length is
@@ -378,8 +379,6 @@ enum iwl_trans_status {
 * @bc_table_dword: set to true if the BC table expects the byte count to be
 *	in DWORD (as opposed to bytes)
 * @scd_set_active: should the transport configure the SCD for HCMD queue
 * @queue_watchdog_timeout: time (in ms) after which queues
 *	are considered stuck and will trigger device restart
 * @command_names: array of command names, must be 256 entries
 *	(one for each command); for debugging only
 * @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until
@@ -390,13 +389,13 @@ struct iwl_trans_config {

	u8 cmd_queue;
	u8 cmd_fifo;
	unsigned int cmd_q_wdg_timeout;
	const u8 *no_reclaim_cmds;
	unsigned int n_no_reclaim_cmds;

	bool rx_buf_size_8k;
	bool bc_table_dword;
	bool scd_set_active;
	unsigned int queue_watchdog_timeout;
	const char *const *command_names;

	u32 sdio_adma_addr;
@@ -511,7 +510,8 @@ struct iwl_trans_ops {
			struct sk_buff_head *skbs);

	void (*txq_enable)(struct iwl_trans *trans, int queue, u16 ssn,
			   const struct iwl_trans_txq_scd_cfg *cfg);
			   const struct iwl_trans_txq_scd_cfg *cfg,
			   unsigned int queue_wdg_timeout);
	void (*txq_disable)(struct iwl_trans *trans, int queue,
			    bool configure_scd);

@@ -829,19 +829,21 @@ static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue,

static inline void
iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
			 const struct iwl_trans_txq_scd_cfg *cfg)
			 const struct iwl_trans_txq_scd_cfg *cfg,
			 unsigned int queue_wdg_timeout)
{
	might_sleep();

	if (unlikely((trans->state != IWL_TRANS_FW_ALIVE)))
		IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);

	trans->ops->txq_enable(trans, queue, ssn, cfg);
	trans->ops->txq_enable(trans, queue, ssn, cfg, queue_wdg_timeout);
}

static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
					int fifo, int sta_id, int tid,
					int frame_limit, u16 ssn)
					int frame_limit, u16 ssn,
					unsigned int queue_wdg_timeout)
{
	struct iwl_trans_txq_scd_cfg cfg = {
		.fifo = fifo,
@@ -851,11 +853,12 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
		.aggregate = sta_id >= 0,
	};

	iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg);
	iwl_trans_txq_enable_cfg(trans, queue, ssn, &cfg, queue_wdg_timeout);
}

static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
					   int fifo)
static inline
void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue, int fifo,
			     unsigned int queue_wdg_timeout)
{
	struct iwl_trans_txq_scd_cfg cfg = {
		.fifo = fifo,
@@ -865,16 +868,16 @@ static inline void iwl_trans_ac_txq_enable(struct iwl_trans *trans, int queue,
		.aggregate = false,
	};

	iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg);
	iwl_trans_txq_enable_cfg(trans, queue, 0, &cfg, queue_wdg_timeout);
}

static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
						u32 txq_bm)
						u32 txqs)
{
	if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
		IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);

	return trans->ops->wait_tx_queue_empty(trans, txq_bm);
	return trans->ops->wait_tx_queue_empty(trans, txqs);
}

static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
Loading