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

Commit b9a82f89 authored by Hante Meuleman's avatar Hante Meuleman Committed by John W. Linville
Browse files
parent 330b4e4b
Loading
Loading
Loading
Loading
+62 −27
Original line number Diff line number Diff line
@@ -55,59 +55,63 @@

/* WOWL bits */
/* Wakeup on Magic packet: */
#define WL_WOWL_MAGIC			(1 << 0)
#define BRCMF_WOWL_MAGIC		(1 << 0)
/* Wakeup on Netpattern */
#define WL_WOWL_NET			(1 << 1)
#define BRCMF_WOWL_NET			(1 << 1)
/* Wakeup on loss-of-link due to Disassoc/Deauth: */
#define WL_WOWL_DIS			(1 << 2)
#define BRCMF_WOWL_DIS			(1 << 2)
/* Wakeup on retrograde TSF: */
#define WL_WOWL_RETR			(1 << 3)
#define BRCMF_WOWL_RETR			(1 << 3)
/* Wakeup on loss of beacon: */
#define WL_WOWL_BCN			(1 << 4)
#define BRCMF_WOWL_BCN			(1 << 4)
/* Wakeup after test: */
#define WL_WOWL_TST			(1 << 5)
#define BRCMF_WOWL_TST			(1 << 5)
/* Wakeup after PTK refresh: */
#define WL_WOWL_M1			(1 << 6)
#define BRCMF_WOWL_M1			(1 << 6)
/* Wakeup after receipt of EAP-Identity Req: */
#define WL_WOWL_EAPID			(1 << 7)
#define BRCMF_WOWL_EAPID		(1 << 7)
/* Wakeind via PME(0) or GPIO(1): */
#define WL_WOWL_PME_GPIO		(1 << 8)
#define BRCMF_WOWL_PME_GPIO		(1 << 8)
/* need tkip phase 1 key to be updated by the driver: */
#define WL_WOWL_NEEDTKIP1		(1 << 9)
#define BRCMF_WOWL_NEEDTKIP1		(1 << 9)
/* enable wakeup if GTK fails: */
#define WL_WOWL_GTK_FAILURE		(1 << 10)
#define BRCMF_WOWL_GTK_FAILURE		(1 << 10)
/* support extended magic packets: */
#define WL_WOWL_EXTMAGPAT		(1 << 11)
#define BRCMF_WOWL_EXTMAGPAT		(1 << 11)
/* support ARP/NS/keepalive offloading: */
#define WL_WOWL_ARPOFFLOAD		(1 << 12)
#define BRCMF_WOWL_ARPOFFLOAD		(1 << 12)
/* read protocol version for EAPOL frames: */
#define WL_WOWL_WPA2			(1 << 13)
#define BRCMF_WOWL_WPA2			(1 << 13)
/* If the bit is set, use key rotaton: */
#define WL_WOWL_KEYROT			(1 << 14)
#define BRCMF_WOWL_KEYROT		(1 << 14)
/* If the bit is set, frm received was bcast frame: */
#define WL_WOWL_BCAST			(1 << 15)
#define BRCMF_WOWL_BCAST		(1 << 15)
/* If the bit is set, scan offload is enabled: */
#define WL_WOWL_SCANOL			(1 << 16)
#define BRCMF_WOWL_SCANOL		(1 << 16)
/* Wakeup on tcpkeep alive timeout: */
#define WL_WOWL_TCPKEEP_TIME		(1 << 17)
#define BRCMF_WOWL_TCPKEEP_TIME		(1 << 17)
/* Wakeup on mDNS Conflict Resolution: */
#define WL_WOWL_MDNS_CONFLICT		(1 << 18)
#define BRCMF_WOWL_MDNS_CONFLICT	(1 << 18)
/* Wakeup on mDNS Service Connect: */
#define WL_WOWL_MDNS_SERVICE		(1 << 19)
#define BRCMF_WOWL_MDNS_SERVICE		(1 << 19)
/* tcp keepalive got data: */
#define WL_WOWL_TCPKEEP_DATA		(1 << 20)
#define BRCMF_WOWL_TCPKEEP_DATA		(1 << 20)
/* Firmware died in wowl mode: */
#define WL_WOWL_FW_HALT			(1 << 21)
#define BRCMF_WOWL_FW_HALT		(1 << 21)
/* Enable detection of radio button changes: */
#define WL_WOWL_ENAB_HWRADIO		(1 << 22)
#define BRCMF_WOWL_ENAB_HWRADIO		(1 << 22)
/* Offloads detected MIC failure(s): */
#define WL_WOWL_MIC_FAIL		(1 << 23)
#define BRCMF_WOWL_MIC_FAIL		(1 << 23)
/* Wakeup in Unassociated state (Net/Magic Pattern): */
#define WL_WOWL_UNASSOC			(1 << 24)
#define BRCMF_WOWL_UNASSOC		(1 << 24)
/* Wakeup if received matched secured pattern: */
#define WL_WOWL_SECURE			(1 << 25)
#define BRCMF_WOWL_SECURE		(1 << 25)
/* Link Down indication in WoWL mode: */
#define WL_WOWL_LINKDOWN		(1 << 31)
#define BRCMF_WOWL_LINKDOWN		(1 << 31)

#define BRCMF_WOWL_MAXPATTERNS		8
#define BRCMF_WOWL_MAXPATTERNSIZE	128


/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
@@ -124,6 +128,12 @@ enum brcmf_fil_p2p_if_types {
	BRCMF_FIL_P2P_IF_DEV,
};

enum brcmf_wowl_pattern_type {
	BRCMF_WOWL_PATTERN_TYPE_BITMAP = 0,
	BRCMF_WOWL_PATTERN_TYPE_ARP,
	BRCMF_WOWL_PATTERN_TYPE_NA
};

struct brcmf_fil_p2p_if_le {
	u8 addr[ETH_ALEN];
	__le16 type;
@@ -484,4 +494,29 @@ struct brcmf_rx_mgmt_data {
	__be32	rate;
};

/**
 * struct brcmf_fil_wowl_pattern_le - wowl pattern configuration struct.
 *
 * @cmd: "add", "del" or "clr".
 * @masksize: Size of the mask in #of bytes
 * @offset: Pattern byte offset in packet
 * @patternoffset: Offset of start of pattern. Starting from field masksize.
 * @patternsize: Size of the pattern itself in #of bytes
 * @id: id
 * @reasonsize: Size of the wakeup reason code
 * @type: Type of pattern (enum brcmf_wowl_pattern_type)
 */
struct brcmf_fil_wowl_pattern_le {
	u8	cmd[4];
	__le32	masksize;
	__le32	offset;
	__le32	patternoffset;
	__le32	patternsize;
	__le32	id;
	__le32	reasonsize;
	__le32	type;
	/* u8 mask[] - Mask follows the structure above */
	/* u8 pattern[] - Pattern follows the mask is at 'patternoffset' */
};

#endif /* FWIL_TYPES_H_ */
+58 −8
Original line number Diff line number Diff line
@@ -2779,6 +2779,44 @@ static __always_inline void brcmf_delay(u32 ms)
	}
}

static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
				     u8 *pattern, u32 patternsize, u8 *mask,
				     u32 packet_offset)
{
	struct brcmf_fil_wowl_pattern_le *filter;
	u32 masksize;
	u32 patternoffset;
	u8 *buf;
	u32 bufsize;
	s32 ret;

	masksize = (patternsize + 7) / 8;
	patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize;

	bufsize = sizeof(*filter) + patternsize + masksize;
	buf = kzalloc(bufsize, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;
	filter = (struct brcmf_fil_wowl_pattern_le *)buf;

	memcpy(filter->cmd, cmd, 4);
	filter->masksize = cpu_to_le32(masksize);
	filter->offset = cpu_to_le32(packet_offset);
	filter->patternoffset = cpu_to_le32(patternoffset);
	filter->patternsize = cpu_to_le32(patternsize);
	filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP);

	if ((mask) && (masksize))
		memcpy(buf + sizeof(*filter), mask, masksize);
	if ((pattern) && (patternsize))
		memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize);

	ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize);

	kfree(buf);
	return ret;
}

static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
{
	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
@@ -2788,10 +2826,11 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
	brcmf_dbg(TRACE, "Enter\n");

	if (cfg->wowl_enabled) {
		brcmf_configure_arp_offload(ifp, true);
		brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
				      cfg->pre_wowl_pmmode);
		brcmf_fil_iovar_data_set(ifp, "wowl_pattern", "clr", 4);
		brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
		brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
		cfg->wowl_enabled = false;
	}
	return 0;
@@ -2802,21 +2841,29 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,
				 struct cfg80211_wowlan *wowl)
{
	u32 wowl_config;
	u32 i;

	brcmf_dbg(TRACE, "Suspend, wowl config.\n");

	brcmf_configure_arp_offload(ifp, false);
	brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->pre_wowl_pmmode);
	brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX);

	wowl_config = 0;
	if (wowl->disconnect)
		wowl_config |= WL_WOWL_DIS | WL_WOWL_BCN | WL_WOWL_RETR;
		/* Note: if "wowl" target and not "wowlpf" then wowl_bcn_loss
		 * should be configured. This paramater is not supported by
		 * wowlpf.
		 */
		wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN | BRCMF_WOWL_RETR;
	if (wowl->magic_pkt)
		wowl_config |= WL_WOWL_MAGIC;
		wowl_config |= BRCMF_WOWL_MAGIC;
	if ((wowl->patterns) && (wowl->n_patterns)) {
		wowl_config |= BRCMF_WOWL_NET;
		for (i = 0; i < wowl->n_patterns; i++) {
			brcmf_config_wowl_pattern(ifp, "add",
				(u8 *)wowl->patterns[i].pattern,
				wowl->patterns[i].pattern_len,
				(u8 *)wowl->patterns[i].mask,
				wowl->patterns[i].pkt_offset);
		}
	}
	brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
	brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
	brcmf_bus_wowl_config(cfg->pub->bus_if, true);
@@ -5440,10 +5487,13 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
	wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
}


#ifdef CONFIG_PM
static const struct wiphy_wowlan_support brcmf_wowlan_support = {
	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
	.n_patterns = BRCMF_WOWL_MAXPATTERNS,
	.pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE,
	.pattern_min_len = 1,
	.max_pkt_offset = 1500,
};
#endif