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

Commit 204cc5c4 authored by David Gnedt's avatar David Gnedt Committed by John W. Linville
Browse files

wl1251: implement hardware ARP filtering



Update hardware ARP filter configuration on BSS_CHANGED_ARP_FILTER
notification from mac80211.
Ported from wl1271 driver.

Signed-off-by: default avatarDavid Gnedt <david.gnedt@davizone.at>
Signed-off-by: default avatarPali Rohár <pali.rohar@gmail.com>
Signed-off-by: default avatarPavel Machek <pavel@ucw.cz>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f7ad1eed
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -960,6 +960,32 @@ out:
	return ret;
}

int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
{
	struct wl1251_acx_arp_filter *acx;
	int ret;

	wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);

	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
	if (!acx)
		return -ENOMEM;

	acx->version = ACX_IPV4_VERSION;
	acx->enable = enable;

	if (enable)
		memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);

	ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER,
				   acx, sizeof(*acx));
	if (ret < 0)
		wl1251_warning("failed to set arp ip filter: %d", ret);

	kfree(acx);
	return ret;
}

int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
		      u8 aifs, u16 txop)
{
+15 −0
Original line number Diff line number Diff line
@@ -1232,6 +1232,20 @@ struct wl1251_acx_bet_enable {
	u8 padding[2];
} __packed;

#define ACX_IPV4_VERSION 4
#define ACX_IPV6_VERSION 6
#define ACX_IPV4_ADDR_SIZE 4
struct wl1251_acx_arp_filter {
	struct acx_header header;
	u8 version;	/* The IP version: 4 - IPv4, 6 - IPv6.*/
	u8 enable;	/* 1 - ARP filtering is enabled, 0 - disabled */
	u8 padding[2];
	u8 address[16];	/* The IP address used to filter ARP packets.
			   ARP packets that do not match this address are
			   dropped. When the IP Version is 4, the last 12
			   bytes of the the address are ignored. */
} __attribute__((packed));

struct wl1251_acx_ac_cfg {
	struct acx_header header;

@@ -1473,6 +1487,7 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl);
int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
			  u8 max_consecutive);
int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address);
int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
		      u8 aifs, u16 txop);
int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
+12 −0
Original line number Diff line number Diff line
@@ -979,6 +979,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
{
	struct wl1251 *wl = hw->priv;
	struct sk_buff *beacon, *skb;
	bool enable;
	int ret;

	wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
@@ -1077,6 +1078,17 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
		}
	}

	if (changed & BSS_CHANGED_ARP_FILTER) {
		__be32 addr = bss_conf->arp_addr_list[0];
		WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);

		enable = bss_conf->arp_addr_cnt == 1 && bss_conf->assoc;
		wl1251_acx_arp_ip_filter(wl, enable, addr);

		if (ret < 0)
			goto out_sleep;
	}

	if (changed & BSS_CHANGED_BEACON) {
		beacon = ieee80211_beacon_get(hw, vif);
		if (!beacon)