diff options
author | Thomas Pedersen <c_tpeder@qca.qualcomm.com> | 2012-07-12 19:17:33 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-07-17 05:57:23 -0400 |
commit | 84f10708f73254878246772cead70a2eb6a123f2 (patch) | |
tree | 39a4ca2f6cc3ab5b33320e3a62d2a8f7c4901b7a /net/wireless/nl80211.c | |
parent | 00f5335079689cd65a9430b5df8974dc35c7914b (diff) |
cfg80211: support TX error rate CQM
Let the user configure serveral TX error conection quality monitoring
parameters: % error rate, survey interval, and # of attempted packets.
On exceeding the TX failure rate over the given interval, the driver
will send a CQM notify event with the actual TX failure rate and
packets attempted.
Signed-off-by: Thomas Pedersen <c_tpeder@qca.qualcomm.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index be8750f91d7..9216e45e53a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -6267,8 +6267,35 @@ nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | |||
6267 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, | 6267 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, |
6268 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, | 6268 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, |
6269 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, | 6269 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, |
6270 | [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 }, | ||
6271 | [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 }, | ||
6272 | [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 }, | ||
6270 | }; | 6273 | }; |
6271 | 6274 | ||
6275 | static int nl80211_set_cqm_txe(struct genl_info *info, | ||
6276 | u32 rate, u32 pkts, u32 intvl) | ||
6277 | { | ||
6278 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6279 | struct wireless_dev *wdev; | ||
6280 | struct net_device *dev = info->user_ptr[1]; | ||
6281 | |||
6282 | if ((rate < 0 || rate > 100) || | ||
6283 | (intvl < 0 || intvl > NL80211_CQM_TXE_MAX_INTVL)) | ||
6284 | return -EINVAL; | ||
6285 | |||
6286 | wdev = dev->ieee80211_ptr; | ||
6287 | |||
6288 | if (!rdev->ops->set_cqm_txe_config) | ||
6289 | return -EOPNOTSUPP; | ||
6290 | |||
6291 | if (wdev->iftype != NL80211_IFTYPE_STATION && | ||
6292 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) | ||
6293 | return -EOPNOTSUPP; | ||
6294 | |||
6295 | return rdev->ops->set_cqm_txe_config(wdev->wiphy, dev, | ||
6296 | rate, pkts, intvl); | ||
6297 | } | ||
6298 | |||
6272 | static int nl80211_set_cqm_rssi(struct genl_info *info, | 6299 | static int nl80211_set_cqm_rssi(struct genl_info *info, |
6273 | s32 threshold, u32 hysteresis) | 6300 | s32 threshold, u32 hysteresis) |
6274 | { | 6301 | { |
@@ -6316,6 +6343,14 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | |||
6316 | threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | 6343 | threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); |
6317 | hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); | 6344 | hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); |
6318 | err = nl80211_set_cqm_rssi(info, threshold, hysteresis); | 6345 | err = nl80211_set_cqm_rssi(info, threshold, hysteresis); |
6346 | } else if (attrs[NL80211_ATTR_CQM_TXE_RATE] && | ||
6347 | attrs[NL80211_ATTR_CQM_TXE_PKTS] && | ||
6348 | attrs[NL80211_ATTR_CQM_TXE_INTVL]) { | ||
6349 | u32 rate, pkts, intvl; | ||
6350 | rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]); | ||
6351 | pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]); | ||
6352 | intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]); | ||
6353 | err = nl80211_set_cqm_txe(info, rate, pkts, intvl); | ||
6319 | } else | 6354 | } else |
6320 | err = -EINVAL; | 6355 | err = -EINVAL; |
6321 | 6356 | ||
@@ -8496,6 +8531,56 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | |||
8496 | } | 8531 | } |
8497 | 8532 | ||
8498 | void | 8533 | void |
8534 | nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev, | ||
8535 | struct net_device *netdev, const u8 *peer, | ||
8536 | u32 num_packets, u32 rate, u32 intvl, gfp_t gfp) | ||
8537 | { | ||
8538 | struct sk_buff *msg; | ||
8539 | struct nlattr *pinfoattr; | ||
8540 | void *hdr; | ||
8541 | |||
8542 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
8543 | if (!msg) | ||
8544 | return; | ||
8545 | |||
8546 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM); | ||
8547 | if (!hdr) { | ||
8548 | nlmsg_free(msg); | ||
8549 | return; | ||
8550 | } | ||
8551 | |||
8552 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
8553 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | ||
8554 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer)) | ||
8555 | goto nla_put_failure; | ||
8556 | |||
8557 | pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM); | ||
8558 | if (!pinfoattr) | ||
8559 | goto nla_put_failure; | ||
8560 | |||
8561 | if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets)) | ||
8562 | goto nla_put_failure; | ||
8563 | |||
8564 | if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate)) | ||
8565 | goto nla_put_failure; | ||
8566 | |||
8567 | if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl)) | ||
8568 | goto nla_put_failure; | ||
8569 | |||
8570 | nla_nest_end(msg, pinfoattr); | ||
8571 | |||
8572 | genlmsg_end(msg, hdr); | ||
8573 | |||
8574 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
8575 | nl80211_mlme_mcgrp.id, gfp); | ||
8576 | return; | ||
8577 | |||
8578 | nla_put_failure: | ||
8579 | genlmsg_cancel(msg, hdr); | ||
8580 | nlmsg_free(msg); | ||
8581 | } | ||
8582 | |||
8583 | void | ||
8499 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 8584 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, |
8500 | struct net_device *netdev, const u8 *peer, | 8585 | struct net_device *netdev, const u8 *peer, |
8501 | u32 num_packets, gfp_t gfp) | 8586 | u32 num_packets, gfp_t gfp) |