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

Commit c5312772 authored by Eliad Peller's avatar Eliad Peller Committed by Luciano Coelho
Browse files

wl12xx: add auto-arp support



The auto-arp feature of wl12xx allows the firmware to automatically
response to arp requests asking for its ip.

in order to use it, we configure the arp response template and
enable the corresponding bit in wl1271_acx_arp_filter (along with
passing its ip)

Signed-off-by: default avatarEliad Peller <eliad@wizery.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
parent b69eb80b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1041,7 +1041,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
	return ret;
}

int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address)
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
{
	struct wl1271_acx_arp_filter *acx;
	int ret;
@@ -1057,7 +1057,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address)
	acx->version = ACX_IPV4_VERSION;
	acx->enable = enable;

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

	ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
+7 −2
Original line number Diff line number Diff line
@@ -868,10 +868,15 @@ struct wl1271_acx_bet_enable {
#define ACX_IPV4_VERSION 4
#define ACX_IPV6_VERSION 6
#define ACX_IPV4_ADDR_SIZE 4

/* bitmap of enabled arp_filter features */
#define ACX_ARP_FILTER_ARP_FILTERING	BIT(0)
#define ACX_ARP_FILTER_AUTO_ARP		BIT(1)

struct wl1271_acx_arp_filter {
	struct acx_header header;
	u8 version;         /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
	u8 enable;          /* 1 to enable ARP filtering, 0 to disable */
	u8 enable;          /* bitmap of enabled ARP filtering features */
	u8 padding[2];
	u8 address[16];     /* The configured device IP address - all ARP
			       requests directed to this IP address will pass
@@ -1168,7 +1173,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
int wl1271_acx_smart_reflex(struct wl1271 *wl);
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address);
int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address);
int wl1271_acx_pm_config(struct wl1271 *wl);
int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable);
int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid);
+41 −0
Original line number Diff line number Diff line
@@ -639,6 +639,47 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
	return skb;
}

int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
{
	int ret;
	struct wl12xx_arp_rsp_template tmpl;
	struct ieee80211_hdr_3addr *hdr;
	struct arphdr *arp_hdr;

	memset(&tmpl, 0, sizeof(tmpl));

	/* mac80211 header */
	hdr = &tmpl.hdr;
	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
					 IEEE80211_STYPE_DATA |
					 IEEE80211_FCTL_TODS);
	memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN);
	memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN);
	memset(hdr->addr3, 0xff, ETH_ALEN);

	/* llc layer */
	memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header));
	tmpl.llc_type = htons(ETH_P_ARP);

	/* arp header */
	arp_hdr = &tmpl.arp_hdr;
	arp_hdr->ar_hrd = htons(ARPHRD_ETHER);
	arp_hdr->ar_pro = htons(ETH_P_IP);
	arp_hdr->ar_hln = ETH_ALEN;
	arp_hdr->ar_pln = 4;
	arp_hdr->ar_op = htons(ARPOP_REPLY);

	/* arp payload */
	memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN);
	tmpl.sender_ip = ip_addr;

	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP,
				      &tmpl, sizeof(tmpl), 0,
				      wl->basic_rate);

	return ret;
}

int wl1271_build_qos_null_data(struct wl1271 *wl)
{
	struct ieee80211_qos_hdr template;
+2 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
			       const u8 *ie, size_t ie_len, u8 band);
struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
					      struct sk_buff *skb);
int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
int wl1271_build_qos_null_data(struct wl1271 *wl);
int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
@@ -124,6 +125,7 @@ enum cmd_templ {
	CMD_TEMPL_CTS,           /*
				  * For CTS-to-self (FastCTS) mechanism
				  * for BT/WLAN coexistence (SoftGemini). */
	CMD_TEMPL_ARP_RSP,
	CMD_TEMPL_MAX = 0xff
};

+7 −0
Original line number Diff line number Diff line
@@ -102,6 +102,13 @@ int wl1271_init_templates_config(struct wl1271 *wl)
	if (ret < 0)
		return ret;

	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL,
				      sizeof
				      (struct wl12xx_arp_rsp_template),
				      0, WL1271_RATE_AUTOMATIC);
	if (ret < 0)
		return ret;

	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
					      WL1271_CMD_TEMPL_MAX_SIZE, i,
Loading