diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx_80211.h | 14 |
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 | ||
1044 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address) | 1044 | int 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 | |||
871 | struct wl1271_acx_arp_filter { | 876 | struct 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); | |||
1168 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); | 1173 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); |
1169 | int wl1271_acx_smart_reflex(struct wl1271 *wl); | 1174 | int wl1271_acx_smart_reflex(struct wl1271 *wl); |
1170 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1175 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1171 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, __be32 address); | 1176 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address); |
1172 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1177 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1173 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | 1178 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); |
1174 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | 1179 | int 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 | ||
642 | int 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 | |||
642 | int wl1271_build_qos_null_data(struct wl1271 *wl) | 683 | int 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); |
52 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | 52 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, |
53 | struct sk_buff *skb); | 53 | struct sk_buff *skb); |
54 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); | ||
54 | int wl1271_build_qos_null_data(struct wl1271 *wl); | 55 | int wl1271_build_qos_null_data(struct wl1271 *wl); |
55 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); | 56 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); |
56 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 57 | int 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 | ||
144 | struct 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 | ||
144 | struct wl12xx_probe_resp_template { | 158 | struct wl12xx_probe_resp_template { |
145 | struct ieee80211_header header; | 159 | struct ieee80211_header header; |