Commit bdd37bed authored by Amitkumar Karwar's avatar Amitkumar Karwar Committed by John W. Linville
Browse files

mwifiex: improve scan delay logic during Tx traffic



Earlier scan command was postponed by 20msec multiple times to give
preference to Tx traffic until we find empty wmm queue.

There is a corner case in which wmm queue becomes empty immediately
after processing the packet(before 20msec) and there may be next
packet coming after some time. In this case we should not resume scan
operation.

We will use new flag to check Tx traffic and resume scan operation
only if there is no traffic for 200msec.

Signed-off-by: default avatarAmitkumar Karwar <akarwar@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b7525dbd
Loading
Loading
Loading
Loading
+58 −45
Original line number Diff line number Diff line
@@ -64,27 +64,25 @@ static void scan_delay_timer_fn(unsigned long data)
	struct cmd_ctrl_node *cmd_node, *tmp_node;
	unsigned long flags;

	if (!mwifiex_wmm_lists_empty(adapter)) {
	if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
		/*
		 * Abort scan operation by cancelling all pending scan
			 * command
		 * commands
		 */
		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
		list_for_each_entry_safe(cmd_node, tmp_node,
						 &adapter->scan_pending_q,
						 list) {
					 &adapter->scan_pending_q, list) {
			list_del(&cmd_node->list);
			cmd_node->wait_q_enabled = false;
			mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
		}
			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
					       flags);
		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);

		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
		adapter->scan_processing = false;
			spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock,
					       flags);
		adapter->scan_delay_cnt = 0;
		adapter->empty_tx_q_cnt = 0;
		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);

		if (priv->user_scan_cfg) {
			dev_dbg(priv->adapter->dev,
@@ -94,30 +92,44 @@ static void scan_delay_timer_fn(unsigned long data)
			kfree(priv->user_scan_cfg);
			priv->user_scan_cfg = NULL;
		}
		} else {
			/*
			 * Tx data queue is still not empty, delay scan
			 * operation further by 20msec.
			 */
			mod_timer(&priv->scan_delay_timer, jiffies +
				  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
			adapter->scan_delay_cnt++;
		goto done;
	}
		queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
	} else {

	if (!atomic_read(&priv->adapter->is_tx_received)) {
		adapter->empty_tx_q_cnt++;
		if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) {
			/*
		 * Tx data queue is empty. Get scan command from scan_pending_q
		 * and put to cmd_pending_q to resume scan operation
			 * No Tx traffic for 200msec. Get scan command from
			 * scan pending queue and put to cmd pending queue to
			 * resume scan operation
			 */
			adapter->scan_delay_cnt = 0;
			adapter->empty_tx_q_cnt = 0;
			spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
			cmd_node = list_first_entry(&adapter->scan_pending_q,
						    struct cmd_ctrl_node, list);
			list_del(&cmd_node->list);
		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
					       flags);

		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
							true);
			goto done;
		}
	} else {
		adapter->empty_tx_q_cnt = 0;
	}

	/* Delay scan operation further by 20msec */
	mod_timer(&priv->scan_delay_timer, jiffies +
		  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
	adapter->scan_delay_cnt++;

done:
	if (atomic_read(&priv->adapter->is_tx_received))
		atomic_set(&priv->adapter->is_tx_received, false);

	return;
}

/*
@@ -345,6 +357,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
	memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
	adapter->arp_filter_size = 0;
	adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
	adapter->empty_tx_q_cnt = 0;
}

/*
+3 −0
Original line number Diff line number Diff line
@@ -520,6 +520,9 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
	mwifiex_wmm_add_buf_txqueue(priv, skb);
	atomic_inc(&priv->adapter->tx_pending);

	if (priv->adapter->scan_delay_cnt)
		atomic_set(&priv->adapter->is_tx_received, true);

	if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
		mwifiex_set_trans_start(dev);
		mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
+3 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ enum {
#define MWIFIEX_MAX_TOTAL_SCAN_TIME	(MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)

#define MWIFIEX_MAX_SCAN_DELAY_CNT			50
#define MWIFIEX_MAX_EMPTY_TX_Q_CNT			10
#define MWIFIEX_SCAN_DELAY_MSEC				20

#define RSN_GTK_OUI_OFFSET				2
@@ -690,6 +691,8 @@ struct mwifiex_adapter {
	u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
	u16 max_mgmt_ie_index;
	u8 scan_delay_cnt;
	u8 empty_tx_q_cnt;
	atomic_t is_tx_received;
};

int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);