Add set_multicast_list callback. The version of set_multicast_list in
struct net_device cannot be used by a driver, because the driver is
interested in cumulative flags and cumulative multicast list from all
interfaces.

Signed-off-by: Jiri Benc <[EMAIL PROTECTED]>

---

 include/net/d80211.h         |   24 ++++++++++++++
 net/d80211/ieee80211.c       |   71 ++++++++++++++++++++++++++++++++++++++++++
 net/d80211/ieee80211_i.h     |    8 +++++
 net/d80211/ieee80211_iface.c |    1 +
 4 files changed, 104 insertions(+), 0 deletions(-)

9ada6736d81619ac81ea1ce283f47c365fe3b24f
diff --git a/include/net/d80211.h b/include/net/d80211.h
index 6894745..7bc66b5 100644
--- a/include/net/d80211.h
+++ b/include/net/d80211.h
@@ -532,6 +532,13 @@ struct ieee80211_hw {
        int (*config_interface)(struct net_device *dev, int if_id,
                                struct ieee80211_if_conf *conf);
 
+       /* ieee80211 drivers should use this and not the function in
+        * net_device. dev->flags, dev->mc_count and dev->mc_list must not
+        * be used; use passed parameters and ieee80211_get_mc_list_item()
+        * instead. */
+       void (*set_multicast_list)(struct net_device *dev,
+                                  unsigned short flags, int mc_count);
+
        /* Set TIM bit handler. If the hardware/firmware takes care of beacon
         * generation, IEEE 802.11 code uses this function to tell the
         * low-level to set (or clear if set==0) TIM bit for the given aid. If
@@ -775,6 +782,23 @@ typedef enum {
 } Netif_Oper;
 int ieee80211_netif_oper(struct net_device *dev, Netif_Oper op);
 
+/**
+ * ieee80211_get_mc_list_item - iteration over items in multicast list
+ * @dev: pointer to &struct net_device as obtained from
+ *     ieee80211_alloc_hw().
+ * @prev: value returned by previous call to ieee80211_get_mc_list_item() or
+ *     NULL to start a new iteration.
+ * @ptr: pointer to buffer of void * type for internal usage of
+ *     ieee80211_get_mc_list_item().
+ *
+ * Iterates over items in multicast list of given device. To get the first
+ * item, pass NULL in @prev and in [EMAIL PROTECTED] In subsequent calls, pass 
the
+ * value returned by previous call in @prev. Don't alter [EMAIL PROTECTED] 
during
+ * iteration. When there are no more items, NULL is returned.
+ */
+struct dev_mc_list *ieee80211_get_mc_list_item(struct net_device *dev,
+                                              struct dev_mc_list *prev,
+                                              void **ptr);
 
 /*
  * Function to get hardware configuration information
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index ea71b6c..fbca700 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1812,6 +1812,75 @@ static int ieee80211_set_mac_address(str
        return 0;
 }
 
+static void ieee80211_set_multicast_list(struct net_device *dev)
+{
+       struct ieee80211_local *local = dev->priv;
+        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       unsigned short flags;
+
+       if (((dev->flags & IFF_ALLMULTI) != 0) ^ (sdata->allmulti != 0)) {
+               if (sdata->allmulti) {
+                       sdata->allmulti = 0;
+                       local->iff_allmultis--;
+               } else {
+                       sdata->allmulti = 1;
+                       local->iff_allmultis++;
+               }
+       }
+       if (((dev->flags & IFF_PROMISC) != 0) ^ (sdata->promisc != 0)) {
+               if (sdata->promisc) {
+                       sdata->promisc = 0;
+                       local->iff_promiscs--;
+               } else {
+                       sdata->promisc = 1;
+                       local->iff_promiscs++;
+               }
+       }
+       if (dev->mc_count != sdata->mc_count) {
+               local->mc_count = local->mc_count - sdata->mc_count +
+                                 dev->mc_count;
+               sdata->mc_count = dev->mc_count;
+       }
+       if (local->hw->set_multicast_list) {
+               flags = sdata->master->flags;
+               if (local->iff_allmultis)
+                       flags |= IFF_ALLMULTI;
+               if (local->iff_promiscs)
+                       flags |= IFF_PROMISC;
+               local->hw->set_multicast_list(sdata->master, flags,
+                                             local->mc_count);
+       }
+}
+
+struct dev_mc_list *ieee80211_get_mc_list_item(struct net_device *dev,
+                                              struct dev_mc_list *prev,
+                                              void **ptr)
+{
+       struct ieee80211_local *local = dev->priv;
+       struct ieee80211_sub_if_data *sdata = *ptr;
+       struct dev_mc_list *mc;
+
+       if (!prev) {
+               WARN_ON(sdata);
+               sdata = NULL;
+       }
+       if (!prev || !prev->next) {
+               if (sdata)
+                       sdata = list_entry(sdata->list.next,
+                                          struct ieee80211_sub_if_data, list);
+               else
+                       sdata = list_entry(local->sub_if_list.next,
+                                          struct ieee80211_sub_if_data, list);
+               if (&sdata->list != &local->sub_if_list)
+                       mc = sdata->dev->mc_list;
+               else
+                       mc = NULL;
+       } else
+               mc = prev->next;
+
+       *ptr = sdata;
+       return mc;
+}
 
 static struct net_device_stats *ieee80211_get_stats(struct net_device *dev)
 {
@@ -3889,6 +3958,7 @@ void ieee80211_if_setup(struct net_devic
                (struct iw_handler_def *) &ieee80211_iw_handler_def;
        dev->do_ioctl = ieee80211_ioctl;
        dev->set_mac_address = ieee80211_set_mac_address;
+       dev->set_multicast_list = ieee80211_set_multicast_list;
        dev->change_mtu = ieee80211_change_mtu;
        dev->tx_timeout = ieee80211_tx_timeout;
        dev->get_stats = ieee80211_get_stats;
@@ -4449,6 +4519,7 @@ EXPORT_SYMBOL(ieee80211_rate_control_unr
 EXPORT_SYMBOL(sta_info_get);
 EXPORT_SYMBOL(sta_info_release);
 EXPORT_SYMBOL(ieee80211_radar_status);
+EXPORT_SYMBOL(ieee80211_get_mc_list_item);
 
 module_init(ieee80211_init);
 module_exit(ieee80211_exit);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 5116a88..37d533d 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -264,6 +264,10 @@ struct ieee80211_sub_if_data {
         struct net_device *master;
         struct ieee80211_local *local;
 
+       int mc_count;
+       unsigned allmulti:1;
+       unsigned promisc:1;
+
         struct net_device_stats stats;
        int drop_unencrypted;
        int eapol; /* 0 = process EAPOL frames as normal data frames,
@@ -327,6 +331,10 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
        struct sta_info *sta_hash[STA_HASH_SIZE];
        struct timer_list sta_cleanup;
 
+       int mc_count;   /* total count of multicast entries in all interfaces */
+       int iff_allmultis, iff_promiscs;
+                       /* number of interfaces with corresponding IFF_ flags */
+
        /* Current rate table. This is a pointer to hw->modes structure. */
        struct ieee80211_rate *curr_rates;
        int num_curr_rates;
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 917428e..2151bd9 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -62,6 +62,7 @@ int ieee80211_if_add(struct net_device *
        ndev->irq = dev->irq;
        ndev->mem_start = dev->mem_start;
        ndev->mem_end = dev->mem_end;
+       ndev->flags = dev->flags & IFF_MULTICAST;
        ieee80211_if_setup(ndev);
 
        sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
-- 
1.3.0

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to