mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 05:56:11 +07:00
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>
This commit is contained in:
parent
4d09b5378d
commit
9ed74ba029
@ -381,7 +381,8 @@ int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1251_acx_group_address_tbl(struct wl1251 *wl)
|
||||
int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
|
||||
void *mc_list, u32 mc_list_len)
|
||||
{
|
||||
struct acx_dot11_grp_addr_tbl *acx;
|
||||
int ret;
|
||||
@ -393,9 +394,9 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl)
|
||||
return -ENOMEM;
|
||||
|
||||
/* MAC filtering */
|
||||
acx->enabled = 0;
|
||||
acx->num_groups = 0;
|
||||
memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
|
||||
acx->enabled = enable;
|
||||
acx->num_groups = mc_list_len;
|
||||
memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
|
||||
|
||||
ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
|
||||
acx, sizeof(*acx));
|
||||
|
@ -350,8 +350,8 @@ struct acx_slot {
|
||||
} __packed;
|
||||
|
||||
|
||||
#define ADDRESS_GROUP_MAX (8)
|
||||
#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
|
||||
#define ACX_MC_ADDRESS_GROUP_MAX (8)
|
||||
#define ACX_MC_ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)
|
||||
|
||||
struct acx_dot11_grp_addr_tbl {
|
||||
struct acx_header header;
|
||||
@ -359,7 +359,7 @@ struct acx_dot11_grp_addr_tbl {
|
||||
u8 enabled;
|
||||
u8 num_groups;
|
||||
u8 pad[2];
|
||||
u8 mac_table[ADDRESS_GROUP_MAX_LEN];
|
||||
u8 mac_table[ACX_MC_ADDRESS_GROUP_MAX_LEN];
|
||||
} __packed;
|
||||
|
||||
|
||||
@ -1463,7 +1463,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
|
||||
int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
|
||||
int wl1251_acx_pd_threshold(struct wl1251 *wl);
|
||||
int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
|
||||
int wl1251_acx_group_address_tbl(struct wl1251 *wl);
|
||||
int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
|
||||
void *mc_list, u32 mc_list_len);
|
||||
int wl1251_acx_service_period_timeout(struct wl1251 *wl);
|
||||
int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
|
||||
int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
|
||||
|
@ -127,7 +127,7 @@ int wl1251_hw_init_phy_config(struct wl1251 *wl)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1251_acx_group_address_tbl(wl);
|
||||
ret = wl1251_acx_group_address_tbl(wl, true, NULL, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "wl1251.h"
|
||||
#include "wl12xx_80211.h"
|
||||
@ -677,6 +678,44 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct wl1251_filter_params {
|
||||
bool enabled;
|
||||
int mc_list_length;
|
||||
u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
|
||||
};
|
||||
|
||||
static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw,
|
||||
struct netdev_hw_addr_list *mc_list)
|
||||
{
|
||||
struct wl1251_filter_params *fp;
|
||||
struct netdev_hw_addr *ha;
|
||||
struct wl1251 *wl = hw->priv;
|
||||
|
||||
if (unlikely(wl->state == WL1251_STATE_OFF))
|
||||
return 0;
|
||||
|
||||
fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
|
||||
if (!fp) {
|
||||
wl1251_error("Out of memory setting filters.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* update multicast filtering parameters */
|
||||
fp->mc_list_length = 0;
|
||||
if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
|
||||
fp->enabled = false;
|
||||
} else {
|
||||
fp->enabled = true;
|
||||
netdev_hw_addr_list_for_each(ha, mc_list) {
|
||||
memcpy(fp->mc_list[fp->mc_list_length],
|
||||
ha->addr, ETH_ALEN);
|
||||
fp->mc_list_length++;
|
||||
}
|
||||
}
|
||||
|
||||
return (u64)(unsigned long)fp;
|
||||
}
|
||||
|
||||
#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
|
||||
FIF_ALLMULTI | \
|
||||
FIF_FCSFAIL | \
|
||||
@ -687,8 +726,9 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed,
|
||||
unsigned int *total,u64 multicast)
|
||||
unsigned int *total, u64 multicast)
|
||||
{
|
||||
struct wl1251_filter_params *fp = (void *)(unsigned long)multicast;
|
||||
struct wl1251 *wl = hw->priv;
|
||||
int ret;
|
||||
|
||||
@ -697,9 +737,11 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
|
||||
*total &= WL1251_SUPPORTED_FILTERS;
|
||||
changed &= WL1251_SUPPORTED_FILTERS;
|
||||
|
||||
if (changed == 0)
|
||||
if (changed == 0) {
|
||||
/* no filters which we support changed */
|
||||
kfree(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
@ -736,6 +778,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS)
|
||||
ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0);
|
||||
else if (fp)
|
||||
ret = wl1251_acx_group_address_tbl(wl, fp->enabled,
|
||||
fp->mc_list,
|
||||
fp->mc_list_length);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* send filters to firmware */
|
||||
wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
|
||||
|
||||
@ -743,6 +794,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
kfree(fp);
|
||||
}
|
||||
|
||||
/* HW encryption */
|
||||
@ -1282,6 +1334,7 @@ static const struct ieee80211_ops wl1251_ops = {
|
||||
.add_interface = wl1251_op_add_interface,
|
||||
.remove_interface = wl1251_op_remove_interface,
|
||||
.config = wl1251_op_config,
|
||||
.prepare_multicast = wl1251_op_prepare_multicast,
|
||||
.configure_filter = wl1251_op_configure_filter,
|
||||
.tx = wl1251_op_tx,
|
||||
.set_key = wl1251_op_set_key,
|
||||
|
@ -93,6 +93,7 @@ enum {
|
||||
} while (0)
|
||||
|
||||
#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
|
||||
CFG_MC_FILTER_EN | \
|
||||
CFG_BSSID_FILTER_EN)
|
||||
|
||||
#define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \
|
||||
|
Loading…
Reference in New Issue
Block a user