mac80211: rt2x00: import and update pending patches
authorDaniel Golle <daniel@makrotopia.org>
Tue, 12 Mar 2019 10:44:27 +0000 (11:44 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Tue, 12 Mar 2019 10:44:27 +0000 (11:44 +0100)
Imported from patchwork, patches marked with '=' have already been in
our tree:
 [v3,1/4] cfg80211: add ratelimited variants of err and warn
 [v3,2/4] rt2x00: use ratelimited variants dev_warn/dev_err
 [v3,3/4] rt2x00: check number of EPROTO errors
=[v3,4/4] rt2x00: do not print error when queue is full

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
21 files changed:
package/kernel/mac80211/patches/rt2x00/020-cfg80211-add-ratelimited-variants-of-err-and-warn.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/020-rt2x00-do-not-print-error-when-queue-is-full.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/021-rt2800-partially-restore-old-mmio-txstatus-behaviour.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/021-rt2x00-use-ratelimited-variants-dev_warn-dev_err.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/022-rt2800-new-flush-implementation-for-SoC-devices.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/022-rt2x00-check-number-of-EPROTO-errors.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/023-rt2800-move-txstatus-pending-routine.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/023-rt2x00-do-not-print-error-when-queue-is-full.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/024-rt2800-partially-restore-old-mmio-txstatus-behaviour.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/024-rt2800mmio-fetch-tx-status-changes.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/025-rt2800-new-flush-implementation-for-SoC-devices.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/025-rt2800mmio-use-timer-and-work-for-handling-tx-status.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/026-rt2800-move-txstatus-pending-routine.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/026-rt2x00-remove-last_nostatus_check.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/027-rt2800mmio-fetch-tx-status-changes.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/027-rt2x00-remove-not-used-entry-field.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/028-rt2800mmio-use-timer-and-work-for-handling-tx-status.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/028-rt2x00mmio-remove-legacy-comment.patch [deleted file]
package/kernel/mac80211/patches/rt2x00/029-rt2x00-remove-last_nostatus_check.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/030-rt2x00-remove-not-used-entry-field.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rt2x00/031-rt2x00mmio-remove-legacy-comment.patch [new file with mode: 0644]

diff --git a/package/kernel/mac80211/patches/rt2x00/020-cfg80211-add-ratelimited-variants-of-err-and-warn.patch b/package/kernel/mac80211/patches/rt2x00/020-cfg80211-add-ratelimited-variants-of-err-and-warn.patch
new file mode 100644 (file)
index 0000000..ace01bb
--- /dev/null
@@ -0,0 +1,39 @@
+From patchwork Tue Mar 12 09:51:40 2019
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10848957
+X-Patchwork-Delegate: johannes@sipsolutions.net
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+To: linux-wireless@vger.kernel.org
+Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
+ Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
+ Mathias Kresin <dev@kresin.me>
+Subject: [PATCH v3 1/4] cfg80211: add ratelimited variants of err and warn
+Date: Tue, 12 Mar 2019 10:51:40 +0100
+Message-Id: <1552384303-29529-2-git-send-email-sgruszka@redhat.com>
+In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+
+wiphy_{err,warn}_ratelimited will be used by rt2x00
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ include/net/cfg80211.h | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -6588,6 +6588,11 @@ int cfg80211_external_auth_request(struc
+ #define wiphy_info(wiphy, format, args...)                    \
+       dev_info(&(wiphy)->dev, format, ##args)
++#define wiphy_err_ratelimited(wiphy, format, args...)         \
++      dev_err_ratelimited(&(wiphy)->dev, format, ##args)
++#define wiphy_warn_ratelimited(wiphy, format, args...)                \
++      dev_warn_ratelimited(&(wiphy)->dev, format, ##args)
++
+ #define wiphy_debug(wiphy, format, args...)                   \
+       wiphy_printk(KERN_DEBUG, wiphy, format, ##args)
diff --git a/package/kernel/mac80211/patches/rt2x00/020-rt2x00-do-not-print-error-when-queue-is-full.patch b/package/kernel/mac80211/patches/rt2x00/020-rt2x00-do-not-print-error-when-queue-is-full.patch
deleted file mode 100644 (file)
index 5098672..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 1a8a8989b779e51e4652a30e9f22c36a1b6ffc4b Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Thu, 20 Dec 2018 16:16:11 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10739037
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 20/28] rt2x00: do not print error when queue is full
-
-For unknown reasons printk() on some context can cause CPU hung on
-embedded MT7620 AP/router MIPS platforms. What can result on wifi
-disconnects.
-
-This patch move queue full messages to debug level what is consistent
-with other mac80211 drivers which drop packet silently if tx queue is
-full. This make MT7620 OpenWRT routers more stable, what was reported
-by various users.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-@@ -671,7 +671,7 @@ int rt2x00queue_write_tx_frame(struct da
-       spin_lock(&queue->tx_lock);
-       if (unlikely(rt2x00queue_full(queue))) {
--              rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
-+              rt2x00_dbg(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
-                          queue->qid);
-               ret = -ENOBUFS;
-               goto out;
diff --git a/package/kernel/mac80211/patches/rt2x00/021-rt2800-partially-restore-old-mmio-txstatus-behaviour.patch b/package/kernel/mac80211/patches/rt2x00/021-rt2800-partially-restore-old-mmio-txstatus-behaviour.patch
deleted file mode 100644 (file)
index 52314a7..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-From 91a5340db0526b7263bc8da14b120ea3129b5f28 Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:31 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804437
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 21/28] rt2800: partially restore old mmio txstatus behaviour
-
-Do not disable txstatus interrupt and add quota of processed tx statuses in
-one tasklet. Quota is needed to allow to fed device with new frames during
-processing of tx statuses.
-
-Patch fixes about 15% performance degradation on some scenarios coused by
-0b0d556e0ebb ("rt2800mmio: use txdone/txstatus routines from lib").
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- .../net/wireless/ralink/rt2x00/rt2800lib.c    |  4 +--
- .../net/wireless/ralink/rt2x00/rt2800lib.h    |  2 +-
- .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 30 +++++--------------
- .../net/wireless/ralink/rt2x00/rt2800usb.c    |  2 +-
- 4 files changed, 12 insertions(+), 26 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -1100,7 +1100,7 @@ void rt2800_txdone_entry(struct queue_en
- }
- EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
--void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
-+void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota)
- {
-       struct data_queue *queue;
-       struct queue_entry *entry;
-@@ -1108,7 +1108,7 @@ void rt2800_txdone(struct rt2x00_dev *rt
-       u8 qid;
-       bool match;
--      while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
-+      while (quota-- > 0 && kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
-               /*
-                * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
-                * guaranteed to be one of the TX QIDs .
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
-@@ -195,7 +195,7 @@ void rt2800_process_rxwi(struct queue_en
- void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
-                        bool match);
--void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
-+void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota);
- void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
- bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
---- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-@@ -255,20 +255,6 @@ void rt2800mmio_autowake_tasklet(unsigne
- }
- EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
--static void rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
--{
--      bool timeout = false;
--
--      while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
--             (timeout = rt2800_txstatus_timeout(rt2x00dev))) {
--
--              rt2800_txdone(rt2x00dev);
--
--              if (timeout)
--                      rt2800_txdone_nostatus(rt2x00dev);
--      }
--}
--
- static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
- {
-       u32 status;
-@@ -305,14 +291,11 @@ void rt2800mmio_txstatus_tasklet(unsigne
- {
-       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
--      do {
--              rt2800mmio_txdone(rt2x00dev);
-+      rt2800_txdone(rt2x00dev, 16);
--      } while (rt2800mmio_fetch_txstatus(rt2x00dev));
-+      if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
-+              tasklet_schedule(&rt2x00dev->txstatus_tasklet);
--      if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
--              rt2800mmio_enable_interrupt(rt2x00dev,
--                                          INT_SOURCE_CSR_TX_FIFO_STATUS);
- }
- EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
-@@ -339,8 +322,10 @@ irqreturn_t rt2800mmio_interrupt(int irq
-       mask = ~reg;
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
-+              rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
-               rt2800mmio_fetch_txstatus(rt2x00dev);
--              tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-+              if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
-+                      tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-       }
-       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
-@@ -500,7 +485,8 @@ void rt2800mmio_flush_queue(struct data_
-                */
-               if (tx_queue) {
-                       tasklet_disable(&rt2x00dev->txstatus_tasklet);
--                      rt2800mmio_txdone(rt2x00dev);
-+                      rt2800_txdone(rt2x00dev, UINT_MAX);
-+                      rt2800_txdone_nostatus(rt2x00dev);
-                       tasklet_enable(&rt2x00dev->txstatus_tasklet);
-               }
---- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
-@@ -480,7 +480,7 @@ static void rt2800usb_work_txdone(struct
-       while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
-              rt2800_txstatus_timeout(rt2x00dev)) {
--              rt2800_txdone(rt2x00dev);
-+              rt2800_txdone(rt2x00dev, UINT_MAX);
-               rt2800_txdone_nostatus(rt2x00dev);
diff --git a/package/kernel/mac80211/patches/rt2x00/021-rt2x00-use-ratelimited-variants-dev_warn-dev_err.patch b/package/kernel/mac80211/patches/rt2x00/021-rt2x00-use-ratelimited-variants-dev_warn-dev_err.patch
new file mode 100644 (file)
index 0000000..2d74a71
--- /dev/null
@@ -0,0 +1,42 @@
+From patchwork Tue Mar 12 09:51:41 2019
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10848959
+X-Patchwork-Delegate: kvalo@adurom.com
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+To: linux-wireless@vger.kernel.org
+Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
+ Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
+ Mathias Kresin <dev@kresin.me>
+Subject: [PATCH v3 2/4] rt2x00: use ratelimited variants dev_warn/dev_err
+Date: Tue, 12 Mar 2019 10:51:41 +0100
+Message-Id: <1552384303-29529-3-git-send-email-sgruszka@redhat.com>
+In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+
+As reported by Randy we can overwhelm logs on some USB error conditions.
+To avoid that use dev_warn_ratelimited() and dev_err_ratelimitd().
+
+Reported-and-tested-by: Randy Oostdyk <linux-kernel@oostdyk.com>
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2x00.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -69,10 +69,10 @@
+       printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt,            \
+              __func__, ##__VA_ARGS__)
+ #define rt2x00_err(dev, fmt, ...)                                     \
+-      wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt,                 \
++      wiphy_err_ratelimited((dev)->hw->wiphy, "%s: Error - " fmt,     \
+                 __func__, ##__VA_ARGS__)
+ #define rt2x00_warn(dev, fmt, ...)                                    \
+-      wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt,              \
++      wiphy_warn_ratelimited((dev)->hw->wiphy, "%s: Warning - " fmt,  \
+                  __func__, ##__VA_ARGS__)
+ #define rt2x00_info(dev, fmt, ...)                                    \
+       wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt,                 \
diff --git a/package/kernel/mac80211/patches/rt2x00/022-rt2800-new-flush-implementation-for-SoC-devices.patch b/package/kernel/mac80211/patches/rt2x00/022-rt2800-new-flush-implementation-for-SoC-devices.patch
deleted file mode 100644 (file)
index e3a914a..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 11f8ad1656035176bad9d89de7ea0e7fe6d82c32 Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:32 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804439
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 22/28] rt2800: new flush implementation for SoC devices
-
-Use new flush_queue() calback for SoC devices, what was already done for
-PCIe devices.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2800soc.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-@@ -203,7 +203,7 @@ static const struct rt2x00lib_ops rt2800
-       .start_queue            = rt2800mmio_start_queue,
-       .kick_queue             = rt2800mmio_kick_queue,
-       .stop_queue             = rt2800mmio_stop_queue,
--      .flush_queue            = rt2x00mmio_flush_queue,
-+      .flush_queue            = rt2800mmio_flush_queue,
-       .write_tx_desc          = rt2800mmio_write_tx_desc,
-       .write_tx_data          = rt2800_write_tx_data,
-       .write_beacon           = rt2800_write_beacon,
diff --git a/package/kernel/mac80211/patches/rt2x00/022-rt2x00-check-number-of-EPROTO-errors.patch b/package/kernel/mac80211/patches/rt2x00/022-rt2x00-check-number-of-EPROTO-errors.patch
new file mode 100644 (file)
index 0000000..251ac28
--- /dev/null
@@ -0,0 +1,96 @@
+From patchwork Tue Mar 12 09:51:42 2019
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10848961
+X-Patchwork-Delegate: kvalo@adurom.com
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+To: linux-wireless@vger.kernel.org
+Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
+ Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
+ Mathias Kresin <dev@kresin.me>
+Subject: [PATCH v3 3/4] rt2x00: check number of EPROTO errors
+Date: Tue, 12 Mar 2019 10:51:42 +0100
+Message-Id: <1552384303-29529-4-git-send-email-sgruszka@redhat.com>
+In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+
+Some USB host devices/drivers on some conditions can always return
+EPROTO error on submitted URBs. That can cause infinity loop in the
+rt2x00 driver.
+
+Since we can have single EPROTO errors we can not mark as device as
+removed to avoid infinity loop. However we can count consecutive
+EPROTO errors and mark device as removed if get lot of it.
+I choose number 10 as threshold.
+
+Reported-and-tested-by: Randy Oostdyk <linux-kernel@oostdyk.com>
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2x00.h    |  1 +
+ drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 22 +++++++++++++++++++---
+ 2 files changed, 20 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -1017,6 +1017,7 @@ struct rt2x00_dev {
+       unsigned int extra_tx_headroom;
+       struct usb_anchor *anchor;
++      unsigned int num_proto_errs;
+       /* Clock for System On Chip devices. */
+       struct clk *clk;
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+@@ -31,6 +31,22 @@
+ #include "rt2x00.h"
+ #include "rt2x00usb.h"
++static bool rt2x00usb_check_usb_error(struct rt2x00_dev *rt2x00dev, int status)
++{
++      if (status == -ENODEV || status == -ENOENT)
++              return true;
++
++      if (status == -EPROTO || status == -ETIMEDOUT)
++              rt2x00dev->num_proto_errs++;
++      else
++              rt2x00dev->num_proto_errs = 0;
++
++      if (rt2x00dev->num_proto_errs > 3)
++              return true;
++
++      return false;
++}
++
+ /*
+  * Interfacing with the HW.
+  */
+@@ -57,7 +73,7 @@ int rt2x00usb_vendor_request(struct rt2x
+               if (status >= 0)
+                       return 0;
+-              if (status == -ENODEV || status == -ENOENT) {
++              if (rt2x00usb_check_usb_error(rt2x00dev, status)) {
+                       /* Device has disappeared. */
+                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+                       break;
+@@ -321,7 +337,7 @@ static bool rt2x00usb_kick_tx_entry(stru
+       status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+       if (status) {
+-              if (status == -ENODEV || status == -ENOENT)
++              if (rt2x00usb_check_usb_error(rt2x00dev, status))
+                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+               rt2x00lib_dmadone(entry);
+@@ -410,7 +426,7 @@ static bool rt2x00usb_kick_rx_entry(stru
+       status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+       if (status) {
+-              if (status == -ENODEV || status == -ENOENT)
++              if (rt2x00usb_check_usb_error(rt2x00dev, status))
+                       clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+               set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
+               rt2x00lib_dmadone(entry);
diff --git a/package/kernel/mac80211/patches/rt2x00/023-rt2800-move-txstatus-pending-routine.patch b/package/kernel/mac80211/patches/rt2x00/023-rt2800-move-txstatus-pending-routine.patch
deleted file mode 100644 (file)
index e5bfbec..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-From 2bbea7645c3d095014a080db170941818650e141 Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:33 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804441
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 23/28] rt2800: move txstatus pending routine
-
-Move rt2800usb_txstatus_pending routine to rt2800lib. It will be reused
-by rt2800mmio code.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- .../net/wireless/ralink/rt2x00/rt2800lib.c    | 17 ++++++++++++++
- .../net/wireless/ralink/rt2x00/rt2800lib.h    |  1 +
- .../net/wireless/ralink/rt2x00/rt2800usb.c    | 22 +++----------------
- 3 files changed, 21 insertions(+), 19 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -1183,6 +1183,23 @@ bool rt2800_txstatus_timeout(struct rt2x
- }
- EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout);
-+/*
-+ * test if there is an entry in any TX queue for which DMA is done
-+ * but the TX status has not been returned yet
-+ */
-+bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev)
-+{
-+      struct data_queue *queue;
-+
-+      tx_queue_for_each(rt2x00dev, queue) {
-+              if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
-+                  rt2x00queue_get_entry(queue, Q_INDEX_DONE))
-+                      return true;
-+      }
-+      return false;
-+}
-+EXPORT_SYMBOL_GPL(rt2800_txstatus_pending);
-+
- void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
- {
-       struct data_queue *queue;
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
-@@ -198,6 +198,7 @@ void rt2800_txdone_entry(struct queue_en
- void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota);
- void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
- bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
-+bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev);
- void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
- void rt2800_clear_beacon(struct queue_entry *entry);
---- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
-@@ -100,22 +100,6 @@ static void rt2800usb_stop_queue(struct
-       }
- }
--/*
-- * test if there is an entry in any TX queue for which DMA is done
-- * but the TX status has not been returned yet
-- */
--static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
--{
--      struct data_queue *queue;
--
--      tx_queue_for_each(rt2x00dev, queue) {
--              if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
--                  rt2x00queue_get_entry(queue, Q_INDEX_DONE))
--                      return true;
--      }
--      return false;
--}
--
- #define TXSTATUS_READ_INTERVAL 1000000
- static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
-@@ -145,7 +129,7 @@ static bool rt2800usb_tx_sta_fifo_read_c
-       if (rt2800_txstatus_timeout(rt2x00dev))
-               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
--      if (rt2800usb_txstatus_pending(rt2x00dev)) {
-+      if (rt2800_txstatus_pending(rt2x00dev)) {
-               /* Read register after 1 ms */
-               hrtimer_start(&rt2x00dev->txstatus_timer,
-                             TXSTATUS_READ_INTERVAL,
-@@ -160,7 +144,7 @@ stop_reading:
-        * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck
-        * here again if status reading is needed.
-        */
--      if (rt2800usb_txstatus_pending(rt2x00dev) &&
-+      if (rt2800_txstatus_pending(rt2x00dev) &&
-           !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
-               return true;
-       else
-@@ -489,7 +473,7 @@ static void rt2800usb_work_txdone(struct
-                * if the medium is busy, thus the TX_STA_FIFO entry is
-                * also delayed -> use a timer to retrieve it.
-                */
--              if (rt2800usb_txstatus_pending(rt2x00dev))
-+              if (rt2800_txstatus_pending(rt2x00dev))
-                       rt2800usb_async_read_tx_status(rt2x00dev);
-       }
- }
diff --git a/package/kernel/mac80211/patches/rt2x00/023-rt2x00-do-not-print-error-when-queue-is-full.patch b/package/kernel/mac80211/patches/rt2x00/023-rt2x00-do-not-print-error-when-queue-is-full.patch
new file mode 100644 (file)
index 0000000..7e2f219
--- /dev/null
@@ -0,0 +1,43 @@
+From patchwork Tue Mar 12 09:51:43 2019
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10848963
+X-Patchwork-Delegate: kvalo@adurom.com
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+To: linux-wireless@vger.kernel.org
+Cc: =?utf-8?q?Tomislav_Po=C5=BEega?= <pozega.tomislav@gmail.com>,
+ Daniel Golle <daniel@makrotopia.org>, Felix Fietkau <nbd@nbd.name>,
+ Mathias Kresin <dev@kresin.me>
+Subject: [PATCH v3 4/4] rt2x00: do not print error when queue is full
+Date: Tue, 12 Mar 2019 10:51:43 +0100
+Message-Id: <1552384303-29529-5-git-send-email-sgruszka@redhat.com>
+In-Reply-To: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+References: <1552384303-29529-1-git-send-email-sgruszka@redhat.com>
+
+For unknown reasons printk() on some context can cause CPU hung on
+embedded MT7620 AP/router MIPS platforms. What can result on wifi
+disconnects.
+
+This patch move queue full messages to debug level what is consistent
+with other mac80211 drivers which drop packet silently if tx queue is
+full. This make MT7620 OpenWRT routers more stable, what was reported
+by various users.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
+@@ -671,7 +671,7 @@ int rt2x00queue_write_tx_frame(struct da
+       spin_lock(&queue->tx_lock);
+       if (unlikely(rt2x00queue_full(queue))) {
+-              rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
++              rt2x00_dbg(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n",
+                          queue->qid);
+               ret = -ENOBUFS;
+               goto out;
diff --git a/package/kernel/mac80211/patches/rt2x00/024-rt2800-partially-restore-old-mmio-txstatus-behaviour.patch b/package/kernel/mac80211/patches/rt2x00/024-rt2800-partially-restore-old-mmio-txstatus-behaviour.patch
new file mode 100644 (file)
index 0000000..52314a7
--- /dev/null
@@ -0,0 +1,128 @@
+From 91a5340db0526b7263bc8da14b120ea3129b5f28 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:31 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804437
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 21/28] rt2800: partially restore old mmio txstatus behaviour
+
+Do not disable txstatus interrupt and add quota of processed tx statuses in
+one tasklet. Quota is needed to allow to fed device with new frames during
+processing of tx statuses.
+
+Patch fixes about 15% performance degradation on some scenarios coused by
+0b0d556e0ebb ("rt2800mmio: use txdone/txstatus routines from lib").
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ .../net/wireless/ralink/rt2x00/rt2800lib.c    |  4 +--
+ .../net/wireless/ralink/rt2x00/rt2800lib.h    |  2 +-
+ .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 30 +++++--------------
+ .../net/wireless/ralink/rt2x00/rt2800usb.c    |  2 +-
+ 4 files changed, 12 insertions(+), 26 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -1100,7 +1100,7 @@ void rt2800_txdone_entry(struct queue_en
+ }
+ EXPORT_SYMBOL_GPL(rt2800_txdone_entry);
+-void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
++void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota)
+ {
+       struct data_queue *queue;
+       struct queue_entry *entry;
+@@ -1108,7 +1108,7 @@ void rt2800_txdone(struct rt2x00_dev *rt
+       u8 qid;
+       bool match;
+-      while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
++      while (quota-- > 0 && kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
+               /*
+                * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
+                * guaranteed to be one of the TX QIDs .
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+@@ -195,7 +195,7 @@ void rt2800_process_rxwi(struct queue_en
+ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi,
+                        bool match);
+-void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
++void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota);
+ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
+ bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+@@ -255,20 +255,6 @@ void rt2800mmio_autowake_tasklet(unsigne
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
+-static void rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev)
+-{
+-      bool timeout = false;
+-
+-      while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
+-             (timeout = rt2800_txstatus_timeout(rt2x00dev))) {
+-
+-              rt2800_txdone(rt2x00dev);
+-
+-              if (timeout)
+-                      rt2800_txdone_nostatus(rt2x00dev);
+-      }
+-}
+-
+ static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
+ {
+       u32 status;
+@@ -305,14 +291,11 @@ void rt2800mmio_txstatus_tasklet(unsigne
+ {
+       struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+-      do {
+-              rt2800mmio_txdone(rt2x00dev);
++      rt2800_txdone(rt2x00dev, 16);
+-      } while (rt2800mmio_fetch_txstatus(rt2x00dev));
++      if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
++              tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+-      if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+-              rt2800mmio_enable_interrupt(rt2x00dev,
+-                                          INT_SOURCE_CSR_TX_FIFO_STATUS);
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet);
+@@ -339,8 +322,10 @@ irqreturn_t rt2800mmio_interrupt(int irq
+       mask = ~reg;
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
++              rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+               rt2800mmio_fetch_txstatus(rt2x00dev);
+-              tasklet_schedule(&rt2x00dev->txstatus_tasklet);
++              if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
++                      tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+       }
+       if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
+@@ -500,7 +485,8 @@ void rt2800mmio_flush_queue(struct data_
+                */
+               if (tx_queue) {
+                       tasklet_disable(&rt2x00dev->txstatus_tasklet);
+-                      rt2800mmio_txdone(rt2x00dev);
++                      rt2800_txdone(rt2x00dev, UINT_MAX);
++                      rt2800_txdone_nostatus(rt2x00dev);
+                       tasklet_enable(&rt2x00dev->txstatus_tasklet);
+               }
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+@@ -480,7 +480,7 @@ static void rt2800usb_work_txdone(struct
+       while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
+              rt2800_txstatus_timeout(rt2x00dev)) {
+-              rt2800_txdone(rt2x00dev);
++              rt2800_txdone(rt2x00dev, UINT_MAX);
+               rt2800_txdone_nostatus(rt2x00dev);
diff --git a/package/kernel/mac80211/patches/rt2x00/024-rt2800mmio-fetch-tx-status-changes.patch b/package/kernel/mac80211/patches/rt2x00/024-rt2800mmio-fetch-tx-status-changes.patch
deleted file mode 100644 (file)
index 4bb62c2..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From f6a9618198e190a2ba09ce3f0aa8e9ee1763bd38 Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:34 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804443
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 24/28] rt2800mmio: fetch tx status changes
-
-Prepare to use rt2800mmio_fetch_txstatus() in concurrent manner and drop
-return value since is not longer needed.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 17 +++++++++--------
- 1 file changed, 9 insertions(+), 8 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-@@ -255,12 +255,12 @@ void rt2800mmio_autowake_tasklet(unsigne
- }
- EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
--static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
-+static void rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
- {
-       u32 status;
--      bool more = false;
-+      unsigned long flags;
--      /* FIXEME: rewrite this comment
-+      /*
-        * The TX_FIFO_STATUS interrupt needs special care. We should
-        * read TX_STA_FIFO but we should do it immediately as otherwise
-        * the register can overflow and we would lose status reports.
-@@ -271,20 +271,21 @@ static bool rt2800mmio_fetch_txstatus(st
-        * because we can schedule the tasklet multiple times (when the
-        * interrupt fires again during tx status processing).
-        *
--       * txstatus tasklet is called with INT_SOURCE_CSR_TX_FIFO_STATUS
--       * disabled so have only one producer and one consumer - we don't
--       * need to lock the kfifo.
-+       * We also read statuses from tx status timeout timer, use
-+       * lock to prevent concurent writes to fifo.
-        */
-+
-+      spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
-+
-       while (!kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
-               status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
-               if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
-                       break;
-               kfifo_put(&rt2x00dev->txstatus_fifo, status);
--              more = true;
-       }
--      return more;
-+      spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
- }
- void rt2800mmio_txstatus_tasklet(unsigned long data)
diff --git a/package/kernel/mac80211/patches/rt2x00/025-rt2800-new-flush-implementation-for-SoC-devices.patch b/package/kernel/mac80211/patches/rt2x00/025-rt2800-new-flush-implementation-for-SoC-devices.patch
new file mode 100644 (file)
index 0000000..e3a914a
--- /dev/null
@@ -0,0 +1,27 @@
+From 11f8ad1656035176bad9d89de7ea0e7fe6d82c32 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:32 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804439
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 22/28] rt2800: new flush implementation for SoC devices
+
+Use new flush_queue() calback for SoC devices, what was already done for
+PCIe devices.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800soc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+@@ -203,7 +203,7 @@ static const struct rt2x00lib_ops rt2800
+       .start_queue            = rt2800mmio_start_queue,
+       .kick_queue             = rt2800mmio_kick_queue,
+       .stop_queue             = rt2800mmio_stop_queue,
+-      .flush_queue            = rt2x00mmio_flush_queue,
++      .flush_queue            = rt2800mmio_flush_queue,
+       .write_tx_desc          = rt2800mmio_write_tx_desc,
+       .write_tx_data          = rt2800_write_tx_data,
+       .write_beacon           = rt2800_write_beacon,
diff --git a/package/kernel/mac80211/patches/rt2x00/025-rt2800mmio-use-timer-and-work-for-handling-tx-status.patch b/package/kernel/mac80211/patches/rt2x00/025-rt2800mmio-use-timer-and-work-for-handling-tx-status.patch
deleted file mode 100644 (file)
index bf038a5..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-From 175c2548332b45b144af673e70fdbb1a947d7aba Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:35 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804445
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 25/28] rt2800mmio: use timer and work for handling tx statuses
- timeouts
-
-Sometimes we can get into situation when there are pending statuses,
-but we do not get INT_SOURCE_CSR_TX_FIFO_STATUS. Handle this situation
-by arming timeout timer and read statuses (it will fix case when
-we just do not have irq) and queue work to handle case we missed
-statues from hardware FIFO.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 81 +++++++++++++++++--
- .../net/wireless/ralink/rt2x00/rt2800mmio.h   |  1 +
- .../net/wireless/ralink/rt2x00/rt2800pci.c    |  2 +-
- .../net/wireless/ralink/rt2x00/rt2800soc.c    |  2 +-
- .../net/wireless/ralink/rt2x00/rt2x00dev.c    |  4 +
- 5 files changed, 82 insertions(+), 8 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-@@ -426,6 +426,9 @@ void rt2800mmio_start_queue(struct data_
- }
- EXPORT_SYMBOL_GPL(rt2800mmio_start_queue);
-+/* 200 ms */
-+#define TXSTATUS_TIMEOUT 200000000
-+
- void rt2800mmio_kick_queue(struct data_queue *queue)
- {
-       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
-@@ -440,6 +443,8 @@ void rt2800mmio_kick_queue(struct data_q
-               entry = rt2x00queue_get_entry(queue, Q_INDEX);
-               rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
-                                         entry->entry_idx);
-+              hrtimer_start(&rt2x00dev->txstatus_timer,
-+                            TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
-               break;
-       case QID_MGMT:
-               entry = rt2x00queue_get_entry(queue, Q_INDEX);
-@@ -484,12 +489,8 @@ void rt2800mmio_flush_queue(struct data_
-                * For TX queues schedule completion tasklet to catch
-                * tx status timeouts, othewise just wait.
-                */
--              if (tx_queue) {
--                      tasklet_disable(&rt2x00dev->txstatus_tasklet);
--                      rt2800_txdone(rt2x00dev, UINT_MAX);
--                      rt2800_txdone_nostatus(rt2x00dev);
--                      tasklet_enable(&rt2x00dev->txstatus_tasklet);
--              }
-+              if (tx_queue)
-+                      queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-               /*
-                * Wait for a little while to give the driver
-@@ -627,6 +628,10 @@ void rt2800mmio_clear_entry(struct queue
-               word = rt2x00_desc_read(entry_priv->desc, 1);
-               rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
-               rt2x00_desc_write(entry_priv->desc, 1, word);
-+
-+              /* If last entry stop txstatus timer */
-+              if (entry->queue->length == 1)
-+                      hrtimer_cancel(&rt2x00dev->txstatus_timer);
-       }
- }
- EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry);
-@@ -759,6 +764,70 @@ int rt2800mmio_enable_radio(struct rt2x0
- }
- EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
-+static void rt2800mmio_work_txdone(struct work_struct *work)
-+{
-+      struct rt2x00_dev *rt2x00dev =
-+          container_of(work, struct rt2x00_dev, txdone_work);
-+
-+      if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-+              return;
-+
-+      while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
-+             rt2800_txstatus_timeout(rt2x00dev)) {
-+
-+              tasklet_disable(&rt2x00dev->txstatus_tasklet);
-+              rt2800_txdone(rt2x00dev, UINT_MAX);
-+              rt2800_txdone_nostatus(rt2x00dev);
-+              tasklet_enable(&rt2x00dev->txstatus_tasklet);
-+      }
-+
-+      if (rt2800_txstatus_pending(rt2x00dev))
-+              hrtimer_start(&rt2x00dev->txstatus_timer,
-+                            TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
-+}
-+
-+static enum hrtimer_restart rt2800mmio_tx_sta_fifo_timeout(struct hrtimer *timer)
-+{
-+      struct rt2x00_dev *rt2x00dev =
-+          container_of(timer, struct rt2x00_dev, txstatus_timer);
-+
-+      if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-+              goto out;
-+
-+      if (!rt2800_txstatus_pending(rt2x00dev))
-+              goto out;
-+
-+      rt2800mmio_fetch_txstatus(rt2x00dev);
-+      if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
-+              tasklet_schedule(&rt2x00dev->txstatus_tasklet);
-+      else
-+              queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-+out:
-+      return HRTIMER_NORESTART;
-+}
-+
-+int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev)
-+{
-+      int retval;
-+
-+      retval = rt2800_probe_hw(rt2x00dev);
-+      if (retval)
-+              return retval;
-+
-+      /*
-+       * Set txstatus timer function.
-+       */
-+      rt2x00dev->txstatus_timer.function = rt2800mmio_tx_sta_fifo_timeout;
-+
-+      /*
-+       * Overwrite TX done handler
-+       */
-+      INIT_WORK(&rt2x00dev->txdone_work, rt2800mmio_work_txdone);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(rt2800mmio_probe_hw);
-+
- MODULE_AUTHOR(DRV_PROJECT);
- MODULE_VERSION(DRV_VERSION);
- MODULE_DESCRIPTION("rt2800 MMIO library");
---- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
-@@ -153,6 +153,7 @@ void rt2800mmio_stop_queue(struct data_q
- void rt2800mmio_queue_init(struct data_queue *queue);
- /* Initialization functions */
-+int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev);
- bool rt2800mmio_get_entry_state(struct queue_entry *entry);
- void rt2800mmio_clear_entry(struct queue_entry *entry);
- int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev);
---- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
-@@ -346,7 +346,7 @@ static const struct rt2x00lib_ops rt2800
-       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
-       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
-       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
--      .probe_hw               = rt2800_probe_hw,
-+      .probe_hw               = rt2800mmio_probe_hw,
-       .get_firmware_name      = rt2800pci_get_firmware_name,
-       .check_firmware         = rt2800_check_firmware,
-       .load_firmware          = rt2800_load_firmware,
---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-@@ -185,7 +185,7 @@ static const struct rt2x00lib_ops rt2800
-       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
-       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
-       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
--      .probe_hw               = rt2800_probe_hw,
-+      .probe_hw               = rt2800mmio_probe_hw,
-       .get_firmware_name      = rt2800soc_get_firmware_name,
-       .check_firmware         = rt2800soc_check_firmware,
-       .load_firmware          = rt2800soc_load_firmware,
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1391,6 +1391,8 @@ int rt2x00lib_probe_dev(struct rt2x00_de
-       mutex_init(&rt2x00dev->conf_mutex);
-       INIT_LIST_HEAD(&rt2x00dev->bar_list);
-       spin_lock_init(&rt2x00dev->bar_list_lock);
-+      hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
-+                   HRTIMER_MODE_REL);
-       set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
-@@ -1515,6 +1517,8 @@ void rt2x00lib_remove_dev(struct rt2x00_
-       cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
-       cancel_work_sync(&rt2x00dev->sleep_work);
-+      hrtimer_cancel(&rt2x00dev->txstatus_timer);
-+
-       /*
-        * Kill the tx status tasklet.
-        */
diff --git a/package/kernel/mac80211/patches/rt2x00/026-rt2800-move-txstatus-pending-routine.patch b/package/kernel/mac80211/patches/rt2x00/026-rt2800-move-txstatus-pending-routine.patch
new file mode 100644 (file)
index 0000000..e5bfbec
--- /dev/null
@@ -0,0 +1,106 @@
+From 2bbea7645c3d095014a080db170941818650e141 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:33 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804441
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 23/28] rt2800: move txstatus pending routine
+
+Move rt2800usb_txstatus_pending routine to rt2800lib. It will be reused
+by rt2800mmio code.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ .../net/wireless/ralink/rt2x00/rt2800lib.c    | 17 ++++++++++++++
+ .../net/wireless/ralink/rt2x00/rt2800lib.h    |  1 +
+ .../net/wireless/ralink/rt2x00/rt2800usb.c    | 22 +++----------------
+ 3 files changed, 21 insertions(+), 19 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -1183,6 +1183,23 @@ bool rt2800_txstatus_timeout(struct rt2x
+ }
+ EXPORT_SYMBOL_GPL(rt2800_txstatus_timeout);
++/*
++ * test if there is an entry in any TX queue for which DMA is done
++ * but the TX status has not been returned yet
++ */
++bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev)
++{
++      struct data_queue *queue;
++
++      tx_queue_for_each(rt2x00dev, queue) {
++              if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
++                  rt2x00queue_get_entry(queue, Q_INDEX_DONE))
++                      return true;
++      }
++      return false;
++}
++EXPORT_SYMBOL_GPL(rt2800_txstatus_pending);
++
+ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev)
+ {
+       struct data_queue *queue;
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+@@ -198,6 +198,7 @@ void rt2800_txdone_entry(struct queue_en
+ void rt2800_txdone(struct rt2x00_dev *rt2x00dev, unsigned int quota);
+ void rt2800_txdone_nostatus(struct rt2x00_dev *rt2x00dev);
+ bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev);
++bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev);
+ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
+ void rt2800_clear_beacon(struct queue_entry *entry);
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c
+@@ -100,22 +100,6 @@ static void rt2800usb_stop_queue(struct
+       }
+ }
+-/*
+- * test if there is an entry in any TX queue for which DMA is done
+- * but the TX status has not been returned yet
+- */
+-static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
+-{
+-      struct data_queue *queue;
+-
+-      tx_queue_for_each(rt2x00dev, queue) {
+-              if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
+-                  rt2x00queue_get_entry(queue, Q_INDEX_DONE))
+-                      return true;
+-      }
+-      return false;
+-}
+-
+ #define TXSTATUS_READ_INTERVAL 1000000
+ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
+@@ -145,7 +129,7 @@ static bool rt2800usb_tx_sta_fifo_read_c
+       if (rt2800_txstatus_timeout(rt2x00dev))
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+-      if (rt2800usb_txstatus_pending(rt2x00dev)) {
++      if (rt2800_txstatus_pending(rt2x00dev)) {
+               /* Read register after 1 ms */
+               hrtimer_start(&rt2x00dev->txstatus_timer,
+                             TXSTATUS_READ_INTERVAL,
+@@ -160,7 +144,7 @@ stop_reading:
+        * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck
+        * here again if status reading is needed.
+        */
+-      if (rt2800usb_txstatus_pending(rt2x00dev) &&
++      if (rt2800_txstatus_pending(rt2x00dev) &&
+           !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
+               return true;
+       else
+@@ -489,7 +473,7 @@ static void rt2800usb_work_txdone(struct
+                * if the medium is busy, thus the TX_STA_FIFO entry is
+                * also delayed -> use a timer to retrieve it.
+                */
+-              if (rt2800usb_txstatus_pending(rt2x00dev))
++              if (rt2800_txstatus_pending(rt2x00dev))
+                       rt2800usb_async_read_tx_status(rt2x00dev);
+       }
+ }
diff --git a/package/kernel/mac80211/patches/rt2x00/026-rt2x00-remove-last_nostatus_check.patch b/package/kernel/mac80211/patches/rt2x00/026-rt2x00-remove-last_nostatus_check.patch
deleted file mode 100644 (file)
index 0daaef5..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From 6013a91f15c9dabd668d5736652b9bcfb0ef0378 Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:36 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804447
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 26/28] rt2x00: remove last_nostatus_check
-
-We do not any longer check txstatus timeout from tasklet, so do not need
-this optimization.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c   | 9 ---------
- drivers/net/wireless/ralink/rt2x00/rt2x00.h      | 2 --
- drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 1 -
- 3 files changed, 12 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -1164,15 +1164,6 @@ bool rt2800_txstatus_timeout(struct rt2x
-       struct data_queue *queue;
-       struct queue_entry *entry;
--      if (!test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags)) {
--              unsigned long tout = msecs_to_jiffies(1000);
--
--              if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
--                      return false;
--      }
--
--      rt2x00dev->last_nostatus_check = jiffies;
--
-       tx_queue_for_each(rt2x00dev, queue) {
-               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-               if (rt2800_entry_txstatus_timeout(rt2x00dev, entry))
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -981,8 +981,6 @@ struct rt2x00_dev {
-        */
-       DECLARE_KFIFO_PTR(txstatus_fifo, u32);
--      unsigned long last_nostatus_check;
--
-       /*
-        * Timer to ensure tx status reports are read (rt2800usb).
-        */
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-@@ -1039,7 +1039,6 @@ void rt2x00queue_start_queues(struct rt2
-        */
-       tx_queue_for_each(rt2x00dev, queue)
-               rt2x00queue_start_queue(queue);
--      rt2x00dev->last_nostatus_check = jiffies;
-       rt2x00queue_start_queue(rt2x00dev->rx);
- }
diff --git a/package/kernel/mac80211/patches/rt2x00/027-rt2800mmio-fetch-tx-status-changes.patch b/package/kernel/mac80211/patches/rt2x00/027-rt2800mmio-fetch-tx-status-changes.patch
new file mode 100644 (file)
index 0000000..4bb62c2
--- /dev/null
@@ -0,0 +1,61 @@
+From f6a9618198e190a2ba09ce3f0aa8e9ee1763bd38 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:34 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804443
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 24/28] rt2800mmio: fetch tx status changes
+
+Prepare to use rt2800mmio_fetch_txstatus() in concurrent manner and drop
+return value since is not longer needed.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+@@ -255,12 +255,12 @@ void rt2800mmio_autowake_tasklet(unsigne
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
+-static bool rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
++static void rt2800mmio_fetch_txstatus(struct rt2x00_dev *rt2x00dev)
+ {
+       u32 status;
+-      bool more = false;
++      unsigned long flags;
+-      /* FIXEME: rewrite this comment
++      /*
+        * The TX_FIFO_STATUS interrupt needs special care. We should
+        * read TX_STA_FIFO but we should do it immediately as otherwise
+        * the register can overflow and we would lose status reports.
+@@ -271,20 +271,21 @@ static bool rt2800mmio_fetch_txstatus(st
+        * because we can schedule the tasklet multiple times (when the
+        * interrupt fires again during tx status processing).
+        *
+-       * txstatus tasklet is called with INT_SOURCE_CSR_TX_FIFO_STATUS
+-       * disabled so have only one producer and one consumer - we don't
+-       * need to lock the kfifo.
++       * We also read statuses from tx status timeout timer, use
++       * lock to prevent concurent writes to fifo.
+        */
++
++      spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
++
+       while (!kfifo_is_full(&rt2x00dev->txstatus_fifo)) {
+               status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
+               if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
+                       break;
+               kfifo_put(&rt2x00dev->txstatus_fifo, status);
+-              more = true;
+       }
+-      return more;
++      spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+ }
+ void rt2800mmio_txstatus_tasklet(unsigned long data)
diff --git a/package/kernel/mac80211/patches/rt2x00/027-rt2x00-remove-not-used-entry-field.patch b/package/kernel/mac80211/patches/rt2x00/027-rt2x00-remove-not-used-entry-field.patch
deleted file mode 100644 (file)
index 53134a5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 2758f09b22bc08e89e0391486b2d707ad2479599 Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:37 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804449
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 27/28] rt2x00: remove not used entry field
-
-Remove not used any longer queue_entry field and flag.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2x00queue.h | 3 ---
- 1 file changed, 3 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
-@@ -361,7 +361,6 @@ enum queue_entry_flags {
-       ENTRY_DATA_PENDING,
-       ENTRY_DATA_IO_FAILED,
-       ENTRY_DATA_STATUS_PENDING,
--      ENTRY_DATA_STATUS_SET,
- };
- /**
-@@ -387,8 +386,6 @@ struct queue_entry {
-       unsigned int entry_idx;
--      u32 status;
--
-       void *priv_data;
- };
diff --git a/package/kernel/mac80211/patches/rt2x00/028-rt2800mmio-use-timer-and-work-for-handling-tx-status.patch b/package/kernel/mac80211/patches/rt2x00/028-rt2800mmio-use-timer-and-work-for-handling-tx-status.patch
new file mode 100644 (file)
index 0000000..bf038a5
--- /dev/null
@@ -0,0 +1,194 @@
+From 175c2548332b45b144af673e70fdbb1a947d7aba Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:35 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804445
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 25/28] rt2800mmio: use timer and work for handling tx statuses
+ timeouts
+
+Sometimes we can get into situation when there are pending statuses,
+but we do not get INT_SOURCE_CSR_TX_FIFO_STATUS. Handle this situation
+by arming timeout timer and read statuses (it will fix case when
+we just do not have irq) and queue work to handle case we missed
+statues from hardware FIFO.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ .../net/wireless/ralink/rt2x00/rt2800mmio.c   | 81 +++++++++++++++++--
+ .../net/wireless/ralink/rt2x00/rt2800mmio.h   |  1 +
+ .../net/wireless/ralink/rt2x00/rt2800pci.c    |  2 +-
+ .../net/wireless/ralink/rt2x00/rt2800soc.c    |  2 +-
+ .../net/wireless/ralink/rt2x00/rt2x00dev.c    |  4 +
+ 5 files changed, 82 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+@@ -426,6 +426,9 @@ void rt2800mmio_start_queue(struct data_
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_start_queue);
++/* 200 ms */
++#define TXSTATUS_TIMEOUT 200000000
++
+ void rt2800mmio_kick_queue(struct data_queue *queue)
+ {
+       struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
+@@ -440,6 +443,8 @@ void rt2800mmio_kick_queue(struct data_q
+               entry = rt2x00queue_get_entry(queue, Q_INDEX);
+               rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid),
+                                         entry->entry_idx);
++              hrtimer_start(&rt2x00dev->txstatus_timer,
++                            TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
+               break;
+       case QID_MGMT:
+               entry = rt2x00queue_get_entry(queue, Q_INDEX);
+@@ -484,12 +489,8 @@ void rt2800mmio_flush_queue(struct data_
+                * For TX queues schedule completion tasklet to catch
+                * tx status timeouts, othewise just wait.
+                */
+-              if (tx_queue) {
+-                      tasklet_disable(&rt2x00dev->txstatus_tasklet);
+-                      rt2800_txdone(rt2x00dev, UINT_MAX);
+-                      rt2800_txdone_nostatus(rt2x00dev);
+-                      tasklet_enable(&rt2x00dev->txstatus_tasklet);
+-              }
++              if (tx_queue)
++                      queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+               /*
+                * Wait for a little while to give the driver
+@@ -627,6 +628,10 @@ void rt2800mmio_clear_entry(struct queue
+               word = rt2x00_desc_read(entry_priv->desc, 1);
+               rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1);
+               rt2x00_desc_write(entry_priv->desc, 1, word);
++
++              /* If last entry stop txstatus timer */
++              if (entry->queue->length == 1)
++                      hrtimer_cancel(&rt2x00dev->txstatus_timer);
+       }
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry);
+@@ -759,6 +764,70 @@ int rt2800mmio_enable_radio(struct rt2x0
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio);
++static void rt2800mmio_work_txdone(struct work_struct *work)
++{
++      struct rt2x00_dev *rt2x00dev =
++          container_of(work, struct rt2x00_dev, txdone_work);
++
++      if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
++              return;
++
++      while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) ||
++             rt2800_txstatus_timeout(rt2x00dev)) {
++
++              tasklet_disable(&rt2x00dev->txstatus_tasklet);
++              rt2800_txdone(rt2x00dev, UINT_MAX);
++              rt2800_txdone_nostatus(rt2x00dev);
++              tasklet_enable(&rt2x00dev->txstatus_tasklet);
++      }
++
++      if (rt2800_txstatus_pending(rt2x00dev))
++              hrtimer_start(&rt2x00dev->txstatus_timer,
++                            TXSTATUS_TIMEOUT, HRTIMER_MODE_REL);
++}
++
++static enum hrtimer_restart rt2800mmio_tx_sta_fifo_timeout(struct hrtimer *timer)
++{
++      struct rt2x00_dev *rt2x00dev =
++          container_of(timer, struct rt2x00_dev, txstatus_timer);
++
++      if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
++              goto out;
++
++      if (!rt2800_txstatus_pending(rt2x00dev))
++              goto out;
++
++      rt2800mmio_fetch_txstatus(rt2x00dev);
++      if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
++              tasklet_schedule(&rt2x00dev->txstatus_tasklet);
++      else
++              queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
++out:
++      return HRTIMER_NORESTART;
++}
++
++int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev)
++{
++      int retval;
++
++      retval = rt2800_probe_hw(rt2x00dev);
++      if (retval)
++              return retval;
++
++      /*
++       * Set txstatus timer function.
++       */
++      rt2x00dev->txstatus_timer.function = rt2800mmio_tx_sta_fifo_timeout;
++
++      /*
++       * Overwrite TX done handler
++       */
++      INIT_WORK(&rt2x00dev->txdone_work, rt2800mmio_work_txdone);
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(rt2800mmio_probe_hw);
++
+ MODULE_AUTHOR(DRV_PROJECT);
+ MODULE_VERSION(DRV_VERSION);
+ MODULE_DESCRIPTION("rt2800 MMIO library");
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h
+@@ -153,6 +153,7 @@ void rt2800mmio_stop_queue(struct data_q
+ void rt2800mmio_queue_init(struct data_queue *queue);
+ /* Initialization functions */
++int rt2800mmio_probe_hw(struct rt2x00_dev *rt2x00dev);
+ bool rt2800mmio_get_entry_state(struct queue_entry *entry);
+ void rt2800mmio_clear_entry(struct queue_entry *entry);
+ int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev);
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+@@ -346,7 +346,7 @@ static const struct rt2x00lib_ops rt2800
+       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
+       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
+       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
+-      .probe_hw               = rt2800_probe_hw,
++      .probe_hw               = rt2800mmio_probe_hw,
+       .get_firmware_name      = rt2800pci_get_firmware_name,
+       .check_firmware         = rt2800_check_firmware,
+       .load_firmware          = rt2800_load_firmware,
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+@@ -185,7 +185,7 @@ static const struct rt2x00lib_ops rt2800
+       .tbtt_tasklet           = rt2800mmio_tbtt_tasklet,
+       .rxdone_tasklet         = rt2800mmio_rxdone_tasklet,
+       .autowake_tasklet       = rt2800mmio_autowake_tasklet,
+-      .probe_hw               = rt2800_probe_hw,
++      .probe_hw               = rt2800mmio_probe_hw,
+       .get_firmware_name      = rt2800soc_get_firmware_name,
+       .check_firmware         = rt2800soc_check_firmware,
+       .load_firmware          = rt2800soc_load_firmware,
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -1391,6 +1391,8 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+       mutex_init(&rt2x00dev->conf_mutex);
+       INIT_LIST_HEAD(&rt2x00dev->bar_list);
+       spin_lock_init(&rt2x00dev->bar_list_lock);
++      hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC,
++                   HRTIMER_MODE_REL);
+       set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+@@ -1515,6 +1517,8 @@ void rt2x00lib_remove_dev(struct rt2x00_
+       cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
+       cancel_work_sync(&rt2x00dev->sleep_work);
++      hrtimer_cancel(&rt2x00dev->txstatus_timer);
++
+       /*
+        * Kill the tx status tasklet.
+        */
diff --git a/package/kernel/mac80211/patches/rt2x00/028-rt2x00mmio-remove-legacy-comment.patch b/package/kernel/mac80211/patches/rt2x00/028-rt2x00mmio-remove-legacy-comment.patch
deleted file mode 100644 (file)
index 199a6e3..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From f44e145869bb517460648e4ed71b7e9001964d06 Mon Sep 17 00:00:00 2001
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-Date: Sat, 9 Feb 2019 12:08:38 +0100
-X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10804451
-X-Patchwork-Delegate: kvalo@adurom.com
-Subject: [PATCH 28/28] rt2x00mmio: remove legacy comment
-
-Remove comment about fields that ware removed.
-
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
-@@ -80,8 +80,6 @@ int rt2x00mmio_regbusy_read(struct rt2x0
-  *
-  * @desc: Pointer to device descriptor
-  * @desc_dma: DMA pointer to &desc.
-- * @data: Pointer to device's entry memory.
-- * @data_dma: DMA pointer to &data.
-  */
- struct queue_entry_priv_mmio {
-       __le32 *desc;
diff --git a/package/kernel/mac80211/patches/rt2x00/029-rt2x00-remove-last_nostatus_check.patch b/package/kernel/mac80211/patches/rt2x00/029-rt2x00-remove-last_nostatus_check.patch
new file mode 100644 (file)
index 0000000..0daaef5
--- /dev/null
@@ -0,0 +1,57 @@
+From 6013a91f15c9dabd668d5736652b9bcfb0ef0378 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:36 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804447
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 26/28] rt2x00: remove last_nostatus_check
+
+We do not any longer check txstatus timeout from tasklet, so do not need
+this optimization.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c   | 9 ---------
+ drivers/net/wireless/ralink/rt2x00/rt2x00.h      | 2 --
+ drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 1 -
+ 3 files changed, 12 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -1164,15 +1164,6 @@ bool rt2800_txstatus_timeout(struct rt2x
+       struct data_queue *queue;
+       struct queue_entry *entry;
+-      if (!test_bit(DEVICE_STATE_FLUSHING, &rt2x00dev->flags)) {
+-              unsigned long tout = msecs_to_jiffies(1000);
+-
+-              if (time_before(jiffies, rt2x00dev->last_nostatus_check + tout))
+-                      return false;
+-      }
+-
+-      rt2x00dev->last_nostatus_check = jiffies;
+-
+       tx_queue_for_each(rt2x00dev, queue) {
+               entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
+               if (rt2800_entry_txstatus_timeout(rt2x00dev, entry))
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -981,8 +981,6 @@ struct rt2x00_dev {
+        */
+       DECLARE_KFIFO_PTR(txstatus_fifo, u32);
+-      unsigned long last_nostatus_check;
+-
+       /*
+        * Timer to ensure tx status reports are read (rt2800usb).
+        */
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
+@@ -1039,7 +1039,6 @@ void rt2x00queue_start_queues(struct rt2
+        */
+       tx_queue_for_each(rt2x00dev, queue)
+               rt2x00queue_start_queue(queue);
+-      rt2x00dev->last_nostatus_check = jiffies;
+       rt2x00queue_start_queue(rt2x00dev->rx);
+ }
diff --git a/package/kernel/mac80211/patches/rt2x00/030-rt2x00-remove-not-used-entry-field.patch b/package/kernel/mac80211/patches/rt2x00/030-rt2x00-remove-not-used-entry-field.patch
new file mode 100644 (file)
index 0000000..53134a5
--- /dev/null
@@ -0,0 +1,34 @@
+From 2758f09b22bc08e89e0391486b2d707ad2479599 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:37 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804449
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 27/28] rt2x00: remove not used entry field
+
+Remove not used any longer queue_entry field and flag.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2x00queue.h | 3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h
+@@ -361,7 +361,6 @@ enum queue_entry_flags {
+       ENTRY_DATA_PENDING,
+       ENTRY_DATA_IO_FAILED,
+       ENTRY_DATA_STATUS_PENDING,
+-      ENTRY_DATA_STATUS_SET,
+ };
+ /**
+@@ -387,8 +386,6 @@ struct queue_entry {
+       unsigned int entry_idx;
+-      u32 status;
+-
+       void *priv_data;
+ };
diff --git a/package/kernel/mac80211/patches/rt2x00/031-rt2x00mmio-remove-legacy-comment.patch b/package/kernel/mac80211/patches/rt2x00/031-rt2x00mmio-remove-legacy-comment.patch
new file mode 100644 (file)
index 0000000..199a6e3
--- /dev/null
@@ -0,0 +1,26 @@
+From f44e145869bb517460648e4ed71b7e9001964d06 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Sat, 9 Feb 2019 12:08:38 +0100
+X-Patchwork-Submitter: Stanislaw Gruszka <sgruszka@redhat.com>
+X-Patchwork-Id: 10804451
+X-Patchwork-Delegate: kvalo@adurom.com
+Subject: [PATCH 28/28] rt2x00mmio: remove legacy comment
+
+Remove comment about fields that ware removed.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00mmio.h
+@@ -80,8 +80,6 @@ int rt2x00mmio_regbusy_read(struct rt2x0
+  *
+  * @desc: Pointer to device descriptor
+  * @desc_dma: DMA pointer to &desc.
+- * @data: Pointer to device's entry memory.
+- * @data_dma: DMA pointer to &data.
+  */
+ struct queue_entry_priv_mmio {
+       __le32 *desc;