Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 170916
b: refs/heads/master
c: c87dec9
h: refs/heads/master
v: v3
  • Loading branch information
Juuso Oikarinen authored and John W. Linville committed Oct 27, 2009
1 parent 2cffc9d commit 241f8b0
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 66497dc3bd569e05a5bcb729d495eebad47aa46a
refs/heads/master: c87dec9f189b884df215756e285b9281cf065206
7 changes: 5 additions & 2 deletions trunk/drivers/net/wireless/wl12xx/wl1271.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ enum {
} while (0)

#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
CFG_BSSID_FILTER_EN)
CFG_BSSID_FILTER_EN | \
CFG_MC_FILTER_EN)

#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
Expand All @@ -123,7 +124,7 @@ enum {
#define WL1271_DEFAULT_BEACON_INT 100
#define WL1271_DEFAULT_DTIM_PERIOD 1

#define ACX_TX_DESCRIPTORS 32
#define ACX_TX_DESCRIPTORS 32

enum wl1271_state {
WL1271_STATE_OFF,
Expand Down Expand Up @@ -345,7 +346,9 @@ struct wl1271 {
bool tx_queue_stopped;

struct work_struct tx_work;

struct work_struct filter_work;
struct wl1271_filter_params *filter_params;

/* Pending TX frames */
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
Expand Down
9 changes: 5 additions & 4 deletions trunk/drivers/net/wireless/wl12xx/wl1271_acx.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
return ret;
}

int wl1271_acx_group_address_tbl(struct wl1271 *wl)
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
void *mc_list, u32 mc_list_len)
{
struct acx_dot11_grp_addr_tbl *acx;
int ret;
Expand All @@ -314,9 +315,9 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl)
}

/* 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 = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
acx, sizeof(*acx));
Expand Down
8 changes: 4 additions & 4 deletions trunk/drivers/net/wireless/wl12xx/wl1271_acx.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,8 @@ struct acx_slot {
} __attribute__ ((packed));


#define ADDRESS_GROUP_MAX (8)
#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
#define ACX_MC_ADDRESS_GROUP_MAX (8)
#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)

struct acx_dot11_grp_addr_tbl {
struct acx_header header;
Expand All @@ -313,7 +313,6 @@ struct acx_dot11_grp_addr_tbl {
u8 mac_table[ADDRESS_GROUP_MAX_LEN];
} __attribute__ ((packed));


#define RX_TIMEOUT_PS_POLL_MIN 0
#define RX_TIMEOUT_PS_POLL_MAX (200000)
#define RX_TIMEOUT_PS_POLL_DEF (15)
Expand Down Expand Up @@ -1193,7 +1192,8 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time);
int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
int wl1271_acx_pd_threshold(struct wl1271 *wl);
int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
int wl1271_acx_group_address_tbl(struct wl1271 *wl);
int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
void *mc_list, u32 mc_list_len);
int wl1271_acx_service_period_timeout(struct wl1271 *wl);
int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl);
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/net/wireless/wl12xx/wl1271_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ static int wl1271_init_phy_config(struct wl1271 *wl)
if (ret < 0)
return ret;

ret = wl1271_acx_group_address_tbl(wl);
ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
if (ret < 0)
return ret;

Expand Down
121 changes: 105 additions & 16 deletions trunk/drivers/net/wireless/wl12xx/wl1271_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,12 +379,39 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
return ret;
}

struct wl1271_filter_params {
unsigned int filters;
unsigned int changed;
int mc_list_length;
u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
};

#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
FIF_FCSFAIL | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_CONTROL | \
FIF_OTHER_BSS)

static void wl1271_filter_work(struct work_struct *work)
{
struct wl1271 *wl =
container_of(work, struct wl1271, filter_work);
struct wl1271_filter_params *fp;
unsigned long flags;
bool enabled = true;
int ret;

/* first, get the filter parameters */
spin_lock_irqsave(&wl->wl_lock, flags);
fp = wl->filter_params;
wl->filter_params = NULL;
spin_unlock_irqrestore(&wl->wl_lock, flags);

if (!fp)
return;

/* then, lock the mutex without risk of lock-up */
mutex_lock(&wl->mutex);

if (wl->state == WL1271_STATE_OFF)
Expand All @@ -394,6 +421,20 @@ static void wl1271_filter_work(struct work_struct *work)
if (ret < 0)
goto out;

/* configure the mc filter regardless of the changed flags */
if (fp->filters & FIF_ALLMULTI)
enabled = false;

ret = wl1271_acx_group_address_tbl(wl, enabled,
fp->mc_list, fp->mc_list_length);
if (ret < 0)
goto out_sleep;

/* determine, whether supported filter values have changed */
if (fp->changed == 0)
goto out;

/* apply configured filters */
ret = wl1271_cmd_join(wl);
if (ret < 0)
goto out_sleep;
Expand All @@ -403,6 +444,7 @@ static void wl1271_filter_work(struct work_struct *work)

out:
mutex_unlock(&wl->mutex);
kfree(fp);
}

int wl1271_plt_start(struct wl1271 *wl)
Expand Down Expand Up @@ -544,12 +586,20 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
static void wl1271_op_stop(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
unsigned long flags;
int i;

wl1271_info("down");

wl1271_debug(DEBUG_MAC80211, "mac80211 stop");

/* complete/cancel ongoing work */
cancel_work_sync(&wl->filter_work);
spin_lock_irqsave(&wl->wl_lock, flags);
kfree(wl->filter_params);
wl->filter_params = NULL;
spin_unlock_irqrestore(&wl->wl_lock, flags);

mutex_lock(&wl->mutex);

WARN_ON(wl->state != WL1271_STATE_ON);
Expand Down Expand Up @@ -784,16 +834,52 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
return ret;
}

#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
FIF_FCSFAIL | \
FIF_BCN_PRBRESP_PROMISC | \
FIF_CONTROL | \
FIF_OTHER_BSS)
static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
struct dev_addr_list *mc_list)
{
struct wl1271 *wl = hw->priv;
struct wl1271_filter_params *fp;
unsigned long flags;
int i;

/*
* FIXME: we should return a hash that will be passed to
* configure_filter() instead of saving everything in the context.
*/

fp = kzalloc(sizeof(*fp), GFP_KERNEL);
if (!fp) {
wl1271_error("Out of memory setting filters.");
return 0;
}

/* update multicast filtering parameters */
if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
mc_count = 0;
fp->filters |= FIF_ALLMULTI;
}

fp->mc_list_length = 0;
for (i = 0; i < mc_count; i++) {
if (mc_list->da_addrlen == ETH_ALEN) {
memcpy(fp->mc_list[fp->mc_list_length],
mc_list->da_addr, ETH_ALEN);
fp->mc_list_length++;
} else
wl1271_warning("Unknown mc address length.");
}

spin_lock_irqsave(&wl->wl_lock, flags);
kfree(wl->filter_params);
wl->filter_params = fp;
spin_unlock_irqrestore(&wl->wl_lock, flags);

return 1;
}

static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
unsigned int *total,u64 multicast)
unsigned int *total, u64 multicast)
{
struct wl1271 *wl = hw->priv;

Expand All @@ -802,19 +888,21 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
*total &= WL1271_SUPPORTED_FILTERS;
changed &= WL1271_SUPPORTED_FILTERS;

if (changed == 0)
if (!multicast)
return;

/* FIXME: wl->rx_config and wl->rx_filter are not protected */
wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
wl->rx_filter = WL1271_DEFAULT_RX_FILTER;

/*
* FIXME: workqueues need to be properly cancelled on stop(), for
* now let's just disable changing the filter settings. They will
* be updated any on config().
* FIXME: for now we are still using a workqueue for filter
* configuration, but with the new mac80211, this is not needed,
* since configure_filter can now sleep. We now have
* prepare_multicast, which needs to be atomic instead.
*/
/* schedule_work(&wl->filter_work); */

/* store current filter config */
wl->filter_params->filters = *total;
wl->filter_params->changed = changed;

ieee80211_queue_work(wl->hw, &wl->filter_work);
}

static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
Expand Down Expand Up @@ -1177,6 +1265,7 @@ static const struct ieee80211_ops wl1271_ops = {
.remove_interface = wl1271_op_remove_interface,
.config = wl1271_op_config,
/* .config_interface = wl1271_op_config_interface, */
.prepare_multicast = wl1271_op_prepare_multicast,
.configure_filter = wl1271_op_configure_filter,
.tx = wl1271_op_tx,
.set_key = wl1271_op_set_key,
Expand Down

0 comments on commit 241f8b0

Please sign in to comment.