summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanusz Dziedzic <janusz.dziedzic@tieto.com>2011-07-14 11:55:04 +0200
committerPhilippe LANGLAIS <philippe.langlais@stericsson.com>2011-10-13 09:36:55 +0200
commit929810b06f7836638bec699a890eb83c4401e42d (patch)
tree430adf6d906f112da3e66e5bf0aec11a72ee0371
parentbcb008932faf093642cc8fc939722e14c0cc3f34 (diff)
cw1200: Multicast filtering support.
Change-Id: Iccec781533e5ac017ee0ed04741fc224a899f9d9 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27175 Reviewed-by: Janusz DZIEDZIC <janusz.dziedzic@tieto.com> Tested-by: Janusz DZIEDZIC <janusz.dziedzic@tieto.com> Reviewed-by: Dmitry TARNYAGIN <dmitry.tarnyagin@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33482 Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Tested-by: Dmitry TARNYAGIN <dmitry.tarnyagin@stericsson.com> Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
-rw-r--r--drivers/staging/cw1200/cw1200.h1
-rw-r--r--drivers/staging/cw1200/main.c1
-rw-r--r--drivers/staging/cw1200/sta.c31
-rw-r--r--drivers/staging/cw1200/sta.h3
-rw-r--r--drivers/staging/cw1200/wsm.h28
5 files changed, 64 insertions, 0 deletions
diff --git a/drivers/staging/cw1200/cw1200.h b/drivers/staging/cw1200/cw1200.h
index cd5061d1097..f732af75fa0 100644
--- a/drivers/staging/cw1200/cw1200.h
+++ b/drivers/staging/cw1200/cw1200.h
@@ -109,6 +109,7 @@ struct cw1200_common {
struct wsm_rx_filter rx_filter;
struct wsm_beacon_filter_control bf_control;
u8 ba_tid_mask;
+ struct wsm_multicast_filter multicast_filter;
/* BH */
atomic_t bh_rx;
diff --git a/drivers/staging/cw1200/main.c b/drivers/staging/cw1200/main.c
index 7a4c2536976..3b3c12488cb 100644
--- a/drivers/staging/cw1200/main.c
+++ b/drivers/staging/cw1200/main.c
@@ -214,6 +214,7 @@ static const struct ieee80211_ops cw1200_ops = {
.set_rts_threshold = cw1200_set_rts_threshold,
.config = cw1200_config,
.bss_info_changed = cw1200_bss_info_changed,
+ .prepare_multicast = cw1200_prepare_multicast,
.configure_filter = cw1200_configure_filter,
.conf_tx = cw1200_conf_tx,
.get_stats = cw1200_get_stats,
diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c
index fb5576f688a..6906d932430 100644
--- a/drivers/staging/cw1200/sta.c
+++ b/drivers/staging/cw1200/sta.c
@@ -357,6 +357,8 @@ void cw1200_update_filtering(struct cw1200_common *priv)
ret = wsm_beacon_filter_control(priv, &priv->bf_control);
if (!ret)
ret = wsm_set_bssid_filtering(priv, !priv->rx_filter.bssid);
+ if (!ret)
+ ret = wsm_set_multicast_filter(priv, &priv->multicast_filter);
if (ret)
wiphy_err(priv->hw->wiphy,
"%s: Update filtering failed: %d.\n",
@@ -364,6 +366,35 @@ void cw1200_update_filtering(struct cw1200_common *priv)
return;
}
+u64 cw1200_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list)
+{
+ struct cw1200_common *priv = hw->priv;
+ struct netdev_hw_addr *ha;
+ int count = 0;
+
+ /* Disable multicast filtering */
+ memset(&priv->multicast_filter, 0x00, sizeof(priv->multicast_filter));
+
+ if (netdev_hw_addr_list_count(mc_list) > WSM_MAX_GRP_ADDRTABLE_ENTRIES)
+ return 0;
+
+ /* Enable if requested */
+ netdev_hw_addr_list_for_each(ha, mc_list) {
+ sta_printk(KERN_DEBUG "[STA] multicast: %pM\n", ha->addr);
+ memcpy(&priv->multicast_filter.macAddress[count],
+ ha->addr, ETH_ALEN);
+ count++;
+ }
+
+ if (count) {
+ priv->multicast_filter.enable = __cpu_to_le32(1);
+ priv->multicast_filter.numOfAddresses = __cpu_to_le32(count);
+ }
+
+ return netdev_hw_addr_list_count(mc_list);
+}
+
void cw1200_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
diff --git a/drivers/staging/cw1200/sta.h b/drivers/staging/cw1200/sta.h
index 2a3c8836c0b..8951a4a176b 100644
--- a/drivers/staging/cw1200/sta.h
+++ b/drivers/staging/cw1200/sta.h
@@ -42,6 +42,9 @@ int cw1200_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
void cw1200_flush(struct ieee80211_hw *hw, bool drop);
+u64 cw1200_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list);
+
/* ******************************************************************** */
/* WSM callbacks */
diff --git a/drivers/staging/cw1200/wsm.h b/drivers/staging/cw1200/wsm.h
index d8db64da9b3..9b33a6e2b83 100644
--- a/drivers/staging/cw1200/wsm.h
+++ b/drivers/staging/cw1200/wsm.h
@@ -358,6 +358,7 @@ struct cw1200_common;
/* 4.5 dot11GroupAddressesTable */
#define WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE 0x0004
+#define WSM_MAX_GRP_ADDRTABLE_ENTRIES 8
/* 4.6 dot11WepDefaultKeyId */
#define WSM_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID 0x0005
@@ -1446,6 +1447,33 @@ static inline int wsm_set_bssid_filtering(struct cw1200_common *priv,
&arg, sizeof(arg));
}
+/* Multicat filtering - 4.5 */
+struct wsm_multicast_filter {
+ __le32 enable;
+ __le32 numOfAddresses;
+ u8 macAddress[WSM_MAX_GRP_ADDRTABLE_ENTRIES][ETH_ALEN];
+} __packed;
+
+static inline int wsm_set_multicast_filter(struct cw1200_common *priv,
+ struct wsm_multicast_filter *fp)
+{
+ return wsm_write_mib(priv, WSM_MIB_ID_DOT11_GROUP_ADDRESSES_TABLE,
+ fp, sizeof(*fp));
+}
+
+/* IPv4 filtering - 4.10 */
+struct wsm_ipv4_filter {
+ __le32 enable;
+ u8 ipv4Address[4];
+} __packed;
+
+static inline int wsm_set_ipv4_arp_filter(struct cw1200_common *priv,
+ struct wsm_ipv4_filter *fp)
+{
+ return wsm_write_mib(priv, WSM_MIB_ID_ARP_IP_ADDRESSES_TABLE,
+ fp, sizeof(*fp));
+}
+
/* UseMultiTxConfMessage */
static inline int wsm_use_multi_tx_conf(struct cw1200_common *priv,