Add two top-level switches to wiphy structure to control AMSDU and AMPDU
aggregation. Enable read/update of AMSDU and AMPDU aggregation from
the userspace using set_wiphy/get_wiphy commands.

Signed-off-by: Sergey Matyukevich <[email protected]>
---
 include/net/cfg80211.h       |  7 +++++++
 include/uapi/linux/nl80211.h |  6 ++++++
 net/wireless/core.c          |  3 +++
 net/wireless/nl80211.c       | 31 +++++++++++++++++++++++++++++++
 4 files changed, 47 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1fa41b7a1be3..fbf01d156069 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2368,6 +2368,8 @@ enum cfg80211_connect_params_changed {
  * @WIPHY_PARAM_TXQ_LIMIT: TXQ packet limit has been changed
  * @WIPHY_PARAM_TXQ_MEMORY_LIMIT: TXQ memory limit has been changed
  * @WIPHY_PARAM_TXQ_QUANTUM: TXQ scheduler quantum
+ * @WIPHY_PARAM_AMPDU_ENABLED: wiphy->ampdu_enabled has changed
+ * @WIPHY_PARAM_AMSDU_ENABLED: wiphy->amsdu_enabled has changed
  */
 enum wiphy_params_flags {
        WIPHY_PARAM_RETRY_SHORT         = 1 << 0,
@@ -2379,6 +2381,8 @@ enum wiphy_params_flags {
        WIPHY_PARAM_TXQ_LIMIT           = 1 << 6,
        WIPHY_PARAM_TXQ_MEMORY_LIMIT    = 1 << 7,
        WIPHY_PARAM_TXQ_QUANTUM         = 1 << 8,
+       WIPHY_PARAM_AMPDU_ENABLED       = 1 << 9,
+       WIPHY_PARAM_AMSDU_ENABLED       = 1 << 10,
 };
 
 /**
@@ -4163,6 +4167,9 @@ struct wiphy {
        u32 txq_memory_limit;
        u32 txq_quantum;
 
+       u8 ampdu_enabled;
+       u8 amsdu_enabled;
+
        char priv[0] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 6d610bae30a9..a9f8fa814ecd 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2254,6 +2254,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder
  *     statistics, see &enum nl80211_ftm_responder_stats.
  *
+ * @NL80211_ATTR_WIPHY_AMPDU_ENABLED: enable/disable AMPDU aggregation.
+ * @NL80211_ATTR_WIPHY_AMSDU_ENABLED: enable/disable AMSDU aggregation.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2699,6 +2702,9 @@ enum nl80211_attrs {
 
        NL80211_ATTR_FTM_RESPONDER_STATS,
 
+       NL80211_ATTR_WIPHY_AMPDU_ENABLED,
+       NL80211_ATTR_WIPHY_AMSDU_ENABLED,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5bd01058b9e6..182f8f04166d 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -524,6 +524,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, 
int sizeof_priv,
        rdev->wiphy.max_sched_scan_plans = 1;
        rdev->wiphy.max_sched_scan_plan_interval = U32_MAX;
 
+       rdev->wiphy.ampdu_enabled = 1;
+       rdev->wiphy.amsdu_enabled = 1;
+
        return &rdev->wiphy;
 }
 EXPORT_SYMBOL(wiphy_new_nm);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 744b5851bbf9..5c04b6996e64 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -497,6 +497,9 @@ static const struct nla_policy 
nl80211_policy[NUM_NL80211_ATTR] = {
                .type = NLA_NESTED,
                .validation_data = nl80211_ftm_responder_policy,
        },
+
+       [NL80211_ATTR_WIPHY_AMPDU_ENABLED] = { .type = NLA_U8 },
+       [NL80211_ATTR_WIPHY_AMSDU_ENABLED] = { .type = NLA_U8 },
 };
 
 /* policy for the key attributes */
@@ -2118,6 +2121,14 @@ static int nl80211_send_wiphy(struct 
cfg80211_registered_device *rdev,
                                goto nla_put_failure;
                }
 
+               if (nla_put_u8(msg, NL80211_ATTR_WIPHY_AMPDU_ENABLED,
+                              rdev->wiphy.ampdu_enabled))
+                       goto nla_put_failure;
+
+               if (nla_put_u8(msg, NL80211_ATTR_WIPHY_AMSDU_ENABLED,
+                              rdev->wiphy.amsdu_enabled))
+                       goto nla_put_failure;
+
                /* done */
                state->split_start = 0;
                break;
@@ -2514,6 +2525,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct 
genl_info *info)
        u32 frag_threshold = 0, rts_threshold = 0;
        u8 coverage_class = 0;
        u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0;
+       u8 amsdu = 0, ampdu = 0;
 
        ASSERT_RTNL();
 
@@ -2743,11 +2755,22 @@ static int nl80211_set_wiphy(struct sk_buff *skb, 
struct genl_info *info)
                changed |= WIPHY_PARAM_TXQ_QUANTUM;
        }
 
+       if (info->attrs[NL80211_ATTR_WIPHY_AMPDU_ENABLED]) {
+               ampdu = 
nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_AMPDU_ENABLED]);
+               changed |= WIPHY_PARAM_AMPDU_ENABLED;
+       }
+
+       if (info->attrs[NL80211_ATTR_WIPHY_AMSDU_ENABLED]) {
+               amsdu = 
nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_AMSDU_ENABLED]);
+               changed |= WIPHY_PARAM_AMSDU_ENABLED;
+       }
+
        if (changed) {
                u8 old_retry_short, old_retry_long;
                u32 old_frag_threshold, old_rts_threshold;
                u8 old_coverage_class;
                u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
+               u8 old_amsdu, old_ampdu;
 
                if (!rdev->ops->set_wiphy_params)
                        return -EOPNOTSUPP;
@@ -2760,6 +2783,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct 
genl_info *info)
                old_txq_limit = rdev->wiphy.txq_limit;
                old_txq_memory_limit = rdev->wiphy.txq_memory_limit;
                old_txq_quantum = rdev->wiphy.txq_quantum;
+               old_ampdu = rdev->wiphy.ampdu_enabled;
+               old_amsdu = rdev->wiphy.amsdu_enabled;
 
                if (changed & WIPHY_PARAM_RETRY_SHORT)
                        rdev->wiphy.retry_short = retry_short;
@@ -2777,6 +2802,10 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct 
genl_info *info)
                        rdev->wiphy.txq_memory_limit = txq_memory_limit;
                if (changed & WIPHY_PARAM_TXQ_QUANTUM)
                        rdev->wiphy.txq_quantum = txq_quantum;
+               if (changed & WIPHY_PARAM_AMPDU_ENABLED)
+                       rdev->wiphy.ampdu_enabled = ampdu;
+               if (changed & WIPHY_PARAM_AMSDU_ENABLED)
+                       rdev->wiphy.amsdu_enabled = amsdu;
 
                result = rdev_set_wiphy_params(rdev, changed);
                if (result) {
@@ -2788,6 +2817,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct 
genl_info *info)
                        rdev->wiphy.txq_limit = old_txq_limit;
                        rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
                        rdev->wiphy.txq_quantum = old_txq_quantum;
+                       rdev->wiphy.ampdu_enabled = old_ampdu;
+                       rdev->wiphy.amsdu_enabled = old_amsdu;
                        return result;
                }
        }
-- 
2.11.0

Reply via email to