From 384e5abd02db83dfcfa0aa926dfb4372afbb10bc Mon Sep 17 00:00:00 2001 From: LEAN-ESX Date: Mon, 11 Nov 2019 20:28:16 -0800 Subject: [PATCH] mac80211: update upstream patches --- package/kernel/mac80211/Makefile | 4 +- .../mac80211/files/lib/wifi/mac80211.sh | 2 +- .../mac80211/patches/ath/552-ahb_of.patch | 19 +- ...0-allow-to-specify-watchdog-interval.patch | 56 +++ ...d-helpers-for-reading-dma-done-index.patch | 144 ++++++ ...2800-initial-watchdog-implementation.patch | 158 +++++++ ...063-rt2800-add-pre_reset_hw-callback.patch | 96 ++++ ...t-nullify-initialization-vector-data.patch | 51 ++ .../rt2x00/065-rt2x00-add-restart-hw.patch | 151 ++++++ ...00-do-not-enable-watchdog-by-default.patch | 71 +++ .../067-rt2x00usb-fix-rx-queue-hang.patch | 67 +++ ...sb-remove-unnecessary-rx-flag-checks.patch | 51 ++ ...o-check-return-value-of-debugfs_crea.patch | 248 ++++++++++ ...w-rt2800usb-device-PLANEX-GW-USMicro.patch | 29 ++ ...s-on-start-to-fix-AP-mode-regression.patch | 102 ++++ ...t-IEEE80211_TX_STAT_AMPDU_NO_BACK-on.patch | 40 ++ ...-rt2x00-clear-up-IV-s-on-key-removal.patch | 46 ++ ...able-TX_PIN_CFG_LNA_PE_-bits-per-ban.patch | 61 +++ ...remove-errornous-duplicate-condition.patch | 88 ++++ .../602-rt2x00-introduce-rt2x00eeprom.patch | 10 +- ...isabling_bands_through_platform_data.patch | 4 +- ...07-rt2x00-add_platform_data_mac_addr.patch | 2 +- ...00-allow_disabling_bands_through_dts.patch | 2 +- ...c-loadable-via-OF-on-rt288x-305x-SoC.patch | 2 +- ...0-rt2x00-change-led-polarity-from-OF.patch | 2 +- .../611-rt2x00-add-AP+STA-support.patch | 2 +- ...dd-support-for-external-PA-on-MT7620.patch | 6 +- ...-rt2x00-add-rf-self-txdc-calibration.patch | 8 +- .../rt2x00/983-rt2x00-add-r-calibration.patch | 8 +- .../984-rt2x00-add-rxdcoc-calibration.patch | 8 +- .../985-rt2x00-add-rxiq-calibration.patch | 8 +- .../986-rt2x00-add-TX-LOFT-calibration.patch | 8 +- ...l-remove-divisions-in-tx-status-path.patch | 61 +++ ...l_ht-replace-rate-stats-ewma-with-a-.patch | 235 ++++++++++ ...l_ht-rename-prob_ewma-to-prob_avg-us.patch | 437 ++++++++++++++++++ 35 files changed, 2243 insertions(+), 44 deletions(-) create mode 100644 package/kernel/mac80211/patches/rt2x00/060-rt2x00-allow-to-specify-watchdog-interval.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/061-rt2800-add-helpers-for-reading-dma-done-index.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/062-rt2800-initial-watchdog-implementation.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/063-rt2800-add-pre_reset_hw-callback.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/064-rt2800-do-not-nullify-initialization-vector-data.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/065-rt2x00-add-restart-hw.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/066-rt2800-do-not-enable-watchdog-by-default.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/067-rt2x00usb-fix-rx-queue-hang.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/068-rt2x00usb-remove-unnecessary-rx-flag-checks.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/069-rt2x00-no-need-to-check-return-value-of-debugfs_crea.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/070-rt2800usb-Add-new-rt2800usb-device-PLANEX-GW-USMicro.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/071-rt2x00-clear-IV-s-on-start-to-fix-AP-mode-regression.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/072-rt2x00-do-not-set-IEEE80211_TX_STAT_AMPDU_NO_BACK-on.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/073-rt2x00-clear-up-IV-s-on-key-removal.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/074-Revert-rt2800-enable-TX_PIN_CFG_LNA_PE_-bits-per-ban.patch create mode 100644 package/kernel/mac80211/patches/rt2x00/075-rt2800-remove-errornous-duplicate-condition.patch create mode 100644 package/kernel/mac80211/patches/subsys/362-mac80211-minstrel-remove-divisions-in-tx-status-path.patch create mode 100644 package/kernel/mac80211/patches/subsys/363-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch create mode 100644 package/kernel/mac80211/patches/subsys/364-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 70b80e880..8545f2329 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -299,14 +299,14 @@ endef define KernelPackage/rsi91x $(call KernelPackage/mac80211/Default) TITLE:=Redpine Signals Inc 91x WLAN driver support - DEPENDS+= +kmod-mac80211 +rs9113-firmware + DEPENDS+= +kmod-mac80211 +rs9113-firmware +@DRIVER_11N_SUPPORT FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_91x.ko endef define KernelPackage/rsi91x-usb $(call KernelPackage/mac80211/Default) TITLE:=Redpine Signals USB bus support - DEPENDS+= +kmod-mac80211 +kmod-usb2 +kmod-rsi91x +rs9113-firmware + DEPENDS+=@USB_SUPPORT +kmod-usb-core +kmod-mac80211 +kmod-rsi91x +rs9113-firmware FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rsi/rsi_usb.ko AUTOLOAD:=$(call AutoProbe,rsi_usb) endef diff --git a/package/kernel/mac80211/files/lib/wifi/mac80211.sh b/package/kernel/mac80211/files/lib/wifi/mac80211.sh index 511a9188d..6103b5d04 100644 --- a/package/kernel/mac80211/files/lib/wifi/mac80211.sh +++ b/package/kernel/mac80211/files/lib/wifi/mac80211.sh @@ -113,7 +113,7 @@ detect_mac80211() { set wireless.radio${devidx}.hwmode=11${mode_band} ${dev_id} ${ht_capab} - set wireless.radio${devidx}.disabled=1 + set wireless.radio${devidx}.disabled=0 set wireless.default_radio${devidx}=wifi-iface set wireless.default_radio${devidx}.device=radio${devidx} diff --git a/package/kernel/mac80211/patches/ath/552-ahb_of.patch b/package/kernel/mac80211/patches/ath/552-ahb_of.patch index 08735d287..c16bf424e 100644 --- a/package/kernel/mac80211/patches/ath/552-ahb_of.patch +++ b/package/kernel/mac80211/patches/ath/552-ahb_of.patch @@ -16,7 +16,7 @@ static const struct platform_device_id ath9k_platform_id_table[] = { { -@@ -69,6 +77,235 @@ static const struct ath_bus_ops ath_ahb_ +@@ -69,6 +77,242 @@ static const struct ath_bus_ops ath_ahb_ .eeprom_read = ath_ahb_eeprom_read, }; @@ -232,7 +232,14 @@ + pdata->external_reset = data->wmac_reset; + } + -+ if (data->bootstrap_reg && data->bootstrap_ref) { ++ if (data->dev_id == AR9300_DEVID_AR953X) { ++ /* ++ * QCA953x only supports 25MHz refclk. ++ * Some vendors have an invalid bootstrap option ++ * set, which would break the WMAC here. ++ */ ++ pdata->is_clk_25mhz = true; ++ } else if (data->bootstrap_reg && data->bootstrap_ref) { + u32 t = ath79_reset_rr(data->bootstrap_reg); + if (t & data->bootstrap_ref) + pdata->is_clk_25mhz = false; @@ -252,7 +259,7 @@ static int ath_ahb_probe(struct platform_device *pdev) { void __iomem *mem; -@@ -80,6 +317,17 @@ static int ath_ahb_probe(struct platform +@@ -80,6 +324,17 @@ static int ath_ahb_probe(struct platform int ret = 0; struct ath_hw *ah; char hw_name[64]; @@ -270,7 +277,7 @@ if (!dev_get_platdata(&pdev->dev)) { dev_err(&pdev->dev, "no platform data specified\n"); -@@ -122,13 +370,16 @@ static int ath_ahb_probe(struct platform +@@ -122,13 +377,16 @@ static int ath_ahb_probe(struct platform sc->mem = mem; sc->irq = irq; @@ -288,7 +295,7 @@ if (ret) { dev_err(&pdev->dev, "failed to initialize device\n"); goto err_irq; -@@ -159,6 +410,9 @@ static int ath_ahb_remove(struct platfor +@@ -159,6 +417,9 @@ static int ath_ahb_remove(struct platfor free_irq(sc->irq, sc); ieee80211_free_hw(sc->hw); } @@ -298,7 +305,7 @@ return 0; } -@@ -168,6 +422,9 @@ static struct platform_driver ath_ahb_dr +@@ -168,6 +429,9 @@ static struct platform_driver ath_ahb_dr .remove = ath_ahb_remove, .driver = { .name = "ath9k", diff --git a/package/kernel/mac80211/patches/rt2x00/060-rt2x00-allow-to-specify-watchdog-interval.patch b/package/kernel/mac80211/patches/rt2x00/060-rt2x00-allow-to-specify-watchdog-interval.patch new file mode 100644 index 000000000..828d3c8b2 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/060-rt2x00-allow-to-specify-watchdog-interval.patch @@ -0,0 +1,56 @@ +From 9f3e3323e9966d9f21bea0c81b1acb36c0e15cec Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Sat, 15 Jun 2019 12:00:54 +0200 +Subject: [PATCH 01/15] rt2x00: allow to specify watchdog interval + +Allow subdriver to change watchdog interval by intialize +link->watchdog_interval value before rt2x00link_register(). + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + + drivers/net/wireless/ralink/rt2x00/rt2x00link.c | 13 +++++++++---- + 2 files changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -336,6 +336,7 @@ struct link { + * to bring the device/driver back into the desired state. + */ + struct delayed_work watchdog_work; ++ unsigned int watchdog_interval; + + /* + * Work structure for scheduling periodic AGC adjustments. +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c +@@ -398,7 +398,7 @@ void rt2x00link_start_watchdog(struct rt + rt2x00dev->ops->lib->watchdog) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->watchdog_work, +- WATCHDOG_INTERVAL); ++ link->watchdog_interval); + } + + void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) +@@ -424,11 +424,16 @@ static void rt2x00link_watchdog(struct w + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->watchdog_work, +- WATCHDOG_INTERVAL); ++ link->watchdog_interval); + } + + void rt2x00link_register(struct rt2x00_dev *rt2x00dev) + { +- INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); +- INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); ++ struct link *link = &rt2x00dev->link; ++ ++ INIT_DELAYED_WORK(&link->work, rt2x00link_tuner); ++ INIT_DELAYED_WORK(&link->watchdog_work, rt2x00link_watchdog); ++ ++ if (link->watchdog_interval == 0) ++ link->watchdog_interval = WATCHDOG_INTERVAL; + } diff --git a/package/kernel/mac80211/patches/rt2x00/061-rt2800-add-helpers-for-reading-dma-done-index.patch b/package/kernel/mac80211/patches/rt2x00/061-rt2800-add-helpers-for-reading-dma-done-index.patch new file mode 100644 index 000000000..adfc5c5b5 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/061-rt2800-add-helpers-for-reading-dma-done-index.patch @@ -0,0 +1,144 @@ +From 2034afe4db4a2a4f22541d7f7b426e38d2093d38 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Sat, 15 Jun 2019 12:00:55 +0200 +Subject: [PATCH 02/15] rt2800: add helpers for reading dma done index + +For mmio we do not properlly trace dma done Q_INDEX_DMA_DONE index +for TX queues. That would require implementing INT_SOURCE_CSR_*_DMA_DONE +interrupts, what is rather not worth to do due to adding extra +CPU load (small but still somewhat not necessary otherwise). + +We can just read TX DMA done indexes from registers directly. What +will be used by watchdog. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + .../net/wireless/ralink/rt2x00/rt2800lib.h | 8 +++++ + .../net/wireless/ralink/rt2x00/rt2800mmio.c | 31 +++++++++++++++++++ + .../net/wireless/ralink/rt2x00/rt2800mmio.h | 2 ++ + .../net/wireless/ralink/rt2x00/rt2800pci.c | 1 + + .../net/wireless/ralink/rt2x00/rt2800soc.c | 1 + + .../net/wireless/ralink/rt2x00/rt2800usb.c | 9 ++++++ + 6 files changed, 52 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -76,6 +76,7 @@ struct rt2800_ops { + const u8 *data, const size_t len); + int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); + __le32 *(*drv_get_txwi)(struct queue_entry *entry); ++ unsigned int (*drv_get_dma_done)(struct data_queue *queue); + }; + + static inline u32 rt2800_register_read(struct rt2x00_dev *rt2x00dev, +@@ -177,6 +178,13 @@ static inline __le32 *rt2800_drv_get_txw + return rt2800ops->drv_get_txwi(entry); + } + ++static inline unsigned int rt2800_drv_get_dma_done(struct data_queue *queue) ++{ ++ const struct rt2800_ops *rt2800ops = queue->rt2x00dev->ops->drv; ++ ++ return rt2800ops->drv_get_dma_done(queue); ++} ++ + void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, + const u8 command, const u8 token, + const u8 arg0, const u8 arg1); +--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c +@@ -36,6 +36,37 @@ + #include "rt2800lib.h" + #include "rt2800mmio.h" + ++unsigned int rt2800mmio_get_dma_done(struct data_queue *queue) ++{ ++ struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; ++ struct queue_entry *entry; ++ int idx, qid; ++ ++ switch (queue->qid) { ++ case QID_AC_VO: ++ case QID_AC_VI: ++ case QID_AC_BE: ++ case QID_AC_BK: ++ qid = queue->qid; ++ idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(qid)); ++ break; ++ case QID_MGMT: ++ idx = rt2x00mmio_register_read(rt2x00dev, TX_DTX_IDX(5)); ++ break; ++ case QID_RX: ++ entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE); ++ idx = entry->entry_idx; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ idx = 0; ++ break; ++ } ++ ++ return idx; ++} ++EXPORT_SYMBOL_GPL(rt2800mmio_get_dma_done); ++ + /* + * TX descriptor initialization + */ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.h +@@ -126,6 +126,8 @@ + #define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000) + #define RXD_W3_PLCP_RSSI FIELD32(0x00040000) + ++unsigned int rt2800mmio_get_dma_done(struct data_queue *queue); ++ + /* TX descriptor initialization */ + __le32 *rt2800mmio_get_txwi(struct queue_entry *entry); + void rt2800mmio_write_tx_desc(struct queue_entry *entry, +--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -337,6 +337,7 @@ static const struct rt2800_ops rt2800pci + .drv_write_firmware = rt2800pci_write_firmware, + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, ++ .drv_get_dma_done = rt2800mmio_get_dma_done, + }; + + static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -183,6 +183,7 @@ static const struct rt2800_ops rt2800soc + .drv_write_firmware = rt2800soc_write_firmware, + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, ++ .drv_get_dma_done = rt2800mmio_get_dma_done, + }; + + static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +@@ -390,6 +390,14 @@ static int rt2800usb_set_device_state(st + return retval; + } + ++static unsigned int rt2800usb_get_dma_done(struct data_queue *queue) ++{ ++ struct queue_entry *entry; ++ ++ entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE); ++ return entry->entry_idx; ++} ++ + /* + * TX descriptor initialization + */ +@@ -672,6 +680,7 @@ static const struct rt2800_ops rt2800usb + .drv_write_firmware = rt2800usb_write_firmware, + .drv_init_registers = rt2800usb_init_registers, + .drv_get_txwi = rt2800usb_get_txwi, ++ .drv_get_dma_done = rt2800usb_get_dma_done, + }; + + static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { diff --git a/package/kernel/mac80211/patches/rt2x00/062-rt2800-initial-watchdog-implementation.patch b/package/kernel/mac80211/patches/rt2x00/062-rt2800-initial-watchdog-implementation.patch new file mode 100644 index 000000000..24032b534 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/062-rt2800-initial-watchdog-implementation.patch @@ -0,0 +1,158 @@ +From 759c5b599cf4ddb3b56e66d459b1bf0fe2724fb8 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Sat, 15 Jun 2019 12:00:56 +0200 +Subject: [PATCH 03/15] rt2800: initial watchdog implementation + +Add watchdog for rt2800 devices. For now it only detect hung +and print error. + +[Note: I verified that printing messages from process context is +fine on MT7620 (WT3020) platform that have problem when printk +is called from interrupt context]. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 56 +++++++++++++++++++ + .../net/wireless/ralink/rt2x00/rt2800lib.h | 2 + + .../net/wireless/ralink/rt2x00/rt2800pci.c | 1 + + .../net/wireless/ralink/rt2x00/rt2800soc.c | 1 + + .../net/wireless/ralink/rt2x00/rt2800usb.c | 1 + + .../net/wireless/ralink/rt2x00/rt2x00queue.h | 6 ++ + 6 files changed, 67 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -1223,6 +1223,60 @@ void rt2800_txdone_nostatus(struct rt2x0 + } + EXPORT_SYMBOL_GPL(rt2800_txdone_nostatus); + ++static int rt2800_check_hung(struct data_queue *queue) ++{ ++ unsigned int cur_idx = rt2800_drv_get_dma_done(queue); ++ ++ if (queue->wd_idx != cur_idx) ++ queue->wd_count = 0; ++ else ++ queue->wd_count++; ++ ++ return queue->wd_count > 16; ++} ++ ++void rt2800_watchdog(struct rt2x00_dev *rt2x00dev) ++{ ++ struct data_queue *queue; ++ bool hung_tx = false; ++ bool hung_rx = false; ++ ++ if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) ++ return; ++ ++ queue_for_each(rt2x00dev, queue) { ++ switch (queue->qid) { ++ case QID_AC_VO: ++ case QID_AC_VI: ++ case QID_AC_BE: ++ case QID_AC_BK: ++ case QID_MGMT: ++ if (rt2x00queue_empty(queue)) ++ continue; ++ hung_tx = rt2800_check_hung(queue); ++ break; ++ case QID_RX: ++ /* For station mode we should reactive at least ++ * beacons. TODO: need to find good way detect ++ * RX hung for AP mode. ++ */ ++ if (rt2x00dev->intf_sta_count == 0) ++ continue; ++ hung_rx = rt2800_check_hung(queue); ++ break; ++ default: ++ break; ++ } ++ } ++ ++ if (hung_tx) ++ rt2x00_warn(rt2x00dev, "Watchdog TX hung detected\n"); ++ ++ if (hung_rx) ++ rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n"); ++} ++EXPORT_SYMBOL_GPL(rt2800_watchdog); ++ + static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, + unsigned int index) + { +@@ -10222,6 +10276,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); + } + ++ rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100); ++ + /* + * Set the rssi offset. + */ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -208,6 +208,8 @@ void rt2800_txdone_nostatus(struct rt2x0 + bool rt2800_txstatus_timeout(struct rt2x00_dev *rt2x00dev); + bool rt2800_txstatus_pending(struct rt2x00_dev *rt2x00dev); + ++void rt2800_watchdog(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/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -362,6 +362,7 @@ static const struct rt2x00lib_ops rt2800 + .link_tuner = rt2800_link_tuner, + .gain_calibration = rt2800_gain_calibration, + .vco_calibration = rt2800_vco_calibration, ++ .watchdog = rt2800_watchdog, + .start_queue = rt2800mmio_start_queue, + .kick_queue = rt2800mmio_kick_queue, + .stop_queue = rt2800mmio_stop_queue, +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -208,6 +208,7 @@ static const struct rt2x00lib_ops rt2800 + .link_tuner = rt2800_link_tuner, + .gain_calibration = rt2800_gain_calibration, + .vco_calibration = rt2800_vco_calibration, ++ .watchdog = rt2800_watchdog, + .start_queue = rt2800mmio_start_queue, + .kick_queue = rt2800mmio_kick_queue, + .stop_queue = rt2800mmio_stop_queue, +--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +@@ -698,6 +698,7 @@ static const struct rt2x00lib_ops rt2800 + .link_tuner = rt2800_link_tuner, + .gain_calibration = rt2800_gain_calibration, + .vco_calibration = rt2800_vco_calibration, ++ .watchdog = rt2800_watchdog, + .start_queue = rt2800usb_start_queue, + .kick_queue = rt2x00usb_kick_queue, + .stop_queue = rt2800usb_stop_queue, +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.h +@@ -446,6 +446,9 @@ enum data_queue_flags { + * @length: Number of frames in queue. + * @index: Index pointers to entry positions in the queue, + * use &enum queue_index to get a specific index field. ++ * @wd_count: watchdog counter number of times entry does change ++ * in the queue ++ * @wd_idx: index of queue entry saved by watchdog + * @txop: maximum burst time. + * @aifs: The aifs value for outgoing frames (field ignored in RX queue). + * @cw_min: The cw min value for outgoing frames (field ignored in RX queue). +@@ -473,6 +476,9 @@ struct data_queue { + unsigned short length; + unsigned short index[Q_INDEX_MAX]; + ++ unsigned short wd_count; ++ unsigned int wd_idx; ++ + unsigned short txop; + unsigned short aifs; + unsigned short cw_min; diff --git a/package/kernel/mac80211/patches/rt2x00/063-rt2800-add-pre_reset_hw-callback.patch b/package/kernel/mac80211/patches/rt2x00/063-rt2800-add-pre_reset_hw-callback.patch new file mode 100644 index 000000000..f7d3c32ee --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/063-rt2800-add-pre_reset_hw-callback.patch @@ -0,0 +1,96 @@ +From 09db3b000619b38d504e1fff66efed33dfacb6c0 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Sat, 15 Jun 2019 12:00:57 +0200 +Subject: [PATCH 04/15] rt2800: add pre_reset_hw callback + +Add routine to cleanup interfaces data before hw reset as +ieee80211_restart_hw() will do setup interfaces again. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 19 +++++++++++++++++++ + .../net/wireless/ralink/rt2x00/rt2800lib.h | 1 + + .../net/wireless/ralink/rt2x00/rt2800pci.c | 1 + + .../net/wireless/ralink/rt2x00/rt2800soc.c | 1 + + .../net/wireless/ralink/rt2x00/rt2800usb.c | 1 + + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + + 6 files changed, 24 insertions(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -1854,6 +1854,25 @@ int rt2800_sta_remove(struct ieee80211_h + } + EXPORT_SYMBOL_GPL(rt2800_sta_remove); + ++void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ struct data_queue *queue = rt2x00dev->bcn; ++ struct queue_entry *entry; ++ int i, wcid; ++ ++ for (wcid = WCID_START; wcid < WCID_END; wcid++) { ++ drv_data->wcid_to_sta[wcid - WCID_START] = NULL; ++ __clear_bit(wcid - WCID_START, drv_data->sta_ids); ++ } ++ ++ for (i = 0; i < queue->limit; i++) { ++ entry = &queue->entries[i]; ++ clear_bit(ENTRY_BCN_ASSIGNED, &entry->flags); ++ } ++} ++EXPORT_SYMBOL_GPL(rt2800_pre_reset_hw); ++ + void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) + { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +@@ -268,5 +268,6 @@ void rt2800_disable_wpdma(struct rt2x00_ + void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, + unsigned short *txwi_size, + unsigned short *rxwi_size); ++void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev); + + #endif /* RT2800LIB_H */ +--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +@@ -379,6 +379,7 @@ static const struct rt2x00lib_ops rt2800 + .config_erp = rt2800_config_erp, + .config_ant = rt2800_config_ant, + .config = rt2800_config, ++ .pre_reset_hw = rt2800_pre_reset_hw, + }; + + static const struct rt2x00_ops rt2800pci_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +@@ -225,6 +225,7 @@ static const struct rt2x00lib_ops rt2800 + .config_erp = rt2800_config_erp, + .config_ant = rt2800_config_ant, + .config = rt2800_config, ++ .pre_reset_hw = rt2800_pre_reset_hw, + }; + + static const struct rt2x00_ops rt2800soc_ops = { +--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +@@ -717,6 +717,7 @@ static const struct rt2x00lib_ops rt2800 + .config_erp = rt2800_config_erp, + .config_ant = rt2800_config_ant, + .config = rt2800_config, ++ .pre_reset_hw = rt2800_pre_reset_hw, + }; + + static void rt2800usb_queue_init(struct data_queue *queue) +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -627,6 +627,7 @@ struct rt2x00lib_ops { + void (*config) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int changed_flags); ++ void (*pre_reset_hw) (struct rt2x00_dev *rt2x00dev); + int (*sta_add) (struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta); diff --git a/package/kernel/mac80211/patches/rt2x00/064-rt2800-do-not-nullify-initialization-vector-data.patch b/package/kernel/mac80211/patches/rt2x00/064-rt2800-do-not-nullify-initialization-vector-data.patch new file mode 100644 index 000000000..df34bfffa --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/064-rt2800-do-not-nullify-initialization-vector-data.patch @@ -0,0 +1,51 @@ +From 710e6cc1595e25378c4b9977f7a8b4ad4a72a109 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Sat, 15 Jun 2019 12:00:58 +0200 +Subject: [PATCH 05/15] rt2800: do not nullify initialization vector data + +If we restart hw we should keep existing IV (initialization vector) +otherwise HW encryption will be broken after restart. + +Also fix some coding style issues on the way. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -1658,14 +1658,15 @@ static void rt2800_config_wcid_attr_ciph + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + +- memset(&iveiv_entry, 0, sizeof(iveiv_entry)); ++ rt2800_register_multiread(rt2x00dev, offset, ++ &iveiv_entry, sizeof(iveiv_entry)); + if ((crypto->cipher == CIPHER_TKIP) || + (crypto->cipher == CIPHER_TKIP_NO_MIC) || + (crypto->cipher == CIPHER_AES)) + iveiv_entry.iv[3] |= 0x20; + iveiv_entry.iv[3] |= key->keyidx << 6; + rt2800_register_multiwrite(rt2x00dev, offset, +- &iveiv_entry, sizeof(iveiv_entry)); ++ &iveiv_entry, sizeof(iveiv_entry)); + } + + int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, +@@ -6090,13 +6091,11 @@ static int rt2800_init_registers(struct + * ASIC will keep garbage value after boot, clear encryption keys. + */ + for (i = 0; i < 4; i++) +- rt2800_register_write(rt2x00dev, +- SHARED_KEY_MODE_ENTRY(i), 0); ++ rt2800_register_write(rt2x00dev, SHARED_KEY_MODE_ENTRY(i), 0); + + for (i = 0; i < 256; i++) { + rt2800_config_wcid(rt2x00dev, NULL, i); + rt2800_delete_wcid_attr(rt2x00dev, i); +- rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + } + + /* diff --git a/package/kernel/mac80211/patches/rt2x00/065-rt2x00-add-restart-hw.patch b/package/kernel/mac80211/patches/rt2x00/065-rt2x00-add-restart-hw.patch new file mode 100644 index 000000000..225aed16c --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/065-rt2x00-add-restart-hw.patch @@ -0,0 +1,151 @@ +From e403fa31ed71e87de8e5991e23406b8377c9c894 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Sat, 15 Jun 2019 12:00:59 +0200 +Subject: [PATCH 06/15] rt2x00: add restart hw + +Add ieee80211_restart_hw() to watchdog and debugfs file for testing +if restart works as expected. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 4 +++ + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 7 ++++ + .../net/wireless/ralink/rt2x00/rt2x00debug.c | 35 +++++++++++++++++++ + .../net/wireless/ralink/rt2x00/rt2x00dev.c | 10 ++++-- + 4 files changed, 54 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -1274,6 +1274,9 @@ void rt2800_watchdog(struct rt2x00_dev * + + if (hung_rx) + rt2x00_warn(rt2x00dev, "Watchdog RX hung detected\n"); ++ ++ if (hung_tx || hung_rx) ++ ieee80211_restart_hw(rt2x00dev->hw); + } + EXPORT_SYMBOL_GPL(rt2800_watchdog); + +@@ -10294,6 +10297,7 @@ int rt2800_probe_hw(struct rt2x00_dev *r + __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); + } + ++ __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags); + rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100); + + /* +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -723,6 +723,7 @@ enum rt2x00_capability_flags { + CAPABILITY_VCO_RECALIBRATION, + CAPABILITY_EXTERNAL_PA_TX0, + CAPABILITY_EXTERNAL_PA_TX1, ++ CAPABILITY_RESTART_HW, + }; + + /* +@@ -1279,6 +1280,12 @@ rt2x00_has_cap_vco_recalibration(struct + return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION); + } + ++static inline bool ++rt2x00_has_cap_restart_hw(struct rt2x00_dev *rt2x00dev) ++{ ++ return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RESTART_HW); ++} ++ + /** + * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. + * @entry: Pointer to &struct queue_entry +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +@@ -63,6 +63,7 @@ struct rt2x00debug_intf { + * - chipset file + * - device state flags file + * - device capability flags file ++ * - hardware restart file + * - register folder + * - csr offset/value files + * - eeprom offset/value files +@@ -79,6 +80,7 @@ struct rt2x00debug_intf { + struct dentry *chipset_entry; + struct dentry *dev_flags; + struct dentry *cap_flags; ++ struct dentry *restart_hw; + struct dentry *register_folder; + struct dentry *csr_off_entry; + struct dentry *csr_val_entry; +@@ -577,6 +579,34 @@ static const struct file_operations rt2x + .llseek = default_llseek, + }; + ++static ssize_t rt2x00debug_write_restart_hw(struct file *file, ++ const char __user *buf, ++ size_t length, ++ loff_t *offset) ++{ ++ struct rt2x00debug_intf *intf = file->private_data; ++ struct rt2x00_dev *rt2x00dev = intf->rt2x00dev; ++ static unsigned long last_reset; ++ ++ if (!rt2x00_has_cap_restart_hw(rt2x00dev)) ++ return -EOPNOTSUPP; ++ ++ if (time_before(jiffies, last_reset + msecs_to_jiffies(2000))) ++ return -EBUSY; ++ ++ last_reset = jiffies; ++ ++ ieee80211_restart_hw(rt2x00dev->hw); ++ return length; ++} ++ ++static const struct file_operations rt2x00debug_restart_hw = { ++ .owner = THIS_MODULE, ++ .write = rt2x00debug_write_restart_hw, ++ .open = simple_open, ++ .llseek = generic_file_llseek, ++}; ++ + static struct dentry *rt2x00debug_create_file_driver(const char *name, + struct rt2x00debug_intf + *intf, +@@ -672,6 +702,10 @@ void rt2x00debug_register(struct rt2x00_ + intf->driver_folder, intf, + &rt2x00debug_fop_cap_flags); + ++ intf->restart_hw = debugfs_create_file("restart_hw", 0200, ++ intf->driver_folder, intf, ++ &rt2x00debug_restart_hw); ++ + intf->register_folder = + debugfs_create_dir("register", intf->driver_folder); + +@@ -753,6 +787,7 @@ void rt2x00debug_deregister(struct rt2x0 + debugfs_remove(intf->csr_off_entry); + debugfs_remove(intf->register_folder); + debugfs_remove(intf->dev_flags); ++ debugfs_remove(intf->restart_hw); + debugfs_remove(intf->cap_flags); + debugfs_remove(intf->chipset_entry); + debugfs_remove(intf->driver_entry); +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1269,8 +1269,14 @@ int rt2x00lib_start(struct rt2x00_dev *r + { + int retval; + +- if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) +- return 0; ++ if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) { ++ /* ++ * This is special case for ieee80211_restart_hw(), otherwise ++ * mac80211 never call start() two times in row without stop(); ++ */ ++ rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev); ++ rt2x00lib_stop(rt2x00dev); ++ } + + /* + * If this is the first interface which is added, diff --git a/package/kernel/mac80211/patches/rt2x00/066-rt2800-do-not-enable-watchdog-by-default.patch b/package/kernel/mac80211/patches/rt2x00/066-rt2800-do-not-enable-watchdog-by-default.patch new file mode 100644 index 000000000..37e03dbb5 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/066-rt2800-do-not-enable-watchdog-by-default.patch @@ -0,0 +1,71 @@ +From 0f47aeeada2a1fe296258eab9a08ced258009481 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Sat, 15 Jun 2019 12:01:00 +0200 +Subject: [PATCH 07/15] rt2800: do not enable watchdog by default + +Make watchdog disabled by default and add module parameter to enable it. + +User will have to create file in /etc/modprobe.d/ with + +options rt2800lib watchdog=1 + +to enable the watchdog or load "rt2800lib watchdog=1" module manually +before loading rt2800{soc,pci,usb} module. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 12 ++++++++++-- + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + + drivers/net/wireless/ralink/rt2x00/rt2x00link.c | 2 +- + 3 files changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -41,6 +41,10 @@ + #include "rt2800lib.h" + #include "rt2800.h" + ++static bool modparam_watchdog; ++module_param_named(watchdog, modparam_watchdog, bool, S_IRUGO); ++MODULE_PARM_DESC(watchdog, "Enable watchdog to detect tx/rx hangs and reset hardware if detected"); ++ + /* + * Register access. + * All access to the CSR registers will go through the methods +@@ -10297,8 +10301,12 @@ int rt2800_probe_hw(struct rt2x00_dev *r + __set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); + } + +- __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags); +- rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100); ++ if (modparam_watchdog) { ++ __set_bit(CAPABILITY_RESTART_HW, &rt2x00dev->cap_flags); ++ rt2x00dev->link.watchdog_interval = msecs_to_jiffies(100); ++ } else { ++ rt2x00dev->link.watchdog_disabled = true; ++ } + + /* + * Set the rssi offset. +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -337,6 +337,7 @@ struct link { + */ + struct delayed_work watchdog_work; + unsigned int watchdog_interval; ++ bool watchdog_disabled; + + /* + * Work structure for scheduling periodic AGC adjustments. +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00link.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00link.c +@@ -395,7 +395,7 @@ void rt2x00link_start_watchdog(struct rt + struct link *link = &rt2x00dev->link; + + if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && +- rt2x00dev->ops->lib->watchdog) ++ rt2x00dev->ops->lib->watchdog && !link->watchdog_disabled) + ieee80211_queue_delayed_work(rt2x00dev->hw, + &link->watchdog_work, + link->watchdog_interval); diff --git a/package/kernel/mac80211/patches/rt2x00/067-rt2x00usb-fix-rx-queue-hang.patch b/package/kernel/mac80211/patches/rt2x00/067-rt2x00usb-fix-rx-queue-hang.patch new file mode 100644 index 000000000..62505cd53 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/067-rt2x00usb-fix-rx-queue-hang.patch @@ -0,0 +1,67 @@ +From 41a531ffa4c5aeb062f892227c00fabb3b4a9c91 Mon Sep 17 00:00:00 2001 +From: Soeren Moch +Date: Mon, 1 Jul 2019 12:53:13 +0200 +Subject: [PATCH 08/15] rt2x00usb: fix rx queue hang + +Since commit ed194d136769 ("usb: core: remove local_irq_save() around + ->complete() handler") the handler rt2x00usb_interrupt_rxdone() is +not running with interrupts disabled anymore. So this completion handler +is not guaranteed to run completely before workqueue processing starts +for the same queue entry. +Be sure to set all other flags in the entry correctly before marking +this entry ready for workqueue processing. This way we cannot miss error +conditions that need to be signalled from the completion handler to the +worker thread. +Note that rt2x00usb_work_rxdone() processes all available entries, not +only such for which queue_work() was called. + +This patch is similar to what commit df71c9cfceea ("rt2x00: fix order +of entry flags modification") did for TX processing. + +This fixes a regression on a RT5370 based wifi stick in AP mode, which +suddenly stopped data transmission after some period of heavy load. Also +stopping the hanging hostapd resulted in the error message "ieee80211 +phy0: rt2x00queue_flush_queue: Warning - Queue 14 failed to flush". +Other operation modes are probably affected as well, this just was +the used testcase. + +Fixes: ed194d136769 ("usb: core: remove local_irq_save() around ->complete() handler") +Cc: stable@vger.kernel.org # 4.20+ +Signed-off-by: Soeren Moch +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +@@ -383,15 +383,10 @@ static void rt2x00usb_interrupt_rxdone(s + struct queue_entry *entry = (struct queue_entry *)urb->context; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + +- if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) ++ if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + return; + + /* +- * Report the frame as DMA done +- */ +- rt2x00lib_dmadone(entry); +- +- /* + * Check if the received data is simply too small + * to be actually valid, or if the urb is signaling + * a problem. +@@ -400,6 +395,11 @@ static void rt2x00usb_interrupt_rxdone(s + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + + /* ++ * Report the frame as DMA done ++ */ ++ rt2x00lib_dmadone(entry); ++ ++ /* + * Schedule the delayed work for reading the RX status + * from the device. + */ diff --git a/package/kernel/mac80211/patches/rt2x00/068-rt2x00usb-remove-unnecessary-rx-flag-checks.patch b/package/kernel/mac80211/patches/rt2x00/068-rt2x00usb-remove-unnecessary-rx-flag-checks.patch new file mode 100644 index 000000000..3fa5ee6d3 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/068-rt2x00usb-remove-unnecessary-rx-flag-checks.patch @@ -0,0 +1,51 @@ +From 3b902fa811cf6bf7f9ad0ffb77d0a133e0b3bd61 Mon Sep 17 00:00:00 2001 +From: Soeren Moch +Date: Mon, 1 Jul 2019 12:53:14 +0200 +Subject: [PATCH 09/15] rt2x00usb: remove unnecessary rx flag checks + +In contrast to the TX path, there is no need to separately read the transfer +status from the device after receiving RX data. Consequently, there is no +real STATUS_PENDING RX processing queue entry state. +Remove the unnecessary ENTRY_DATA_STATUS_PENDING flag checks from the RX path. +Also remove the misleading comment about reading RX status from device. + +Suggested-by: Stanislaw Gruszka +Signed-off-by: Soeren Moch +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c +@@ -360,8 +360,7 @@ static void rt2x00usb_work_rxdone(struct + while (!rt2x00queue_empty(rt2x00dev->rx)) { + entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); + +- if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || +- !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) ++ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + break; + + /* +@@ -400,8 +399,7 @@ static void rt2x00usb_interrupt_rxdone(s + rt2x00lib_dmadone(entry); + + /* +- * Schedule the delayed work for reading the RX status +- * from the device. ++ * Schedule the delayed work for processing RX data + */ + queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); + } +@@ -413,8 +411,7 @@ static bool rt2x00usb_kick_rx_entry(stru + struct queue_entry_priv_usb *entry_priv = entry->priv_data; + int status; + +- if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || +- test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) ++ if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + return false; + + rt2x00lib_dmastart(entry); diff --git a/package/kernel/mac80211/patches/rt2x00/069-rt2x00-no-need-to-check-return-value-of-debugfs_crea.patch b/package/kernel/mac80211/patches/rt2x00/069-rt2x00-no-need-to-check-return-value-of-debugfs_crea.patch new file mode 100644 index 000000000..d83f9b46c --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/069-rt2x00-no-need-to-check-return-value-of-debugfs_crea.patch @@ -0,0 +1,248 @@ +From 1dc244064c47d6df7925ca0895f8365e68d3abd1 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Wed, 3 Jul 2019 13:39:56 +0200 +Subject: [PATCH 10/15] rt2x00: no need to check return value of debugfs_create + functions + +When calling debugfs functions, there is no need to ever check the +return value. The function can work or not, but the code logic should +never do something different based on this. + +Because we don't need to save the individual debugfs files and +directories, remove the local storage of them and just remove the entire +debugfs directory in a single call, making things a lot simpler. + +Cc: Stanislaw Gruszka +Cc: Helmut Schaa +Cc: Kalle Valo +Cc: "David S. Miller" +Cc: linux-wireless@vger.kernel.org +Cc: netdev@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + .../net/wireless/ralink/rt2x00/rt2x00debug.c | 136 +++++------------- + 1 file changed, 35 insertions(+), 101 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +@@ -76,26 +76,6 @@ struct rt2x00debug_intf { + * - crypto stats file + */ + struct dentry *driver_folder; +- struct dentry *driver_entry; +- struct dentry *chipset_entry; +- struct dentry *dev_flags; +- struct dentry *cap_flags; +- struct dentry *restart_hw; +- struct dentry *register_folder; +- struct dentry *csr_off_entry; +- struct dentry *csr_val_entry; +- struct dentry *eeprom_off_entry; +- struct dentry *eeprom_val_entry; +- struct dentry *bbp_off_entry; +- struct dentry *bbp_val_entry; +- struct dentry *rf_off_entry; +- struct dentry *rf_val_entry; +- struct dentry *rfcsr_off_entry; +- struct dentry *rfcsr_val_entry; +- struct dentry *queue_folder; +- struct dentry *queue_frame_dump_entry; +- struct dentry *queue_stats_entry; +- struct dentry *crypto_stats_entry; + + /* + * The frame dump file only allows a single reader, +@@ -607,39 +587,34 @@ static const struct file_operations rt2x + .llseek = generic_file_llseek, + }; + +-static struct dentry *rt2x00debug_create_file_driver(const char *name, +- struct rt2x00debug_intf +- *intf, +- struct debugfs_blob_wrapper +- *blob) ++static void rt2x00debug_create_file_driver(const char *name, ++ struct rt2x00debug_intf *intf, ++ struct debugfs_blob_wrapper *blob) + { + char *data; + + data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL); + if (!data) +- return NULL; ++ return; + + blob->data = data; + data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name); + data += sprintf(data, "version:\t%s\n", DRV_VERSION); + blob->size = strlen(blob->data); + +- return debugfs_create_blob(name, 0400, intf->driver_folder, blob); ++ debugfs_create_blob(name, 0400, intf->driver_folder, blob); + } + +-static struct dentry *rt2x00debug_create_file_chipset(const char *name, +- struct rt2x00debug_intf +- *intf, +- struct +- debugfs_blob_wrapper +- *blob) ++static void rt2x00debug_create_file_chipset(const char *name, ++ struct rt2x00debug_intf *intf, ++ struct debugfs_blob_wrapper *blob) + { + const struct rt2x00debug *debug = intf->debug; + char *data; + + data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL); + if (!data) +- return NULL; ++ return; + + blob->data = data; + data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); +@@ -665,13 +640,15 @@ static struct dentry *rt2x00debug_create + + blob->size = strlen(blob->data); + +- return debugfs_create_blob(name, 0400, intf->driver_folder, blob); ++ debugfs_create_blob(name, 0400, intf->driver_folder, blob); + } + + void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) + { + const struct rt2x00debug *debug = rt2x00dev->ops->debugfs; + struct rt2x00debug_intf *intf; ++ struct dentry *queue_folder; ++ struct dentry *register_folder; + + intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL); + if (!intf) { +@@ -687,43 +664,27 @@ void rt2x00debug_register(struct rt2x00_ + debugfs_create_dir(intf->rt2x00dev->ops->name, + rt2x00dev->hw->wiphy->debugfsdir); + +- intf->driver_entry = +- rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob); +- +- intf->chipset_entry = +- rt2x00debug_create_file_chipset("chipset", +- intf, &intf->chipset_blob); +- +- intf->dev_flags = debugfs_create_file("dev_flags", 0400, +- intf->driver_folder, intf, +- &rt2x00debug_fop_dev_flags); +- +- intf->cap_flags = debugfs_create_file("cap_flags", 0400, +- intf->driver_folder, intf, +- &rt2x00debug_fop_cap_flags); +- +- intf->restart_hw = debugfs_create_file("restart_hw", 0200, +- intf->driver_folder, intf, +- &rt2x00debug_restart_hw); ++ rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob); ++ rt2x00debug_create_file_chipset("chipset", intf, &intf->chipset_blob); ++ debugfs_create_file("dev_flags", 0400, intf->driver_folder, intf, ++ &rt2x00debug_fop_dev_flags); ++ debugfs_create_file("cap_flags", 0400, intf->driver_folder, intf, ++ &rt2x00debug_fop_cap_flags); ++ debugfs_create_file("restart_hw", 0200, intf->driver_folder, intf, ++ &rt2x00debug_restart_hw); + +- intf->register_folder = +- debugfs_create_dir("register", intf->driver_folder); ++ register_folder = debugfs_create_dir("register", intf->driver_folder); + + #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ + ({ \ + if (debug->__name.read) { \ +- (__intf)->__name##_off_entry = \ +- debugfs_create_u32(__stringify(__name) "_offset", \ +- 0600, \ +- (__intf)->register_folder, \ +- &(__intf)->offset_##__name); \ ++ debugfs_create_u32(__stringify(__name) "_offset", 0600, \ ++ register_folder, \ ++ &(__intf)->offset_##__name); \ + \ +- (__intf)->__name##_val_entry = \ +- debugfs_create_file(__stringify(__name) "_value", \ +- 0600, \ +- (__intf)->register_folder, \ +- (__intf), \ +- &rt2x00debug_fop_##__name); \ ++ debugfs_create_file(__stringify(__name) "_value", 0600, \ ++ register_folder, (__intf), \ ++ &rt2x00debug_fop_##__name); \ + } \ + }) + +@@ -735,26 +696,21 @@ void rt2x00debug_register(struct rt2x00_ + + #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY + +- intf->queue_folder = +- debugfs_create_dir("queue", intf->driver_folder); ++ queue_folder = debugfs_create_dir("queue", intf->driver_folder); + +- intf->queue_frame_dump_entry = +- debugfs_create_file("dump", 0400, intf->queue_folder, +- intf, &rt2x00debug_fop_queue_dump); ++ debugfs_create_file("dump", 0400, queue_folder, intf, ++ &rt2x00debug_fop_queue_dump); + + skb_queue_head_init(&intf->frame_dump_skbqueue); + init_waitqueue_head(&intf->frame_dump_waitqueue); + +- intf->queue_stats_entry = +- debugfs_create_file("queue", 0400, intf->queue_folder, +- intf, &rt2x00debug_fop_queue_stats); ++ debugfs_create_file("queue", 0400, queue_folder, intf, ++ &rt2x00debug_fop_queue_stats); + + #ifdef CPTCFG_RT2X00_LIB_CRYPTO + if (rt2x00_has_cap_hw_crypto(rt2x00dev)) +- intf->crypto_stats_entry = +- debugfs_create_file("crypto", 0444, intf->queue_folder, +- intf, +- &rt2x00debug_fop_crypto_stats); ++ debugfs_create_file("crypto", 0444, queue_folder, intf, ++ &rt2x00debug_fop_crypto_stats); + #endif + + return; +@@ -769,31 +725,7 @@ void rt2x00debug_deregister(struct rt2x0 + + skb_queue_purge(&intf->frame_dump_skbqueue); + +-#ifdef CPTCFG_RT2X00_LIB_CRYPTO +- debugfs_remove(intf->crypto_stats_entry); +-#endif +- debugfs_remove(intf->queue_stats_entry); +- debugfs_remove(intf->queue_frame_dump_entry); +- debugfs_remove(intf->queue_folder); +- debugfs_remove(intf->rfcsr_val_entry); +- debugfs_remove(intf->rfcsr_off_entry); +- debugfs_remove(intf->rf_val_entry); +- debugfs_remove(intf->rf_off_entry); +- debugfs_remove(intf->bbp_val_entry); +- debugfs_remove(intf->bbp_off_entry); +- debugfs_remove(intf->eeprom_val_entry); +- debugfs_remove(intf->eeprom_off_entry); +- debugfs_remove(intf->csr_val_entry); +- debugfs_remove(intf->csr_off_entry); +- debugfs_remove(intf->register_folder); +- debugfs_remove(intf->dev_flags); +- debugfs_remove(intf->restart_hw); +- debugfs_remove(intf->cap_flags); +- debugfs_remove(intf->chipset_entry); +- debugfs_remove(intf->driver_entry); +- debugfs_remove(intf->driver_folder); +- kfree(intf->chipset_blob.data); +- kfree(intf->driver_blob.data); ++ debugfs_remove_recursive(intf->driver_folder); + kfree(intf); + + rt2x00dev->debugfs_intf = NULL; diff --git a/package/kernel/mac80211/patches/rt2x00/070-rt2800usb-Add-new-rt2800usb-device-PLANEX-GW-USMicro.patch b/package/kernel/mac80211/patches/rt2x00/070-rt2800usb-Add-new-rt2800usb-device-PLANEX-GW-USMicro.patch new file mode 100644 index 000000000..29fb43541 --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/070-rt2800usb-Add-new-rt2800usb-device-PLANEX-GW-USMicro.patch @@ -0,0 +1,29 @@ +From 706f0182b1add0fc41a8c40662f659b7426f0629 Mon Sep 17 00:00:00 2001 +From: Masanari Iida +Date: Sun, 28 Jul 2019 23:07:42 +0900 +Subject: [PATCH 11/15] rt2800usb: Add new rt2800usb device PLANEX GW-USMicroN + +This patch add a device ID for PLANEX GW-USMicroN. +Without this patch, I had to echo the device IDs in order to +recognize the device. + +# lsusb |grep PLANEX +Bus 002 Device 005: ID 2019:ed14 PLANEX GW-USMicroN + +Signed-off-by: Masanari Iida +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2800usb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800usb.c +@@ -1097,6 +1097,7 @@ static const struct usb_device_id rt2800 + { USB_DEVICE(0x0846, 0x9013) }, + { USB_DEVICE(0x0846, 0x9019) }, + /* Planex */ ++ { USB_DEVICE(0x2019, 0xed14) }, + { USB_DEVICE(0x2019, 0xed19) }, + /* Ralink */ + { USB_DEVICE(0x148f, 0x3573) }, diff --git a/package/kernel/mac80211/patches/rt2x00/071-rt2x00-clear-IV-s-on-start-to-fix-AP-mode-regression.patch b/package/kernel/mac80211/patches/rt2x00/071-rt2x00-clear-IV-s-on-start-to-fix-AP-mode-regression.patch new file mode 100644 index 000000000..917204f9c --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/071-rt2x00-clear-IV-s-on-start-to-fix-AP-mode-regression.patch @@ -0,0 +1,102 @@ +From 95844124385eae4bd9ca5f9514a0fc33d561ac3c Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Mon, 19 Aug 2019 13:20:07 +0200 +Subject: [PATCH 12/15] rt2x00: clear IV's on start to fix AP mode regression + +To do not brake HW restart we should keep initialization vectors data. +I assumed that on start the data is already initialized to zeros, but +that not true on some scenarios and we should clear it. So add +additional flag to check if we are under HW restart and clear IV's +data if we are not. + +Patch fixes AP mode regression. + +Reported-and-tested-by: Emil Karlson +Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data") +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 +++++++++ + drivers/net/wireless/ralink/rt2x00/rt2x00.h | 1 + + drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 13 ++++++++----- + 3 files changed, 18 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -6106,6 +6106,15 @@ static int rt2800_init_registers(struct + } + + /* ++ * Clear encryption initialization vectors on start, but keep them ++ * for watchdog reset. Otherwise we will have wrong IVs and not be ++ * able to keep connections after reset. ++ */ ++ if (!test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags)) ++ for (i = 0; i < 256; i++) ++ rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); ++ ++ /* + * Clear all beacons + */ + for (i = 0; i < 8; i++) +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h +@@ -669,6 +669,7 @@ enum rt2x00_state_flags { + DEVICE_STATE_ENABLED_RADIO, + DEVICE_STATE_SCANNING, + DEVICE_STATE_FLUSHING, ++ DEVICE_STATE_RESET, + + /* + * Driver configuration +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1267,13 +1267,14 @@ static int rt2x00lib_initialize(struct r + + int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) + { +- int retval; ++ int retval = 0; + + if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) { + /* + * This is special case for ieee80211_restart_hw(), otherwise + * mac80211 never call start() two times in row without stop(); + */ ++ set_bit(DEVICE_STATE_RESET, &rt2x00dev->flags); + rt2x00dev->ops->lib->pre_reset_hw(rt2x00dev); + rt2x00lib_stop(rt2x00dev); + } +@@ -1284,14 +1285,14 @@ int rt2x00lib_start(struct rt2x00_dev *r + */ + retval = rt2x00lib_load_firmware(rt2x00dev); + if (retval) +- return retval; ++ goto out; + + /* + * Initialize the device. + */ + retval = rt2x00lib_initialize(rt2x00dev); + if (retval) +- return retval; ++ goto out; + + rt2x00dev->intf_ap_count = 0; + rt2x00dev->intf_sta_count = 0; +@@ -1300,11 +1301,13 @@ int rt2x00lib_start(struct rt2x00_dev *r + /* Enable the radio */ + retval = rt2x00lib_enable_radio(rt2x00dev); + if (retval) +- return retval; ++ goto out; + + set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags); + +- return 0; ++out: ++ clear_bit(DEVICE_STATE_RESET, &rt2x00dev->flags); ++ return retval; + } + + void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) diff --git a/package/kernel/mac80211/patches/rt2x00/072-rt2x00-do-not-set-IEEE80211_TX_STAT_AMPDU_NO_BACK-on.patch b/package/kernel/mac80211/patches/rt2x00/072-rt2x00-do-not-set-IEEE80211_TX_STAT_AMPDU_NO_BACK-on.patch new file mode 100644 index 000000000..22c952d8d --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/072-rt2x00-do-not-set-IEEE80211_TX_STAT_AMPDU_NO_BACK-on.patch @@ -0,0 +1,40 @@ +From 567a9b766b47caffe4b1bf74823e7bc18532d875 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Fri, 23 Aug 2019 09:09:56 +0200 +Subject: [PATCH 13/15] rt2x00: do not set IEEE80211_TX_STAT_AMPDU_NO_BACK on + tx status + +According to documentation IEEE80211_TX_STAT_AMPDU_NO_BACK is suppose +to be used when we do not recive BA (BlockAck). However on rt2x00 we +use it when remote station fail to decode one or more subframes within +AMPDU (some bits are not set in BlockAck bitmap). Setting the flag result +in sent of BAR (BlockAck Request) frame and this might result of abuse +of BA session, since remote station can sent BA with incorrect +sequence numbers after receiving BAR. This problem is visible especially +when connecting two rt2800 devices. + +Previously I observed some performance benefits when using the flag +when connecting with iwlwifi devices. But currently possibly due +to reacent changes in rt2x00 removing the flag has no effect on +those test cases. + +So remove the IEEE80211_TX_STAT_AMPDU_NO_BACK. + +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -382,9 +382,6 @@ static void rt2x00lib_fill_tx_status(str + IEEE80211_TX_CTL_AMPDU; + tx_info->status.ampdu_len = 1; + tx_info->status.ampdu_ack_len = success ? 1 : 0; +- +- if (!success) +- tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + } + + if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { diff --git a/package/kernel/mac80211/patches/rt2x00/073-rt2x00-clear-up-IV-s-on-key-removal.patch b/package/kernel/mac80211/patches/rt2x00/073-rt2x00-clear-up-IV-s-on-key-removal.patch new file mode 100644 index 000000000..de445221b --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/073-rt2x00-clear-up-IV-s-on-key-removal.patch @@ -0,0 +1,46 @@ +From 14d5e14c8a6c257eb322ddeb294ac4c243a7d2e1 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Fri, 23 Aug 2019 14:48:03 +0200 +Subject: [PATCH 14/15] rt2x00: clear up IV's on key removal + +After looking at code I realized that my previous fix +95844124385e ("rt2x00: clear IV's on start to fix AP mode regression") +was incomplete. We can still have wrong IV's after re-keyring. +To fix that, clear up IV's also on key removal. + +Fixes: 710e6cc1595e ("rt2800: do not nullify initialization vector data") +Signed-off-by: Stanislaw Gruszka +tested-by: Emil Karlson +Signed-off-by: Kalle Valo +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -1665,13 +1665,18 @@ static void rt2800_config_wcid_attr_ciph + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + +- rt2800_register_multiread(rt2x00dev, offset, +- &iveiv_entry, sizeof(iveiv_entry)); +- if ((crypto->cipher == CIPHER_TKIP) || +- (crypto->cipher == CIPHER_TKIP_NO_MIC) || +- (crypto->cipher == CIPHER_AES)) +- iveiv_entry.iv[3] |= 0x20; +- iveiv_entry.iv[3] |= key->keyidx << 6; ++ if (crypto->cmd == SET_KEY) { ++ rt2800_register_multiread(rt2x00dev, offset, ++ &iveiv_entry, sizeof(iveiv_entry)); ++ if ((crypto->cipher == CIPHER_TKIP) || ++ (crypto->cipher == CIPHER_TKIP_NO_MIC) || ++ (crypto->cipher == CIPHER_AES)) ++ iveiv_entry.iv[3] |= 0x20; ++ iveiv_entry.iv[3] |= key->keyidx << 6; ++ } else { ++ memset(&iveiv_entry, 0, sizeof(iveiv_entry)); ++ } ++ + rt2800_register_multiwrite(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + } diff --git a/package/kernel/mac80211/patches/rt2x00/074-Revert-rt2800-enable-TX_PIN_CFG_LNA_PE_-bits-per-ban.patch b/package/kernel/mac80211/patches/rt2x00/074-Revert-rt2800-enable-TX_PIN_CFG_LNA_PE_-bits-per-ban.patch new file mode 100644 index 000000000..c57fe67cc --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/074-Revert-rt2800-enable-TX_PIN_CFG_LNA_PE_-bits-per-ban.patch @@ -0,0 +1,61 @@ +From 13fa451568ab9e8b3074ef741477c7938c713c42 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Thu, 29 Aug 2019 13:29:59 +0200 +Subject: [PATCH 15/15] Revert "rt2800: enable TX_PIN_CFG_LNA_PE_ bits per + band" + +This reverts commit 9ad3b55654455258a9463384edb40077439d879f. + +As reported by Sergey: + +"I got some problem after upgrade kernel to 5.2 version (debian testing +linux-image-5.2.0-2-amd64). 5Ghz client stopped to see AP. +Some tests with 1metre distance between client-AP: 2.4Ghz -22dBm, for +5Ghz - 53dBm !, for longer distance (8m + walls) 2.4 - 61dBm, 5Ghz not +visible." + +It was identified that rx signal level degradation was caused by +9ad3b5565445 ("rt2800: enable TX_PIN_CFG_LNA_PE_ bits per band"). +So revert this commit. + +Cc: # v5.1+ +Reported-and-tested-by: Sergey Maranchuk +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -4253,24 +4253,18 @@ static void rt2800_config_channel(struct + switch (rt2x00dev->default_ant.rx_chain_num) { + case 3: + /* Turn on tertiary LNAs */ +- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, +- rf->channel > 14); +- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, +- rf->channel <= 14); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1); + /* fall-through */ + case 2: + /* Turn on secondary LNAs */ +- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, +- rf->channel > 14); +- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, +- rf->channel <= 14); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); + /* fall-through */ + case 1: + /* Turn on primary LNAs */ +- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, +- rf->channel > 14); +- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, +- rf->channel <= 14); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); + break; + } + diff --git a/package/kernel/mac80211/patches/rt2x00/075-rt2800-remove-errornous-duplicate-condition.patch b/package/kernel/mac80211/patches/rt2x00/075-rt2800-remove-errornous-duplicate-condition.patch new file mode 100644 index 000000000..caa8f809d --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/075-rt2800-remove-errornous-duplicate-condition.patch @@ -0,0 +1,88 @@ +From patchwork Sat Nov 2 17:47:01 2019 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Daniel Golle +X-Patchwork-Id: 11224189 +X-Patchwork-Delegate: kvalo@adurom.com +Return-Path: +Date: Sat, 2 Nov 2019 18:47:01 +0100 +From: Daniel Golle +To: Stanislaw Gruszka +Cc: linux-wireless@vger.kernel.org, Roman Yeryomin , + wbob +Subject: [PATCH v2] rt2800: remove errornous duplicate condition +Message-ID: <20191102174701.GA1489@makrotopia.org> +References: <20191102154639.GA4589@redhat.com> +MIME-Version: 1.0 +Content-Disposition: inline +In-Reply-To: <20191102154639.GA4589@redhat.com> +User-Agent: Mutt/1.12.2 (2019-09-21) +Sender: linux-wireless-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: linux-wireless@vger.kernel.org + +On 2019-10-28 06:07, wbob wrote: +> Hello Roman, +> +> while reading around drivers/net/wireless/ralink/rt2x00/rt2800lib.c +> I stumbled on what I think is an edit of yours made in error in march +> 2017: +> +> https://github.com/torvalds/linux/commit/41977e86#diff-dae5dc10da180f3b055809a48118e18aR5281 +> +> RT6352 in line 5281 should not have been introduced as the "else if" +> below line 5291 can then not take effect for a RT6352 device. Another +> possibility is for line 5291 to be not for RT6352, but this seems +> very unlikely. Are you able to clarify still after this substantial time? +> +> 5277: static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) +> ... +> 5279: } else if (rt2x00_rt(rt2x00dev, RT5390) || +> 5280: rt2x00_rt(rt2x00dev, RT5392) || +> 5281: rt2x00_rt(rt2x00dev, RT6352)) { +> ... +> 5291: } else if (rt2x00_rt(rt2x00dev, RT6352)) { +> ... + +Hence remove errornous line 5281 to make the driver actually +execute the correct initialization routine for MT7620 chips. + +As it was requested by Stanislaw Gruszka remove setting values of +MIMO_PS_CFG and TX_PIN_CFG. MIMO_PS_CFG is responsible for MIMO +power-safe mode (which is disabled), hence we can drop setting it. +TX_PIN_CFG is set correctly in other functions, and as setting this +value breaks some devices, rather don't set it here during init, but +only modify it later on. + +Fixes: 41977e86c984 ("rt2x00: add support for MT7620") +Reported-by: wbob +Reported-by: Roman Yeryomin +Signed-off-by: Daniel Golle +Acked-by: Stanislaw Gruszka +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -5850,8 +5850,7 @@ static int rt2800_init_registers(struct + rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21); + rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40); + } else if (rt2x00_rt(rt2x00dev, RT5390) || +- rt2x00_rt(rt2x00dev, RT5392) || +- rt2x00_rt(rt2x00dev, RT6352)) { ++ rt2x00_rt(rt2x00dev, RT5392)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +@@ -5865,8 +5864,6 @@ static int rt2800_init_registers(struct + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0000); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +- rt2800_register_write(rt2x00dev, MIMO_PS_CFG, 0x00000002); +- rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x00150F0F); + rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000); + rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0); + rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0); diff --git a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch index 697d8188f..4890a1436 100644 --- a/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch +++ b/package/kernel/mac80211/patches/rt2x00/602-rt2x00-introduce-rt2x00eeprom.patch @@ -57,7 +57,7 @@ struct rt2800_ops { u32 (*register_read)(struct rt2x00_dev *rt2x00dev, const unsigned int offset); -@@ -145,6 +147,15 @@ static inline int rt2800_read_eeprom(str +@@ -146,6 +148,15 @@ static inline int rt2800_read_eeprom(str { const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; @@ -105,7 +105,7 @@ .drv_init_registers = rt2800mmio_init_registers, --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -702,6 +702,7 @@ enum rt2x00_capability_flags { +@@ -706,6 +706,7 @@ enum rt2x00_capability_flags { REQUIRE_HT_TX_DESC, REQUIRE_PS_AUTOWAKE, REQUIRE_DELAYED_RFKILL, @@ -113,7 +113,7 @@ /* * Capabilities -@@ -977,6 +978,11 @@ struct rt2x00_dev { +@@ -982,6 +983,11 @@ struct rt2x00_dev { const struct firmware *fw; /* @@ -127,7 +127,7 @@ DECLARE_KFIFO_PTR(txstatus_fifo, u32); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1423,6 +1423,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de +@@ -1429,6 +1429,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep); @@ -138,7 +138,7 @@ /* * Let the driver probe the device to detect the capabilities. */ -@@ -1566,6 +1570,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ +@@ -1572,6 +1576,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ * Free the driver data. */ kfree(rt2x00dev->drv_data); diff --git a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch index 202dfc0b8..7387872b9 100644 --- a/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch +++ b/package/kernel/mac80211/patches/rt2x00/606-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -12,7 +12,7 @@ #endif /* _RT2X00_PLATFORM_H */ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1026,6 +1026,22 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1023,6 +1023,22 @@ static int rt2x00lib_probe_hw_modes(stru unsigned int num_rates; unsigned int i; @@ -37,7 +37,7 @@ num_rates += 4; --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -409,6 +409,7 @@ struct hw_mode_spec { +@@ -411,6 +411,7 @@ struct hw_mode_spec { unsigned int supported_bands; #define SUPPORT_BAND_2GHZ 0x00000001 #define SUPPORT_BAND_5GHZ 0x00000002 diff --git a/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch index b8b018804..bca7be853 100644 --- a/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch +++ b/package/kernel/mac80211/patches/rt2x00/607-rt2x00-add_platform_data_mac_addr.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1004,8 +1004,13 @@ static void rt2x00lib_rate(struct ieee80 +@@ -1001,8 +1001,13 @@ static void rt2x00lib_rate(struct ieee80 void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) { diff --git a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch index ca66aa8e3..724e626ca 100644 --- a/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch +++ b/package/kernel/mac80211/patches/rt2x00/608-rt2x00-allow_disabling_bands_through_dts.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1030,6 +1030,16 @@ static int rt2x00lib_probe_hw_modes(stru +@@ -1027,6 +1027,16 @@ static int rt2x00lib_probe_hw_modes(stru struct ieee80211_rate *rates; unsigned int num_rates; unsigned int i; diff --git a/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch index ed219c801..51bf548ad 100644 --- a/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch +++ b/package/kernel/mac80211/patches/rt2x00/609-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -13,7 +13,7 @@ Signed-off-by: John Crispin --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c -@@ -232,10 +232,17 @@ static int rt2800soc_probe(struct platfo +@@ -235,10 +235,17 @@ static int rt2800soc_probe(struct platfo return rt2x00soc_probe(pdev, &rt2800soc_ops); } diff --git a/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch index f0c079b62..88eedec14 100644 --- a/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch +++ b/package/kernel/mac80211/patches/rt2x00/610-rt2x00-change-led-polarity-from-OF.patch @@ -8,7 +8,7 @@ #include "rt2x00.h" #include "rt2800lib.h" -@@ -9458,6 +9459,17 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9542,6 +9543,17 @@ static int rt2800_init_eeprom(struct rt2 rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); diff --git a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch index 062b18a63..8e43bece8 100644 --- a/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch +++ b/package/kernel/mac80211/patches/rt2x00/611-rt2x00-add-AP+STA-support.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c -@@ -1361,7 +1361,7 @@ static inline void rt2x00lib_set_if_comb +@@ -1367,7 +1367,7 @@ static inline void rt2x00lib_set_if_comb */ if_limit = &rt2x00dev->if_limits_ap; if_limit->max = rt2x00dev->ops->max_ap_intf; diff --git a/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch b/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch index 2b6aa43c2..68d990ea5 100644 --- a/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch +++ b/package/kernel/mac80211/patches/rt2x00/650-rt2x00-add-support-for-external-PA-on-MT7620.patch @@ -30,7 +30,7 @@ Signed-off-by: Tomislav Po=C5=BEega * EEPROM LNA --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -4290,6 +4290,45 @@ static void rt2800_config_channel(struct +@@ -4370,6 +4370,45 @@ static void rt2800_config_channel(struct rt2800_iq_calibrate(rt2x00dev, rf->channel); } @@ -76,7 +76,7 @@ Signed-off-by: Tomislav Po=C5=BEega bbp = rt2800_bbp_read(rt2x00dev, 4); rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); rt2800_bbp_write(rt2x00dev, 4, bbp); -@@ -9487,7 +9526,8 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9571,7 +9610,8 @@ static int rt2800_init_eeprom(struct rt2 */ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1); @@ -86,7 +86,7 @@ Signed-off-by: Tomislav Po=C5=BEega if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352)) __set_bit(CAPABILITY_EXTERNAL_PA_TX0, -@@ -9498,6 +9538,18 @@ static int rt2800_init_eeprom(struct rt2 +@@ -9582,6 +9622,18 @@ static int rt2800_init_eeprom(struct rt2 &rt2x00dev->cap_flags); } diff --git a/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch b/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch index 454f55b1c..8a030e01f 100644 --- a/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/982-rt2x00-add-rf-self-txdc-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8349,6 +8349,58 @@ static void rt2800_init_rfcsr_5592(struc +@@ -8433,6 +8433,58 @@ static void rt2800_init_rfcsr_5592(struc rt2800_led_open_drain_enable(rt2x00dev); } @@ -59,7 +59,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -8956,6 +9008,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9040,6 +9092,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); @@ -69,7 +69,7 @@ } --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h -@@ -243,6 +243,7 @@ void rt2800_link_tuner(struct rt2x00_dev +@@ -253,6 +253,7 @@ void rt2800_link_tuner(struct rt2x00_dev const u32 count); void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev); @@ -79,7 +79,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -572,6 +572,7 @@ struct rt2x00lib_ops { +@@ -574,6 +574,7 @@ struct rt2x00lib_ops { struct link_qual *qual, const u32 count); void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); void (*vco_calibration) (struct rt2x00_dev *rt2x00dev); diff --git a/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch b/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch index 6f0d5b577..6c3a39626 100644 --- a/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/983-rt2x00-add-r-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8401,6 +8401,160 @@ void rt2800_rf_self_txdc_cal(struct rt2x +@@ -8485,6 +8485,160 @@ void rt2800_rf_self_txdc_cal(struct rt2x } EXPORT_SYMBOL_GPL(rt2800_rf_self_txdc_cal); @@ -161,7 +161,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9008,6 +9162,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9092,6 +9246,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); @@ -171,7 +171,7 @@ rt2800_bw_filter_calibration(rt2x00dev, false); --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h -@@ -244,6 +244,8 @@ void rt2800_link_tuner(struct rt2x00_dev +@@ -254,6 +254,8 @@ void rt2800_link_tuner(struct rt2x00_dev void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev); void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev); @@ -182,7 +182,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -573,6 +573,8 @@ struct rt2x00lib_ops { +@@ -575,6 +575,8 @@ struct rt2x00lib_ops { void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); void (*vco_calibration) (struct rt2x00_dev *rt2x00dev); void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev); diff --git a/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch b/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch index fbeace27d..a6df4f6de 100644 --- a/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/984-rt2x00-add-rxdcoc-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8555,6 +8555,71 @@ void rt2800_r_calibration(struct rt2x00_ +@@ -8639,6 +8639,71 @@ void rt2800_r_calibration(struct rt2x00_ } EXPORT_SYMBOL_GPL(rt2800_r_calibration); @@ -72,7 +72,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9164,6 +9229,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9248,6 +9313,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_r_calibration(rt2x00dev); rt2800_rf_self_txdc_cal(rt2x00dev); @@ -82,7 +82,7 @@ } --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h -@@ -246,6 +246,7 @@ void rt2800_vco_calibration(struct rt2x0 +@@ -256,6 +256,7 @@ void rt2800_vco_calibration(struct rt2x0 void rt2800_rf_self_txdc_cal(struct rt2x00_dev *rt2x00dev); int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2); void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev); @@ -92,7 +92,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -575,6 +575,7 @@ struct rt2x00lib_ops { +@@ -577,6 +577,7 @@ struct rt2x00lib_ops { void (*rf_self_txdc_cal) (struct rt2x00_dev *rt2x00dev); int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2); void (*r_calibration) (struct rt2x00_dev *rt2x00dev); diff --git a/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch b/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch index f469c4ebc..0a528a0e5 100644 --- a/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/985-rt2x00-add-rxiq-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -8620,6 +8620,386 @@ void rt2800_rxdcoc_calibration(struct rt +@@ -8704,6 +8704,386 @@ void rt2800_rxdcoc_calibration(struct rt } EXPORT_SYMBOL_GPL(rt2800_rxdcoc_calibration); @@ -387,7 +387,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9232,6 +9612,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9316,6 +9696,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rxdcoc_calibration(rt2x00dev); rt2800_bw_filter_calibration(rt2x00dev, true); rt2800_bw_filter_calibration(rt2x00dev, false); @@ -397,7 +397,7 @@ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h -@@ -247,6 +247,7 @@ void rt2800_rf_self_txdc_cal(struct rt2x +@@ -257,6 +257,7 @@ void rt2800_rf_self_txdc_cal(struct rt2x int rt2800_calcrcalibrationcode(struct rt2x00_dev *rt2x00dev, int d1, int d2); void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev); void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev); @@ -407,7 +407,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -576,6 +576,7 @@ struct rt2x00lib_ops { +@@ -578,6 +578,7 @@ struct rt2x00lib_ops { int (*calcrcalibrationcode) (struct rt2x00_dev *rt2x00dev, int d1, int d2); void (*r_calibration) (struct rt2x00_dev *rt2x00dev); void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev); diff --git a/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch b/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch index 31a860c1a..e0bdbf857 100644 --- a/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch +++ b/package/kernel/mac80211/patches/rt2x00/986-rt2x00-add-TX-LOFT-calibration.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c -@@ -9000,6 +9000,954 @@ restore_value: +@@ -9084,6 +9084,954 @@ restore_value: } EXPORT_SYMBOL_GPL(rt2800_rxiq_calibration); @@ -955,7 +955,7 @@ static void rt2800_bbp_core_soft_reset(struct rt2x00_dev *rt2x00dev, bool set_bw, bool is_ht40) { -@@ -9612,6 +10560,7 @@ static void rt2800_init_rfcsr_6352(struc +@@ -9696,6 +10644,7 @@ static void rt2800_init_rfcsr_6352(struc rt2800_rxdcoc_calibration(rt2x00dev); rt2800_bw_filter_calibration(rt2x00dev, true); rt2800_bw_filter_calibration(rt2x00dev, false); @@ -982,7 +982,7 @@ /* RT2800 driver data structure */ struct rt2800_drv_data { -@@ -248,6 +258,7 @@ int rt2800_calcrcalibrationcode(struct r +@@ -258,6 +268,7 @@ int rt2800_calcrcalibrationcode(struct r void rt2800_r_calibration(struct rt2x00_dev *rt2x00dev); void rt2800_rxdcoc_calibration(struct rt2x00_dev *rt2x00dev); void rt2800_rxiq_calibration(struct rt2x00_dev *rt2x00dev); @@ -992,7 +992,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h -@@ -577,6 +577,7 @@ struct rt2x00lib_ops { +@@ -579,6 +579,7 @@ struct rt2x00lib_ops { void (*r_calibration) (struct rt2x00_dev *rt2x00dev); void (*rxdcoc_calibration) (struct rt2x00_dev *rt2x00dev); void (*rxiq_calibration) (struct rt2x00_dev *rt2x00dev); diff --git a/package/kernel/mac80211/patches/subsys/362-mac80211-minstrel-remove-divisions-in-tx-status-path.patch b/package/kernel/mac80211/patches/subsys/362-mac80211-minstrel-remove-divisions-in-tx-status-path.patch new file mode 100644 index 000000000..d38d33b41 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/362-mac80211-minstrel-remove-divisions-in-tx-status-path.patch @@ -0,0 +1,61 @@ +From: Felix Fietkau +Date: Sat, 28 Sep 2019 15:44:06 +0200 +Subject: [PATCH] mac80211: minstrel: remove divisions in tx status path + +Use a slightly different threshold for downgrading spatial streams to +make it easier to calculate without divisions. +Slightly reduces CPU overhead. + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel.c ++++ b/net/mac80211/rc80211_minstrel.c +@@ -295,8 +295,7 @@ minstrel_tx_status(void *priv, struct ie + if (mi->sample_deferred > 0) + mi->sample_deferred--; + +- if (time_after(jiffies, mi->last_stats_update + +- (mp->update_interval * HZ) / 1000)) ++ if (time_after(jiffies, mi->last_stats_update + mp->update_interval)) + minstrel_update_stats(mp, mi); + } + +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -937,23 +937,21 @@ minstrel_ht_tx_status(void *priv, struct + */ + rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); + if (rate->attempts > 30 && +- MINSTREL_FRAC(rate->success, rate->attempts) < +- MINSTREL_FRAC(20, 100)) { ++ rate->success < rate->attempts / 4) { + minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true); + update = true; + } + + rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]); + if (rate2->attempts > 30 && +- MINSTREL_FRAC(rate2->success, rate2->attempts) < +- MINSTREL_FRAC(20, 100)) { ++ rate2->success < rate2->attempts / 4) { + minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false); + update = true; + } + } + + if (time_after(jiffies, mi->last_stats_update + +- (mp->update_interval / 2 * HZ) / 1000)) { ++ mp->update_interval / 2)) { + update = true; + minstrel_ht_update_stats(mp, mi, true); + } +@@ -1640,7 +1638,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h + mp->has_mrr = true; + + mp->hw = hw; +- mp->update_interval = 100; ++ mp->update_interval = HZ / 10; + + #ifdef CPTCFG_MAC80211_DEBUGFS + mp->fixed_rate_idx = (u32) -1; diff --git a/package/kernel/mac80211/patches/subsys/363-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch b/package/kernel/mac80211/patches/subsys/363-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch new file mode 100644 index 000000000..5e2a01786 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/363-mac80211-minstrel_ht-replace-rate-stats-ewma-with-a-.patch @@ -0,0 +1,235 @@ +From: Felix Fietkau +Date: Sat, 28 Sep 2019 15:46:06 +0200 +Subject: [PATCH] mac80211: minstrel_ht: replace rate stats ewma with a + better moving average + +Rate success probability usually fluctuates a lot under normal conditions. +With a simple EWMA, noise and fluctuation can be reduced by increasing the +window length, but that comes at the cost of introducing lag on sudden +changes. + +This change replaces the EWMA implementation with a moving average that's +designed to significantly reduce lag while keeping a bigger window size +by being better at filtering out noise. + +It is only slightly more expensive than the simple EWMA and still avoids +divisions in its calculation. + +The algorithm is adapted from an implementation intended for a completely +different field (stock market trading), where the tradeoff of lag vs +noise filtering is equally important. + +The algorithm works in the same way as the "smoothing filter" from +http://www.stockspotter.com/files/PredictiveIndicators.pdf adapted for +fixed-point math with some constants, using only addition, bit shifts +and multiplication + +To better make use of the filtering and bigger window size, the update +interval is cut in half. + +For testing, the algorithm can be reverted to the older one via debugfs + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel.c ++++ b/net/mac80211/rc80211_minstrel.c +@@ -157,14 +157,18 @@ minstrel_update_rates(struct minstrel_pr + * Recalculate statistics and counters of a given rate + */ + void +-minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) ++minstrel_calc_rate_stats(struct minstrel_priv *mp, ++ struct minstrel_rate_stats *mrs) + { + unsigned int cur_prob; + + if (unlikely(mrs->attempts > 0)) { + mrs->sample_skipped = 0; + cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); +- if (unlikely(!mrs->att_hist)) { ++ if (mp->new_avg) { ++ mrs->prob_ewma = minstrel_filter_avg_add(&mrs->avg, ++ cur_prob); ++ } else if (unlikely(!mrs->att_hist)) { + mrs->prob_ewma = cur_prob; + } else { + /* update exponential weighted moving variance */ +@@ -206,7 +210,7 @@ minstrel_update_stats(struct minstrel_pr + struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats; + + /* Update statistics of success probability per rate */ +- minstrel_calc_rate_stats(mrs); ++ minstrel_calc_rate_stats(mp, mrs); + + /* Sample less often below the 10% chance of success. + * Sample less often above the 95% chance of success. */ +@@ -295,7 +299,8 @@ minstrel_tx_status(void *priv, struct ie + if (mi->sample_deferred > 0) + mi->sample_deferred--; + +- if (time_after(jiffies, mi->last_stats_update + mp->update_interval)) ++ if (time_after(jiffies, mi->last_stats_update + ++ mp->update_interval / (mp->new_avg ? 2 : 1))) + minstrel_update_stats(mp, mi); + } + +--- a/net/mac80211/rc80211_minstrel.h ++++ b/net/mac80211/rc80211_minstrel.h +@@ -22,6 +22,21 @@ + #define MAX_THR_RATES 4 + + /* ++ * Coefficients for moving average with noise filter (period=16), ++ * scaled by 10 bits ++ * ++ * a1 = exp(-pi * sqrt(2) / period) ++ * coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period) ++ * coeff3 = -sqr(a1) ++ * coeff1 = 1 - coeff2 - coeff3 ++ */ ++#define MINSTREL_AVG_COEFF1 (MINSTREL_FRAC(1, 1) - \ ++ MINSTREL_AVG_COEFF2 - \ ++ MINSTREL_AVG_COEFF3) ++#define MINSTREL_AVG_COEFF2 0x00001499 ++#define MINSTREL_AVG_COEFF3 -0x0000092e ++ ++/* + * Perform EWMA (Exponentially Weighted Moving Average) calculation + */ + static inline int +@@ -48,6 +63,41 @@ minstrel_ewmv(int old_ewmv, int cur_prob + return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV; + } + ++struct minstrel_avg_ctx { ++ s32 prev[2]; ++}; ++ ++static inline int minstrel_filter_avg_add(struct minstrel_avg_ctx *ctx, s32 in) ++{ ++ s32 out_1 = ctx->prev[0]; ++ s32 out_2 = ctx->prev[1]; ++ s32 val; ++ ++ if (!in) ++ in += 1; ++ ++ if (!out_1) { ++ val = out_1 = in; ++ goto out; ++ } ++ ++ val = MINSTREL_AVG_COEFF1 * in; ++ val += MINSTREL_AVG_COEFF2 * out_1; ++ val += MINSTREL_AVG_COEFF3 * out_2; ++ val >>= MINSTREL_SCALE; ++ ++ if (val > 1 << MINSTREL_SCALE) ++ val = 1 << MINSTREL_SCALE; ++ if (val < 0) ++ val = 1; ++ ++out: ++ ctx->prev[1] = out_1; ++ ctx->prev[0] = val; ++ ++ return val; ++} ++ + struct minstrel_rate_stats { + /* current / last sampling period attempts/success counters */ + u16 attempts, last_attempts; +@@ -56,6 +106,8 @@ struct minstrel_rate_stats { + /* total attempts/success counters */ + u32 att_hist, succ_hist; + ++ struct minstrel_avg_ctx avg; ++ + /* statistis of packet delivery probability + * prob_ewma - exponential weighted moving average of prob + * prob_ewmsd - exp. weighted moving standard deviation of prob */ +@@ -114,6 +166,7 @@ struct minstrel_sta_info { + struct minstrel_priv { + struct ieee80211_hw *hw; + bool has_mrr; ++ bool new_avg; + u32 sample_switch; + unsigned int cw_min; + unsigned int cw_max; +@@ -153,7 +206,8 @@ extern const struct rate_control_ops mac + void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); + + /* Recalculate success probabilities and counters for a given rate using EWMA */ +-void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); ++void minstrel_calc_rate_stats(struct minstrel_priv *mp, ++ struct minstrel_rate_stats *mrs); + int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma); + + /* debugfs */ +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -704,7 +704,7 @@ minstrel_ht_update_stats(struct minstrel + + mrs = &mg->rates[i]; + mrs->retry_updated = false; +- minstrel_calc_rate_stats(mrs); ++ minstrel_calc_rate_stats(mp, mrs); + cur_prob = mrs->prob_ewma; + + if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) +@@ -740,6 +740,8 @@ minstrel_ht_update_stats(struct minstrel + + /* try to sample all available rates during each interval */ + mi->sample_count *= 8; ++ if (mp->new_avg) ++ mi->sample_count /= 2; + + if (sample) + minstrel_ht_rate_sample_switch(mp, mi); +@@ -856,6 +858,7 @@ minstrel_ht_tx_status(void *priv, struct + struct ieee80211_tx_rate *ar = info->status.rates; + struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL; + struct minstrel_priv *mp = priv; ++ u32 update_interval = mp->update_interval / 2; + bool last, update = false; + bool sample_status = false; + int i; +@@ -910,6 +913,10 @@ minstrel_ht_tx_status(void *priv, struct + + switch (mi->sample_mode) { + case MINSTREL_SAMPLE_IDLE: ++ if (mp->new_avg && ++ (mp->hw->max_rates > 1 || ++ mi->total_packets_cur < SAMPLE_SWITCH_THR)) ++ update_interval /= 2; + break; + + case MINSTREL_SAMPLE_ACTIVE: +@@ -950,8 +957,7 @@ minstrel_ht_tx_status(void *priv, struct + } + } + +- if (time_after(jiffies, mi->last_stats_update + +- mp->update_interval / 2)) { ++ if (time_after(jiffies, mi->last_stats_update + update_interval)) { + update = true; + minstrel_ht_update_stats(mp, mi, true); + } +@@ -1639,6 +1645,7 @@ minstrel_ht_alloc(struct ieee80211_hw *h + + mp->hw = hw; + mp->update_interval = HZ / 10; ++ mp->new_avg = true; + + #ifdef CPTCFG_MAC80211_DEBUGFS + mp->fixed_rate_idx = (u32) -1; +@@ -1646,6 +1653,8 @@ minstrel_ht_alloc(struct ieee80211_hw *h + &mp->fixed_rate_idx); + debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir, + &mp->sample_switch); ++ debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir, ++ &mp->new_avg); + #endif + + minstrel_ht_init_cck_rates(mp); diff --git a/package/kernel/mac80211/patches/subsys/364-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch b/package/kernel/mac80211/patches/subsys/364-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch new file mode 100644 index 000000000..c91964350 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/364-mac80211-minstrel_ht-rename-prob_ewma-to-prob_avg-us.patch @@ -0,0 +1,437 @@ +From: Felix Fietkau +Date: Tue, 8 Oct 2019 18:54:46 +0200 +Subject: [PATCH] mac80211: minstrel_ht: rename prob_ewma to prob_avg, use it + for the new average + +Reduces per-rate data structure size + +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/rc80211_minstrel.c ++++ b/net/mac80211/rc80211_minstrel.c +@@ -70,7 +70,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, + } + + /* return current EMWA throughput */ +-int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma) ++int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg) + { + int usecs; + +@@ -79,13 +79,13 @@ int minstrel_get_tp_avg(struct minstrel_ + usecs = 1000000; + + /* reset thr. below 10% success */ +- if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100)) ++ if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100)) + return 0; + +- if (prob_ewma > MINSTREL_FRAC(90, 100)) ++ if (prob_avg > MINSTREL_FRAC(90, 100)) + return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs)); + else +- return MINSTREL_TRUNC(100000 * (prob_ewma / usecs)); ++ return MINSTREL_TRUNC(100000 * (prob_avg / usecs)); + } + + /* find & sort topmost throughput rates */ +@@ -98,8 +98,8 @@ minstrel_sort_best_tp_rates(struct minst + + for (j = MAX_THR_RATES; j > 0; --j) { + tmp_mrs = &mi->r[tp_list[j - 1]].stats; +- if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <= +- minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma)) ++ if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_avg) <= ++ minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_avg)) + break; + } + +@@ -166,21 +166,21 @@ minstrel_calc_rate_stats(struct minstrel + mrs->sample_skipped = 0; + cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); + if (mp->new_avg) { +- mrs->prob_ewma = minstrel_filter_avg_add(&mrs->avg, +- cur_prob); ++ minstrel_filter_avg_add(&mrs->prob_avg, ++ &mrs->prob_avg_1, cur_prob); + } else if (unlikely(!mrs->att_hist)) { +- mrs->prob_ewma = cur_prob; ++ mrs->prob_avg = cur_prob; + } else { + /* update exponential weighted moving variance */ + mrs->prob_ewmv = minstrel_ewmv(mrs->prob_ewmv, + cur_prob, +- mrs->prob_ewma, ++ mrs->prob_avg, + EWMA_LEVEL); + + /*update exponential weighted moving avarage */ +- mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, +- cur_prob, +- EWMA_LEVEL); ++ mrs->prob_avg = minstrel_ewma(mrs->prob_avg, ++ cur_prob, ++ EWMA_LEVEL); + } + mrs->att_hist += mrs->attempts; + mrs->succ_hist += mrs->success; +@@ -214,8 +214,8 @@ minstrel_update_stats(struct minstrel_pr + + /* Sample less often below the 10% chance of success. + * Sample less often above the 95% chance of success. */ +- if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || +- mrs->prob_ewma < MINSTREL_FRAC(10, 100)) { ++ if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || ++ mrs->prob_avg < MINSTREL_FRAC(10, 100)) { + mr->adjusted_retry_count = mrs->retry_count >> 1; + if (mr->adjusted_retry_count > 2) + mr->adjusted_retry_count = 2; +@@ -235,14 +235,14 @@ minstrel_update_stats(struct minstrel_pr + * choose the maximum throughput rate as max_prob_rate + * (2) if all success probabilities < 95%, the rate with + * highest success probability is chosen as max_prob_rate */ +- if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) { +- tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_ewma); ++ if (mrs->prob_avg >= MINSTREL_FRAC(95, 100)) { ++ tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_avg); + tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate], +- tmp_mrs->prob_ewma); ++ tmp_mrs->prob_avg); + if (tmp_cur_tp >= tmp_prob_tp) + tmp_prob_rate = i; + } else { +- if (mrs->prob_ewma >= tmp_mrs->prob_ewma) ++ if (mrs->prob_avg >= tmp_mrs->prob_avg) + tmp_prob_rate = i; + } + } +@@ -436,7 +436,7 @@ minstrel_get_rate(void *priv, struct iee + * has a probability of >95%, we shouldn't be attempting + * to use it, as this only wastes precious airtime */ + if (!mrr_capable && +- (mi->r[ndx].stats.prob_ewma > MINSTREL_FRAC(95, 100))) ++ (mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100))) + return; + + mi->prev_sample = true; +@@ -587,7 +587,7 @@ static u32 minstrel_get_expected_through + * computing cur_tp + */ + tmp_mrs = &mi->r[idx].stats; +- tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_ewma) * 10; ++ tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_avg) * 10; + tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; + + return tmp_cur_tp; +--- a/net/mac80211/rc80211_minstrel.h ++++ b/net/mac80211/rc80211_minstrel.h +@@ -63,14 +63,10 @@ minstrel_ewmv(int old_ewmv, int cur_prob + return weight * (old_ewmv + MINSTREL_TRUNC(diff * incr)) / EWMA_DIV; + } + +-struct minstrel_avg_ctx { +- s32 prev[2]; +-}; +- +-static inline int minstrel_filter_avg_add(struct minstrel_avg_ctx *ctx, s32 in) ++static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in) + { +- s32 out_1 = ctx->prev[0]; +- s32 out_2 = ctx->prev[1]; ++ s32 out_1 = *prev_1; ++ s32 out_2 = *prev_2; + s32 val; + + if (!in) +@@ -92,8 +88,8 @@ static inline int minstrel_filter_avg_ad + val = 1; + + out: +- ctx->prev[1] = out_1; +- ctx->prev[0] = val; ++ *prev_2 = out_1; ++ *prev_1 = val; + + return val; + } +@@ -106,14 +102,15 @@ struct minstrel_rate_stats { + /* total attempts/success counters */ + u32 att_hist, succ_hist; + +- struct minstrel_avg_ctx avg; +- + /* statistis of packet delivery probability + * prob_ewma - exponential weighted moving average of prob + * prob_ewmsd - exp. weighted moving standard deviation of prob */ +- u16 prob_ewma; + u16 prob_ewmv; + ++ /* prob_avg - moving average of prob */ ++ u16 prob_avg; ++ u16 prob_avg_1; ++ + /* maximum retry counts */ + u8 retry_count; + u8 retry_count_rtscts; +@@ -208,7 +205,7 @@ void minstrel_add_sta_debugfs(void *priv + /* Recalculate success probabilities and counters for a given rate using EWMA */ + void minstrel_calc_rate_stats(struct minstrel_priv *mp, + struct minstrel_rate_stats *mrs); +-int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_ewma); ++int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg); + + /* debugfs */ + int minstrel_stats_open(struct inode *inode, struct file *file); +--- a/net/mac80211/rc80211_minstrel_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_debugfs.c +@@ -91,8 +91,9 @@ minstrel_stats_open(struct inode *inode, + p += sprintf(p, "%6u ", mr->perfect_tx_time); + + tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); +- tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); +- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); ++ tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); ++ eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); ++ + prob_ewmsd = minstrel_get_ewmsd10(mrs); + + p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" +@@ -151,8 +152,8 @@ minstrel_stats_csv_open(struct inode *in + p += sprintf(p, "%u,",mr->perfect_tx_time); + + tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); +- tp_avg = minstrel_get_tp_avg(mr, mrs->prob_ewma); +- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); ++ tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); ++ eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); + prob_ewmsd = minstrel_get_ewmsd10(mrs); + + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,%u," +--- a/net/mac80211/rc80211_minstrel_ht.c ++++ b/net/mac80211/rc80211_minstrel_ht.c +@@ -313,12 +313,12 @@ minstrel_ht_avg_ampdu_len(struct minstre + */ + int + minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, +- int prob_ewma) ++ int prob_avg) + { + unsigned int nsecs = 0; + + /* do not account throughput if sucess prob is below 10% */ +- if (prob_ewma < MINSTREL_FRAC(10, 100)) ++ if (prob_avg < MINSTREL_FRAC(10, 100)) + return 0; + + if (group != MINSTREL_CCK_GROUP) +@@ -332,11 +332,11 @@ minstrel_ht_get_tp_avg(struct minstrel_h + * account for collision related packet error rate fluctuation + * (prob is scaled - see MINSTREL_FRAC above) + */ +- if (prob_ewma > MINSTREL_FRAC(90, 100)) ++ if (prob_avg > MINSTREL_FRAC(90, 100)) + return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000) + / nsecs)); + else +- return MINSTREL_TRUNC(100000 * ((prob_ewma * 1000) / nsecs)); ++ return MINSTREL_TRUNC(100000 * ((prob_avg * 1000) / nsecs)); + } + + /* +@@ -356,13 +356,13 @@ minstrel_ht_sort_best_tp_rates(struct mi + + cur_group = index / MCS_GROUP_RATES; + cur_idx = index % MCS_GROUP_RATES; +- cur_prob = mi->groups[cur_group].rates[cur_idx].prob_ewma; ++ cur_prob = mi->groups[cur_group].rates[cur_idx].prob_avg; + cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, cur_prob); + + do { + tmp_group = tp_list[j - 1] / MCS_GROUP_RATES; + tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES; +- tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; ++ tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; + tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, + tmp_prob); + if (cur_tp_avg < tmp_tp_avg || +@@ -399,7 +399,7 @@ minstrel_ht_set_best_prob_rate(struct mi + + tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; + tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; +- tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; ++ tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; + tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); + + /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from +@@ -411,11 +411,11 @@ minstrel_ht_set_best_prob_rate(struct mi + + max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; + max_gpr_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; +- max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_ewma; ++ max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg; + +- if (mrs->prob_ewma > MINSTREL_FRAC(75, 100)) { ++ if (mrs->prob_avg > MINSTREL_FRAC(75, 100)) { + cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, +- mrs->prob_ewma); ++ mrs->prob_avg); + if (cur_tp_avg > tmp_tp_avg) + mi->max_prob_rate = index; + +@@ -425,9 +425,9 @@ minstrel_ht_set_best_prob_rate(struct mi + if (cur_tp_avg > max_gpr_tp_avg) + mg->max_group_prob_rate = index; + } else { +- if (mrs->prob_ewma > tmp_prob) ++ if (mrs->prob_avg > tmp_prob) + mi->max_prob_rate = index; +- if (mrs->prob_ewma > max_gpr_prob) ++ if (mrs->prob_avg > max_gpr_prob) + mg->max_group_prob_rate = index; + } + } +@@ -449,12 +449,12 @@ minstrel_ht_assign_best_tp_rates(struct + + tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES; + tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES; +- tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; ++ tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; + tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); + + tmp_group = tmp_mcs_tp_rate[0] / MCS_GROUP_RATES; + tmp_idx = tmp_mcs_tp_rate[0] % MCS_GROUP_RATES; +- tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_ewma; ++ tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; + tmp_mcs_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); + + if (tmp_cck_tp_rate && tmp_cck_tp > tmp_mcs_tp) { +@@ -485,7 +485,7 @@ minstrel_ht_prob_rate_reduce_streams(str + continue; + + tmp_idx = mg->max_group_prob_rate % MCS_GROUP_RATES; +- tmp_prob = mi->groups[group].rates[tmp_idx].prob_ewma; ++ tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg; + + if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) && + (minstrel_mcs_groups[group].streams < tmp_max_streams)) { +@@ -590,7 +590,7 @@ minstrel_ht_rate_sample_switch(struct mi + * If that fails, look again for a rate that is at least as fast + */ + mrs = minstrel_get_ratestats(mi, mi->max_tp_rate[0]); +- faster_rate = mrs->prob_ewma > MINSTREL_FRAC(75, 100); ++ faster_rate = mrs->prob_avg > MINSTREL_FRAC(75, 100); + minstrel_ht_find_probe_rates(mi, rates, &n_rates, faster_rate); + if (!n_rates && faster_rate) + minstrel_ht_find_probe_rates(mi, rates, &n_rates, false); +@@ -705,7 +705,7 @@ minstrel_ht_update_stats(struct minstrel + mrs = &mg->rates[i]; + mrs->retry_updated = false; + minstrel_calc_rate_stats(mp, mrs); +- cur_prob = mrs->prob_ewma; ++ cur_prob = mrs->prob_avg; + + if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) + continue; +@@ -979,7 +979,7 @@ minstrel_calc_retransmit(struct minstrel + unsigned int overhead = 0, overhead_rtscts = 0; + + mrs = minstrel_get_ratestats(mi, index); +- if (mrs->prob_ewma < MINSTREL_FRAC(1, 10)) { ++ if (mrs->prob_avg < MINSTREL_FRAC(1, 10)) { + mrs->retry_count = 1; + mrs->retry_count_rtscts = 1; + return; +@@ -1036,7 +1036,7 @@ minstrel_ht_set_rate(struct minstrel_pri + if (!mrs->retry_updated) + minstrel_calc_retransmit(mp, mi, index); + +- if (mrs->prob_ewma < MINSTREL_FRAC(20, 100) || !mrs->retry_count) { ++ if (mrs->prob_avg < MINSTREL_FRAC(20, 100) || !mrs->retry_count) { + ratetbl->rate[offset].count = 2; + ratetbl->rate[offset].count_rts = 2; + ratetbl->rate[offset].count_cts = 2; +@@ -1070,11 +1070,11 @@ minstrel_ht_set_rate(struct minstrel_pri + } + + static inline int +-minstrel_ht_get_prob_ewma(struct minstrel_ht_sta *mi, int rate) ++minstrel_ht_get_prob_avg(struct minstrel_ht_sta *mi, int rate) + { + int group = rate / MCS_GROUP_RATES; + rate %= MCS_GROUP_RATES; +- return mi->groups[group].rates[rate].prob_ewma; ++ return mi->groups[group].rates[rate].prob_avg; + } + + static int +@@ -1086,7 +1086,7 @@ minstrel_ht_get_max_amsdu_len(struct min + unsigned int duration; + + /* Disable A-MSDU if max_prob_rate is bad */ +- if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100)) ++ if (mi->groups[group].rates[rate].prob_avg < MINSTREL_FRAC(50, 100)) + return 1; + + duration = g->duration[rate]; +@@ -1109,7 +1109,7 @@ minstrel_ht_get_max_amsdu_len(struct min + * data packet size + */ + if (duration > MCS_DURATION(1, 0, 260) || +- (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) < ++ (minstrel_ht_get_prob_avg(mi, mi->max_tp_rate[0]) < + MINSTREL_FRAC(75, 100))) + return 3200; + +@@ -1216,7 +1216,7 @@ minstrel_get_sample_rate(struct minstrel + * rate, to avoid wasting airtime. + */ + sample_dur = minstrel_get_duration(sample_idx); +- if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || ++ if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || + minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur) + return -1; + +@@ -1679,7 +1679,7 @@ static u32 minstrel_ht_get_expected_thro + + i = mi->max_tp_rate[0] / MCS_GROUP_RATES; + j = mi->max_tp_rate[0] % MCS_GROUP_RATES; +- prob = mi->groups[i].rates[j].prob_ewma; ++ prob = mi->groups[i].rates[j].prob_avg; + + /* convert tp_avg from pkt per second in kbps */ + tp_avg = minstrel_ht_get_tp_avg(mi, i, j, prob) * 10; +--- a/net/mac80211/rc80211_minstrel_ht.h ++++ b/net/mac80211/rc80211_minstrel_ht.h +@@ -122,6 +122,6 @@ struct minstrel_ht_sta_priv { + + void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); + int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, +- int prob_ewma); ++ int prob_avg); + + #endif +--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c ++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c +@@ -102,8 +102,8 @@ minstrel_ht_stats_dump(struct minstrel_h + p += sprintf(p, "%6u ", tx_time); + + tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); +- tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); +- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); ++ tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg); ++ eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); + prob_ewmsd = minstrel_get_ewmsd10(mrs); + + p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u" +@@ -250,8 +250,8 @@ minstrel_ht_stats_csv_dump(struct minstr + p += sprintf(p, "%u,", tx_time); + + tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100)); +- tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_ewma); +- eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); ++ tp_avg = minstrel_ht_get_tp_avg(mi, i, j, mrs->prob_avg); ++ eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); + prob_ewmsd = minstrel_get_ewmsd10(mrs); + + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u.%u,%u,%u,"