* [RFC 1/2] cfg80211/mac80211: bind RTS threshold to vif.
2012-05-17 9:58 [RFC 0/2] bind RTS threshold to vif Lukasz Kucharczyk
@ 2012-05-17 9:58 ` Lukasz Kucharczyk
2012-05-17 9:58 ` [RFC 2/2] iw: handle rts threshold per netdev Lukasz Kucharczyk
2012-05-17 11:40 ` [RFC 0/2] bind RTS threshold to vif Marek Lindner
2 siblings, 0 replies; 5+ messages in thread
From: Lukasz Kucharczyk @ 2012-05-17 9:58 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, lukasz.kucharczyk
Add possibility to set rts threshold for vif
in preparation to multi channel operation.
Driver's set_rts_threshold callback has additional
<struct ieee80211_vif *vif> parameter.
>From userspace, it's possible to set rts threshold for:
* phy: .set_rts_threshold will be called with vif == NULL.
Driver should apply new value for all interfaces.
(backward compatible)
* vif: .set_rts_threshold will be called with vif != NULL.
Driver should apply new value only for corresponding
interface. If driver doesn't support setting RTS
threshold for vif, it should return -ENOTSUPP.
Change-Id: I2b786525a23ab179cc163fd8d80c89d976d9df67
Signed-off-by: Lukasz Kucharczyk <lukasz.kucharczyk@tieto.com>
---
include/net/cfg80211.h | 8 +++++-
include/net/mac80211.h | 3 +-
net/mac80211/cfg.c | 21 +++++++++++++------
net/mac80211/debugfs_netdev.c | 6 +++++
net/mac80211/driver-ops.h | 10 +++++++-
net/mac80211/driver-trace.h | 32 +++++++++++++++++++++++++++--
net/mac80211/iface.c | 2 +
net/mac80211/tx.c | 3 +-
net/mac80211/util.c | 16 ++++++++++++--
net/wireless/core.c | 1 -
net/wireless/debugfs.c | 3 --
net/wireless/nl80211.c | 43 ++++++++++++++++++++++++++++++++--------
12 files changed, 115 insertions(+), 33 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d6cb205..77a8496 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1632,6 +1632,10 @@ struct cfg80211_ops {
int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
+ int (*set_rts_threshold)(struct wiphy *wiphy,
+ struct net_device *dev,
+ int rts_threshold);
+
int (*set_tx_power)(struct wiphy *wiphy,
enum nl80211_tx_power_setting type, int mbm);
int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
@@ -1959,7 +1963,6 @@ struct wiphy_wowlan_support {
* @retry_long: Retry limit for long frames (dot11LongRetryLimit)
* @frag_threshold: Fragmentation threshold (dot11FragmentationThreshold);
* -1 = fragmentation disabled, only odd values >= 256 used
- * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
* @_net: the network namespace this wiphy currently lives in
* @perm_addr: permanent MAC address of this device
* @addr_mask: If the device supports multiple MAC addresses by masking,
@@ -2080,7 +2083,6 @@ struct wiphy {
u8 retry_short;
u8 retry_long;
u32 frag_threshold;
- u32 rts_threshold;
u8 coverage_class;
char fw_version[ETHTOOL_BUSINFO_LEN];
@@ -2283,6 +2285,7 @@ struct cfg80211_cached_keys;
* @cleanup_work: work struct used for cleanup that can't be done directly
* @beacon_interval: beacon interval used on this device for transmitting
* beacons, 0 when not valid
+ * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled
*/
struct wireless_dev {
struct wiphy *wiphy;
@@ -2322,6 +2325,7 @@ struct wireless_dev {
int ps_timeout;
int beacon_interval;
+ u32 rts_threshold;
u32 ap_unexpected_nlpid;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index baba4af..e9b3716 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2296,7 +2296,8 @@ struct ieee80211_ops {
void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
u32 *iv32, u16 *iv16);
int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
- int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
+ int (*set_rts_threshold)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u32 value);
int (*sta_add)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0221270..81c9355 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1883,13 +1883,6 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return err;
}
- if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
- err = drv_set_rts_threshold(local, wiphy->rts_threshold);
-
- if (err)
- return err;
- }
-
if (changed & WIPHY_PARAM_RETRY_SHORT)
local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
if (changed & WIPHY_PARAM_RETRY_LONG)
@@ -1901,6 +1894,19 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
return 0;
}
+static int ieee80211_set_rts_threshold(struct wiphy *wiphy,
+ struct net_device *dev,
+ int rts_threshold)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata = NULL;
+
+ if (dev)
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ return drv_set_rts_threshold(local, sdata, rts_threshold);
+}
+
static int ieee80211_set_tx_power(struct wiphy *wiphy,
enum nl80211_tx_power_setting type, int mbm)
{
@@ -2946,6 +2952,7 @@ struct cfg80211_ops mac80211_config_ops = {
.join_ibss = ieee80211_join_ibss,
.leave_ibss = ieee80211_leave_ibss,
.set_wiphy_params = ieee80211_set_wiphy_params,
+ .set_rts_threshold = ieee80211_set_rts_threshold,
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
.set_wds_peer = ieee80211_set_wds_peer,
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ea0122d..a4de84d 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -168,6 +168,7 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz,
IEEE80211_IF_FILE(flags, flags, HEX);
IEEE80211_IF_FILE(state, state, LHEX);
IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
+IEEE80211_IF_FILE(rts_threshold, wdev.rts_threshold, DEC);
/* STA attributes */
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
@@ -524,6 +525,7 @@ static void add_common_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(rc_rateidx_mask_5ghz);
DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz);
DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz);
+ DEBUGFS_ADD(rts_threshold);
}
static void add_sta_files(struct ieee80211_sub_if_data *sdata)
@@ -536,6 +538,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
DEBUGFS_ADD_MODE(uapsd_queues, 0600);
DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600);
+ DEBUGFS_ADD(rts_threshold);
}
static void add_ap_files(struct ieee80211_sub_if_data *sdata)
@@ -545,16 +548,19 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata)
DEBUGFS_ADD(dtim_count);
DEBUGFS_ADD(num_buffered_multicast);
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
+ DEBUGFS_ADD(rts_threshold);
}
static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD_MODE(tsf, 0600);
+ DEBUGFS_ADD(rts_threshold);
}
static void add_wds_files(struct ieee80211_sub_if_data *sdata)
{
DEBUGFS_ADD(peer);
+ DEBUGFS_ADD(rts_threshold);
}
#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 5e56b7c..05036a6 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -431,15 +431,21 @@ static inline int drv_set_frag_threshold(struct ieee80211_local *local,
}
static inline int drv_set_rts_threshold(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
u32 value)
{
int ret = 0;
+ struct ieee80211_vif *vif = NULL;
might_sleep();
- trace_drv_set_rts_threshold(local, value);
+ if (sdata)
+ vif = &sdata->vif;
+
+ trace_drv_set_rts_threshold(local, sdata, value);
if (local->ops->set_rts_threshold)
- ret = local->ops->set_rts_threshold(&local->hw, value);
+ ret = local->ops->set_rts_threshold(&local->hw, vif, value);
+
trace_drv_return_int(local, ret);
return ret;
}
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6de00b2..6859fc2 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -567,9 +567,35 @@ DEFINE_EVENT(local_u32_evt, drv_set_frag_threshold,
TP_ARGS(local, value)
);
-DEFINE_EVENT(local_u32_evt, drv_set_rts_threshold,
- TP_PROTO(struct ieee80211_local *local, u32 value),
- TP_ARGS(local, value)
+TRACE_EVENT(drv_set_rts_threshold,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata, u32 value),
+ TP_ARGS(local, sdata, value),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(enum nl80211_iftype, vif_type)
+ __field(void *, sdata)
+ __field(bool, p2p)
+ __string(vif_name, "<nodev>")
+ __field(u32, value)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->vif_type = sdata ? sdata->vif.type :
+ NL80211_IFTYPE_UNSPECIFIED;
+ __entry->sdata = sdata;
+ __entry->p2p = sdata ? sdata->vif.p2p : false;
+ __assign_str(vif_name, (sdata && sdata->dev) ?
+ sdata->dev->name : "<nodev>");
+ __entry->value = value;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT " RTS:%d",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->value
+ )
);
TRACE_EVENT(drv_set_coverage_class,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 9b89fc6..70dccf2 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1003,6 +1003,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
skb_queue_head_init(&sdata->skb_queue);
INIT_WORK(&sdata->work, ieee80211_iface_work);
+ sdata->wdev.rts_threshold = (u32) -1;
+
switch (type) {
case NL80211_IFTYPE_P2P_GO:
type = NL80211_IFTYPE_AP;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 56c68db..7f11f7d 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -650,9 +650,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
tx->sdata->vif.type == NL80211_IFTYPE_ADHOC);
/* set up RTS protection if desired */
- if (len > tx->local->hw.wiphy->rts_threshold) {
+ if (len > tx->sdata->wdev.rts_threshold)
txrc.rts = rts = true;
- }
/*
* Use short preamble if the BSS can handle it, but not for
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 22f2216..d9b0432 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1236,9 +1236,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
/* setup fragmentation threshold */
drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
- /* setup RTS threshold */
- drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
-
/* reset coverage class */
drv_set_coverage_class(local, hw->wiphy->coverage_class);
@@ -1397,6 +1394,19 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (ieee80211_sdata_running(sdata))
ieee80211_enable_keys(sdata);
+
+ /* setup RTS threshold */
+ list_for_each_entry(sdata, &local->interfaces, list)
+ if (drv_set_rts_threshold(local, sdata,
+ sdata->wdev.rts_threshold)) {
+ /* If setting rts threshold for particular interface
+ * failed, it means that driver only supports
+ * setting rts threshold for hw */
+ drv_set_rts_threshold(local, NULL,
+ sdata->wdev.rts_threshold);
+ break;
+ }
+
wake_up:
ieee80211_wake_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
diff --git a/net/wireless/core.c b/net/wireless/core.c
index e1171de..a36bd5f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -423,7 +423,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->wiphy.retry_short = 7;
rdev->wiphy.retry_long = 4;
rdev->wiphy.frag_threshold = (u32) -1;
- rdev->wiphy.rts_threshold = (u32) -1;
rdev->wiphy.coverage_class = 0;
return &rdev->wiphy;
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 920cabe..1314427 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -31,8 +31,6 @@ static const struct file_operations name## _ops = { \
.llseek = generic_file_llseek, \
};
-DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
- wiphy->rts_threshold)
DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
wiphy->frag_threshold);
DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
@@ -107,7 +105,6 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
{
struct dentry *phyd = rdev->wiphy.debugfsdir;
- DEBUGFS_ADD(rts_threshold);
DEBUGFS_ADD(fragmentation_threshold);
DEBUGFS_ADD(short_retry_limit);
DEBUGFS_ADD(long_retry_limit);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fa05e96..8656dd8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -730,8 +730,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
dev->wiphy.retry_long) ||
nla_put_u32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
dev->wiphy.frag_threshold) ||
- nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
- dev->wiphy.rts_threshold) ||
nla_put_u8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
dev->wiphy.coverage_class) ||
nla_put_u8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
@@ -1464,9 +1462,38 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]) {
+ u32 old_rts_threshold;
rts_threshold = nla_get_u32(
info->attrs[NL80211_ATTR_WIPHY_RTS_THRESHOLD]);
- changed |= WIPHY_PARAM_RTS_THRESHOLD;
+ if (!rdev->ops->set_rts_threshold) {
+ result = -EOPNOTSUPP;
+ goto bad_res;
+ }
+
+ if (netdev) {
+ wdev = netdev->ieee80211_ptr;
+ } else {
+ mutex_lock(&rdev->devlist_mtx);
+ wdev = list_entry(rdev->netdev_list.next,
+ typeof(*wdev), list);
+ mutex_unlock(&rdev->devlist_mtx);
+ }
+ old_rts_threshold = wdev->rts_threshold;
+
+ wdev->rts_threshold = rts_threshold;
+ result = rdev->ops->set_rts_threshold(&rdev->wiphy, netdev,
+ rts_threshold);
+
+ if (result) {
+ wdev->rts_threshold = old_rts_threshold;
+ goto bad_res;
+ } else if (!netdev) {
+ mutex_lock(&rdev->devlist_mtx);
+ list_for_each_entry(wdev, &rdev->netdev_list, list) {
+ wdev->rts_threshold = rts_threshold;
+ }
+ mutex_unlock(&rdev->devlist_mtx);
+ }
}
if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
@@ -1477,7 +1504,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (changed) {
u8 old_retry_short, old_retry_long;
- u32 old_frag_threshold, old_rts_threshold;
+ u32 old_frag_threshold;
u8 old_coverage_class;
if (!rdev->ops->set_wiphy_params) {
@@ -1488,7 +1515,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
old_retry_short = rdev->wiphy.retry_short;
old_retry_long = rdev->wiphy.retry_long;
old_frag_threshold = rdev->wiphy.frag_threshold;
- old_rts_threshold = rdev->wiphy.rts_threshold;
old_coverage_class = rdev->wiphy.coverage_class;
if (changed & WIPHY_PARAM_RETRY_SHORT)
@@ -1497,8 +1523,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev->wiphy.retry_long = retry_long;
if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
rdev->wiphy.frag_threshold = frag_threshold;
- if (changed & WIPHY_PARAM_RTS_THRESHOLD)
- rdev->wiphy.rts_threshold = rts_threshold;
if (changed & WIPHY_PARAM_COVERAGE_CLASS)
rdev->wiphy.coverage_class = coverage_class;
@@ -1507,7 +1531,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev->wiphy.retry_short = old_retry_short;
rdev->wiphy.retry_long = old_retry_long;
rdev->wiphy.frag_threshold = old_frag_threshold;
- rdev->wiphy.rts_threshold = old_rts_threshold;
rdev->wiphy.coverage_class = old_coverage_class;
}
}
@@ -1537,7 +1560,9 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
dev->ieee80211_ptr->iftype) ||
nla_put_u32(msg, NL80211_ATTR_GENERATION,
rdev->devlist_generation ^
- (cfg80211_rdev_list_generation << 2)))
+ (cfg80211_rdev_list_generation << 2)) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
+ dev->ieee80211_ptr->rts_threshold))
goto nla_put_failure;
if (rdev->ops->get_channel) {
--
1.7.0.4
^ permalink raw reply related [flat|nested] 5+ messages in thread