diff options
author | Janusz Dziedzic <janusz.dziedzic@tieto.com> | 2011-07-14 11:55:04 +0200 |
---|---|---|
committer | Philippe LANGLAIS <philippe.langlais@stericsson.com> | 2011-10-13 09:36:55 +0200 |
commit | 929810b06f7836638bec699a890eb83c4401e42d (patch) | |
tree | 430adf6d906f112da3e66e5bf0aec11a72ee0371 | |
parent | bcb008932faf093642cc8fc939722e14c0cc3f34 (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.h | 1 | ||||
-rw-r--r-- | drivers/staging/cw1200/main.c | 1 | ||||
-rw-r--r-- | drivers/staging/cw1200/sta.c | 31 | ||||
-rw-r--r-- | drivers/staging/cw1200/sta.h | 3 | ||||
-rw-r--r-- | drivers/staging/cw1200/wsm.h | 28 |
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, |