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

Commit 0d472953 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ath10k: add support for wowlan offload for wcn3990 WLAN module"

parents bb4747de 2fde1865
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