From 27cdeea170c9a4e6acfd6a670c9d4a0e6f63c917 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 24 Apr 2011 17:22:59 +0200 Subject: [PATCH] --- yaml --- r: 247189 b: refs/heads/master c: be8d98eab81d1f6445461a1631513f7091805e53 h: refs/heads/master i: 247187: 3d09bb39486ad26891788356b53b4b0f1df1922b v: v3 --- [refs] | 2 +- trunk/drivers/net/wireless/p54/fwio.c | 31 +++++++++++++++++++++++++++ trunk/drivers/net/wireless/p54/lmac.h | 1 + trunk/drivers/net/wireless/p54/main.c | 31 +++++++++++++++++++++++++++ trunk/drivers/net/wireless/p54/p54.h | 2 ++ 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index bb0f16072da2..b8633c5b7ed8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 04ad1fb2640a4f23e99ccb705c179d64abac03f2 +refs/heads/master: be8d98eab81d1f6445461a1631513f7091805e53 diff --git a/trunk/drivers/net/wireless/p54/fwio.c b/trunk/drivers/net/wireless/p54/fwio.c index 2fab7d20ffc2..b6a061cbbdec 100644 --- a/trunk/drivers/net/wireless/p54/fwio.c +++ b/trunk/drivers/net/wireless/p54/fwio.c @@ -727,3 +727,34 @@ int p54_fetch_statistics(struct p54_common *priv) p54_tx(priv, skb); return 0; } + +int p54_set_groupfilter(struct p54_common *priv) +{ + struct p54_group_address_table *grp; + struct sk_buff *skb; + bool on = false; + + skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*grp), + P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + grp = (struct p54_group_address_table *)skb_put(skb, sizeof(*grp)); + + on = !(priv->filter_flags & FIF_ALLMULTI) && + (priv->mc_maclist_num > 0 && + priv->mc_maclist_num <= MC_FILTER_ADDRESS_NUM); + + if (on) { + grp->filter_enable = cpu_to_le16(1); + grp->num_address = cpu_to_le16(priv->mc_maclist_num); + memcpy(grp->mac_list, priv->mc_maclist, sizeof(grp->mac_list)); + } else { + grp->filter_enable = cpu_to_le16(0); + grp->num_address = cpu_to_le16(0); + memset(grp->mac_list, 0, sizeof(grp->mac_list)); + } + + p54_tx(priv, skb); + return 0; +} diff --git a/trunk/drivers/net/wireless/p54/lmac.h b/trunk/drivers/net/wireless/p54/lmac.h index eb581abc1079..3d8d622bec55 100644 --- a/trunk/drivers/net/wireless/p54/lmac.h +++ b/trunk/drivers/net/wireless/p54/lmac.h @@ -540,6 +540,7 @@ int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set); int p54_setup_mac(struct p54_common *priv); int p54_set_ps(struct p54_common *priv); int p54_fetch_statistics(struct p54_common *priv); +int p54_set_groupfilter(struct p54_common *priv); /* e/v DCF setup */ int p54_set_edcf(struct p54_common *priv); diff --git a/trunk/drivers/net/wireless/p54/main.c b/trunk/drivers/net/wireless/p54/main.c index 356e6bb443a6..c5c1254ec093 100644 --- a/trunk/drivers/net/wireless/p54/main.c +++ b/trunk/drivers/net/wireless/p54/main.c @@ -308,6 +308,31 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) 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); diff --git a/trunk/drivers/net/wireless/p54/p54.h b/trunk/drivers/net/wireless/p54/p54.h index 50730fc23fe5..799d05e12595 100644 --- a/trunk/drivers/net/wireless/p54/p54.h +++ b/trunk/drivers/net/wireless/p54/p54.h @@ -211,8 +211,10 @@ struct p54_common { /* BBP/MAC state */ u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; + u8 mc_maclist[4][ETH_ALEN]; u16 wakeup_timer; unsigned int filter_flags; + int mc_maclist_num; int mode; u32 tsf_low32, tsf_high32; u32 basic_rate_mask;