Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352700
b: refs/heads/master
c: 164eb02
h: refs/heads/master
v: v3
  • Loading branch information
Simon Wunderlich authored and Johannes Berg committed Feb 15, 2013
1 parent 4b170ed commit c01cea0
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 2 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: 04f39047af2a6df64b763ea5a271db24879d0391
refs/heads/master: 164eb02d070af987890e1db1c12b8ae0394b19f7
14 changes: 14 additions & 0 deletions trunk/include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,12 @@ struct ieee80211_low_level_stats {
* enum ieee80211_chanctx_change - change flag for channel context
* @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
* @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
* @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed
*/
enum ieee80211_chanctx_change {
IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
IEEE80211_CHANCTX_CHANGE_RADAR = BIT(2),
};

/**
Expand All @@ -165,6 +167,7 @@ enum ieee80211_chanctx_change {
* @rx_chains_dynamic: The number of RX chains that must be enabled
* after RTS/CTS handshake to receive SMPS MIMO transmissions;
* this will always be >= @rx_chains_static.
* @radar_enabled: whether radar detection is enabled on this channel.
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information.
*/
Expand All @@ -173,6 +176,8 @@ struct ieee80211_chanctx_conf {

u8 rx_chains_static, rx_chains_dynamic;

bool radar_enabled;

u8 drv_priv[0] __aligned(sizeof(void *));
};

Expand Down Expand Up @@ -967,6 +972,7 @@ enum ieee80211_smps_mode {
*
* @channel: the channel to tune to
* @channel_type: the channel (HT) type
* @radar_enabled: whether radar detection is enabled
*
* @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
* (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11,
Expand All @@ -993,6 +999,7 @@ struct ieee80211_conf {

struct ieee80211_channel *channel;
enum nl80211_channel_type channel_type;
bool radar_enabled;
enum ieee80211_smps_mode smps_mode;
};

Expand Down Expand Up @@ -3944,6 +3951,13 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
enum nl80211_cqm_rssi_threshold_event rssi_event,
gfp_t gfp);

/**
* ieee80211_radar_detected - inform that a radar was detected
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
*/
void ieee80211_radar_detected(struct ieee80211_hw *hw);

/**
* ieee80211_chswitch_done - Complete channel switch process
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
Expand Down
36 changes: 35 additions & 1 deletion trunk/net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
/* TODO: make hostapd tell us what it wants */
sdata->smps_mode = IEEE80211_SMPS_OFF;
sdata->needed_rx_chains = sdata->local->rx_chains;
sdata->radar_required = params->radar_required;

err = ieee80211_vif_use_channel(sdata, &params->chandef,
IEEE80211_CHANCTX_SHARED);
Expand Down Expand Up @@ -2395,7 +2396,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
INIT_LIST_HEAD(&roc->dependents);

/* if there's one pending or we're scanning, queue this one */
if (!list_empty(&local->roc_list) || local->scanning)
if (!list_empty(&local->roc_list) ||
local->scanning || local->radar_detect_enabled)
goto out_check_combine;

/* if not HW assist, just queue & schedule work */
Expand Down Expand Up @@ -2645,6 +2647,37 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
return ieee80211_cancel_roc(local, cookie, false);
}

static int ieee80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
unsigned long timeout;
int err;

if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;

/* whatever, but channel contexts should not complain about that one */
sdata->smps_mode = IEEE80211_SMPS_OFF;
sdata->needed_rx_chains = local->rx_chains;
sdata->radar_required = true;

mutex_lock(&local->iflist_mtx);
err = ieee80211_vif_use_channel(sdata, chandef,
IEEE80211_CHANCTX_SHARED);
mutex_unlock(&local->iflist_mtx);
if (err)
return err;

timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
ieee80211_queue_delayed_work(&sdata->local->hw,
&sdata->dfs_cac_timer_work, timeout);

return 0;
}

static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
unsigned int wait, const u8 *buf, size_t len,
Expand Down Expand Up @@ -3350,4 +3383,5 @@ struct cfg80211_ops mac80211_config_ops = {
.get_et_stats = ieee80211_get_et_stats,
.get_et_strings = ieee80211_get_et_strings,
.get_channel = ieee80211_cfg_get_channel,
.start_radar_detection = ieee80211_start_radar_detection,
};
33 changes: 33 additions & 0 deletions trunk/net/mac80211/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
if (ctx->refcount > 0) {
ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
ieee80211_recalc_smps_chanctx(local, ctx);
ieee80211_recalc_radar_chanctx(local, ctx);
}
}

Expand All @@ -216,6 +217,37 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
ieee80211_free_chanctx(local, ctx);
}

void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *chanctx)
{
struct ieee80211_sub_if_data *sdata;
bool radar_enabled = false;

lockdep_assert_held(&local->chanctx_mtx);

rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (sdata->radar_required) {
radar_enabled = true;
break;
}
}
rcu_read_unlock();

if (radar_enabled == chanctx->conf.radar_enabled)
return;

chanctx->conf.radar_enabled = radar_enabled;
local->radar_detect_enabled = chanctx->conf.radar_enabled;

if (!local->use_chanctx) {
local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
}

drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
}

void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *chanctx)
{
Expand Down Expand Up @@ -331,6 +363,7 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
}

ieee80211_recalc_smps_chanctx(local, ctx);
ieee80211_recalc_radar_chanctx(local, ctx);
out:
mutex_unlock(&local->chanctx_mtx);
return ret;
Expand Down
14 changes: 14 additions & 0 deletions trunk/net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,9 @@ struct ieee80211_sub_if_data {
int user_power_level; /* in dBm */
int ap_power_level; /* in dBm */

bool radar_required;
struct delayed_work dfs_cac_timer_work;

/*
* AP this belongs to: self in AP mode and
* corresponding AP in VLAN mode, NULL for
Expand Down Expand Up @@ -942,6 +945,10 @@ struct ieee80211_local {
/* wowlan is enabled -- don't reconfig on resume */
bool wowlan;

/* DFS/radar detection is enabled */
bool radar_detect_enabled;
struct work_struct radar_detected_work;

/* number of RX chains the hardware has */
u8 rx_chains;

Expand Down Expand Up @@ -1606,6 +1613,13 @@ void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,

void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *chanctx);
void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
struct ieee80211_chanctx *chanctx);

void ieee80211_dfs_cac_timer(unsigned long data);
void ieee80211_dfs_cac_timer_work(struct work_struct *work);
void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
void ieee80211_dfs_radar_detected_work(struct work_struct *work);

#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
Expand Down
12 changes: 12 additions & 0 deletions trunk/net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,

cancel_work_sync(&sdata->recalc_smps);

cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);

if (sdata->wdev.cac_started) {
mutex_lock(&local->iflist_mtx);
ieee80211_vif_release_channel(sdata);
mutex_unlock(&local->iflist_mtx);
cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL);
}

/* APs need special treatment */
if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct ieee80211_sub_if_data *vlan, *tmpsdata;
Expand Down Expand Up @@ -1513,6 +1523,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
spin_lock_init(&sdata->cleanup_stations_lock);
INIT_LIST_HEAD(&sdata->cleanup_stations);
INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
ieee80211_dfs_cac_timer_work);

for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
struct ieee80211_supported_band *sband;
Expand Down
13 changes: 13 additions & 0 deletions trunk/net/mac80211/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,

INIT_WORK(&local->restart_work, ieee80211_restart_work);

INIT_WORK(&local->radar_detected_work,
ieee80211_dfs_radar_detected_work);

INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
local->smps_mode = IEEE80211_SMPS_OFF;

Expand Down Expand Up @@ -713,6 +716,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
*/
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
return -EINVAL;

/* DFS currently not supported with channel context drivers */
for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
const struct ieee80211_iface_combination *comb;

comb = &local->hw.wiphy->iface_combinations[i];

if (comb->radar_detect_widths)
return -EINVAL;
}
}

/* Only HW csum features are currently compatible with mac80211 */
Expand Down
13 changes: 13 additions & 0 deletions trunk/net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,19 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
}

void ieee80211_dfs_cac_timer_work(struct work_struct *work)
{
struct delayed_work *delayed_work =
container_of(work, struct delayed_work, work);
struct ieee80211_sub_if_data *sdata =
container_of(delayed_work, struct ieee80211_sub_if_data,
dfs_cac_timer_work);

ieee80211_vif_release_channel(sdata);

cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
}

/* MLME */
static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
Expand Down
2 changes: 2 additions & 0 deletions trunk/net/mac80211/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)

ieee80211_scan_cancel(local);

ieee80211_dfs_cac_cancel(local);

if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
Expand Down
3 changes: 3 additions & 0 deletions trunk/net/mac80211/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
static bool ieee80211_can_scan(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
if (local->radar_detect_enabled)
return false;

if (!list_empty(&local->roc_list))
return false;

Expand Down
19 changes: 19 additions & 0 deletions trunk/net/mac80211/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -1862,6 +1862,25 @@ TRACE_EVENT(drv_set_default_unicast_key,
LOCAL_PR_ARG, VIF_PR_ARG, __entry->key_idx)
);

TRACE_EVENT(api_radar_detected,
TP_PROTO(struct ieee80211_local *local),

TP_ARGS(local),

TP_STRUCT__entry(
LOCAL_ENTRY
),

TP_fast_assign(
LOCAL_ASSIGN;
),

TP_printk(
LOCAL_PR_FMT " radar detected",
LOCAL_PR_ARG
)
);

#ifdef CONFIG_MAC80211_MESSAGE_TRACING
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mac80211_msg
Expand Down
46 changes: 46 additions & 0 deletions trunk/net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2133,3 +2133,49 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,

return ts;
}

void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;

mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);

if (sdata->wdev.cac_started) {
ieee80211_vif_release_channel(sdata);
cfg80211_cac_event(sdata->dev,
NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL);
}
}
mutex_unlock(&local->iflist_mtx);
}

void ieee80211_dfs_radar_detected_work(struct work_struct *work)
{
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, radar_detected_work);
struct cfg80211_chan_def chandef;

ieee80211_dfs_cac_cancel(local);

if (local->use_chanctx)
/* currently not handled */
WARN_ON(1);
else {
cfg80211_chandef_create(&chandef, local->hw.conf.channel,
local->hw.conf.channel_type);
cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
}
}

void ieee80211_radar_detected(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);

trace_api_radar_detected(local);

ieee80211_queue_work(hw, &local->radar_detected_work);
}
EXPORT_SYMBOL(ieee80211_radar_detected);

0 comments on commit c01cea0

Please sign in to comment.