p54: implement multicast filter
[pandora-kernel.git] / drivers / net / wireless / p54 / main.c
index 356e6bb..c5c1254 100644 (file)
@@ -308,6 +308,31 @@ out:
        return ret;
 }
 
+static u64 p54_prepare_multicast(struct ieee80211_hw *dev,
+                                struct netdev_hw_addr_list *mc_list)
+{
+       struct p54_common *priv = dev->priv;
+       struct netdev_hw_addr *ha;
+       int i;
+
+       BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) !=
+               ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list));
+       /*
+        * The first entry is reserved for the global broadcast MAC.
+        * Otherwise the firmware will drop it and ARP will no longer work.
+        */
+       i = 1;
+       priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list) + i;
+       netdev_hw_addr_list_for_each(ha, mc_list) {
+               memcpy(&priv->mc_maclist[i], ha->addr, ETH_ALEN);
+               i++;
+               if (i >= ARRAY_SIZE(priv->mc_maclist))
+                       break;
+       }
+
+       return 1; /* update */
+}
+
 static void p54_configure_filter(struct ieee80211_hw *dev,
                                 unsigned int changed_flags,
                                 unsigned int *total_flags,
@@ -316,12 +341,16 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
        struct p54_common *priv = dev->priv;
 
        *total_flags &= FIF_PROMISC_IN_BSS |
+                       FIF_ALLMULTI |
                        FIF_OTHER_BSS;
 
        priv->filter_flags = *total_flags;
 
        if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS))
                p54_setup_mac(priv);
+
+       if (changed_flags & FIF_ALLMULTI || multicast)
+               p54_set_groupfilter(priv);
 }
 
 static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
@@ -591,6 +620,7 @@ static const struct ieee80211_ops p54_ops = {
        .config                 = p54_config,
        .flush                  = p54_flush,
        .bss_info_changed       = p54_bss_info_changed,
+       .prepare_multicast      = p54_prepare_multicast,
        .configure_filter       = p54_configure_filter,
        .conf_tx                = p54_conf_tx,
        .get_stats              = p54_get_stats,
@@ -660,6 +690,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
        init_completion(&priv->beacon_comp);
        INIT_DELAYED_WORK(&priv->work, p54_work);
 
+       memset(&priv->mc_maclist[0], ~0, ETH_ALEN);
        return dev;
 }
 EXPORT_SYMBOL_GPL(p54_init_common);