aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 2b3cf39dd4b1..3951b5b13424 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -229,10 +229,12 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
229static void ath5k_remove_interface(struct ieee80211_hw *hw, 229static void ath5k_remove_interface(struct ieee80211_hw *hw,
230 struct ieee80211_if_init_conf *conf); 230 struct ieee80211_if_init_conf *conf);
231static int ath5k_config(struct ieee80211_hw *hw, u32 changed); 231static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
232static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
233 int mc_count, struct dev_addr_list *mc_list);
232static void ath5k_configure_filter(struct ieee80211_hw *hw, 234static void ath5k_configure_filter(struct ieee80211_hw *hw,
233 unsigned int changed_flags, 235 unsigned int changed_flags,
234 unsigned int *new_flags, 236 unsigned int *new_flags,
235 int mc_count, struct dev_mc_list *mclist); 237 u64 multicast);
236static int ath5k_set_key(struct ieee80211_hw *hw, 238static int ath5k_set_key(struct ieee80211_hw *hw,
237 enum set_key_cmd cmd, 239 enum set_key_cmd cmd,
238 struct ieee80211_vif *vif, struct ieee80211_sta *sta, 240 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
@@ -260,6 +262,7 @@ static const struct ieee80211_ops ath5k_hw_ops = {
260 .add_interface = ath5k_add_interface, 262 .add_interface = ath5k_add_interface,
261 .remove_interface = ath5k_remove_interface, 263 .remove_interface = ath5k_remove_interface,
262 .config = ath5k_config, 264 .config = ath5k_config,
265 .prepare_multicast = ath5k_prepare_multicast,
263 .configure_filter = ath5k_configure_filter, 266 .configure_filter = ath5k_configure_filter,
264 .set_key = ath5k_set_key, 267 .set_key = ath5k_set_key,
265 .get_stats = ath5k_get_stats, 268 .get_stats = ath5k_get_stats,
@@ -2853,6 +2856,37 @@ unlock:
2853 return ret; 2856 return ret;
2854} 2857}
2855 2858
2859static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw,
2860 int mc_count, struct dev_addr_list *mclist)
2861{
2862 u32 mfilt[2], val;
2863 int i;
2864 u8 pos;
2865
2866 mfilt[0] = 0;
2867 mfilt[1] = 1;
2868
2869 for (i = 0; i < mc_count; i++) {
2870 if (!mclist)
2871 break;
2872 /* calculate XOR of eight 6-bit values */
2873 val = get_unaligned_le32(mclist->dmi_addr + 0);
2874 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2875 val = get_unaligned_le32(mclist->dmi_addr + 3);
2876 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2877 pos &= 0x3f;
2878 mfilt[pos / 32] |= (1 << (pos % 32));
2879 /* XXX: we might be able to just do this instead,
2880 * but not sure, needs testing, if we do use this we'd
2881 * neet to inform below to not reset the mcast */
2882 /* ath5k_hw_set_mcast_filterindex(ah,
2883 * mclist->dmi_addr[5]); */
2884 mclist = mclist->next;
2885 }
2886
2887 return ((u64)(mfilt[1]) << 32) | mfilt[0];
2888}
2889
2856#define SUPPORTED_FIF_FLAGS \ 2890#define SUPPORTED_FIF_FLAGS \
2857 FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ 2891 FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
2858 FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ 2892 FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
@@ -2878,16 +2912,14 @@ unlock:
2878static void ath5k_configure_filter(struct ieee80211_hw *hw, 2912static void ath5k_configure_filter(struct ieee80211_hw *hw,
2879 unsigned int changed_flags, 2913 unsigned int changed_flags,
2880 unsigned int *new_flags, 2914 unsigned int *new_flags,
2881 int mc_count, struct dev_mc_list *mclist) 2915 u64 multicast)
2882{ 2916{
2883 struct ath5k_softc *sc = hw->priv; 2917 struct ath5k_softc *sc = hw->priv;
2884 struct ath5k_hw *ah = sc->ah; 2918 struct ath5k_hw *ah = sc->ah;
2885 u32 mfilt[2], val, rfilt; 2919 u32 mfilt[2], rfilt;
2886 u8 pos;
2887 int i;
2888 2920
2889 mfilt[0] = 0; 2921 mfilt[0] = multicast;
2890 mfilt[1] = 0; 2922 mfilt[1] = multicast >> 32;
2891 2923
2892 /* Only deal with supported flags */ 2924 /* Only deal with supported flags */
2893 changed_flags &= SUPPORTED_FIF_FLAGS; 2925 changed_flags &= SUPPORTED_FIF_FLAGS;
@@ -2913,24 +2945,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
2913 if (*new_flags & FIF_ALLMULTI) { 2945 if (*new_flags & FIF_ALLMULTI) {
2914 mfilt[0] = ~0; 2946 mfilt[0] = ~0;
2915 mfilt[1] = ~0; 2947 mfilt[1] = ~0;
2916 } else {
2917 for (i = 0; i < mc_count; i++) {
2918 if (!mclist)
2919 break;
2920 /* calculate XOR of eight 6-bit values */
2921 val = get_unaligned_le32(mclist->dmi_addr + 0);
2922 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2923 val = get_unaligned_le32(mclist->dmi_addr + 3);
2924 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
2925 pos &= 0x3f;
2926 mfilt[pos / 32] |= (1 << (pos % 32));
2927 /* XXX: we might be able to just do this instead,
2928 * but not sure, needs testing, if we do use this we'd
2929 * neet to inform below to not reset the mcast */
2930 /* ath5k_hw_set_mcast_filterindex(ah,
2931 * mclist->dmi_addr[5]); */
2932 mclist = mclist->next;
2933 }
2934 } 2948 }
2935 2949
2936 /* This is the best we can do */ 2950 /* This is the best we can do */