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

Commit a1777327 authored by Avinash Patil's avatar Avinash Patil Committed by Kalle Valo
Browse files

mwifiex: support for bypass tx queue



This patch adds support for another TX queue in driver- bypass
TX queue. This queue is used for sending data/mgmt packets while
in disconnected state i.e. when port is yet not unblocked.
TDLS setup packets would also be queued in this queue.

Signed-off-by: default avatarAvinash Patil <patila@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 65d48e59
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -2789,6 +2789,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
{
{
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
	struct mwifiex_adapter *adapter = priv->adapter;
	struct mwifiex_adapter *adapter = priv->adapter;
	struct sk_buff *skb, *tmp;


#ifdef CONFIG_DEBUG_FS
#ifdef CONFIG_DEBUG_FS
	mwifiex_dev_debugfs_remove(priv);
	mwifiex_dev_debugfs_remove(priv);
@@ -2796,6 +2797,9 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)


	mwifiex_stop_net_dev_queue(priv->netdev, adapter);
	mwifiex_stop_net_dev_queue(priv->netdev, adapter);


	skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
		mwifiex_write_data_complete(priv->adapter, skb, 0, -1);

	if (netif_carrier_ok(priv->netdev))
	if (netif_carrier_ok(priv->netdev))
		netif_carrier_off(priv->netdev);
		netif_carrier_off(priv->netdev);


+1 −0
Original line number Original line Diff line number Diff line
@@ -499,6 +499,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
		INIT_LIST_HEAD(&priv->sta_list);
		INIT_LIST_HEAD(&priv->sta_list);
		INIT_LIST_HEAD(&priv->auto_tdls_list);
		INIT_LIST_HEAD(&priv->auto_tdls_list);
		skb_queue_head_init(&priv->tdls_txq);
		skb_queue_head_init(&priv->tdls_txq);
		skb_queue_head_init(&priv->bypass_txq);


		spin_lock_init(&priv->tx_ba_stream_tbl_lock);
		spin_lock_init(&priv->tx_ba_stream_tbl_lock);
		spin_lock_init(&priv->rx_reorder_tbl_lock);
		spin_lock_init(&priv->rx_reorder_tbl_lock);
+47 −2
Original line number Original line Diff line number Diff line
@@ -276,6 +276,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
		     !adapter->pm_wakeup_fw_try) &&
		     !adapter->pm_wakeup_fw_try) &&
		    (is_command_pending(adapter) ||
		    (is_command_pending(adapter) ||
		     !skb_queue_empty(&adapter->tx_data_q) ||
		     !skb_queue_empty(&adapter->tx_data_q) ||
		     !mwifiex_bypass_txlist_empty(adapter) ||
		     !mwifiex_wmm_lists_empty(adapter))) {
		     !mwifiex_wmm_lists_empty(adapter))) {
			adapter->pm_wakeup_fw_try = true;
			adapter->pm_wakeup_fw_try = true;
			mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3));
			mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3));
@@ -303,6 +304,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
			     (mwifiex_get_priv(adapter,
			     (mwifiex_get_priv(adapter,
					       MWIFIEX_BSS_ROLE_STA)) ||
					       MWIFIEX_BSS_ROLE_STA)) ||
			    (mwifiex_wmm_lists_empty(adapter) &&
			    (mwifiex_wmm_lists_empty(adapter) &&
			     mwifiex_bypass_txlist_empty(adapter) &&
			     skb_queue_empty(&adapter->tx_data_q))) {
			     skb_queue_empty(&adapter->tx_data_q))) {
				if (adapter->cmd_sent || adapter->curr_cmd ||
				if (adapter->cmd_sent || adapter->curr_cmd ||
					!mwifiex_is_send_cmd_allowed
					!mwifiex_is_send_cmd_allowed
@@ -371,6 +373,22 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
			}
			}
		}
		}


		if ((adapter->scan_chan_gap_enabled ||
		     !adapter->scan_processing) &&
		    !adapter->data_sent &&
		    !mwifiex_bypass_txlist_empty(adapter) &&
		    !mwifiex_is_tdls_chan_switching
			(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
			mwifiex_process_bypass_tx(adapter);
			if (adapter->hs_activated) {
				adapter->is_hs_configured = false;
				mwifiex_hs_activated_event
					(mwifiex_get_priv
					 (adapter, MWIFIEX_BSS_ROLE_ANY),
					 false);
			}
		}

		if ((adapter->scan_chan_gap_enabled ||
		if ((adapter->scan_chan_gap_enabled ||
		     !adapter->scan_processing) &&
		     !adapter->scan_processing) &&
		    !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) &&
		    !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) &&
@@ -389,6 +407,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
		if (adapter->delay_null_pkt && !adapter->cmd_sent &&
		if (adapter->delay_null_pkt && !adapter->cmd_sent &&
		    !adapter->curr_cmd && !is_command_pending(adapter) &&
		    !adapter->curr_cmd && !is_command_pending(adapter) &&
		    (mwifiex_wmm_lists_empty(adapter) &&
		    (mwifiex_wmm_lists_empty(adapter) &&
		     mwifiex_bypass_txlist_empty(adapter) &&
		     skb_queue_empty(&adapter->tx_data_q))) {
		     skb_queue_empty(&adapter->tx_data_q))) {
			if (!mwifiex_send_null_packet
			if (!mwifiex_send_null_packet
			    (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
			    (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
@@ -659,6 +678,26 @@ mwifiex_close(struct net_device *dev)
	return 0;
	return 0;
}
}


static bool
mwifiex_bypass_tx_queue(struct mwifiex_private *priv,
			struct sk_buff *skb)
{
	struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;

	if (ntohs(eth_hdr->h_proto) == ETH_P_PAE ||
	    mwifiex_is_skb_mgmt_frame(skb) ||
	    (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
	     ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
	     (ntohs(eth_hdr->h_proto) == ETH_P_TDLS))) {
		mwifiex_dbg(priv->adapter, DATA,
			    "bypass txqueue; eth type %#x, mgmt %d\n",
			     ntohs(eth_hdr->h_proto),
			     mwifiex_is_skb_mgmt_frame(skb));
		return true;
	}

	return false;
}
/*
/*
 * Add buffer into wmm tx queue and queue work to transmit it.
 * Add buffer into wmm tx queue and queue work to transmit it.
 */
 */
@@ -676,8 +715,14 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
		}
		}
	}
	}


	if (mwifiex_bypass_tx_queue(priv, skb)) {
		atomic_inc(&priv->adapter->tx_pending);
		atomic_inc(&priv->adapter->bypass_tx_pending);
		mwifiex_wmm_add_buf_bypass_txqueue(priv, skb);
	 } else {
		atomic_inc(&priv->adapter->tx_pending);
		atomic_inc(&priv->adapter->tx_pending);
		mwifiex_wmm_add_buf_txqueue(priv, skb);
		mwifiex_wmm_add_buf_txqueue(priv, skb);
	 }


	mwifiex_queue_main_work(priv->adapter);
	mwifiex_queue_main_work(priv->adapter);


+2 −0
Original line number Original line Diff line number Diff line
@@ -664,6 +664,7 @@ struct mwifiex_private {
	struct cfg80211_beacon_data beacon_after;
	struct cfg80211_beacon_data beacon_after;
	struct mwifiex_11h_intf_state state_11h;
	struct mwifiex_11h_intf_state state_11h;
	struct mwifiex_ds_mem_rw mem_rw;
	struct mwifiex_ds_mem_rw mem_rw;
	struct sk_buff_head bypass_txq;
};
};




@@ -834,6 +835,7 @@ struct mwifiex_adapter {
	wait_queue_head_t init_wait_q;
	wait_queue_head_t init_wait_q;
	void *card;
	void *card;
	struct mwifiex_if_ops if_ops;
	struct mwifiex_if_ops if_ops;
	atomic_t bypass_tx_pending;
	atomic_t rx_pending;
	atomic_t rx_pending;
	atomic_t tx_pending;
	atomic_t tx_pending;
	atomic_t cmd_pending;
	atomic_t cmd_pending;
+53 −0
Original line number Original line Diff line number Diff line
@@ -449,6 +449,11 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
	}
	}
}
}


int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter)
{
	return atomic_read(&adapter->bypass_tx_pending) ? false : true;
}

/*
/*
 * This function checks if WMM Tx queue is empty.
 * This function checks if WMM Tx queue is empty.
 */
 */
@@ -581,6 +586,10 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
	skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
	skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
		mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
		mwifiex_write_data_complete(priv->adapter, skb, 0, -1);


	skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
		mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
	atomic_set(&priv->adapter->bypass_tx_pending, 0);

	idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
	idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
	idr_destroy(&priv->ack_status_frames);
	idr_destroy(&priv->ack_status_frames);
}
}
@@ -752,6 +761,18 @@ mwifiex_is_ralist_valid(struct mwifiex_private *priv,
	return false;
	return false;
}
}


/*
 * This function adds a packet to bypass TX queue.
 * This is special TX queue for packets which can be sent even when port_open
 * is false.
 */
void
mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv,
				   struct sk_buff *skb)
{
	skb_queue_tail(&priv->bypass_txq, skb);
}

/*
/*
 * This function adds a packet to WMM queue.
 * This function adds a packet to WMM queue.
 *
 *
@@ -1429,6 +1450,38 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
	return 0;
	return 0;
}
}


void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter)
{
	struct mwifiex_tx_param tx_param;
	struct sk_buff *skb;
	struct mwifiex_txinfo *tx_info;
	struct mwifiex_private *priv;
	int i;

	if (adapter->data_sent || adapter->tx_lock_flag)
		return;

	for (i = 0; i < adapter->priv_num; ++i) {
		priv = adapter->priv[i];

		if (skb_queue_empty(&priv->bypass_txq))
			continue;

		skb = skb_dequeue(&priv->bypass_txq);
		tx_info = MWIFIEX_SKB_TXCB(skb);

		/* no aggregation for bypass packets */
		tx_param.next_pkt_len = 0;

		if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
			skb_queue_head(&priv->bypass_txq, skb);
			tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
		} else {
			atomic_dec(&adapter->bypass_tx_pending);
		}
	}
}

/*
/*
 * This function transmits the highest priority packet awaiting in the
 * This function transmits the highest priority packet awaiting in the
 * WMM Queues.
 * WMM Queues.
Loading