Skip to content

Commit

Permalink
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/jberg/mac80211
  • Loading branch information
John W. Linville committed Jan 4, 2013
2 parents 9a6f734 + 09b1426 commit d339fc8
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 91 deletions.
2 changes: 2 additions & 0 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
if (old_probe_resp)
kfree_rcu(old_probe_resp, rcu_head);

list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
sta_info_flush(local, vlan);
sta_info_flush(local, sdata);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);

Expand Down
38 changes: 38 additions & 0 deletions net/mac80211/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <linux/nl80211.h>
#include <linux/export.h>
#include <linux/rtnetlink.h>
#include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
Expand Down Expand Up @@ -197,6 +198,15 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)

ctx = container_of(conf, struct ieee80211_chanctx, conf);

if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct ieee80211_sub_if_data *vlan;

/* for the VLAN list */
ASSERT_RTNL();
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
rcu_assign_pointer(vlan->vif.chanctx_conf, NULL);
}

ieee80211_unassign_vif_chanctx(sdata, ctx);
if (ctx->refcount == 0)
ieee80211_free_chanctx(local, ctx);
Expand Down Expand Up @@ -316,6 +326,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
goto out;
}

if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct ieee80211_sub_if_data *vlan;

/* for the VLAN list */
ASSERT_RTNL();
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf);
}

ieee80211_recalc_smps_chanctx(local, ctx);
out:
mutex_unlock(&local->chanctx_mtx);
Expand All @@ -331,6 +350,25 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
mutex_unlock(&sdata->local->chanctx_mtx);
}

void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_sub_if_data *ap;
struct ieee80211_chanctx_conf *conf;

if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
return;

ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);

mutex_lock(&local->chanctx_mtx);

conf = rcu_dereference_protected(ap->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));
rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
mutex_unlock(&local->chanctx_mtx);
}

void ieee80211_iter_chan_contexts_atomic(
struct ieee80211_hw *hw,
void (*iter)(struct ieee80211_hw *hw,
Expand Down
9 changes: 4 additions & 5 deletions net/mac80211/ibss.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,8 +703,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
sdata_info(sdata,
"No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");

ieee80211_request_internal_scan(sdata,
ifibss->ssid, ifibss->ssid_len, NULL);
ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
NULL);
}

static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
Expand Down Expand Up @@ -802,9 +802,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
IEEE80211_SCAN_INTERVAL)) {
sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");

ieee80211_request_internal_scan(sdata,
ifibss->ssid, ifibss->ssid_len,
ifibss->fixed_channel ? ifibss->channel : NULL);
ieee80211_request_ibss_scan(sdata, ifibss->ssid,
ifibss->ssid_len, chan);
} else {
int interval = IEEE80211_SCAN_INTERVAL;

Expand Down
16 changes: 9 additions & 7 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ struct ieee80211_bss {

u32 device_ts;

u8 dtim_period;

bool wmm_used;
bool uapsd_supported;

Expand Down Expand Up @@ -140,7 +138,6 @@ enum ieee80211_bss_corrupt_data_flags {

/**
* enum ieee80211_valid_data_flags - BSS valid data flags
* @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
* @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
Expand All @@ -151,7 +148,6 @@ enum ieee80211_bss_corrupt_data_flags {
* beacon/probe response.
*/
enum ieee80211_bss_valid_data_flags {
IEEE80211_BSS_VALID_DTIM = BIT(0),
IEEE80211_BSS_VALID_WMM = BIT(1),
IEEE80211_BSS_VALID_RATES = BIT(2),
IEEE80211_BSS_VALID_ERP = BIT(3)
Expand Down Expand Up @@ -440,6 +436,7 @@ struct ieee80211_if_managed {
unsigned long timers_running; /* used for quiesce/restart */
bool powersave; /* powersave requested for this iface */
bool broken_ap; /* AP is broken -- turn off powersave */
u8 dtim_period;
enum ieee80211_smps_mode req_smps, /* requested smps mode */
driver_smps_mode; /* smps mode request */

Expand Down Expand Up @@ -773,6 +770,10 @@ struct ieee80211_sub_if_data {
u32 mntr_flags;
} u;

spinlock_t cleanup_stations_lock;
struct list_head cleanup_stations;
struct work_struct cleanup_stations_wk;

#ifdef CONFIG_MAC80211_DEBUGFS
struct {
struct dentry *dir;
Expand Down Expand Up @@ -1329,9 +1330,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,

/* scan/BSS handling */
void ieee80211_scan_work(struct work_struct *work);
int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
const u8 *ssid, u8 ssid_len,
struct ieee80211_channel *chan);
int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
const u8 *ssid, u8 ssid_len,
struct ieee80211_channel *chan);
int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req);
void ieee80211_scan_cancel(struct ieee80211_local *local);
Expand Down Expand Up @@ -1628,6 +1629,7 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
const struct cfg80211_chan_def *chandef,
enum ieee80211_chanctx_mode mode);
void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);

void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *chanctx);
Expand Down
48 changes: 23 additions & 25 deletions net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,8 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)

static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
{
int meshhdrlen;
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0;

/* FIX: what would be proper limits for MTU?
* This interface uses 802.3 frames. */
if (new_mtu < 256 ||
new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN)
return -EINVAL;
}

dev->mtu = new_mtu;
return 0;
Expand Down Expand Up @@ -586,11 +577,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)

switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
/* no need to tell driver, but set carrier */
if (rtnl_dereference(sdata->bss->beacon))
/* no need to tell driver, but set carrier and chanctx */
if (rtnl_dereference(sdata->bss->beacon)) {
ieee80211_vif_vlan_copy_chanctx(sdata);
netif_carrier_on(dev);
else
} else {
netif_carrier_off(dev);
}
break;
case NL80211_IFTYPE_MONITOR:
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
Expand Down Expand Up @@ -839,6 +832,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
list_del(&sdata->u.vlan.list);
rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
/* no need to tell driver */
break;
case NL80211_IFTYPE_MONITOR:
Expand All @@ -865,20 +859,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
cancel_work_sync(&sdata->work);
/*
* When we get here, the interface is marked down.
* Call rcu_barrier() to wait both for the RX path
* Call synchronize_rcu() to wait for the RX path
* should it be using the interface and enqueuing
* frames at this very time on another CPU, and
* for the sta free call_rcu callbacks.
*/
rcu_barrier();

/*
* free_sta_rcu() enqueues a work for the actual
* sta cleanup, so we need to flush it while
* sdata is still valid.
* frames at this very time on another CPU.
*/
flush_workqueue(local->workqueue);

synchronize_rcu();
skb_queue_purge(&sdata->skb_queue);

/*
Expand Down Expand Up @@ -1498,6 +1483,15 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
mutex_unlock(&local->iflist_mtx);
}

static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
{
struct ieee80211_sub_if_data *sdata;

sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);

ieee80211_cleanup_sdata_stas(sdata);
}

int ieee80211_if_add(struct ieee80211_local *local, const char *name,
struct wireless_dev **new_wdev, enum nl80211_iftype type,
struct vif_params *params)
Expand Down Expand Up @@ -1573,6 +1567,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,

INIT_LIST_HEAD(&sdata->key_list);

spin_lock_init(&sdata->cleanup_stations_lock);
INIT_LIST_HEAD(&sdata->cleanup_stations);
INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);

for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
struct ieee80211_supported_band *sband;
sband = local->hw.wiphy->bands[i];
Expand Down
8 changes: 4 additions & 4 deletions net/mac80211/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
return -ENOMEM;
sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
for (i = 0; i < RMC_BUCKETS; i++)
INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list);
INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]);
return 0;
}

Expand All @@ -177,7 +177,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
return;

for (i = 0; i < RMC_BUCKETS; i++)
list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) {
list_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
list_del(&p->list);
kmem_cache_free(rm_cache, p);
}
Expand Down Expand Up @@ -210,7 +210,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
/* Don't care about endianness since only match matters */
memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask;
list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) {
list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
++entries;
if (time_after(jiffies, p->exp_time) ||
(entries == RMC_QUEUE_MAX_LEN)) {
Expand All @@ -229,7 +229,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
p->seqnum = seqnum;
p->exp_time = jiffies + RMC_TIMEOUT;
memcpy(p->sa, sa, ETH_ALEN);
list_add(&p->list, &rmc->bucket[idx].list);
list_add(&p->list, &rmc->bucket[idx]);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion net/mac80211/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ struct rmc_entry {
};

struct mesh_rmc {
struct rmc_entry bucket[RMC_BUCKETS];
struct list_head bucket[RMC_BUCKETS];
u32 idx_mask;
};

Expand Down
Loading

0 comments on commit d339fc8

Please sign in to comment.