aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti
diff options
context:
space:
mode:
authorDavid Gnedt <david.gnedt@davizone.at>2014-01-07 07:08:30 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-01-09 10:56:06 -0500
commit9ed74ba029fc920701cdcada8e25889a6d64a335 (patch)
treecc4a3602356342153a6fca3f49e8995de3882291 /drivers/net/wireless/ti
parent4d09b5378defd4ef685f9d33e0d35b380109eafa (diff)
wl1251: implement multicast address filtering (fwd)
Port multicast address filtering from wl1271 driver. It sets up the hardware multicast address filter in configure_filter() with addresses supplied through prepare_multicast(). Signed-off-by: David Gnedt <david.gnedt@davizone.at> Signed-off-by: Pali Rohár <pali.rohar@gmail.com> Signed-off-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r--drivers/net/wireless/ti/wl1251/acx.c9
-rw-r--r--drivers/net/wireless/ti/wl1251/acx.h9
-rw-r--r--drivers/net/wireless/ti/wl1251/init.c2
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c57
-rw-r--r--drivers/net/wireless/ti/wl1251/wl1251.h1
5 files changed, 67 insertions, 11 deletions
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index b390adfb5d89..4205970494de 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -381,7 +381,8 @@ out:
381 return ret; 381 return ret;
382} 382}
383 383
384int wl1251_acx_group_address_tbl(struct wl1251 *wl) 384int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
385 void *mc_list, u32 mc_list_len)
385{ 386{
386 struct acx_dot11_grp_addr_tbl *acx; 387 struct acx_dot11_grp_addr_tbl *acx;
387 int ret; 388 int ret;
@@ -393,9 +394,9 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl)
393 return -ENOMEM; 394 return -ENOMEM;
394 395
395 /* MAC filtering */ 396 /* MAC filtering */
396 acx->enabled = 0; 397 acx->enabled = enable;
397 acx->num_groups = 0; 398 acx->num_groups = mc_list_len;
398 memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); 399 memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
399 400
400 ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, 401 ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
401 acx, sizeof(*acx)); 402 acx, sizeof(*acx));
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index 5360bbecd073..2bdec38699f4 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -350,8 +350,8 @@ struct acx_slot {
350} __packed; 350} __packed;
351 351
352 352
353#define ADDRESS_GROUP_MAX (8) 353#define ACX_MC_ADDRESS_GROUP_MAX (8)
354#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) 354#define ACX_MC_ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)
355 355
356struct acx_dot11_grp_addr_tbl { 356struct acx_dot11_grp_addr_tbl {
357 struct acx_header header; 357 struct acx_header header;
@@ -359,7 +359,7 @@ struct acx_dot11_grp_addr_tbl {
359 u8 enabled; 359 u8 enabled;
360 u8 num_groups; 360 u8 num_groups;
361 u8 pad[2]; 361 u8 pad[2];
362 u8 mac_table[ADDRESS_GROUP_MAX_LEN]; 362 u8 mac_table[ACX_MC_ADDRESS_GROUP_MAX_LEN];
363} __packed; 363} __packed;
364 364
365 365
@@ -1463,7 +1463,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
1463int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter); 1463int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
1464int wl1251_acx_pd_threshold(struct wl1251 *wl); 1464int wl1251_acx_pd_threshold(struct wl1251 *wl);
1465int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time); 1465int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
1466int wl1251_acx_group_address_tbl(struct wl1251 *wl); 1466int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
1467 void *mc_list, u32 mc_list_len);
1467int wl1251_acx_service_period_timeout(struct wl1251 *wl); 1468int wl1251_acx_service_period_timeout(struct wl1251 *wl);
1468int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); 1469int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
1469int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter); 1470int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 4b78965ebf6f..1d799bffaa9f 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -127,7 +127,7 @@ int wl1251_hw_init_phy_config(struct wl1251 *wl)
127 if (ret < 0) 127 if (ret < 0)
128 return ret; 128 return ret;
129 129
130 ret = wl1251_acx_group_address_tbl(wl); 130 ret = wl1251_acx_group_address_tbl(wl, true, NULL, 0);
131 if (ret < 0) 131 if (ret < 0)
132 return ret; 132 return ret;
133 133
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index afd79aa69869..cda38813596e 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -28,6 +28,7 @@
28#include <linux/etherdevice.h> 28#include <linux/etherdevice.h>
29#include <linux/vmalloc.h> 29#include <linux/vmalloc.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/netdevice.h>
31 32
32#include "wl1251.h" 33#include "wl1251.h"
33#include "wl12xx_80211.h" 34#include "wl12xx_80211.h"
@@ -677,6 +678,44 @@ out:
677 return ret; 678 return ret;
678} 679}
679 680
681struct wl1251_filter_params {
682 bool enabled;
683 int mc_list_length;
684 u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
685};
686
687static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw,
688 struct netdev_hw_addr_list *mc_list)
689{
690 struct wl1251_filter_params *fp;
691 struct netdev_hw_addr *ha;
692 struct wl1251 *wl = hw->priv;
693
694 if (unlikely(wl->state == WL1251_STATE_OFF))
695 return 0;
696
697 fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
698 if (!fp) {
699 wl1251_error("Out of memory setting filters.");
700 return 0;
701 }
702
703 /* update multicast filtering parameters */
704 fp->mc_list_length = 0;
705 if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
706 fp->enabled = false;
707 } else {
708 fp->enabled = true;
709 netdev_hw_addr_list_for_each(ha, mc_list) {
710 memcpy(fp->mc_list[fp->mc_list_length],
711 ha->addr, ETH_ALEN);
712 fp->mc_list_length++;
713 }
714 }
715
716 return (u64)(unsigned long)fp;
717}
718
680#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ 719#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
681 FIF_ALLMULTI | \ 720 FIF_ALLMULTI | \
682 FIF_FCSFAIL | \ 721 FIF_FCSFAIL | \
@@ -687,8 +726,9 @@ out:
687 726
688static void wl1251_op_configure_filter(struct ieee80211_hw *hw, 727static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
689 unsigned int changed, 728 unsigned int changed,
690 unsigned int *total,u64 multicast) 729 unsigned int *total, u64 multicast)
691{ 730{
731 struct wl1251_filter_params *fp = (void *)(unsigned long)multicast;
692 struct wl1251 *wl = hw->priv; 732 struct wl1251 *wl = hw->priv;
693 int ret; 733 int ret;
694 734
@@ -697,9 +737,11 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
697 *total &= WL1251_SUPPORTED_FILTERS; 737 *total &= WL1251_SUPPORTED_FILTERS;
698 changed &= WL1251_SUPPORTED_FILTERS; 738 changed &= WL1251_SUPPORTED_FILTERS;
699 739
700 if (changed == 0) 740 if (changed == 0) {
701 /* no filters which we support changed */ 741 /* no filters which we support changed */
742 kfree(fp);
702 return; 743 return;
744 }
703 745
704 mutex_lock(&wl->mutex); 746 mutex_lock(&wl->mutex);
705 747
@@ -736,6 +778,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
736 if (ret < 0) 778 if (ret < 0)
737 goto out; 779 goto out;
738 780
781 if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS)
782 ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0);
783 else if (fp)
784 ret = wl1251_acx_group_address_tbl(wl, fp->enabled,
785 fp->mc_list,
786 fp->mc_list_length);
787 if (ret < 0)
788 goto out;
789
739 /* send filters to firmware */ 790 /* send filters to firmware */
740 wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter); 791 wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
741 792
@@ -743,6 +794,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
743 794
744out: 795out:
745 mutex_unlock(&wl->mutex); 796 mutex_unlock(&wl->mutex);
797 kfree(fp);
746} 798}
747 799
748/* HW encryption */ 800/* HW encryption */
@@ -1282,6 +1334,7 @@ static const struct ieee80211_ops wl1251_ops = {
1282 .add_interface = wl1251_op_add_interface, 1334 .add_interface = wl1251_op_add_interface,
1283 .remove_interface = wl1251_op_remove_interface, 1335 .remove_interface = wl1251_op_remove_interface,
1284 .config = wl1251_op_config, 1336 .config = wl1251_op_config,
1337 .prepare_multicast = wl1251_op_prepare_multicast,
1285 .configure_filter = wl1251_op_configure_filter, 1338 .configure_filter = wl1251_op_configure_filter,
1286 .tx = wl1251_op_tx, 1339 .tx = wl1251_op_tx,
1287 .set_key = wl1251_op_set_key, 1340 .set_key = wl1251_op_set_key,
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 58bb414c51e5..e231cdc44fc5 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -93,6 +93,7 @@ enum {
93 } while (0) 93 } while (0)
94 94
95#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ 95#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
96 CFG_MC_FILTER_EN | \
96 CFG_BSSID_FILTER_EN) 97 CFG_BSSID_FILTER_EN)
97 98
98#define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \ 99#define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \