From: Ahmad Masri <[email protected]>

Add support for Access Category to select queue for transmit packets.
The callback wil_select_queue will return the queue id [0..3] to use for
the current skb transmission.

This feature is disabled by default. Use ac_queues module param to enable.

Signed-off-by: Ahmad Masri <[email protected]>
Signed-off-by: Maya Erez <[email protected]>
---
 drivers/net/wireless/ath/wil6210/netdev.c       | 43 +++++++++++++++++++++++--
 drivers/net/wireless/ath/wil6210/wil_platform.h |  2 ++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/wil6210/netdev.c 
b/drivers/net/wireless/ath/wil6210/netdev.c
index ca10626..dfc9617 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -20,6 +20,8 @@
 #include "wil6210.h"
 #include "txrx.h"
 
+#define WIL6210_TX_QUEUES (4)
+
 bool wil_has_other_active_ifaces(struct wil6210_priv *wil,
                                 struct net_device *ndev, bool up, bool ok)
 {
@@ -91,10 +93,43 @@ static int wil_stop(struct net_device *ndev)
        return rc;
 }
 
+/**
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 3
+ * AC_VI -> queue 2
+ * AC_BE -> queue 1
+ * AC_BK -> queue 0
+ */
+static u16 wil_select_queue(struct net_device *ndev,
+                           struct sk_buff *skb,
+                           struct net_device *sb_dev,
+                           select_queue_fallback_t fallback)
+{
+       static const u16 wil_1d_to_queue[8] = {1, 0, 0, 1, 2, 2, 3, 3};
+       struct wil6210_priv *wil = ndev_to_wil(ndev);
+       u16 qid;
+
+       if (!wil->config.ac_queues)
+               return 0;
+
+       /* determine the priority */
+       if (skb->priority == 0 || skb->priority > 7)
+               skb->priority = cfg80211_classify8021d(skb, NULL);
+
+       qid = wil_1d_to_queue[skb->priority];
+
+       wil_dbg_txrx(wil, "select queue for priority %d -> queue %d\n",
+                    skb->priority, qid);
+
+       return qid;
+}
+
 static const struct net_device_ops wil_netdev_ops = {
        .ndo_open               = wil_open,
        .ndo_stop               = wil_stop,
        .ndo_start_xmit         = wil_start_xmit,
+       .ndo_select_queue       = wil_select_queue,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
 };
@@ -317,8 +352,12 @@ struct wil6210_vif *
                return ERR_PTR(-EINVAL);
        }
 
-       ndev = alloc_netdev(sizeof(*vif), name, name_assign_type,
-                           wil_dev_setup);
+       if (wil->config.ac_queues)
+               ndev = alloc_netdev_mqs(sizeof(*vif), name, name_assign_type,
+                                       wil_dev_setup, WIL6210_TX_QUEUES, 1);
+       else
+               ndev = alloc_netdev(sizeof(*vif), name, name_assign_type,
+                                   wil_dev_setup);
        if (!ndev) {
                dev_err(wil_to_dev(wil), "alloc_netdev failed\n");
                return ERR_PTR(-ENOMEM);
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h 
b/drivers/net/wireless/ath/wil6210/wil_platform.h
index 6132888..cab6af3 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -60,6 +60,8 @@ struct wil_platform_config {
        u8 disable_ap_sme;
        /* Max number of stations associated to the AP */
        unsigned int max_assoc_sta;
+       /* enable access category for transmit packets, default - no */
+       u8 ac_queues;
 };
 
 /**
-- 
1.9.1

Reply via email to