diff options
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_acx.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 142 |
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 | ||
1078 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1078 | int 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); | |||
1117 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); | 1117 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); |
1118 | int wl1271_acx_smart_reflex(struct wl1271 *wl); | 1118 | int wl1271_acx_smart_reflex(struct wl1271 *wl); |
1119 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1119 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1120 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1120 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 mode, u8 *address); |
1121 | u8 version); | ||
1122 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1121 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1123 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | 1122 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); |
1124 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | 1123 | int 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 | ||
821 | static 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 | |||
897 | out: | ||
898 | mutex_unlock(&wl->mutex); | ||
899 | |||
900 | return NOTIFY_OK; | ||
901 | } | ||
902 | |||
903 | static struct notifier_block wl1271_dev_notifier = { | ||
904 | .notifier_call = wl1271_dev_notify, | ||
905 | }; | ||
906 | |||
907 | |||
908 | static int wl1271_op_start(struct ieee80211_hw *hw) | 820 | static 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: | |||
1008 | out: | 920 | out: |
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 | ||
1311 | static 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 | |||
1349 | out_sleep: | ||
1350 | wl1271_ps_elp_sleep(wl); | ||
1351 | |||
1352 | out: | ||
1353 | mutex_unlock(&wl->mutex); | ||
1354 | |||
1355 | return ret; | ||
1356 | } | ||
1357 | |||
1403 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, | 1358 | static 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, |