diff options
-rw-r--r-- | include/net/mac80211.h | 7 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 16 | ||||
-rw-r--r-- | net/mac80211/iface.c | 11 | ||||
-rw-r--r-- | net/mac80211/trace.h | 24 |
4 files changed, 58 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8c0ca11a39c4..f5db5e970428 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -2259,6 +2259,9 @@ enum ieee80211_roc_type { | |||
2259 | * See the section "Frame filtering" for more information. | 2259 | * See the section "Frame filtering" for more information. |
2260 | * This callback must be implemented and can sleep. | 2260 | * This callback must be implemented and can sleep. |
2261 | * | 2261 | * |
2262 | * @set_multicast_list: Configure the device's interface specific RX multicast | ||
2263 | * filter. This callback is optional. This callback must be atomic. | ||
2264 | * | ||
2262 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit | 2265 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit |
2263 | * must be set or cleared for a given STA. Must be atomic. | 2266 | * must be set or cleared for a given STA. Must be atomic. |
2264 | * | 2267 | * |
@@ -2605,6 +2608,10 @@ struct ieee80211_ops { | |||
2605 | unsigned int changed_flags, | 2608 | unsigned int changed_flags, |
2606 | unsigned int *total_flags, | 2609 | unsigned int *total_flags, |
2607 | u64 multicast); | 2610 | u64 multicast); |
2611 | void (*set_multicast_list)(struct ieee80211_hw *hw, | ||
2612 | struct ieee80211_vif *vif, bool allmulti, | ||
2613 | struct netdev_hw_addr_list *mc_list); | ||
2614 | |||
2608 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 2615 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
2609 | bool set); | 2616 | bool set); |
2610 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2617 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 832acea4a5cb..025b7592b797 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -241,6 +241,22 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | |||
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | 243 | ||
244 | static inline void drv_set_multicast_list(struct ieee80211_local *local, | ||
245 | struct ieee80211_sub_if_data *sdata, | ||
246 | struct netdev_hw_addr_list *mc_list) | ||
247 | { | ||
248 | bool allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
249 | |||
250 | trace_drv_set_multicast_list(local, sdata, mc_list->count); | ||
251 | |||
252 | check_sdata_in_driver(sdata); | ||
253 | |||
254 | if (local->ops->set_multicast_list) | ||
255 | local->ops->set_multicast_list(&local->hw, &sdata->vif, | ||
256 | allmulti, mc_list); | ||
257 | trace_drv_return_void(local); | ||
258 | } | ||
259 | |||
244 | static inline void drv_configure_filter(struct ieee80211_local *local, | 260 | static inline void drv_configure_filter(struct ieee80211_local *local, |
245 | unsigned int changed_flags, | 261 | unsigned int changed_flags, |
246 | unsigned int *total_flags, | 262 | unsigned int *total_flags, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d85282f64405..9875e321c9e8 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -919,6 +919,17 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
919 | atomic_dec(&local->iff_promiscs); | 919 | atomic_dec(&local->iff_promiscs); |
920 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | 920 | sdata->flags ^= IEEE80211_SDATA_PROMISC; |
921 | } | 921 | } |
922 | |||
923 | /* | ||
924 | * TODO: If somebody needs this on AP interfaces, | ||
925 | * it can be enabled easily but multicast | ||
926 | * addresses from VLANs need to be synced. | ||
927 | */ | ||
928 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
929 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
930 | sdata->vif.type != NL80211_IFTYPE_AP) | ||
931 | drv_set_multicast_list(local, sdata, &dev->mc); | ||
932 | |||
922 | spin_lock_bh(&local->filter_lock); | 933 | spin_lock_bh(&local->filter_lock); |
923 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); | 934 | __hw_addr_sync(&local->mc_list, &dev->mc, dev->addr_len); |
924 | spin_unlock_bh(&local->filter_lock); | 935 | spin_unlock_bh(&local->filter_lock); |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index e7db2b804e0c..d97e4305cf1e 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -431,6 +431,30 @@ TRACE_EVENT(drv_prepare_multicast, | |||
431 | ) | 431 | ) |
432 | ); | 432 | ); |
433 | 433 | ||
434 | TRACE_EVENT(drv_set_multicast_list, | ||
435 | TP_PROTO(struct ieee80211_local *local, | ||
436 | struct ieee80211_sub_if_data *sdata, int mc_count), | ||
437 | |||
438 | TP_ARGS(local, sdata, mc_count), | ||
439 | |||
440 | TP_STRUCT__entry( | ||
441 | LOCAL_ENTRY | ||
442 | __field(bool, allmulti) | ||
443 | __field(int, mc_count) | ||
444 | ), | ||
445 | |||
446 | TP_fast_assign( | ||
447 | LOCAL_ASSIGN; | ||
448 | __entry->allmulti = sdata->flags & IEEE80211_SDATA_ALLMULTI; | ||
449 | __entry->mc_count = mc_count; | ||
450 | ), | ||
451 | |||
452 | TP_printk( | ||
453 | LOCAL_PR_FMT " configure mc filter, count=%d, allmulti=%d", | ||
454 | LOCAL_PR_ARG, __entry->mc_count, __entry->allmulti | ||
455 | ) | ||
456 | ); | ||
457 | |||
434 | TRACE_EVENT(drv_configure_filter, | 458 | TRACE_EVENT(drv_configure_filter, |
435 | TP_PROTO(struct ieee80211_local *local, | 459 | TP_PROTO(struct ieee80211_local *local, |
436 | unsigned int changed_flags, | 460 | unsigned int changed_flags, |