diff options
author | Jouni Malinen <j@w1.fi> | 2008-10-30 10:59:24 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-11-10 15:17:40 -0500 |
commit | 318884875bdddca663ecc373c813cf8e117d9e43 (patch) | |
tree | de9cfbe0bf24bea0ab1546a0613fbc9417bb6cb8 | |
parent | 1e898ff83c31c303f73c3893d1ac519e4d9b59e5 (diff) |
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>
-rw-r--r-- | include/linux/nl80211.h | 43 | ||||
-rw-r--r-- | include/net/cfg80211.h | 23 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 25 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 67 |
4 files changed, 151 insertions, 7 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 5009809588c0..79827345351d 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -25,8 +25,9 @@ | |||
25 | * | 25 | * |
26 | * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request | 26 | * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request |
27 | * to get a list of all present wiphys. | 27 | * to get a list of all present wiphys. |
28 | * @NL80211_CMD_SET_WIPHY: set wiphy name, needs %NL80211_ATTR_WIPHY and | 28 | * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or |
29 | * %NL80211_ATTR_WIPHY_NAME. | 29 | * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME |
30 | * and/or %NL80211_ATTR_WIPHY_TXQ_PARAMS. | ||
30 | * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request | 31 | * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request |
31 | * or rename notification. Has attributes %NL80211_ATTR_WIPHY and | 32 | * or rename notification. Has attributes %NL80211_ATTR_WIPHY and |
32 | * %NL80211_ATTR_WIPHY_NAME. | 33 | * %NL80211_ATTR_WIPHY_NAME. |
@@ -178,6 +179,7 @@ enum nl80211_commands { | |||
178 | * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. | 179 | * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. |
179 | * /sys/class/ieee80211/<phyname>/index | 180 | * /sys/class/ieee80211/<phyname>/index |
180 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) | 181 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) |
182 | * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters | ||
181 | * | 183 | * |
182 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on | 184 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on |
183 | * @NL80211_ATTR_IFNAME: network interface name | 185 | * @NL80211_ATTR_IFNAME: network interface name |
@@ -312,6 +314,8 @@ enum nl80211_attrs { | |||
312 | 314 | ||
313 | NL80211_ATTR_BSS_BASIC_RATES, | 315 | NL80211_ATTR_BSS_BASIC_RATES, |
314 | 316 | ||
317 | NL80211_ATTR_WIPHY_TXQ_PARAMS, | ||
318 | |||
315 | /* add attributes here, update the policy in nl80211.c */ | 319 | /* add attributes here, update the policy in nl80211.c */ |
316 | 320 | ||
317 | __NL80211_ATTR_AFTER_LAST, | 321 | __NL80211_ATTR_AFTER_LAST, |
@@ -324,6 +328,7 @@ enum nl80211_attrs { | |||
324 | */ | 328 | */ |
325 | #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY | 329 | #define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY |
326 | #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES | 330 | #define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES |
331 | #define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS | ||
327 | 332 | ||
328 | #define NL80211_MAX_SUPP_RATES 32 | 333 | #define NL80211_MAX_SUPP_RATES 32 |
329 | #define NL80211_MAX_SUPP_REG_RULES 32 | 334 | #define NL80211_MAX_SUPP_REG_RULES 32 |
@@ -698,4 +703,38 @@ enum nl80211_meshconf_params { | |||
698 | NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 | 703 | NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 |
699 | }; | 704 | }; |
700 | 705 | ||
706 | /** | ||
707 | * enum nl80211_txq_attr - TX queue parameter attributes | ||
708 | * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved | ||
709 | * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*) | ||
710 | * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning | ||
711 | * disabled | ||
712 | * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form | ||
713 | * 2^n-1 in the range 1..32767] | ||
714 | * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form | ||
715 | * 2^n-1 in the range 1..32767] | ||
716 | * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] | ||
717 | * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal | ||
718 | * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number | ||
719 | */ | ||
720 | enum nl80211_txq_attr { | ||
721 | __NL80211_TXQ_ATTR_INVALID, | ||
722 | NL80211_TXQ_ATTR_QUEUE, | ||
723 | NL80211_TXQ_ATTR_TXOP, | ||
724 | NL80211_TXQ_ATTR_CWMIN, | ||
725 | NL80211_TXQ_ATTR_CWMAX, | ||
726 | NL80211_TXQ_ATTR_AIFS, | ||
727 | |||
728 | /* keep last */ | ||
729 | __NL80211_TXQ_ATTR_AFTER_LAST, | ||
730 | NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 | ||
731 | }; | ||
732 | |||
733 | enum nl80211_txq_q { | ||
734 | NL80211_TXQ_Q_VO, | ||
735 | NL80211_TXQ_Q_VI, | ||
736 | NL80211_TXQ_Q_BE, | ||
737 | NL80211_TXQ_Q_BK | ||
738 | }; | ||
739 | |||
701 | #endif /* __LINUX_NL80211_H */ | 740 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7caf3c76a12f..448023193e55 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -371,6 +371,24 @@ struct mesh_config { | |||
371 | u16 dot11MeshHWMPnetDiameterTraversalTime; | 371 | u16 dot11MeshHWMPnetDiameterTraversalTime; |
372 | }; | 372 | }; |
373 | 373 | ||
374 | /** | ||
375 | * struct ieee80211_txq_params - TX queue parameters | ||
376 | * @queue: TX queue identifier (NL80211_TXQ_Q_*) | ||
377 | * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled | ||
378 | * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range | ||
379 | * 1..32767] | ||
380 | * @cwmax: Maximum contention window [a value of the form 2^n-1 in the range | ||
381 | * 1..32767] | ||
382 | * @aifs: Arbitration interframe space [0..255] | ||
383 | */ | ||
384 | struct ieee80211_txq_params { | ||
385 | enum nl80211_txq_q queue; | ||
386 | u16 txop; | ||
387 | u16 cwmin; | ||
388 | u16 cwmax; | ||
389 | u8 aifs; | ||
390 | }; | ||
391 | |||
374 | /* from net/wireless.h */ | 392 | /* from net/wireless.h */ |
375 | struct wiphy; | 393 | struct wiphy; |
376 | 394 | ||
@@ -430,6 +448,8 @@ struct wiphy; | |||
430 | * @set_mesh_cfg: set mesh parameters (by now, just mesh id) | 448 | * @set_mesh_cfg: set mesh parameters (by now, just mesh id) |
431 | * | 449 | * |
432 | * @change_bss: Modify parameters for a given BSS. | 450 | * @change_bss: Modify parameters for a given BSS. |
451 | * | ||
452 | * @set_txq_params: Set TX queue parameters | ||
433 | */ | 453 | */ |
434 | struct cfg80211_ops { | 454 | struct cfg80211_ops { |
435 | int (*add_virtual_intf)(struct wiphy *wiphy, char *name, | 455 | int (*add_virtual_intf)(struct wiphy *wiphy, char *name, |
@@ -490,6 +510,9 @@ struct cfg80211_ops { | |||
490 | const struct mesh_config *nconf, u32 mask); | 510 | const struct mesh_config *nconf, u32 mask); |
491 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, | 511 | int (*change_bss)(struct wiphy *wiphy, struct net_device *dev, |
492 | struct bss_parameters *params); | 512 | struct bss_parameters *params); |
513 | |||
514 | int (*set_txq_params)(struct wiphy *wiphy, | ||
515 | struct ieee80211_txq_params *params); | ||
493 | }; | 516 | }; |
494 | 517 | ||
495 | #endif /* __NET_CFG80211_H */ | 518 | #endif /* __NET_CFG80211_H */ |
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, | |||
1069 | return 0; | 1069 | return 0; |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | static int ieee80211_set_txq_params(struct wiphy *wiphy, | ||
1073 | struct ieee80211_txq_params *params) | ||
1074 | { | ||
1075 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1076 | struct ieee80211_tx_queue_params p; | ||
1077 | |||
1078 | if (!local->ops->conf_tx) | ||
1079 | return -EOPNOTSUPP; | ||
1080 | |||
1081 | memset(&p, 0, sizeof(p)); | ||
1082 | p.aifs = params->aifs; | ||
1083 | p.cw_max = params->cwmax; | ||
1084 | p.cw_min = params->cwmin; | ||
1085 | p.txop = params->txop; | ||
1086 | if (local->ops->conf_tx(local_to_hw(local), params->queue, &p)) { | ||
1087 | printk(KERN_DEBUG "%s: failed to set TX queue " | ||
1088 | "parameters for queue %d\n", local->mdev->name, | ||
1089 | params->queue); | ||
1090 | return -EINVAL; | ||
1091 | } | ||
1092 | |||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1072 | struct cfg80211_ops mac80211_config_ops = { | 1096 | struct cfg80211_ops mac80211_config_ops = { |
1073 | .add_virtual_intf = ieee80211_add_iface, | 1097 | .add_virtual_intf = ieee80211_add_iface, |
1074 | .del_virtual_intf = ieee80211_del_iface, | 1098 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1095,4 +1119,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1095 | .get_mesh_params = ieee80211_get_mesh_params, | 1119 | .get_mesh_params = ieee80211_get_mesh_params, |
1096 | #endif | 1120 | #endif |
1097 | .change_bss = ieee80211_change_bss, | 1121 | .change_bss = ieee80211_change_bss, |
1122 | .set_txq_params = ieee80211_set_txq_params, | ||
1098 | }; | 1123 | }; |
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 = { | |||
58 | [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, | 58 | [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, |
59 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, | 59 | [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, |
60 | .len = BUS_ID_SIZE-1 }, | 60 | .len = BUS_ID_SIZE-1 }, |
61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | ||
61 | 62 | ||
62 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 63 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
63 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 64 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
@@ -286,20 +287,76 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
286 | return -ENOBUFS; | 287 | return -ENOBUFS; |
287 | } | 288 | } |
288 | 289 | ||
290 | static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { | ||
291 | [NL80211_TXQ_ATTR_QUEUE] = { .type = NLA_U8 }, | ||
292 | [NL80211_TXQ_ATTR_TXOP] = { .type = NLA_U16 }, | ||
293 | [NL80211_TXQ_ATTR_CWMIN] = { .type = NLA_U16 }, | ||
294 | [NL80211_TXQ_ATTR_CWMAX] = { .type = NLA_U16 }, | ||
295 | [NL80211_TXQ_ATTR_AIFS] = { .type = NLA_U8 }, | ||
296 | }; | ||
297 | |||
298 | static int parse_txq_params(struct nlattr *tb[], | ||
299 | struct ieee80211_txq_params *txq_params) | ||
300 | { | ||
301 | if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || | ||
302 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || | ||
303 | !tb[NL80211_TXQ_ATTR_AIFS]) | ||
304 | return -EINVAL; | ||
305 | |||
306 | txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); | ||
307 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); | ||
308 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); | ||
309 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); | ||
310 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
289 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | 315 | static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) |
290 | { | 316 | { |
291 | struct cfg80211_registered_device *rdev; | 317 | struct cfg80211_registered_device *rdev; |
292 | int result; | 318 | int result = 0, rem_txq_params = 0; |
293 | 319 | struct nlattr *nl_txq_params; | |
294 | if (!info->attrs[NL80211_ATTR_WIPHY_NAME]) | ||
295 | return -EINVAL; | ||
296 | 320 | ||
297 | rdev = cfg80211_get_dev_from_info(info); | 321 | rdev = cfg80211_get_dev_from_info(info); |
298 | if (IS_ERR(rdev)) | 322 | if (IS_ERR(rdev)) |
299 | return PTR_ERR(rdev); | 323 | return PTR_ERR(rdev); |
300 | 324 | ||
301 | result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); | 325 | if (info->attrs[NL80211_ATTR_WIPHY_NAME]) { |
326 | result = cfg80211_dev_rename( | ||
327 | rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); | ||
328 | if (result) | ||
329 | goto bad_res; | ||
330 | } | ||
331 | |||
332 | if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { | ||
333 | struct ieee80211_txq_params txq_params; | ||
334 | struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; | ||
335 | |||
336 | if (!rdev->ops->set_txq_params) { | ||
337 | result = -EOPNOTSUPP; | ||
338 | goto bad_res; | ||
339 | } | ||
340 | |||
341 | nla_for_each_nested(nl_txq_params, | ||
342 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | ||
343 | rem_txq_params) { | ||
344 | nla_parse(tb, NL80211_TXQ_ATTR_MAX, | ||
345 | nla_data(nl_txq_params), | ||
346 | nla_len(nl_txq_params), | ||
347 | txq_params_policy); | ||
348 | result = parse_txq_params(tb, &txq_params); | ||
349 | if (result) | ||
350 | goto bad_res; | ||
351 | |||
352 | result = rdev->ops->set_txq_params(&rdev->wiphy, | ||
353 | &txq_params); | ||
354 | if (result) | ||
355 | goto bad_res; | ||
356 | } | ||
357 | } | ||
302 | 358 | ||
359 | bad_res: | ||
303 | cfg80211_put_dev(rdev); | 360 | cfg80211_put_dev(rdev); |
304 | return result; | 361 | return result; |
305 | } | 362 | } |