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

Commit a3713f8b authored by Emmanuel Grumbach's avatar Emmanuel Grumbach
Browse files

iwlwifi: mvm: prepare the code towards TSO implementation



Differentiate between the cases where the skb is a large
send and the other cases.
Advertise TSO even if, at this stage, skb_gso_segment will
be called and it will do all the work.

Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 41837ca9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -668,7 +668,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
		hw->netdev_features &= ~NETIF_F_RXCSUM;

	if (IWL_MVM_SW_TX_CSUM_OFFLOAD)
		hw->netdev_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
		hw->netdev_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
			NETIF_F_TSO | NETIF_F_TSO6;

	ret = ieee80211_register_hw(mvm->hw);
	if (ret)
+76 −2
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@
 *****************************************************************************/
#include <linux/ieee80211.h>
#include <linux/etherdevice.h>
#include <linux/tcp.h>

#include "iwl-trans.h"
#include "iwl-eeprom-parse.h"
@@ -425,10 +426,38 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
	return 0;
}

static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb_gso,
			  struct ieee80211_sta *sta,
			  struct sk_buff_head *mpdus_skb)
{
	struct sk_buff *tmp, *next;
	char cb[sizeof(skb_gso->cb)];

	memcpy(cb, skb_gso->cb, sizeof(cb));
	next = skb_gso_segment(skb_gso, 0);
	if (IS_ERR(next))
		return -EINVAL;
	else if (next)
		consume_skb(skb_gso);

	while (next) {
		tmp = next;
		next = tmp->next;
		memcpy(tmp->cb, cb, sizeof(tmp->cb));

		tmp->prev = NULL;
		tmp->next = NULL;

		__skb_queue_tail(mpdus_skb, tmp);
	}

	return 0;
}

/*
 * Sets the fields in the Tx cmd that are crypto related
 */
int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
			   struct ieee80211_sta *sta)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -525,6 +554,51 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
	return -1;
}

int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
		   struct ieee80211_sta *sta)
{
	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
	struct sk_buff_head mpdus_skbs;
	unsigned int payload_len;
	int ret;

	if (WARN_ON_ONCE(!mvmsta))
		return -1;

	if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
		return -1;

	if (!skb_is_gso(skb))
		return iwl_mvm_tx_mpdu(mvm, skb, sta);

	payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) -
		tcp_hdrlen(skb) + skb->data_len;

	if (payload_len <= skb_shinfo(skb)->gso_size)
		return iwl_mvm_tx_mpdu(mvm, skb, sta);

	__skb_queue_head_init(&mpdus_skbs);

	ret = iwl_mvm_tx_tso(mvm, skb, sta, &mpdus_skbs);
	if (ret)
		return ret;

	if (WARN_ON(skb_queue_empty(&mpdus_skbs)))
		return ret;

	while (!skb_queue_empty(&mpdus_skbs)) {
		struct sk_buff *skb = __skb_dequeue(&mpdus_skbs);

		ret = iwl_mvm_tx_mpdu(mvm, skb, sta);
		if (ret) {
			__skb_queue_purge(&mpdus_skbs);
			return ret;
		}
	}

	return 0;
}

static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
				      struct ieee80211_sta *sta, u8 tid)
{