diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 4920ef372b02..c40aaa33336b 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1415,10 +1415,12 @@ struct hdd_context_s { qdf_spinlock_t hdd_scan_req_q_lock; qdf_list_t hdd_scan_req_q; uint8_t miracast_value; + #ifdef WLAN_NS_OFFLOAD /* IPv6 notifier callback for handling NS offload on change in IP */ struct notifier_block ipv6_notifier; #endif + bool ns_offload_enable; /* IPv4 notifier callback for handling ARP offload on change in IP */ struct notifier_block ipv4_notifier; diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index c3891254d4c6..d57cf3bd172f 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -4817,6 +4817,79 @@ fail: return; } +static const struct nla_policy +ns_offload_set_policy[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG] = {.type = NLA_U8}, +}; + +/** + * __wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * Return: 0 on success, negative errno on failure + */ +static int +__wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int status; + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX + 1]; + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + + ENTER_DEV(wdev->netdev); + + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + return status; + if (!pHddCtx->config->fhostNSOffload) { + hdd_err("ND Offload not supported"); + return -EINVAL; + } + + if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX, + (struct nlattr *)data, + data_len, ns_offload_set_policy)) { + hdd_err("nla_parse failed"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]) { + hdd_err("ND Offload flag attribute not present"); + return -EINVAL; + } + + pHddCtx->ns_offload_enable = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG]); + + return 0; +} + +/** + * wlan_hdd_cfg80211_set_ns_offload() - enable/disable NS offload + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +static int wlan_hdd_cfg80211_set_ns_offload(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_ns_offload(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + /** __wlan_hdd_cfg80211_get_preferred_freq_list() - get preferred frequency list * @wiphy: Pointer to wireless phy * @wdev: Pointer to wireless device @@ -7402,6 +7475,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_monitor_rssi }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_set_ns_offload + }, { .info.vendor_id = QCA_NL80211_VENDOR_ID, .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET, diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 3191adce1a8d..ba117961a7d2 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -373,6 +373,9 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80, QCA_NL80211_VENDOR_SUBCMD_NDP = 81, + /* NS Offload enable/disable cmd */ + QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD = 82, + QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER = 83, QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS = 85, @@ -2079,6 +2082,27 @@ enum qca_wlan_vendor_attr_link_properties { QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_attr_nd_offload - vendor NS offload support + * + * @QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_INVALID - Invalid + * @QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG - Flag to set NS offload + * @QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST - To keep track of the last enum + * @QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX - max value possible for this type + * + * enum values are used for NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD sub command. + */ +enum qca_wlan_vendor_attr_nd_offload { + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, + + /* Keep last */ + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX = + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST - 1, +}; + /** * enum qca_wlan_vendor_features - vendor device/driver features * @QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD: Device supports key diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 19f1099c3bce..f2d1bf7e7689 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -6055,6 +6055,9 @@ hdd_context_t *hdd_context_create(struct device *dev) hdd_notice("Setting configuredMcastBcastFilter: %d", hdd_ctx->config->mcastBcastFilterSetting); + if (hdd_ctx->config->fhostNSOffload) + hdd_ctx->ns_offload_enable = true; + cds_set_fatal_event(hdd_ctx->config->enable_fatal_event); hdd_override_ini_config(hdd_ctx); diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index dde5cbbeba17..ca8e57ccf1e9 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -492,7 +492,8 @@ void __hdd_ipv6_notifier_work_queue(struct work_struct *work) if (eConnectionState_Associated == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState || ndi_connected) - if (pHddCtx->config->fhostNSOffload) + if (pHddCtx->config->fhostNSOffload && + pHddCtx->ns_offload_enable) hdd_conf_ns_offload(pAdapter, true); EXIT(); } @@ -557,7 +558,8 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable) hdd_conf_arp_offload(pAdapter, fenable); wlan_hdd_set_mc_addr_list(pAdapter, fenable); - if (pHddCtx->config->fhostNSOffload) + if (pHddCtx->config->fhostNSOffload && + pHddCtx->ns_offload_enable) hdd_conf_ns_offload(pAdapter, fenable); } EXIT();