diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 97bfebfcce903b5165b64bd839b60379e23ecc78..1fc04853ec955afa86137e7b04f1cbe839439ab1 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -538,6 +538,9 @@ * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME * messages. Note that per PHY only one application may register. * + * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether + * No Acknowledgement Policy should be applied. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -675,6 +678,8 @@ enum nl80211_commands { NL80211_CMD_UNEXPECTED_4ADDR_FRAME, + NL80211_CMD_SET_NOACK_MAP, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1185,6 +1190,9 @@ enum nl80211_commands { * abides to when initiating radiation on DFS channels. A country maps * to one DFS region. * + * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of + * up to 16 TIDs. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1428,6 +1436,8 @@ enum nl80211_attrs { NL80211_ATTR_DISABLE_HT, NL80211_ATTR_HT_CAPABILITY_MASK, + NL80211_ATTR_NOACK_MAP, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d5e18913f293af6eb2329e1ee4a88bc0cd9383c8..38ce452da20f6768aaa88e8968a543049cee7c96 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1465,6 +1465,8 @@ struct cfg80211_gtk_rekey_data { * * @probe_client: probe an associated client, must return a cookie that it * later passes to cfg80211_probe_status(). + * + * @set_noack_map: Set the NoAck Map for the TIDs. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1658,6 +1660,10 @@ struct cfg80211_ops { int (*probe_client)(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, u64 *cookie); + int (*set_noack_map)(struct wiphy *wiphy, + struct net_device *dev, + u16 noack_map); + struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy); }; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a1cabde7cb5f506263a2e173d04de29a9f48447a..6026c29c338df741e366aebee2a5e112d17c4920 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -204,6 +204,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_HT_CAPABILITY_MASK] = { .len = NL80211_HT_CAPABILITY_LEN }, + [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, }; /* policy for the key attributes */ @@ -904,6 +905,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) CMD(sched_scan_start, START_SCHED_SCAN); CMD(probe_client, PROBE_CLIENT); + CMD(set_noack_map, SET_NOACK_MAP); if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { i++; NLA_PUT_U32(msg, i, NL80211_CMD_REGISTER_BEACONS); @@ -1759,6 +1761,23 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) return rdev->ops->del_virtual_intf(&rdev->wiphy, dev); } +static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + u16 noack_map; + + if (!info->attrs[NL80211_ATTR_NOACK_MAP]) + return -EINVAL; + + if (!rdev->ops->set_noack_map) + return -EOPNOTSUPP; + + noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]); + + return rdev->ops->set_noack_map(&rdev->wiphy, dev, noack_map); +} + struct get_key_cookie { struct sk_buff *msg; int error; @@ -6604,6 +6623,15 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_WIPHY | NL80211_FLAG_NEED_RTNL, }, + { + .cmd = NL80211_CMD_SET_NOACK_MAP, + .doit = nl80211_set_noack_map, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV | + NL80211_FLAG_NEED_RTNL, + }, + }; static struct genl_multicast_group nl80211_mlme_mcgrp = {