aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/wl12xx/acx.c4
-rw-r--r--drivers/net/wireless/wl12xx/acx.h9
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c41
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h2
-rw-r--r--drivers/net/wireless/wl12xx/init.c7
-rw-r--r--drivers/net/wireless/wl12xx/main.c24
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_80211.h14
7 files changed, 93 insertions, 8 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 7cbaeb6d2a3..cc4068d2b4a 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1041,7 +1041,7 @@ out:
1041 return ret; 1041 return ret;
1042} 1042}
1043 1043
1044int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address) 1044int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
1045{ 1045{
1046 struct wl1271_acx_arp_filter *acx; 1046 struct wl1271_acx_arp_filter *acx;
1047 int ret; 1047 int ret;
@@ -1057,7 +1057,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address)
1057 acx->version = ACX_IPV4_VERSION; 1057 acx->version = ACX_IPV4_VERSION;
1058 acx->enable = enable; 1058 acx->enable = enable;
1059 1059
1060 if (enable == true) 1060 if (enable)
1061 memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE); 1061 memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
1062 1062
1063 ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, 1063 ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 75a6306ff55..9cbc3f40c8d 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -868,10 +868,15 @@ struct wl1271_acx_bet_enable {
868#define ACX_IPV4_VERSION 4 868#define ACX_IPV4_VERSION 4
869#define ACX_IPV6_VERSION 6 869#define ACX_IPV6_VERSION 6
870#define ACX_IPV4_ADDR_SIZE 4 870#define ACX_IPV4_ADDR_SIZE 4
871
872/* bitmap of enabled arp_filter features */
873#define ACX_ARP_FILTER_ARP_FILTERING BIT(0)
874#define ACX_ARP_FILTER_AUTO_ARP BIT(1)
875
871struct wl1271_acx_arp_filter { 876struct wl1271_acx_arp_filter {
872 struct acx_header header; 877 struct acx_header header;
873 u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ 878 u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
874 u8 enable; /* 1 to enable ARP filtering, 0 to disable */ 879 u8 enable; /* bitmap of enabled ARP filtering features */
875 u8 padding[2]; 880 u8 padding[2];
876 u8 address[16]; /* The configured device IP address - all ARP 881 u8 address[16]; /* The configured device IP address - all ARP
877 requests directed to this IP address will pass 882 requests directed to this IP address will pass
@@ -1168,7 +1173,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
1168int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); 1173int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
1169int wl1271_acx_smart_reflex(struct wl1271 *wl); 1174int wl1271_acx_smart_reflex(struct wl1271 *wl);
1170int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); 1175int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
1171int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address); 1176int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address);
1172int wl1271_acx_pm_config(struct wl1271 *wl); 1177int wl1271_acx_pm_config(struct wl1271 *wl);
1173int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); 1178int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable);
1174int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); 1179int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid);
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 8e438e27e49..0106628aa5a 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -639,6 +639,47 @@ out:
639 return skb; 639 return skb;
640} 640}
641 641
642int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
643{
644 int ret;
645 struct wl12xx_arp_rsp_template tmpl;
646 struct ieee80211_hdr_3addr *hdr;
647 struct arphdr *arp_hdr;
648
649 memset(&tmpl, 0, sizeof(tmpl));
650
651 /* mac80211 header */
652 hdr = &tmpl.hdr;
653 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
654 IEEE80211_STYPE_DATA |
655 IEEE80211_FCTL_TODS);
656 memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN);
657 memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN);
658 memset(hdr->addr3, 0xff, ETH_ALEN);
659
660 /* llc layer */
661 memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header));
662 tmpl.llc_type = htons(ETH_P_ARP);
663
664 /* arp header */
665 arp_hdr = &tmpl.arp_hdr;
666 arp_hdr->ar_hrd = htons(ARPHRD_ETHER);
667 arp_hdr->ar_pro = htons(ETH_P_IP);
668 arp_hdr->ar_hln = ETH_ALEN;
669 arp_hdr->ar_pln = 4;
670 arp_hdr->ar_op = htons(ARPOP_REPLY);
671
672 /* arp payload */
673 memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN);
674 tmpl.sender_ip = ip_addr;
675
676 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP,
677 &tmpl, sizeof(tmpl), 0,
678 wl->basic_rate);
679
680 return ret;
681}
682
642int wl1271_build_qos_null_data(struct wl1271 *wl) 683int wl1271_build_qos_null_data(struct wl1271 *wl)
643{ 684{
644 struct ieee80211_qos_hdr template; 685 struct ieee80211_qos_hdr template;
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 111d112544f..2a1d9db7ceb 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -51,6 +51,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
51 const u8 *ie, size_t ie_len, u8 band); 51 const u8 *ie, size_t ie_len, u8 band);
52struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, 52struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
53 struct sk_buff *skb); 53 struct sk_buff *skb);
54int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
54int wl1271_build_qos_null_data(struct wl1271 *wl); 55int wl1271_build_qos_null_data(struct wl1271 *wl);
55int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); 56int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
56int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); 57int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
@@ -124,6 +125,7 @@ enum cmd_templ {
124 CMD_TEMPL_CTS, /* 125 CMD_TEMPL_CTS, /*
125 * For CTS-to-self (FastCTS) mechanism 126 * For CTS-to-self (FastCTS) mechanism
126 * for BT/WLAN coexistence (SoftGemini). */ 127 * for BT/WLAN coexistence (SoftGemini). */
128 CMD_TEMPL_ARP_RSP,
127 CMD_TEMPL_MAX = 0xff 129 CMD_TEMPL_MAX = 0xff
128}; 130};
129 131
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 7949d346aad..0392e37f0d6 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -102,6 +102,13 @@ int wl1271_init_templates_config(struct wl1271 *wl)
102 if (ret < 0) 102 if (ret < 0)
103 return ret; 103 return ret;
104 104
105 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL,
106 sizeof
107 (struct wl12xx_arp_rsp_template),
108 0, WL1271_RATE_AUTOMATIC);
109 if (ret < 0)
110 return ret;
111
105 for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { 112 for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
106 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, 113 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
107 WL1271_CMD_TEMPL_MAX_SIZE, i, 114 WL1271_CMD_TEMPL_MAX_SIZE, i,
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0b79c49cd87..f7d7cad730a 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2110,10 +2110,26 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
2110 __be32 addr = bss_conf->arp_addr_list[0]; 2110 __be32 addr = bss_conf->arp_addr_list[0];
2111 WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); 2111 WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
2112 2112
2113 if (bss_conf->arp_addr_cnt == 1 && bss_conf->arp_filter_enabled) 2113 if (bss_conf->arp_addr_cnt == 1 &&
2114 ret = wl1271_acx_arp_ip_filter(wl, true, addr); 2114 bss_conf->arp_filter_enabled) {
2115 else 2115 /*
2116 ret = wl1271_acx_arp_ip_filter(wl, false, addr); 2116 * The template should have been configured only upon
2117 * association. however, it seems that the correct ip
2118 * isn't being set (when sending), so we have to
2119 * reconfigure the template upon every ip change.
2120 */
2121 ret = wl1271_cmd_build_arp_rsp(wl, addr);
2122 if (ret < 0) {
2123 wl1271_warning("build arp rsp failed: %d", ret);
2124 goto out_sleep;
2125 }
2126
2127 ret = wl1271_acx_arp_ip_filter(wl,
2128 (ACX_ARP_FILTER_ARP_FILTERING |
2129 ACX_ARP_FILTER_AUTO_ARP),
2130 addr);
2131 } else
2132 ret = wl1271_acx_arp_ip_filter(wl, 0, addr);
2117 2133
2118 if (ret < 0) 2134 if (ret < 0)
2119 goto out_sleep; 2135 goto out_sleep;
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index 18462802721..8ee0d3a8fa6 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -2,6 +2,7 @@
2#define __WL12XX_80211_H__ 2#define __WL12XX_80211_H__
3 3
4#include <linux/if_ether.h> /* ETH_ALEN */ 4#include <linux/if_ether.h> /* ETH_ALEN */
5#include <linux/if_arp.h>
5 6
6/* RATES */ 7/* RATES */
7#define IEEE80211_CCK_RATE_1MB 0x02 8#define IEEE80211_CCK_RATE_1MB 0x02
@@ -140,6 +141,19 @@ struct wl12xx_probe_req_template {
140 struct wl12xx_ie_rates ext_rates; 141 struct wl12xx_ie_rates ext_rates;
141} __packed; 142} __packed;
142 143
144struct wl12xx_arp_rsp_template {
145 struct ieee80211_hdr_3addr hdr;
146
147 u8 llc_hdr[sizeof(rfc1042_header)];
148 u16 llc_type;
149
150 struct arphdr arp_hdr;
151 u8 sender_hw[ETH_ALEN];
152 u32 sender_ip;
153 u8 target_hw[ETH_ALEN];
154 u32 target_ip;
155} __packed;
156
143 157
144struct wl12xx_probe_resp_template { 158struct wl12xx_probe_resp_template {
145 struct ieee80211_header header; 159 struct ieee80211_header header;