Commit c7a61af5 authored by Bryan O'Donoghue's avatar Bryan O'Donoghue Committed by Kalle Valo
Browse files

wcn36xx: Add ipv6 address tracking



Taking code from iwlwifi this commit adds a standard callback for
ipv6_addr_change().

This callback allows wcn36xx to know the set of ipv6 addresses. Something
we need to know in order to get wowlan working with ipv6.

Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
Tested-by: default avatarBenjamin Li <benl@squareup.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210605011140.2004643-6-bryan.odonoghue@linaro.org
parent 6feb634f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3466,6 +3466,7 @@ struct wcn36xx_hal_rem_bcn_filter_req {
#define WCN36XX_HAL_OFFLOAD_BCAST_FILTER_ENABLE             0x2
#define WCN36XX_HAL_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE	\
	(WCN36XX_HAL_OFFLOAD_ENABLE | WCN36XX_HAL_OFFLOAD_BCAST_FILTER_ENABLE)
#define WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX		0x02

struct wcn36xx_hal_ns_offload_params {
	u8 src_ipv6_addr[WCN36XX_HAL_IPV6_ADDR_LEN];
+32 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/rpmsg.h>
#include <linux/soc/qcom/smem_state.h>
#include <linux/soc/qcom/wcnss_ctrl.h>
#include <net/ipv6.h>
#include "wcn36xx.h"
#include "testmode.h"

@@ -1208,6 +1209,34 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
	return ret;
}

#if IS_ENABLED(CONFIG_IPV6)
static void wcn36xx_ipv6_addr_change(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif,
				     struct inet6_dev *idev)
{
	struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
	struct inet6_ifaddr *ifa;
	int idx = 0;

	memset(vif_priv->tentative_addrs, 0, sizeof(vif_priv->tentative_addrs));

	read_lock_bh(&idev->lock);
	list_for_each_entry(ifa, &idev->addr_list, if_list) {
		vif_priv->target_ipv6_addrs[idx] = ifa->addr;
		if (ifa->flags & IFA_F_TENTATIVE)
			__set_bit(idx, vif_priv->tentative_addrs);
		idx++;
		if (idx >= WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX)
			break;
		wcn36xx_dbg(WCN36XX_DBG_MAC, "%pI6 %s\n", &ifa->addr,
			    (ifa->flags & IFA_F_TENTATIVE) ? "tentative" : NULL);
	}
	read_unlock_bh(&idev->lock);

	vif_priv->num_target_ipv6_addrs = idx;
}
#endif

static const struct ieee80211_ops wcn36xx_ops = {
	.start			= wcn36xx_start,
	.stop			= wcn36xx_stop,
@@ -1231,6 +1260,9 @@ static const struct ieee80211_ops wcn36xx_ops = {
	.sta_add		= wcn36xx_sta_add,
	.sta_remove		= wcn36xx_sta_remove,
	.ampdu_action		= wcn36xx_ampdu_action,
#if IS_ENABLED(CONFIG_IPV6)
	.ipv6_addr_change	= wcn36xx_ipv6_addr_change,
#endif

	CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd)
};
+8 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define _WCN36XX_H_

#include <linux/completion.h>
#include <linux/in6.h>
#include <linux/printk.h>
#include <linux/spinlock.h>
#include <net/mac80211.h>
@@ -136,6 +137,13 @@ struct wcn36xx_vif {
	u8 self_dpu_desc_index;
	u8 self_ucast_dpu_sign;

#if IS_ENABLED(CONFIG_IPV6)
	/* IPv6 addresses for WoWLAN */
	struct in6_addr target_ipv6_addrs[WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX];
	unsigned long tentative_addrs[BITS_TO_LONGS(WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX)];
	int num_target_ipv6_addrs;
#endif

	struct list_head sta_list;
};