ipq806x: NSS Hardware Offloading mac80211 patch
This commit is contained in:
@@ -82,6 +82,7 @@ config-$(CONFIG_PACKAGE_CFG80211_TESTMODE) += NL80211_TESTMODE
|
||||
|
||||
config-$(call config_package,mac80211) += MAC80211
|
||||
config-$(CONFIG_PACKAGE_MAC80211_MESH) += MAC80211_MESH
|
||||
config-$(CONFIG_PACKAGE_MAC80211_NSS_SUPPORT) += MAC80211_NSS_SUPPORT
|
||||
|
||||
include ath.mk
|
||||
include broadcom.mk
|
||||
@@ -125,7 +126,7 @@ define KernelPackage/mac80211
|
||||
$(call KernelPackage/mac80211/Default)
|
||||
TITLE:=Linux 802.11 Wireless Networking Stack
|
||||
# +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:=\
|
||||
CONFIG_AVERAGE=y
|
||||
FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
|
||||
@@ -136,6 +137,16 @@ endef
|
||||
define KernelPackage/mac80211/config
|
||||
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
|
||||
bool "Export mac80211 internals in DebugFS"
|
||||
select KERNEL_DEBUG_FS
|
||||
@@ -428,7 +439,8 @@ endif
|
||||
|
||||
MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \
|
||||
$(KERNEL_MAKE_FLAGS) \
|
||||
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES)" \
|
||||
EXTRA_CFLAGS="-I$(PKG_BUILD_DIR)/include $(IREMAP_CFLAGS) $(C_DEFINES) \
|
||||
-I$(STAGING_DIR)/usr/include/qca-nss-drv" \
|
||||
KLIB_BUILD="$(LINUX_DIR)" \
|
||||
MODPROBE=true \
|
||||
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
|
||||
@@ -1002,6 +1006,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
|
||||
@@ -663,6 +663,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;
|
||||
@@ -1094,6 +1103,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
|
||||
@@ -1325,6 +1417,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
|
||||
@@ -2570,6 +2570,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)
|
||||
{
|
||||
@@ -2590,6 +2597,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
|
||||
@@ -4439,6 +4452,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;
|
||||
@@ -4524,6 +4538,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
|
||||
@@ -37,6 +37,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,
|
||||
@@ -1686,6 +1691,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
|
||||
@@ -4380,6 +4395,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