ipq806x: NSS Hardware Offloading mac80211 support
This commit is contained in:
		@@ -78,6 +78,7 @@ config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
config-$(call config_package,mac80211) += MAC80211
 | 
					config-$(call config_package,mac80211) += MAC80211
 | 
				
			||||||
config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH
 | 
					config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH
 | 
				
			||||||
 | 
					config-$(CONFIG_PACKAGE_MAC80211_NSS_SUPPORT) += MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include ath.mk
 | 
					include ath.mk
 | 
				
			||||||
include broadcom.mk
 | 
					include broadcom.mk
 | 
				
			||||||
@@ -121,7 +122,7 @@ define KernelPackage/mac80211
 | 
				
			|||||||
  $(call KernelPackage/mac80211/Default)
 | 
					  $(call KernelPackage/mac80211/Default)
 | 
				
			||||||
  TITLE:=Linux 802.11 Wireless Networking Stack
 | 
					  TITLE:=Linux 802.11 Wireless Networking Stack
 | 
				
			||||||
  # +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c
 | 
					  # +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c
 | 
				
			||||||
  DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common
 | 
					  DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common +PACKAGE_kmod-qca-nss-drv:kmod-qca-nss-drv
 | 
				
			||||||
  KCONFIG:=\
 | 
					  KCONFIG:=\
 | 
				
			||||||
	CONFIG_AVERAGE=y
 | 
						CONFIG_AVERAGE=y
 | 
				
			||||||
  FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
 | 
					  FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
 | 
				
			||||||
@@ -132,6 +133,16 @@ endef
 | 
				
			|||||||
define KernelPackage/mac80211/config
 | 
					define KernelPackage/mac80211/config
 | 
				
			||||||
  if PACKAGE_kmod-mac80211
 | 
					  if PACKAGE_kmod-mac80211
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							 if PACKAGE_kmod-qca-nss-drv
 | 
				
			||||||
 | 
							config PACKAGE_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
								bool "Enable NSS support for IPQ platform"
 | 
				
			||||||
 | 
								default y
 | 
				
			||||||
 | 
								help
 | 
				
			||||||
 | 
								  This option enables support for NSS in boards
 | 
				
			||||||
 | 
								  like Netgear R7800.
 | 
				
			||||||
 | 
						endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	config PACKAGE_MAC80211_DEBUGFS
 | 
						config PACKAGE_MAC80211_DEBUGFS
 | 
				
			||||||
		bool "Export mac80211 internals in DebugFS"
 | 
							bool "Export mac80211 internals in DebugFS"
 | 
				
			||||||
		select KERNEL_DEBUG_FS
 | 
							select KERNEL_DEBUG_FS
 | 
				
			||||||
@@ -273,9 +284,12 @@ ifeq ($(BUILD_VARIANT),smallbuffers)
 | 
				
			|||||||
	C_DEFINES+= -DCONFIG_ATH10K_SMALLBUFFERS
 | 
						C_DEFINES+= -DCONFIG_ATH10K_SMALLBUFFERS
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MAKE_OPTS:= \
 | 
					C_DEFINES+= -DSTANDALONE_CT
 | 
				
			||||||
	$(subst -C $(LINUX_DIR),-C "$(PKG_BUILD_DIR)",$(KERNEL_MAKEOPTS)) \
 | 
					
 | 
				
			||||||
	EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES)" \
 | 
					MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \
 | 
				
			||||||
 | 
						$(KERNEL_MAKE_FLAGS) \
 | 
				
			||||||
 | 
						EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES) \
 | 
				
			||||||
 | 
							-I$(STAGING_DIR)/usr/include/qca-nss-drv" \
 | 
				
			||||||
	KLIB_BUILD="$(LINUX_DIR)" \
 | 
						KLIB_BUILD="$(LINUX_DIR)" \
 | 
				
			||||||
	MODPROBE=true \
 | 
						MODPROBE=true \
 | 
				
			||||||
	KLIB=$(TARGET_MODULES_DIR) \
 | 
						KLIB=$(TARGET_MODULES_DIR) \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,292 @@
 | 
				
			|||||||
 | 
					--- a/local-symbols
 | 
				
			||||||
 | 
					+++ b/local-symbols
 | 
				
			||||||
 | 
					@@ -39,6 +39,7 @@ LIB80211_CRYPT_CCMP=
 | 
				
			||||||
 | 
					 LIB80211_CRYPT_TKIP=
 | 
				
			||||||
 | 
					 LIB80211_DEBUG=
 | 
				
			||||||
 | 
					 MAC80211=
 | 
				
			||||||
 | 
					+MAC80211_NSS_SUPPORT=
 | 
				
			||||||
 | 
					 MAC80211_HAS_RC=
 | 
				
			||||||
 | 
					 MAC80211_RC_MINSTREL=
 | 
				
			||||||
 | 
					 MAC80211_RC_DEFAULT_MINSTREL=
 | 
				
			||||||
 | 
					--- a/net/mac80211/Kconfig
 | 
				
			||||||
 | 
					+++ b/net/mac80211/Kconfig
 | 
				
			||||||
 | 
					@@ -19,6 +19,13 @@ comment "CFG80211 needs to be enabled fo
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 if MAC80211 != n
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+config MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+	bool "Enable NSS support for IPQ platform"
 | 
				
			||||||
 | 
					+	default n
 | 
				
			||||||
 | 
					+	---help---
 | 
				
			||||||
 | 
					+	This option enables support for NSS in boards
 | 
				
			||||||
 | 
					+	like AP148.
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 config MAC80211_HAS_RC
 | 
				
			||||||
 | 
					 	bool
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					--- a/net/mac80211/ieee80211_i.h
 | 
				
			||||||
 | 
					+++ b/net/mac80211/ieee80211_i.h
 | 
				
			||||||
 | 
					@@ -36,6 +36,10 @@
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 extern const struct cfg80211_ops mac80211_config_ops;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+#include <nss_api_if.h>
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 struct ieee80211_local;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Maximum number of broadcast/multicast frames to buffer when some of the
 | 
				
			||||||
 | 
					@@ -1034,6 +1038,12 @@ struct ieee80211_sub_if_data {
 | 
				
			||||||
 | 
					 	} debugfs;
 | 
				
			||||||
 | 
					 #endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+	struct nss_virt_if_handle *nssctx;
 | 
				
			||||||
 | 
					+	struct sk_buff_head rx_queue;
 | 
				
			||||||
 | 
					+	struct work_struct rx_work;
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* must be last, dynamically sized area in this! */
 | 
				
			||||||
 | 
					 	struct ieee80211_vif vif;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					--- a/net/mac80211/iface.c
 | 
				
			||||||
 | 
					+++ b/net/mac80211/iface.c
 | 
				
			||||||
 | 
					@@ -664,6 +664,15 @@ static int ieee80211_stop(struct net_dev
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+	if (sdata->nssctx) {
 | 
				
			||||||
 | 
					+		cancel_work_sync(&sdata->rx_work);
 | 
				
			||||||
 | 
					+		skb_queue_purge(&sdata->rx_queue);
 | 
				
			||||||
 | 
					+		nss_virt_if_destroy_sync(sdata->nssctx);
 | 
				
			||||||
 | 
					+		sdata->nssctx = NULL;
 | 
				
			||||||
 | 
					+		sdata_info(sdata, "Destroyed NSS virtual interface\n");
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 	/* close dependent VLAN and MBSSID interfaces before locking wiphy */
 | 
				
			||||||
 | 
					 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
 | 
				
			||||||
 | 
					 		struct ieee80211_sub_if_data *vlan, *tmpsdata;
 | 
				
			||||||
 | 
					@@ -1188,6 +1197,89 @@ void ieee80211_del_virtual_monitor(struc
 | 
				
			||||||
 | 
					 	kfree(sdata);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+#define case_rtn_string(val) case val: return #val
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static const char *nss_tx_status_str(nss_tx_status_t status)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	switch (status) {
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_SUCCESS);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_QUEUE);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_NOT_READY);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_TOO_LARGE);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_TOO_SHORT);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_NOT_SUPPORTED);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_BAD_PARAM);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_NOT_ENABLED);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_SYNC_BAD_PARAM);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_SYNC_TIMEOUT);
 | 
				
			||||||
 | 
					+		case_rtn_string(NSS_TX_FAILURE_SYNC_FW_ERR);
 | 
				
			||||||
 | 
					+	default:
 | 
				
			||||||
 | 
					+		return "Unknown NSS TX status";
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static void netif_rx_nss_work(struct work_struct *work)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int ret;
 | 
				
			||||||
 | 
					+	unsigned long flags;
 | 
				
			||||||
 | 
					+	struct sk_buff *skb;
 | 
				
			||||||
 | 
					+	struct sk_buff_head *list;
 | 
				
			||||||
 | 
					+	struct ieee80211_sub_if_data *sdata =
 | 
				
			||||||
 | 
					+	    container_of(work, struct ieee80211_sub_if_data, rx_work);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	list = &sdata->rx_queue;
 | 
				
			||||||
 | 
					+	skb = skb_dequeue(list);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	while (skb != NULL) {
 | 
				
			||||||
 | 
					+		skb_push(skb, ETH_HLEN);
 | 
				
			||||||
 | 
					+		ret = nss_virt_if_tx_buf(sdata->nssctx, skb);
 | 
				
			||||||
 | 
					+		if (unlikely(ret)) {
 | 
				
			||||||
 | 
					+			if (net_ratelimit() && ret != NSS_TX_FAILURE_TOO_SHORT) {
 | 
				
			||||||
 | 
					+				sdata_err(sdata, "NSS TX failed with error: %s\n",
 | 
				
			||||||
 | 
					+					nss_tx_status_str(ret));
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+			skb_pull(skb, ETH_HLEN);
 | 
				
			||||||
 | 
					+			netif_receive_skb(skb);
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		skb = skb_dequeue(list);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Check if we there are more packet to process and resched */
 | 
				
			||||||
 | 
					+	skb = skb_peek(list);
 | 
				
			||||||
 | 
					+	if (skb)
 | 
				
			||||||
 | 
					+		schedule_work(&sdata->rx_work);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* This callback is registered for nss redirect to receive packet exceptioned from nss in Rx path.
 | 
				
			||||||
 | 
					+ * When packet does not match any of the ecm rules is redirected back here.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+void receive_from_nss(struct net_device *dev, struct sk_buff *sk_buff, struct napi_struct *napi)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct net_device *netdev;
 | 
				
			||||||
 | 
					+	struct sk_buff *skb;
 | 
				
			||||||
 | 
					+	struct ieee80211_sub_if_data *sdata;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!dev) {
 | 
				
			||||||
 | 
					+		kfree(sk_buff);
 | 
				
			||||||
 | 
					+		return;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	netdev = (struct net_device *)dev;
 | 
				
			||||||
 | 
					+	sdata = netdev_priv(netdev);
 | 
				
			||||||
 | 
					+	if (sdata->dev != dev) {
 | 
				
			||||||
 | 
					+		kfree(sk_buff);
 | 
				
			||||||
 | 
					+		return;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	skb = (struct sk_buff *)sk_buff;
 | 
				
			||||||
 | 
					+	skb->dev = netdev;
 | 
				
			||||||
 | 
					+	skb->protocol = eth_type_trans(skb, netdev);
 | 
				
			||||||
 | 
					+	napi_gro_receive(napi, skb);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /*
 | 
				
			||||||
 | 
					  * NOTE: Be very careful when changing this function, it must NOT return
 | 
				
			||||||
 | 
					  * an error on interface type changes that have been pre-checked, so most
 | 
				
			||||||
 | 
					@@ -1419,6 +1511,17 @@ int ieee80211_do_open(struct wireless_de
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	ieee80211_recalc_ps(local);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+	sdata->nssctx = nss_virt_if_create_sync(dev);
 | 
				
			||||||
 | 
					+	if (sdata->nssctx) {
 | 
				
			||||||
 | 
					+		sdata_info(sdata, "Created a NSS virtual interface\n");
 | 
				
			||||||
 | 
					+		nss_virt_if_register(sdata->nssctx, receive_from_nss, sdata->dev);
 | 
				
			||||||
 | 
					+		skb_queue_head_init(&sdata->rx_queue);
 | 
				
			||||||
 | 
					+		INIT_WORK(&sdata->rx_work, &netif_rx_nss_work);
 | 
				
			||||||
 | 
					+	} else
 | 
				
			||||||
 | 
					+		sdata_err(sdata, "Failed to create a NSS virtual interface\n");
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
 | 
				
			||||||
 | 
					 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
 | 
				
			||||||
 | 
					 	    local->ops->wake_tx_queue) {
 | 
				
			||||||
 | 
					--- a/net/mac80211/rx.c
 | 
				
			||||||
 | 
					+++ b/net/mac80211/rx.c
 | 
				
			||||||
 | 
					@@ -2573,6 +2573,13 @@ static bool ieee80211_frame_allowed(stru
 | 
				
			||||||
 | 
					 	return true;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+static inline void netif_rx_nss(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	skb_queue_tail(&sdata->rx_queue, skb);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	schedule_work(&sdata->rx_work);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
 | 
				
			||||||
 | 
					 						 struct ieee80211_rx_data *rx)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -2593,6 +2600,12 @@ static void ieee80211_deliver_skb_to_loc
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		memset(skb->cb, 0, sizeof(skb->cb));
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+		if (sdata->nssctx) {
 | 
				
			||||||
 | 
					+			netif_rx_nss(skb, sdata);
 | 
				
			||||||
 | 
					+			return;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 		/*
 | 
				
			||||||
 | 
					 		 * 802.1X over 802.11 requires that the authenticator address
 | 
				
			||||||
 | 
					 		 * be used for EAPOL frames. However, 802.1X allows the use of
 | 
				
			||||||
 | 
					@@ -4489,6 +4502,7 @@ static void ieee80211_rx_8023(struct iee
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct ieee80211_sta_rx_stats *stats;
 | 
				
			||||||
 | 
					 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 | 
				
			||||||
 | 
					+	struct ieee80211_sub_if_data *sdata = rx->sdata;
 | 
				
			||||||
 | 
					 	struct sta_info *sta = rx->sta;
 | 
				
			||||||
 | 
					 	struct sk_buff *skb = rx->skb;
 | 
				
			||||||
 | 
					 	void *sa = skb->data + ETH_ALEN;
 | 
				
			||||||
 | 
					@@ -4574,6 +4588,13 @@ static void ieee80211_rx_8023(struct iee
 | 
				
			||||||
 | 
					 	/* deliver to local stack */
 | 
				
			||||||
 | 
					 	skb->protocol = eth_type_trans(skb, fast_rx->dev);
 | 
				
			||||||
 | 
					 	ieee80211_deliver_skb_to_local_stack(skb, rx);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+       if (sdata->nssctx) {
 | 
				
			||||||
 | 
					+               netif_rx_nss(skb, sdata);
 | 
				
			||||||
 | 
					+               return;
 | 
				
			||||||
 | 
					+       }
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
 | 
				
			||||||
 | 
					--- a/net/mac80211/tx.c
 | 
				
			||||||
 | 
					+++ b/net/mac80211/tx.c
 | 
				
			||||||
 | 
					@@ -36,6 +36,11 @@
 | 
				
			||||||
 | 
					 #include "wme.h"
 | 
				
			||||||
 | 
					 #include "rate.h"
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+#include <net/ip.h>
 | 
				
			||||||
 | 
					+#include <net/dsfield.h>
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /* misc utils */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
 | 
				
			||||||
 | 
					@@ -1687,6 +1692,16 @@ static bool ieee80211_tx_frags(struct ie
 | 
				
			||||||
 | 
					 					return true;
 | 
				
			||||||
 | 
					 				}
 | 
				
			||||||
 | 
					 			} else {
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+				if (skb_queue_len(&local->pending[q]) >= 1000) {
 | 
				
			||||||
 | 
					+					spin_unlock_irqrestore(
 | 
				
			||||||
 | 
					+						&local->queue_stop_reason_lock,
 | 
				
			||||||
 | 
					+						flags);
 | 
				
			||||||
 | 
					+					ieee80211_purge_tx_queue(&local->hw,
 | 
				
			||||||
 | 
					+								 skbs);
 | 
				
			||||||
 | 
					+					return false;
 | 
				
			||||||
 | 
					+				}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 				/*
 | 
				
			||||||
 | 
					 				 * Since queue is stopped, queue up frames for
 | 
				
			||||||
 | 
					@@ -4296,6 +4311,31 @@ out:
 | 
				
			||||||
 | 
					 netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 | 
				
			||||||
 | 
					 				       struct net_device *dev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#ifdef CPTCFG_MAC80211_NSS_SUPPORT
 | 
				
			||||||
 | 
					+	/* Packets from NSS does not have valid protocol, priority and other
 | 
				
			||||||
 | 
					+	 * network stack values. Derive required parameters (priority
 | 
				
			||||||
 | 
					+	 * and network_header) from payload for QoS header.
 | 
				
			||||||
 | 
					+	 * XXX: Here the assumption is that packet are in 802.3 format.
 | 
				
			||||||
 | 
					+	 * As of now priority is handled only for IPv4 and IPv6.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (sdata->nssctx && likely(!skb->protocol)) {
 | 
				
			||||||
 | 
					+		skb_set_network_header(skb, 14);
 | 
				
			||||||
 | 
					+		switch (((struct ethhdr *)skb->data)->h_proto) {
 | 
				
			||||||
 | 
					+		case htons(ETH_P_IP):
 | 
				
			||||||
 | 
					+			skb->priority = (ipv4_get_dsfield(ip_hdr(skb)) &
 | 
				
			||||||
 | 
					+					 0xfc) >> 5;
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					+		case htons(ETH_P_IPV6):
 | 
				
			||||||
 | 
					+			skb->priority = (ipv6_get_dsfield(ipv6_hdr(skb)) &
 | 
				
			||||||
 | 
					+					 0xfc) >> 5;
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+#endif
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
 | 
				
			||||||
 | 
					 		struct sk_buff_head queue;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
		Reference in New Issue
	
	Block a user