Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fde1865 authored by Sarada Prasanna Garnayak's avatar Sarada Prasanna Garnayak Committed by Gerrit - the friendly Code Review server
Browse files

ath10k: add support for wowlan offload for wcn3990 WLAN module



Define data structure and callback for the ARP and NS offload
for the ath10k wcn3990 WLAN module. Configure the ARP offload
parameter and enable ARP offload request flag for each vdev
if the vdev in station mode.

This feature adds support to wakeup the device from sleep state
through wowlan event if the ARP request pattern matched with
pattern configured by WLAN module during wow suspend.

CRs-Fixed: 2146265
Change-Id: I54c3491493ad46a7db2adbf71ae1668cf9a88e51
Signed-off-by: default avatarSarada Prasanna Garnayak <sgarna@codeaurora.org>
parent af5f7035
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/pci.h>
#include <linux/uuid.h>
#include <linux/time.h>
#include <linux/inetdevice.h>
#include <soc/qcom/socinfo.h>

#include "htt.h"
@@ -430,6 +431,8 @@ struct ath10k_vif {
	struct work_struct ap_csa_work;
	struct delayed_work connection_loss_work;
	struct cfg80211_bitrate_mask bitrate_mask;
	struct wmi_ns_arp_offload_req arp_offload;
	struct wmi_ns_arp_offload_req ns_offload;
};

struct ath10k_vif_iter {
+4 −0
Original line number Diff line number Diff line
@@ -1387,6 +1387,10 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,

	lockdep_assert_held(&ar->conf_mutex);

	/* Clear arp and ns offload cache */
	memset(&arvif->arp_offload, 0, sizeof(arvif->arp_offload));
	memset(&arvif->ns_offload, 0, sizeof(arvif->ns_offload));

	reinit_completion(&ar->vdev_setup_done);
	reinit_completion(&ar->vdev_delete_done);

+19 −0
Original line number Diff line number Diff line
@@ -160,6 +160,8 @@ struct wmi_ops {
					      u32 num_ac);
	struct sk_buff *(*gen_sta_keepalive)(struct ath10k *ar,
					     const struct wmi_sta_keepalive_arg *arg);
	struct sk_buff *(*gen_set_arp_ns_offload)(struct ath10k *ar,
						  struct ath10k_vif *arvif);
	struct sk_buff *(*gen_wow_enable)(struct ath10k *ar);
	struct sk_buff *(*gen_wow_add_wakeup_event)(struct ath10k *ar, u32 vdev_id,
						    enum wmi_wow_wakeup_event event,
@@ -1186,6 +1188,23 @@ ath10k_wmi_sta_keepalive(struct ath10k *ar,
	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
}

static inline int
ath10k_wmi_set_arp_ns_offload(struct ath10k *ar, struct ath10k_vif *arvif)
{
	struct sk_buff *skb;
	u32 cmd_id;

	if (!ar->wmi.ops->gen_set_arp_ns_offload)
		return -EOPNOTSUPP;

	skb = ar->wmi.ops->gen_set_arp_ns_offload(ar, arvif);
	if (IS_ERR(skb))
		return PTR_ERR(skb);

	cmd_id = ar->wmi.cmd->set_arp_ns_offload_cmdid;
	return ath10k_wmi_cmd_send(ar, skb, cmd_id);
}

static inline int
ath10k_wmi_wow_enable(struct ath10k *ar)
{
+77 −0
Original line number Diff line number Diff line
@@ -3009,6 +3009,82 @@ ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar,
	return skb;
}

static struct sk_buff *
ath10k_wmi_tlv_op_gen_set_arp_ns_offload(struct ath10k *ar,
					 struct ath10k_vif *arvif)
{
	struct wmi_tlv_arp_ns_offload_cmd *cmd;
	struct wmi_tlv *tlv;
	struct sk_buff *skb;
	size_t len;
	void *ptr;
	int i;
	struct wmi_ns_arp_offload_req *arp = &arvif->arp_offload;
	struct wmi_ns_offload *ns_tuple[WMI_MAX_NS_OFFLOADS];
	struct wmi_arp_offload *arp_tuple[WMI_MAX_ARP_OFFLOADS];

	len = sizeof(*cmd) + sizeof(*tlv) +
		sizeof(*tlv) + WMI_MAX_NS_OFFLOADS *
		(sizeof(struct wmi_ns_offload) + sizeof(*tlv)) +
		sizeof(*tlv) + WMI_MAX_ARP_OFFLOADS *
		(sizeof(struct wmi_arp_offload) + sizeof(*tlv));

	skb = ath10k_wmi_alloc_skb(ar, len);
	if (!skb)
		return ERR_PTR(-ENOMEM);

	ptr = (void *)skb->data;
	tlv = ptr;
	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SET_ARP_NS_OFFLOAD_CMD);
	tlv->len = __cpu_to_le16(sizeof(*cmd));
	cmd = (struct wmi_tlv_arp_ns_offload_cmd *)tlv->value;
	cmd->flags = __cpu_to_le32(0);
	cmd->vdev_id = __cpu_to_le32(arvif->vdev_id);

	ptr += (sizeof(*tlv) + sizeof(*cmd));
	tlv = ptr;
	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
	tlv->len = __cpu_to_le16(WMI_MAX_NS_OFFLOADS *
		(sizeof(struct wmi_ns_offload) + sizeof(*tlv)));
	ptr += sizeof(*tlv);
	tlv = ptr;

	for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NS_OFFLOAD_TUPLE);
		tlv->len = __cpu_to_le16(sizeof(struct wmi_ns_offload));
		ns_tuple[i] = (struct wmi_ns_offload *)tlv->value;
		ns_tuple[i]->flags |= __cpu_to_le32(WMI_ARP_NS_OFFLOAD_DISABLE);
		ptr += (sizeof(*tlv) + sizeof(struct wmi_ns_offload));
		tlv = ptr;
	}

	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
	tlv->len = __cpu_to_le16(WMI_MAX_ARP_OFFLOADS *
		(sizeof(struct wmi_arp_offload) + sizeof(*tlv)));
	ptr += sizeof(*tlv);
	tlv = ptr;

	for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
		tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_ARP_OFFLOAD_TUPLE);
		tlv->len = __cpu_to_le16(sizeof(struct wmi_arp_offload));
		arp_tuple[i] = (struct wmi_arp_offload *)tlv->value;
		if (arp->enable_offload && (i == 0)) {
			arp_tuple[i]->flags |=
				__cpu_to_le32(WMI_ARPOFF_FLAGS_VALID);
			memcpy(&arp_tuple[i]->target_ipaddr,
			       &arp->params.ipv4_addr, 4);
		} else {
			arp_tuple[i]->flags |=
				__cpu_to_le32(WMI_ARP_NS_OFFLOAD_DISABLE);
		}
		ptr += (sizeof(*tlv) + sizeof(struct wmi_arp_offload));
		tlv = ptr;
	}

	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set arp ns offload\n");
	return skb;
}

static struct sk_buff *
ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar)
{
@@ -3695,6 +3771,7 @@ static const struct wmi_ops wmi_tlv_ops = {
	.gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie,
	.gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd,
	.gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive,
	.gen_set_arp_ns_offload = ath10k_wmi_tlv_op_gen_set_arp_ns_offload,
	.gen_wow_enable = ath10k_wmi_tlv_op_gen_wow_enable,
	.gen_wow_add_wakeup_event = ath10k_wmi_tlv_op_gen_wow_add_wakeup_event,
	.gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
+6 −0
Original line number Diff line number Diff line
@@ -1557,6 +1557,12 @@ struct wmi_tlv_wow_enable_cmd {
	__le32 pause_iface_config;
} __packed;

struct wmi_tlv_arp_ns_offload_cmd {
	__le32 flags;
	__le32 vdev_id;
	__le32 num_ns_ext_tuples;
} __packed;

struct wmi_tlv_wow_host_wakeup_ind {
	__le32 reserved;
} __packed;
Loading