aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-17 10:16:53 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-20 11:35:58 -0400
commit3ac64beecd27400d12cc7afb4108eef26c499f6a (patch)
treeda0220085f68e30fe61ba9b8833dc6311d6dc25e /drivers/net/wireless/zd1211rw
parentea416a793d2b611f22b42ba094fd2e5bd30fff43 (diff)
mac80211: allow configure_filter callback to sleep
Over time, a whole bunch of drivers have come up with their own scheme to delay the configure_filter operation to a workqueue. To be able to simplify things, allow configure_filter to sleep, and add a new prepare_multicast callback that drivers that need the multicast address list implement. This new callback must be atomic, but most drivers either don't care or just calculate a hash which can be done atomically and then uploaded to the hardware non-atomically. A cursory look suggests that at76c50x-usb, ar9170, mwl8k (which is actually very broken now), rt2x00, wl1251, wl1271 and zd1211 should make use of this new capability. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 55b7fbdc85dc..6d666359a42f 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -796,18 +796,40 @@ static void set_rx_filter_handler(struct work_struct *work)
796 dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); 796 dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
797} 797}
798 798
799static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
800 int mc_count, struct dev_addr_list *mclist)
801{
802 struct zd_mac *mac = zd_hw_mac(hw);
803 struct zd_mc_hash hash;
804 int i;
805
806 zd_mc_clear(&hash);
807
808 for (i = 0; i < mc_count; i++) {
809 if (!mclist)
810 break;
811 dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr);
812 zd_mc_add_addr(&hash, mclist->dmi_addr);
813 mclist = mclist->next;
814 }
815
816 return hash.low | ((u64)hash.high << 32);
817}
818
799#define SUPPORTED_FIF_FLAGS \ 819#define SUPPORTED_FIF_FLAGS \
800 (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ 820 (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
801 FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) 821 FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
802static void zd_op_configure_filter(struct ieee80211_hw *hw, 822static void zd_op_configure_filter(struct ieee80211_hw *hw,
803 unsigned int changed_flags, 823 unsigned int changed_flags,
804 unsigned int *new_flags, 824 unsigned int *new_flags,
805 int mc_count, struct dev_mc_list *mclist) 825 u64 multicast)
806{ 826{
807 struct zd_mc_hash hash; 827 struct zd_mc_hash hash = {
828 .low = multicast,
829 .high = multicast >> 32,
830 };
808 struct zd_mac *mac = zd_hw_mac(hw); 831 struct zd_mac *mac = zd_hw_mac(hw);
809 unsigned long flags; 832 unsigned long flags;
810 int i;
811 833
812 /* Only deal with supported flags */ 834 /* Only deal with supported flags */
813 changed_flags &= SUPPORTED_FIF_FLAGS; 835 changed_flags &= SUPPORTED_FIF_FLAGS;
@@ -819,25 +841,16 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
819 if (!changed_flags) 841 if (!changed_flags)
820 return; 842 return;
821 843
822 if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) { 844 if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI))
823 zd_mc_add_all(&hash); 845 zd_mc_add_all(&hash);
824 } else {
825 zd_mc_clear(&hash);
826 for (i = 0; i < mc_count; i++) {
827 if (!mclist)
828 break;
829 dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n",
830 mclist->dmi_addr);
831 zd_mc_add_addr(&hash, mclist->dmi_addr);
832 mclist = mclist->next;
833 }
834 }
835 846
836 spin_lock_irqsave(&mac->lock, flags); 847 spin_lock_irqsave(&mac->lock, flags);
837 mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); 848 mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
838 mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); 849 mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
839 mac->multicast_hash = hash; 850 mac->multicast_hash = hash;
840 spin_unlock_irqrestore(&mac->lock, flags); 851 spin_unlock_irqrestore(&mac->lock, flags);
852
853 /* XXX: these can be called here now, can sleep now! */
841 queue_work(zd_workqueue, &mac->set_multicast_hash_work); 854 queue_work(zd_workqueue, &mac->set_multicast_hash_work);
842 855
843 if (changed_flags & FIF_CONTROL) 856 if (changed_flags & FIF_CONTROL)
@@ -940,6 +953,7 @@ static const struct ieee80211_ops zd_ops = {
940 .add_interface = zd_op_add_interface, 953 .add_interface = zd_op_add_interface,
941 .remove_interface = zd_op_remove_interface, 954 .remove_interface = zd_op_remove_interface,
942 .config = zd_op_config, 955 .config = zd_op_config,
956 .prepare_multicast = zd_op_prepare_multicast,
943 .configure_filter = zd_op_configure_filter, 957 .configure_filter = zd_op_configure_filter,
944 .bss_info_changed = zd_op_bss_info_changed, 958 .bss_info_changed = zd_op_bss_info_changed,
945 .get_tsf = zd_op_get_tsf, 959 .get_tsf = zd_op_get_tsf,