aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.c19
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.h3
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c142
3 files changed, 56 insertions, 108 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 5cadb9d06c76..b45ebbcf6c4a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -1075,13 +1075,12 @@ out:
1075 return ret; 1075 return ret;
1076} 1076}
1077 1077
1078int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, 1078int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 mode, u8 *address)
1079 u8 version)
1080{ 1079{
1081 struct wl1271_acx_arp_filter *acx; 1080 struct wl1271_acx_arp_filter *acx;
1082 int ret; 1081 int ret;
1083 1082
1084 wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable); 1083 wl1271_debug(DEBUG_ACX, "acx arp ip filter, mode: %d", mode);
1085 1084
1086 acx = kzalloc(sizeof(*acx), GFP_KERNEL); 1085 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
1087 if (!acx) { 1086 if (!acx) {
@@ -1089,17 +1088,11 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
1089 goto out; 1088 goto out;
1090 } 1089 }
1091 1090
1092 acx->version = version; 1091 acx->version = ACX_IPV4_VERSION;
1093 acx->enable = enable; 1092 acx->enable = mode;
1094 1093
1095 if (enable == true) { 1094 if (mode != ACX_ARP_DISABLE)
1096 if (version == ACX_IPV4_VERSION) 1095 memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE);
1097 memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE);
1098 else if (version == ACX_IPV6_VERSION)
1099 memcpy(acx->address, address, sizeof(acx->address));
1100 else
1101 wl1271_error("Invalid IP version");
1102 }
1103 1096
1104 ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, 1097 ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
1105 acx, sizeof(*acx)); 1098 acx, sizeof(*acx));
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 914b29b92999..6a6f3e3ebf34 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -1117,8 +1117,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
1117int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); 1117int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
1118int wl1271_acx_smart_reflex(struct wl1271 *wl); 1118int wl1271_acx_smart_reflex(struct wl1271 *wl);
1119int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); 1119int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
1120int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, 1120int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 mode, u8 *address);
1121 u8 version);
1122int wl1271_acx_pm_config(struct wl1271 *wl); 1121int wl1271_acx_pm_config(struct wl1271 *wl);
1123int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); 1122int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable);
1124int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); 1123int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid);
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 5970fde49d40..a37244c88fee 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -28,7 +28,6 @@
28#include <linux/crc32.h> 28#include <linux/crc32.h>
29#include <linux/etherdevice.h> 29#include <linux/etherdevice.h>
30#include <linux/vmalloc.h> 30#include <linux/vmalloc.h>
31#include <linux/inetdevice.h>
32#include <linux/platform_device.h> 31#include <linux/platform_device.h>
33#include <linux/slab.h> 32#include <linux/slab.h>
34 33
@@ -818,93 +817,6 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
818 return NETDEV_TX_OK; 817 return NETDEV_TX_OK;
819} 818}
820 819
821static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
822 void *arg)
823{
824 struct net_device *dev;
825 struct wireless_dev *wdev;
826 struct wiphy *wiphy;
827 struct ieee80211_hw *hw;
828 struct wl1271 *wl;
829 struct wl1271 *wl_temp;
830 struct in_device *idev;
831 struct in_ifaddr *ifa = arg;
832 int ret = 0;
833
834 /* FIXME: this ugly function should probably be implemented in the
835 * mac80211, and here should only be a simple callback handling actual
836 * setting of the filters. Now we need to dig up references to
837 * various structures to gain access to what we need.
838 * Also, because of this, there is no "initial" setting of the filter
839 * in "op_start", because we don't want to dig up struct net_device
840 * there - the filter will be set upon first change of the interface
841 * IP address. */
842
843 dev = ifa->ifa_dev->dev;
844
845 wdev = dev->ieee80211_ptr;
846 if (wdev == NULL)
847 return NOTIFY_DONE;
848
849 wiphy = wdev->wiphy;
850 if (wiphy == NULL)
851 return NOTIFY_DONE;
852
853 hw = wiphy_priv(wiphy);
854 if (hw == NULL)
855 return NOTIFY_DONE;
856
857 /* Check that the interface is one supported by this driver. */
858 wl_temp = hw->priv;
859 list_for_each_entry(wl, &wl_list, list) {
860 if (wl == wl_temp)
861 break;
862 }
863 if (wl != wl_temp)
864 return NOTIFY_DONE;
865
866 /* Get the interface IP address for the device. "ifa" will become
867 NULL if:
868 - there is no IPV4 protocol address configured
869 - there are multiple (virtual) IPV4 addresses configured
870 When "ifa" is NULL, filtering will be disabled.
871 */
872 ifa = NULL;
873 idev = dev->ip_ptr;
874 if (idev)
875 ifa = idev->ifa_list;
876
877 if (ifa && ifa->ifa_next)
878 ifa = NULL;
879
880 mutex_lock(&wl->mutex);
881
882 if (wl->state == WL1271_STATE_OFF)
883 goto out;
884
885 ret = wl1271_ps_elp_wakeup(wl, false);
886 if (ret < 0)
887 goto out;
888 if (ifa)
889 ret = wl1271_acx_arp_ip_filter(wl, true,
890 (u8 *)&ifa->ifa_address,
891 ACX_IPV4_VERSION);
892 else
893 ret = wl1271_acx_arp_ip_filter(wl, false, NULL,
894 ACX_IPV4_VERSION);
895 wl1271_ps_elp_sleep(wl);
896
897out:
898 mutex_unlock(&wl->mutex);
899
900 return NOTIFY_OK;
901}
902
903static struct notifier_block wl1271_dev_notifier = {
904 .notifier_call = wl1271_dev_notify,
905};
906
907
908static int wl1271_op_start(struct ieee80211_hw *hw) 820static int wl1271_op_start(struct ieee80211_hw *hw)
909{ 821{
910 wl1271_debug(DEBUG_MAC80211, "mac80211 start"); 822 wl1271_debug(DEBUG_MAC80211, "mac80211 start");
@@ -1008,10 +920,8 @@ power_off:
1008out: 920out:
1009 mutex_unlock(&wl->mutex); 921 mutex_unlock(&wl->mutex);
1010 922
1011 if (!ret) { 923 if (!ret)
1012 list_add(&wl->list, &wl_list); 924 list_add(&wl->list, &wl_list);
1013 register_inetaddr_notifier(&wl1271_dev_notifier);
1014 }
1015 925
1016 return ret; 926 return ret;
1017} 927}
@@ -1022,8 +932,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
1022 struct wl1271 *wl = hw->priv; 932 struct wl1271 *wl = hw->priv;
1023 int i; 933 int i;
1024 934
1025 unregister_inetaddr_notifier(&wl1271_dev_notifier);
1026
1027 mutex_lock(&wl->mutex); 935 mutex_lock(&wl->mutex);
1028 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); 936 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
1029 937
@@ -1400,6 +1308,53 @@ struct wl1271_filter_params {
1400 u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; 1308 u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
1401}; 1309};
1402 1310
1311static int wl1271_op_configure_arp_filter(struct ieee80211_hw *hw,
1312 struct ieee80211_vif *vif,
1313 struct in_ifaddr *ifa_list)
1314{
1315 struct wl1271 *wl = hw->priv;
1316 int ret = 0;
1317
1318 WARN_ON(vif != wl->vif);
1319
1320 /* disable filtering if there are multiple addresses */
1321 if (ifa_list && ifa_list->ifa_next)
1322 ifa_list = NULL;
1323
1324 mutex_lock(&wl->mutex);
1325
1326 if (wl->state == WL1271_STATE_OFF)
1327 goto out;
1328
1329 WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
1330
1331 ret = wl1271_ps_elp_wakeup(wl, false);
1332 if (ret < 0)
1333 goto out;
1334
1335 if (ifa_list) {
1336 ret = wl1271_cmd_build_arp_reply(wl, &ifa_list->ifa_address);
1337 if (ret < 0)
1338 goto out_sleep;
1339 ret = wl1271_acx_arp_ip_filter(wl, ACX_ARP_FILTER_AND_REPLY,
1340 (u8 *)&ifa_list->ifa_address);
1341 if (ret < 0)
1342 goto out_sleep;
1343 } else {
1344 ret = wl1271_acx_arp_ip_filter(wl, ACX_ARP_DISABLE, NULL);
1345 if (ret < 0)
1346 goto out_sleep;
1347 }
1348
1349out_sleep:
1350 wl1271_ps_elp_sleep(wl);
1351
1352out:
1353 mutex_unlock(&wl->mutex);
1354
1355 return ret;
1356}
1357
1403static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, 1358static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw,
1404 struct netdev_hw_addr_list *mc_list) 1359 struct netdev_hw_addr_list *mc_list)
1405{ 1360{
@@ -2213,6 +2168,7 @@ static const struct ieee80211_ops wl1271_ops = {
2213 .add_interface = wl1271_op_add_interface, 2168 .add_interface = wl1271_op_add_interface,
2214 .remove_interface = wl1271_op_remove_interface, 2169 .remove_interface = wl1271_op_remove_interface,
2215 .config = wl1271_op_config, 2170 .config = wl1271_op_config,
2171 .configure_arp_filter = wl1271_op_configure_arp_filter,
2216 .prepare_multicast = wl1271_op_prepare_multicast, 2172 .prepare_multicast = wl1271_op_prepare_multicast,
2217 .configure_filter = wl1271_op_configure_filter, 2173 .configure_filter = wl1271_op_configure_filter,
2218 .tx = wl1271_op_tx, 2174 .tx = wl1271_op_tx,