diff options
author | Jouni Malinen <j@w1.fi> | 2008-10-30 17:59:24 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-10 23:17:40 +0300 |
commit | 318884875bdddca663ecc373c813cf8e117d9e43 (patch) | |
tree | de9cfbe0bf24bea0ab1546a0613fbc9417bb6cb8 /net | |
parent | 1e898ff83c31c303f73c3893d1ac519e4d9b59e5 (diff) | |
download | linux-318884875bdddca663ecc373c813cf8e117d9e43.tar.xz |
nl80211: Add TX queue parameter configuration
Add a new attribute, NL80211_ATTR_WIPHY_TXQ_PARAMS, that can be used with
NL80211_CMD_SET_WIPHY for userspace (e.g., hostapd) to set TX queue
parameters (txop, cwmin, cwmax, aifs).
Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/cfg.c | 25 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 67 |
2 files changed, 87 insertions, 5 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 442a4d7b1808..fe672faa819d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1069,6 +1069,30 @@ static int ieee80211_change_bss(struct wiphy *wiphy, return 0; } +static int ieee80211_set_txq_params(struct wiphy *wiphy, + struct ieee80211_txq_params *params) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + struct ieee80211_tx_queue_params p; + + if (!local->ops->conf_tx) + return -EOPNOTSUPP; + + memset(&p, 0, sizeof(p)); + p.aifs = params->aifs; + p.cw_max = params->cwmax; + p.cw_min = params->cwmin; + p.txop = params->txop; + if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) { + printk(KERN_DEBUG "%s: failed to set TX queue " + "parameters for queue %d\n", local->mdev->name, + params->queue); + return -EINVAL; + } + + return 0; +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1095,4 +1119,5 @@ struct cfg80211_ops mac80211_config_ops = { .get_mesh_params = ieee80211_get_mesh_params, #endif .change_bss = ieee80211_change_bss, + .set_txq_params = ieee80211_set_txq_params, }; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1ea5e3fd3931..e3e1494e769a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -58,6 +58,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, .len = BUS_ID_SIZE-1 }, + [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, @@ -286,20 +287,76 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) return -ENOBUFS; } +static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { + [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 }, + [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 }, + [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 }, + [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 }, + [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 }, +}; + +static int parse_txq_params(struct nlattr *tb[], + struct ieee80211_txq_params *txq_params) +{ + if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || + !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || + !tb[NL80211_TXQ_ATTR_AIFS]) + return -EINVAL; + + txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); + txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); + txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); + txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); + txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); + + return 0; +} + static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev; - int result; - - if (!info->attrs[NL80211_ATTR_WIPHY_NAME]) - return -EINVAL; + int result = 0, rem_txq_params = 0; + struct nlattr *nl_txq_params; rdev = cfg80211_get_dev_from_info(info); if (IS_ERR(rdev)) return PTR_ERR(rdev); - result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); + if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { + result = cfg80211_dev_rename( + rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); + if (result) + goto bad_res; + } + + if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { + struct ieee80211_txq_params txq_params; + struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; + + if (!rdev->ops->set_txq_params) { + result = -EOPNOTSUPP; + goto bad_res; + } + + nla_for_each_nested(nl_txq_params, + info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], + rem_txq_params) { + nla_parse(tb, NL80211_TXQ_ATTR_MAX, + nla_data(nl_txq_params), + nla_len(nl_txq_params), + txq_params_policy); + result = parse_txq_params(tb, &txq_params); + if (result) + goto bad_res; + + result = rdev->ops->set_txq_params(&rdev->wiphy, + &txq_params); + if (result) + goto bad_res; + } + } +bad_res: cfg80211_put_dev(rdev); return result; } |