From: Christian Lamparter <chunkeey@googlemail.com>
To: linux-wireless@vger.kernel.org
Cc: Michael Buesch <mb@bu3sch.de>, Max Filippov <jcmvbkbc@gmail.com>
Subject: [RFT] p54: implement multicast + arp req PS filter
Date: Sat, 2 Apr 2011 00:58:16 +0200 [thread overview]
Message-ID: <201104020058.17232.chunkeey@googlemail.com> (raw)
"For best CPU usage and power consumption, having as few
frames as possible percolate through the stack is
desirable. Hence, the hardware should filter as much
as possible."
Note: The available stlc45xx softmac specification does not
specify whenever these features are implemented in the
common [pci/usb] branches, or not . At least from the data
I could gather, it doesn't look like this is the case.
Therefore, I'm looking for test results from p54spi users.
---
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 2fab7d2..e8c7d02 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -727,3 +727,67 @@ int p54_fetch_statistics(struct p54_common *priv)
p54_tx(priv, skb);
return 0;
}
+
+int p54_set_arpfilter(struct p54_common *priv)
+{
+ struct p54_arp_table *arp;
+ struct sk_buff *skb;
+ struct ieee80211_bss_conf *bss_conf = NULL;
+ bool on = false;
+
+ skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*arp),
+ P54_CONTROL_TYPE_ARPTABLE, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ arp = (struct p54_arp_table *)skb_put(skb, sizeof(*arp));
+ if (priv->vif) {
+ bss_conf = &priv->vif->bss_conf;
+
+ on = bss_conf->arp_filter_enabled &&
+ bss_conf->arp_addr_cnt == 1;
+ }
+
+ if (on) {
+ arp->filter_enable = cpu_to_le16(1);
+ memcpy(arp->ipv4_addr, &bss_conf->arp_addr_list[0],
+ sizeof(arp->ipv4_addr));
+ } else {
+ arp->filter_enable = cpu_to_le16(0);
+ memset(arp->ipv4_addr, 0, sizeof(arp->ipv4_addr));
+ }
+
+ 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/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h
index f666482..2990715 100644
--- a/drivers/net/wireless/p54/lmac.h
+++ b/drivers/net/wireless/p54/lmac.h
@@ -540,6 +540,8 @@ 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_arpfilter(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/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index e6205e4..ef612f5 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -308,6 +308,27 @@ 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 = 0;
+
+ BUILD_BUG_ON(ARRAY_SIZE(priv->mc_maclist) !=
+ ARRAY_SIZE(((struct p54_group_address_table *)NULL)->mac_list));
+
+ priv->mc_maclist_num = netdev_hw_addr_list_count(mc_list);
+ 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 +337,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,
@@ -412,6 +437,9 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev,
}
}
+ if (changed & BSS_CHANGED_ARP_FILTER)
+ WARN_ON(p54_set_arpfilter(priv));
+
mutex_unlock(&priv->conf_mutex);
}
@@ -591,6 +619,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,
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 50730fc..799d05e 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/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;
next reply other threads:[~2011-04-01 22:58 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-01 22:58 Christian Lamparter [this message]
2011-04-07 23:28 ` [RFT] p54: implement multicast + arp req PS filter Max Filippov
2011-04-08 13:08 ` Christian Lamparter
2011-04-09 20:23 ` Max Filippov
2011-04-09 22:24 ` Christian Lamparter
2011-04-09 23:34 ` Max Filippov
2011-04-09 23:54 ` Christian Lamparter
2011-04-10 0:41 ` Max Filippov
2011-04-13 21:48 ` Max Filippov
2011-04-14 19:13 ` Christian Lamparter
2011-04-14 20:34 ` Max Filippov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201104020058.17232.chunkeey@googlemail.com \
--to=chunkeey@googlemail.com \
--cc=jcmvbkbc@gmail.com \
--cc=linux-wireless@vger.kernel.org \
--cc=mb@bu3sch.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).