mac80211: add debugfs interface for U-APSD queue configuration
authorKalle Valo <kalle.valo@nokia.com>
Tue, 12 Jan 2010 08:42:39 +0000 (10:42 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 12 Jan 2010 19:21:00 +0000 (14:21 -0500)
Because it's not yet decided how to configure which queues are U-APSD
enabled, add a debugfs interface for testing purposes.

Signed-off-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/debugfs.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/work.c

index e4b54093d41b3bafd4bdc3458040bc57ad5fc6cb..b3bc32b62a5a66002ad289a18a22dbb7a455d6a2 100644 (file)
@@ -158,6 +158,98 @@ static const struct file_operations noack_ops = {
        .open = mac80211_open_file_generic
 };
 
+static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf,
+                                size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       int res;
+       char buf[10];
+
+       res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_queues);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, res);
+}
+
+static ssize_t uapsd_queues_write(struct file *file,
+                                 const char __user *user_buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       unsigned long val;
+       char buf[10];
+       size_t len;
+       int ret;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+
+       ret = strict_strtoul(buf, 0, &val);
+
+       if (ret)
+               return -EINVAL;
+
+       if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
+               return -ERANGE;
+
+       local->uapsd_queues = val;
+
+       return count;
+}
+
+static const struct file_operations uapsd_queues_ops = {
+       .read = uapsd_queues_read,
+       .write = uapsd_queues_write,
+       .open = mac80211_open_file_generic
+};
+
+static ssize_t uapsd_max_sp_len_read(struct file *file, char __user *user_buf,
+                                    size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       int res;
+       char buf[10];
+
+       res = scnprintf(buf, sizeof(buf), "0x%x\n", local->uapsd_max_sp_len);
+
+       return simple_read_from_buffer(user_buf, count, ppos, buf, res);
+}
+
+static ssize_t uapsd_max_sp_len_write(struct file *file,
+                                     const char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct ieee80211_local *local = file->private_data;
+       unsigned long val;
+       char buf[10];
+       size_t len;
+       int ret;
+
+       len = min(count, sizeof(buf) - 1);
+       if (copy_from_user(buf, user_buf, len))
+               return -EFAULT;
+       buf[len] = '\0';
+
+       ret = strict_strtoul(buf, 0, &val);
+
+       if (ret)
+               return -EINVAL;
+
+       if (val & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
+               return -ERANGE;
+
+       local->uapsd_max_sp_len = val;
+
+       return count;
+}
+
+static const struct file_operations uapsd_max_sp_len_ops = {
+       .read = uapsd_max_sp_len_read,
+       .write = uapsd_max_sp_len_write,
+       .open = mac80211_open_file_generic
+};
+
 static ssize_t queues_read(struct file *file, char __user *user_buf,
                           size_t count, loff_t *ppos)
 {
@@ -314,6 +406,8 @@ void debugfs_hw_add(struct ieee80211_local *local)
        DEBUGFS_ADD(queues);
        DEBUGFS_ADD_MODE(reset, 0200);
        DEBUGFS_ADD(noack);
+       DEBUGFS_ADD(uapsd_queues);
+       DEBUGFS_ADD(uapsd_max_sp_len);
 
        statsd = debugfs_create_dir("statistics", phyd);
 
index 3468e378509a7d239f02cad27f369568b5d438ff..c18f576f18481fa31b587fdbd84a8c5e84edaa2b 100644 (file)
@@ -808,6 +808,20 @@ struct ieee80211_local {
        int wifi_wme_noack_test;
        unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */
 
+       /*
+        * Bitmask of enabled u-apsd queues,
+        * IEEE80211_WMM_IE_STA_QOSINFO_AC_BE & co. Needs a new association
+        * to take effect.
+        */
+       unsigned int uapsd_queues;
+
+       /*
+        * Maximum number of buffered frames AP can deliver during a
+        * service period, IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL or similar.
+        * Needs a new association to take effect.
+        */
+       unsigned int uapsd_max_sp_len;
+
        bool pspolling;
        bool offchannel_ps_enabled;
        /*
index 0054bba08ce1c78d7d160078031cfc97ce9f701e..ec8f767ba95b4979c334754866318f7767c15b08 100644 (file)
@@ -384,6 +384,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
        local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
        local->user_power_level = -1;
+       local->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+       local->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
 
        INIT_LIST_HEAD(&local->interfaces);
        mutex_init(&local->iflist_mtx);
index 39c27d83a4f24cd75f02c48ee03b8ab3f1c29a1e..2746391248d34a1cddc671f9dfa666d1fd9dea1f 100644 (file)
@@ -581,7 +581,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
                return;
 
        if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
-               uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+               uapsd_queues = local->uapsd_queues;
 
        count = wmm_param[6] & 0x0f;
        if (count == ifmgd->wmm_last_param_set)
index a74fd6ee008329fb27815ab9222fd834219ee8c7..81bd5d592bb489f837018a93e15ed5a49a0bc258 100644 (file)
@@ -376,8 +376,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
 
        if (wk->assoc.wmm_used && local->hw.queues >= 4) {
                if (wk->assoc.uapsd_used) {
-                       qos_info = IEEE80211_DEFAULT_UAPSD_QUEUES;
-                       qos_info |= (IEEE80211_DEFAULT_MAX_SP_LEN <<
+                       qos_info = local->uapsd_queues;
+                       qos_info |= (local->uapsd_max_sp_len <<
                                     IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
                } else {
                        qos_info = 0;