--- a/net/mac80211/Kconfig 2019-01-03 21:03:17.839001000 +0800 +++ b/net/mac80211/Kconfig 2019-01-03 21:04:43.931001000 +0800 @@ -16,6 +16,13 @@ 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/local-symbols 2019-01-03 21:24:00.087001000 +0800 +++ b/local-symbols 2019-01-03 21:24:56.535001000 +0800 @@ -47,6 +47,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/ieee80211_i.h 2019-01-03 21:04:57.527001000 +0800 +++ b/net/mac80211/ieee80211_i.h 2019-01-03 21:05:44.827001000 +0800 @@ -35,6 +35,10 @@ extern const struct cfg80211_ops mac80211_config_ops; +#ifdef CPTCFG_MAC80211_NSS_SUPPORT +#include +#endif + struct ieee80211_local; /* Maximum number of broadcast/multicast frames to buffer when some of the @@ -988,6 +992,10 @@ struct ieee80211_sub_if_data { bool hw_80211_encap; +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + struct nss_virt_if_handle *nssctx; +#endif + /* must be last, dynamically sized area in this! */ struct ieee80211_vif vif; }; --- a/net/mac80211/iface.c 2019-01-03 21:06:00.007001000 +0800 +++ b/net/mac80211/iface.c 2019-01-03 21:08:49.535001000 +0800 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include "ieee80211_i.h" @@ -26,6 +27,12 @@ #include "wme.h" #include "rate.h" +#ifdef CPTCFG_MAC80211_NSS_SUPPORT +bool is_nss_enable = true; +module_param(is_nss_enable, bool, 0644); +MODULE_PARM_DESC(is_nss_enable, "NSS enable module param"); +#endif + /** * DOC: Interface list locking * @@ -645,6 +652,13 @@ { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + if (sdata->nssctx) { + nss_virt_if_destroy_sync(sdata->nssctx); + sdata_info(sdata, "Destroyed NSS virtual interface\n"); + } +#endif + ieee80211_do_stop(sdata, true); return 0; @@ -1343,6 +1357,18 @@ ieee80211_recalc_ps(local); +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + if (is_nss_enable) { + sdata->nssctx = nss_virt_if_create_sync(dev); + if (sdata->nssctx) + sdata_info(sdata, "Created a NSS virtual interface\n"); + else + sdata_err(sdata, "Failed to create a NSS virtual interface\n"); + } else { + sdata->nssctx = NULL; + } +#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 2019-01-03 21:09:29.503001000 +0800 +++ b/net/mac80211/rx.c 2019-01-03 21:17:42.463001000 +0800 @@ -32,6 +32,10 @@ #include "wme.h" #include "rate.h" +#ifdef CPTCFG_MAC80211_NSS_SUPPORT +extern bool is_nss_enable; +#endif + static inline void ieee80211_rx_stats(struct net_device *dev, u32 len) { struct pcpu_sw_netstats *tstats = this_cpu_ptr(netdev_tstats(dev)); @@ -42,6 +46,63 @@ u64_stats_update_end(&tstats->syncp); } +#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(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +{ + int ret; + int push_mac_header = 0; + + if (!sdata->nssctx) + goto out; + + if (unlikely((skb->data - skb_mac_header(skb)) == ETH_HLEN)) { + skb_push(skb, ETH_HLEN); + push_mac_header = 1; + } + + ret = nss_virt_if_tx_buf(sdata->nssctx, skb); + if (ret) { + if (net_ratelimit()) { + sdata_err(sdata, "NSS TX failed with error[%d]: %s\n", ret, + nss_tx_status_str(ret)); + } + goto out; + } + + return; +out: + if (unlikely(push_mac_header)) { + skb_pull(skb, ETH_HLEN); + } + netif_receive_skb(skb); +} +#endif + + /* * monitor mode reception * @@ -2604,6 +2665,16 @@ ether_addr_copy(ehdr->h_dest, sdata->vif.addr); /* deliver to local stack */ +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + if (likely(is_nss_enable)) + netif_rx_nss(sdata, skb); + else { + if (rx->napi) + napi_gro_receive(rx->napi, skb); + else + netif_receive_skb(skb); + } +#else if (rx->list) #if LINUX_VERSION_IS_GEQ(4,19,0) list_add_tail(&skb->list, rx->list); @@ -2612,6 +2683,7 @@ #endif else netif_receive_skb(skb); +#endif } } @@ -4461,6 +4533,16 @@ /* deliver to local stack */ skb->protocol = eth_type_trans(skb, fast_rx->dev); memset(skb->cb, 0, sizeof(skb->cb)); +#ifdef CPTCFG_MAC80211_NSS_SUPPORT + if (likely(is_nss_enable)) + netif_rx_nss(rx->sdata, skb); + else { + if (rx->napi) + napi_gro_receive(rx->napi, skb); + else + netif_receive_skb(skb); + } +#else if (rx->list) #if LINUX_VERSION_IS_GEQ(4,19,0) list_add_tail(&skb->list, rx->list); @@ -4469,7 +4551,7 @@ #endif else netif_receive_skb(skb); - +#endif } static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,