From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001 From: James <> Date: Wed, 4 Nov 2015 11:49:21 +0000 Subject: trunk-47381 --- .../kernel/mac80211/patches/000-fix_kconfig.patch | 14 + .../kernel/mac80211/patches/001-fix_build.patch | 167 +++ .../mac80211/patches/002-change_allconfig.patch | 64 ++ .../patches/003-remove_bogus_modparams.patch | 34 + .../mac80211/patches/010-disable_rfkill.patch | 13 + .../mac80211/patches/030-rt2x00_options.patch | 47 + .../mac80211/patches/040-brcmutil_option.patch | 9 + .../mac80211/patches/050-lib80211_option.patch | 30 + .../mac80211/patches/060-no_local_ssb_bcma.patch | 130 +++ .../mac80211/patches/070-ath_common_config.patch | 10 + .../patches/080-disable_clk_backport.patch | 20 + .../100-remove-cryptoapi-dependencies.patch | 376 ++++++ .../110-mac80211_keep_keys_on_stop_ap.patch | 12 + .../120-cfg80211_allow_perm_addr_change.patch | 43 + .../patches/150-disable_addr_notifier.patch | 67 ++ .../patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch | 38 + package/kernel/mac80211/patches/210-ap_scan.patch | 11 + ...00-ath9k-force-rx_clear-when-disabling-rx.patch | 31 + ...mit-retries-for-powersave-response-frames.patch | 121 ++ .../patches/302-ath9k-fix-phyerror-codes.patch | 108 ++ .../patches/303-ath10k-enable-adaptive-CCA.patch | 239 ++++ ...04-ath10k-add-FW-API-support-to-test-mode.patch | 331 ++++++ ...10k-add-fw_stats-support-to-10.4-firmware.patch | 468 ++++++++ ...local-memory-instead-of-shadow-descriptor.patch | 60 + ...ve-send-completion-validation-in-diag-rea.patch | 49 + ...th10k-cleanup-copy-engine-send-completion.patch | 165 +++ ...ve-shadow-copy-of-CE-descriptors-for-sour.patch | 90 ++ .../310-ath10k-remove-supported-chain-mask.patch | 77 ++ ...-HT-VHT-MCS-rateset-only-for-configured-c.patch | 37 + ...-static-HT-VHT-capability-setup-functions.patch | 314 +++++ ...x-crash-on-mesh-local-link-ID-generation-.patch | 42 + .../mac80211/patches/400-ath_move_debug_code.patch | 30 + .../mac80211/patches/401-ath9k_blink_default.patch | 11 + .../mac80211/patches/402-ath_regd_optional.patch | 69 ++ .../mac80211/patches/403-world_regd_fixup.patch | 84 ++ .../mac80211/patches/404-regd_no_assoc_hints.patch | 19 + .../kernel/mac80211/patches/405-ath_regd_us.patch | 26 + .../patches/406-ath_relax_default_regd.patch | 47 + .../patches/410-ath9k_allow_adhoc_and_ap.patch | 10 + .../patches/411-ath5k_allow_adhoc_and_ap.patch | 46 + .../patches/420-ath5k_disable_fast_cc.patch | 18 + .../mac80211/patches/430-add_ath5k_platform.patch | 33 + .../431-add_platform_eeprom_support_to_ath5k.patch | 56 + .../mac80211/patches/432-ath5k_add_pciids.patch | 11 + .../patches/440-ath5k_channel_bw_debugfs.patch | 143 +++ .../patches/500-ath9k_eeprom_debugfs.patch | 65 ++ .../mac80211/patches/501-ath9k_ahb_init.patch | 32 + .../patches/510-ath9k_intr_mitigation_tweak.patch | 18 + .../mac80211/patches/511-ath9k_reduce_rxbuf.patch | 11 + .../patches/512-ath9k_channelbw_debugfs.patch | 125 ++ .../mac80211/patches/513-ath9k_add_pci_ids.patch | 30 + .../522-mac80211_configure_antenna_gain.patch | 160 +++ .../mac80211/patches/530-ath9k_extra_leds.patch | 251 ++++ .../patches/531-ath9k_extra_platform_leds.patch | 71 ++ .../patches/540-ath9k_reduce_ani_interval.patch | 11 + .../patches/541-ath9k_rx_dma_stop_check.patch | 28 + .../mac80211/patches/542-ath9k_debugfs_diag.patch | 139 +++ .../patches/543-ath9k_entropy_from_adc.patch | 186 +++ .../544-ath9k-ar933x-usb-hang-workaround.patch | 79 ++ .../mac80211/patches/545-ath9k_ani_ws_detect.patch | 155 +++ ...00lib-move-rt2800_drv_data-declaration-in.patch | 66 ++ ...00lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch | 80 ++ ...x00-rt2800-serialize-shared-memory-access.patch | 531 +++++++++ ...rt2800lib-fix-beacon-generation-on-RT3593.patch | 131 +++ ...00lib-add-hw_beacon_count-field-to-struct.patch | 62 + ...00lib-init-additional-beacon-offset-regis.patch | 67 ++ ...00lib-fix-max-supported-beacon-count-for-.patch | 24 + ...llow-to-build-rt2800soc-module-for-RT3883.patch | 30 + ...t2x00-rt2800lib-enable-support-for-RT3883.patch | 20 + ...0-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch | 112 ++ ...2800lib-enable-VCO-calibration-for-RF3853.patch | 28 + ...00lib-add-channel-configuration-function-.patch | 235 ++++ ...13-rt2x00-rt2800lib-enable-RF3853-support.patch | 20 + ...00lib-add-MAC-register-initialization-for.patch | 77 ++ ...00soc-fix-rt2800soc_disable_radio-for-RT3.patch | 30 + ...00lib-add-BBP-register-initialization-for.patch | 71 ++ ...00lib-add-RFCSR-initialization-for-RT3883.patch | 178 +++ ...00lib-use-the-extended-EEPROM-map-for-RT3.patch | 22 + ...2800lib-force-rf-type-to-RF3853-on-RT3883.patch | 21 + ...00lib-add-channel-configuration-code-for-.patch | 136 +++ ...00lib-fix-txpower_to_dev-function-for-RT3.patch | 30 + ...00lib-use-correct-txpower-calculation-fun.patch | 23 + ...00lib-hardcode-txmixer-gain-values-to-zer.patch | 33 + ...800lib-use-correct-RT-XWI-size-for-RT3883.patch | 20 + ...800lib-use-correct-beacon-base-for-RT3883.patch | 22 + ...00lib-use-correct-beacon-count-for-RT3883.patch | 22 + ...00lib-fix-antenna-configuration-for-RT388.patch | 22 + ...00lib-fix-LNA-gain-configuration-for-RT38.patch | 32 + ...rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch | 44 + ...00lib-fix-EEPROM-LNA-validation-for-RT388.patch | 42 + ...00lib-fix-txpower-compensation-for-RT3883.patch | 22 + ...00lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch | 23 + ...00lib-use-high-memory-for-beacons-on-RT38.patch | 22 + ...00mmio-add-a-workaround-for-spurious-TX_F.patch | 136 +++ .../mac80211/patches/601-rt2x00-set_pci_mwi.patch | 13 + .../602-rt2x00-introduce-rt2x00_platform_h.patch | 32 + .../603-rt2x00-introduce-rt2x00eeprom.patch | 301 +++++ .../604-rt2x00-of_load_eeprom_filename.patch | 33 + ...-eeprom-on-SoC-from-a-mtd-device-defines-.patch | 101 ++ ...low_disabling_bands_through_platform_data.patch | 47 + .../patches/608-add_platform_data_mac_addr.patch | 63 + ...-rt2x00-allow_disabling_bands_through_dts.patch | 27 + .../patches/610-rt2x00-fix-rt3352-ext-pa.patch | 211 ++++ .../patches/611-rt2x00-rf_vals-rt3352-xtal20.patch | 106 ++ ...e-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch | 33 + .../patches/615-rt2x00-fix_20mhz_clk.patch | 29 + .../patches/616-rt2x00-support-rt5350.patch | 276 +++++ .../619-rt2x00-change-led-polarity-from-OF.patch | 40 + .../patches/620-rt2x00-add-AP+STA-support.patch | 11 + .../mac80211/patches/620-rt2x00-rt3352-rf-id.patch | 15 + .../mac80211/patches/621-rt2x00-ht20_40_fix.patch | 29 + .../700-mwl8k-missing-pci-id-for-WNR854T.patch | 10 + .../801-libertas-configure-sysfs-links.patch | 21 + .../802-libertas-set-wireless-macaddr.patch | 11 + .../patches/805-b43-gpio-mask-module-option.patch | 37 + .../kernel/mac80211/patches/810-b43_no_pio.patch | 86 ++ .../patches/820-b43-add-antenna-control.patch | 131 +++ .../841-b43-reduce-number-of-RX-slots.patch | 11 + .../845-b43-only-use-gpio-0-1-for-led.patch | 17 + .../847-b43-always-take-overlapping-devs.patch | 11 + ...msmac-remove-extra-regulation-restriction.patch | 27 + ...mfmac-register-wiphy-s-during-module_init.patch | 97 ++ ...rkaround-bug-with-some-inconsistent-BSSes.patch | 50 + ...910-00-rt2x00-enable-rt2800soc-for-mt7620.patch | 20 + .../patches/910-01-add-support-for-mt7620.patch | 1202 ++++++++++++++++++++ .../921-ath10k_init_devices_synchronously.patch | 33 + .../patches/930-ath10k_add_tpt_led_trigger.patch | 37 + .../940-mwl8k_init_devices_synchronously.patch | 20 + 128 files changed, 10803 insertions(+) create mode 100644 package/kernel/mac80211/patches/000-fix_kconfig.patch create mode 100644 package/kernel/mac80211/patches/001-fix_build.patch create mode 100644 package/kernel/mac80211/patches/002-change_allconfig.patch create mode 100644 package/kernel/mac80211/patches/003-remove_bogus_modparams.patch create mode 100644 package/kernel/mac80211/patches/010-disable_rfkill.patch create mode 100644 package/kernel/mac80211/patches/030-rt2x00_options.patch create mode 100644 package/kernel/mac80211/patches/040-brcmutil_option.patch create mode 100644 package/kernel/mac80211/patches/050-lib80211_option.patch create mode 100644 package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch create mode 100644 package/kernel/mac80211/patches/070-ath_common_config.patch create mode 100644 package/kernel/mac80211/patches/080-disable_clk_backport.patch create mode 100644 package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch create mode 100644 package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch create mode 100644 package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch create mode 100644 package/kernel/mac80211/patches/150-disable_addr_notifier.patch create mode 100644 package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch create mode 100644 package/kernel/mac80211/patches/210-ap_scan.patch create mode 100644 package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch create mode 100644 package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch create mode 100644 package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch create mode 100644 package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch create mode 100644 package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch create mode 100644 package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch create mode 100644 package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch create mode 100644 package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch create mode 100644 package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch create mode 100644 package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch create mode 100644 package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch create mode 100644 package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch create mode 100644 package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch create mode 100644 package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch create mode 100644 package/kernel/mac80211/patches/400-ath_move_debug_code.patch create mode 100644 package/kernel/mac80211/patches/401-ath9k_blink_default.patch create mode 100644 package/kernel/mac80211/patches/402-ath_regd_optional.patch create mode 100644 package/kernel/mac80211/patches/403-world_regd_fixup.patch create mode 100644 package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch create mode 100644 package/kernel/mac80211/patches/405-ath_regd_us.patch create mode 100644 package/kernel/mac80211/patches/406-ath_relax_default_regd.patch create mode 100644 package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch create mode 100644 package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch create mode 100644 package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch create mode 100644 package/kernel/mac80211/patches/430-add_ath5k_platform.patch create mode 100644 package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch create mode 100644 package/kernel/mac80211/patches/432-ath5k_add_pciids.patch create mode 100644 package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch create mode 100644 package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch create mode 100644 package/kernel/mac80211/patches/501-ath9k_ahb_init.patch create mode 100644 package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch create mode 100644 package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch create mode 100644 package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch create mode 100644 package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch create mode 100644 package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch create mode 100644 package/kernel/mac80211/patches/530-ath9k_extra_leds.patch create mode 100644 package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch create mode 100644 package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch create mode 100644 package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch create mode 100644 package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch create mode 100644 package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch create mode 100644 package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch create mode 100644 package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch create mode 100644 package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch create mode 100644 package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch create mode 100644 package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch create mode 100644 package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch create mode 100644 package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch create mode 100644 package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch create mode 100644 package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch create mode 100644 package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch create mode 100644 package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch create mode 100644 package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch create mode 100644 package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch create mode 100644 package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch create mode 100644 package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch create mode 100644 package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch create mode 100644 package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch create mode 100644 package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch create mode 100644 package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch create mode 100644 package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch create mode 100644 package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch create mode 100644 package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch create mode 100644 package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch create mode 100644 package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch create mode 100644 package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch create mode 100644 package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch create mode 100644 package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch create mode 100644 package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch create mode 100644 package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch create mode 100644 package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch create mode 100644 package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch create mode 100644 package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch create mode 100644 package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch create mode 100644 package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch create mode 100644 package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch create mode 100644 package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch create mode 100644 package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch create mode 100644 package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch create mode 100644 package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch create mode 100644 package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch create mode 100644 package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch create mode 100644 package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch create mode 100644 package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch create mode 100644 package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch create mode 100644 package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch create mode 100644 package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch create mode 100644 package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch create mode 100644 package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch create mode 100644 package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch create mode 100644 package/kernel/mac80211/patches/810-b43_no_pio.patch create mode 100644 package/kernel/mac80211/patches/820-b43-add-antenna-control.patch create mode 100644 package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch create mode 100644 package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch create mode 100644 package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch create mode 100644 package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch create mode 100644 package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch create mode 100644 package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch create mode 100644 package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch create mode 100644 package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch create mode 100644 package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch create mode 100644 package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch create mode 100644 package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch (limited to 'package/kernel/mac80211/patches') diff --git a/package/kernel/mac80211/patches/000-fix_kconfig.patch b/package/kernel/mac80211/patches/000-fix_kconfig.patch new file mode 100644 index 0000000..3987aae --- /dev/null +++ b/package/kernel/mac80211/patches/000-fix_kconfig.patch @@ -0,0 +1,14 @@ +--- a/kconf/Makefile ++++ b/kconf/Makefile +@@ -1,9 +1,9 @@ +-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer ++CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS + + LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o + + conf: conf.o zconf.tab.o +-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE ++mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) + mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC)) + mconf: CFLAGS += $(mconf_CFLAGS) + diff --git a/package/kernel/mac80211/patches/001-fix_build.patch b/package/kernel/mac80211/patches/001-fix_build.patch new file mode 100644 index 0000000..402649d --- /dev/null +++ b/package/kernel/mac80211/patches/001-fix_build.patch @@ -0,0 +1,167 @@ +--- a/Makefile ++++ b/Makefile +@@ -5,7 +5,7 @@ + ifeq ($(KERNELRELEASE),) + + MAKEFLAGS += --no-print-directory +-SHELL := /bin/bash ++SHELL := /usr/bin/env bash + BACKPORT_DIR := $(shell pwd) + + KMODDIR ?= updates +@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/ + KERNEL_CONFIG := $(KLIB_BUILD)/.config + KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile + CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//') ++STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5) + + export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG + +@@ -36,7 +37,8 @@ mrproper: + @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel + @rm -f backport-include/backport/autoconf.h + +-.DEFAULT: ++.SILENT: $(STAMP_KERNEL_CONFIG) ++$(STAMP_KERNEL_CONFIG): + @set -e ; test -f .local-symbols || ( \ + echo "/--------------" ;\ + echo "| You shouldn't run make in the backports tree, but only in" ;\ +@@ -60,57 +62,61 @@ mrproper: + echo "| (that isn't currently running.)" ;\ + echo "\\--" ;\ + false) +- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\ +- then \ +- echo -n "Generating local configuration database from kernel ..." ;\ +- grep -v -f .local-symbols $(KERNEL_CONFIG) | grep = | ( \ +- while read l ; do \ +- if [ "$${l:0:7}" != "CONFIG_" ] ; then \ +- continue ;\ +- fi ;\ +- l=$${l:7} ;\ +- n=$${l%%=*} ;\ +- v=$${l#*=} ;\ +- if [ "$$v" = "m" ] ; then \ +- echo config $$n ;\ +- echo ' tristate' ;\ +- elif [ "$$v" = "y" ] ; then \ +- echo config $$n ;\ +- echo ' bool' ;\ +- else \ +- continue ;\ +- fi ;\ +- echo " default $$v" ;\ +- echo "" ;\ +- done \ +- ) > Kconfig.kernel ;\ +- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \ +- sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\ +- test "$$kver" != "" || echo "Kernel version parse failed!" ;\ +- test "$$kver" != "" ;\ +- kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\ +- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\ +- kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\ +- print=0 ;\ +- for v in $$kvers ; do \ +- if [ "$$print" = "1" ] ; then \ +- echo config KERNEL_$$(echo $$v | tr . _) ;\ +- echo " def_bool y" ;\ +- fi ;\ +- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\ +- done > Kconfig.versions ;\ +- # RHEL as well, sadly we need to grep for it ;\ +- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \ +- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ +- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \ +- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ +- for v in $$(seq 0 $$RHEL_MINOR) ; do \ +- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\ +- echo " def_bool y" ;\ +- done >> Kconfig.versions ;\ +- echo " done." ;\ +- fi ;\ +- echo "$(CONFIG_MD5)" > .kernel_config_md5 ++ @rm -f .kernel_config_md5_* ++ @touch $@ ++ ++Kconfig.kernel: $(STAMP_KERNEL_CONFIG) .local-symbols ++ @printf "Generating local configuration database from kernel ..." ++ @grep -v -f .local-symbols $(KERNEL_CONFIG) | grep = | ( \ ++ while read l ; do \ ++ if [ "$${l:0:7}" != "CONFIG_" ] ; then \ ++ continue ;\ ++ fi ;\ ++ l=$${l:7} ;\ ++ n=$${l%%=*} ;\ ++ v=$${l#*=} ;\ ++ if [ "$$v" = "m" ] ; then \ ++ echo config $$n ;\ ++ echo ' tristate' ;\ ++ elif [ "$$v" = "y" ] ; then \ ++ echo config $$n ;\ ++ echo ' bool' ;\ ++ else \ ++ continue ;\ ++ fi ;\ ++ echo " default $$v" ;\ ++ echo "" ;\ ++ done \ ++ ) > $@ ++ @echo " done." ++ ++Kconfig.versions: Kconfig.kernel ++ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \ ++ sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\ ++ test "$$kver" != "" || echo "Kernel version parse failed!" ;\ ++ test "$$kver" != "" ;\ ++ kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\ ++ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\ ++ kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\ ++ print=0 ;\ ++ for v in $$kvers ; do \ ++ if [ "$$print" = "1" ] ; then \ ++ echo config KERNEL_$$(echo $$v | tr . _) ;\ ++ echo " def_bool y" ;\ ++ fi ;\ ++ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\ ++ done > $@ ++ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \ ++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ ++ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \ ++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\ ++ for v in $$(seq 0 $$RHEL_MINOR) ; do \ ++ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\ ++ echo " def_bool y" ;\ ++ done >> $@ ++ ++.DEFAULT: ++ @$(MAKE) Kconfig.versions + @$(MAKE) -f Makefile.real "$@" + + .PHONY: defconfig-help +--- a/Makefile.real ++++ b/Makefile.real +@@ -59,7 +59,7 @@ defconfig-%:: + + backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel + @$(MAKE) oldconfig +- @echo -n "Building backport-include/backport/autoconf.h ..." ++ @printf "Building backport-include/backport/autoconf.h ..." + @grep -f .local-symbols .config | ( \ + echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\ + echo "#define COMPAT_AUTOCONF_INCLUDED" ;\ +@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c + esac ;\ + done ;\ + echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\ +- ) > backport-include/backport/autoconf.h ++ ) > $@.new ++ @if cmp -s $@ $@.new; then \ ++ rm -f $@.new; \ ++ else \ ++ mv $@.new $@; \ ++ fi + @echo " done." + + .PHONY: modules diff --git a/package/kernel/mac80211/patches/002-change_allconfig.patch b/package/kernel/mac80211/patches/002-change_allconfig.patch new file mode 100644 index 0000000..bd5bebf --- /dev/null +++ b/package/kernel/mac80211/patches/002-change_allconfig.patch @@ -0,0 +1,64 @@ +--- a/kconf/conf.c ++++ b/kconf/conf.c +@@ -593,40 +593,12 @@ int main(int ac, char **av) + case oldconfig: + case listnewconfig: + case olddefconfig: +- conf_read(NULL); +- break; + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case randconfig: +- name = getenv("KCONFIG_ALLCONFIG"); +- if (!name) +- break; +- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { +- if (conf_read_simple(name, S_DEF_USER)) { +- fprintf(stderr, +- _("*** Can't read seed configuration \"%s\"!\n"), +- name); +- exit(1); +- } +- break; +- } +- switch (input_mode) { +- case allnoconfig: name = "allno.config"; break; +- case allyesconfig: name = "allyes.config"; break; +- case allmodconfig: name = "allmod.config"; break; +- case alldefconfig: name = "alldef.config"; break; +- case randconfig: name = "allrandom.config"; break; +- default: break; +- } +- if (conf_read_simple(name, S_DEF_USER) && +- conf_read_simple("all.config", S_DEF_USER)) { +- fprintf(stderr, +- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), +- name); +- exit(1); +- } ++ conf_read(NULL); + break; + default: + break; +--- a/kconf/confdata.c ++++ b/kconf/confdata.c +@@ -1169,6 +1169,8 @@ bool conf_set_all_new_symbols(enum conf_ + } + bool has_changed = false; + ++ sym_clear_all_valid(); ++ + for_all_symbols(i, sym) { + if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID)) + continue; +@@ -1212,8 +1214,6 @@ bool conf_set_all_new_symbols(enum conf_ + + } + +- sym_clear_all_valid(); +- + /* + * We have different type of choice blocks. + * If curr.tri equals to mod then we can select several diff --git a/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch b/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch new file mode 100644 index 0000000..8fa465a --- /dev/null +++ b/package/kernel/mac80211/patches/003-remove_bogus_modparams.patch @@ -0,0 +1,34 @@ +--- a/compat/main.c ++++ b/compat/main.c +@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL"); + #error "You need a CPTCFG_VERSION" + #endif + +-static char *backported_kernel_name = CPTCFG_KERNEL_NAME; +- +-module_param(backported_kernel_name, charp, 0400); +-MODULE_PARM_DESC(backported_kernel_name, +- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")"); +- +-#ifdef BACKPORTS_GIT_TRACKED +-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED; +-module_param(backports_tracker_id, charp, 0400); +-MODULE_PARM_DESC(backports_tracker_id, +- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")"); +-#else +-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION; +-static char *backports_version = CPTCFG_VERSION; +- +-module_param(backported_kernel_version, charp, 0400); +-MODULE_PARM_DESC(backported_kernel_version, +- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")"); +- +-module_param(backports_version, charp, 0400); +-MODULE_PARM_DESC(backports_version, +- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")"); +- +-#endif +- + void backport_dependency_symbol(void) + { + } diff --git a/package/kernel/mac80211/patches/010-disable_rfkill.patch b/package/kernel/mac80211/patches/010-disable_rfkill.patch new file mode 100644 index 0000000..c5a92d6 --- /dev/null +++ b/package/kernel/mac80211/patches/010-disable_rfkill.patch @@ -0,0 +1,13 @@ +--- a/backport-include/linux/rfkill.h ++++ b/backport-include/linux/rfkill.h +@@ -2,6 +2,10 @@ + #define __COMPAT_RFKILL_H + #include + ++#undef CONFIG_RFKILL ++#undef CONFIG_RFKILL_LEDS ++#undef CONFIG_RFKILL_MODULE ++ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) + #include_next + #else diff --git a/package/kernel/mac80211/patches/030-rt2x00_options.patch b/package/kernel/mac80211/patches/030-rt2x00_options.patch new file mode 100644 index 0000000..a25aeb2 --- /dev/null +++ b/package/kernel/mac80211/patches/030-rt2x00_options.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/rt2x00/Kconfig ++++ b/drivers/net/wireless/rt2x00/Kconfig +@@ -225,36 +225,37 @@ config RT2800SOC + + + config RT2800_LIB +- tristate ++ tristate "RT2800 USB/PCI support" + depends on m + + config RT2800_LIB_MMIO +- tristate ++ tristate "RT2800 MMIO support" + depends on m + select RT2X00_LIB_MMIO + select RT2800_LIB + + config RT2X00_LIB_MMIO +- tristate ++ tristate "RT2x00 MMIO support" + depends on m + + config RT2X00_LIB_PCI +- tristate ++ tristate "RT2x00 PCI support" + depends on m + select RT2X00_LIB + + config RT2X00_LIB_SOC +- tristate ++ tristate "RT2x00 SoC support" ++ depends on SOC_RT288X || SOC_RT305X + depends on m + select RT2X00_LIB + + config RT2X00_LIB_USB +- tristate ++ tristate "RT2x00 USB support" + depends on m + select RT2X00_LIB + + config RT2X00_LIB +- tristate ++ tristate "RT2x00 support" + depends on m + + config RT2X00_LIB_FIRMWARE diff --git a/package/kernel/mac80211/patches/040-brcmutil_option.patch b/package/kernel/mac80211/patches/040-brcmutil_option.patch new file mode 100644 index 0000000..8a6cae6 --- /dev/null +++ b/package/kernel/mac80211/patches/040-brcmutil_option.patch @@ -0,0 +1,9 @@ +--- a/drivers/net/wireless/brcm80211/Kconfig ++++ b/drivers/net/wireless/brcm80211/Kconfig +@@ -1,5 +1,5 @@ + config BRCMUTIL +- tristate ++ tristate "Broadcom 802.11 driver utility functions" + depends on m + + config BRCMSMAC diff --git a/package/kernel/mac80211/patches/050-lib80211_option.patch b/package/kernel/mac80211/patches/050-lib80211_option.patch new file mode 100644 index 0000000..50d3df8 --- /dev/null +++ b/package/kernel/mac80211/patches/050-lib80211_option.patch @@ -0,0 +1,30 @@ +--- a/net/wireless/Kconfig ++++ b/net/wireless/Kconfig +@@ -184,7 +184,7 @@ config CFG80211_WEXT_EXPORT + wext compatibility symbols to be exported. + + config LIB80211 +- tristate ++ tristate "lib80211" + depends on m + default n + help +@@ -194,15 +194,15 @@ config LIB80211 + Drivers should select this themselves if needed. + + config LIB80211_CRYPT_WEP +- tristate ++ tristate "lib80211 WEP support" + depends on m + + config LIB80211_CRYPT_CCMP +- tristate ++ tristate "lib80211 CCMP support" + depends on m + + config LIB80211_CRYPT_TKIP +- tristate ++ tristate "lib80211 TKIP support" + depends on m + + config LIB80211_DEBUG diff --git a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch new file mode 100644 index 0000000..69c9e01 --- /dev/null +++ b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch @@ -0,0 +1,130 @@ +--- a/.local-symbols ++++ b/.local-symbols +@@ -454,43 +454,6 @@ USB_IPHETH= + USB_SIERRA_NET= + USB_VL600= + USB_NET_CH9200= +-SSB_POSSIBLE= +-SSB= +-SSB_SPROM= +-SSB_BLOCKIO= +-SSB_PCIHOST_POSSIBLE= +-SSB_PCIHOST= +-SSB_B43_PCI_BRIDGE= +-SSB_PCMCIAHOST_POSSIBLE= +-SSB_PCMCIAHOST= +-SSB_SDIOHOST_POSSIBLE= +-SSB_SDIOHOST= +-SSB_SILENT= +-SSB_DEBUG= +-SSB_SERIAL= +-SSB_DRIVER_PCICORE_POSSIBLE= +-SSB_DRIVER_PCICORE= +-SSB_PCICORE_HOSTMODE= +-SSB_DRIVER_MIPS= +-SSB_SFLASH= +-SSB_EMBEDDED= +-SSB_DRIVER_EXTIF= +-SSB_DRIVER_GIGE= +-SSB_DRIVER_GPIO= +-BCMA_POSSIBLE= +-BCMA= +-BCMA_BLOCKIO= +-BCMA_HOST_PCI_POSSIBLE= +-BCMA_HOST_PCI= +-BCMA_HOST_SOC= +-BCMA_DRIVER_PCI= +-BCMA_DRIVER_PCI_HOSTMODE= +-BCMA_DRIVER_MIPS= +-BCMA_SFLASH= +-BCMA_NFLASH= +-BCMA_DRIVER_GMAC_CMN= +-BCMA_DRIVER_GPIO= +-BCMA_DEBUG= + NFC= + NFC_DIGITAL= + NFC_NCI= +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -2867,7 +2867,7 @@ static struct ssb_device *b43_ssb_gpio_d + { + struct ssb_bus *bus = dev->dev->sdev->bus; + +-#ifdef CPTCFG_SSB_DRIVER_PCICORE ++#ifdef CONFIG_SSB_DRIVER_PCICORE + return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); + #else + return bus->chipco.dev; +@@ -4904,7 +4904,7 @@ static int b43_wireless_core_init(struct + } + if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW) + hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */ +-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE) ++#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE) + if (dev->dev->bus_type == B43_BUS_SSB && + dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && + dev->dev->sdev->bus->pcicore.dev->id.revision <= 10) +--- a/drivers/net/wireless/b43legacy/main.c ++++ b/drivers/net/wireless/b43legacy/main.c +@@ -1937,7 +1937,7 @@ static int b43legacy_gpio_init(struct b4 + if (dev->dev->id.revision >= 2) + mask |= 0x0010; /* FIXME: This is redundant. */ + +-#ifdef CPTCFG_SSB_DRIVER_PCICORE ++#ifdef CONFIG_SSB_DRIVER_PCICORE + pcidev = bus->pcicore.dev; + #endif + gpiodev = bus->chipco.dev ? : pcidev; +@@ -1956,7 +1956,7 @@ static void b43legacy_gpio_cleanup(struc + struct ssb_bus *bus = dev->dev->bus; + struct ssb_device *gpiodev, *pcidev = NULL; + +-#ifdef CPTCFG_SSB_DRIVER_PCICORE ++#ifdef CONFIG_SSB_DRIVER_PCICORE + pcidev = bus->pcicore.dev; + #endif + gpiodev = bus->chipco.dev ? : pcidev; +--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile ++++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile +@@ -43,6 +43,6 @@ brcmsmac-y := \ + brcms_trace_events.o \ + debug.o + +-brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o ++brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o + + obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o +--- a/drivers/net/wireless/brcm80211/brcmsmac/led.h ++++ b/drivers/net/wireless/brcm80211/brcmsmac/led.h +@@ -22,7 +22,7 @@ struct brcms_led { + bool active_low; + }; + +-#ifdef CPTCFG_BCMA_DRIVER_GPIO ++#ifdef CONFIG_BCMA_DRIVER_GPIO + void brcms_led_unregister(struct brcms_info *wl); + int brcms_led_register(struct brcms_info *wl); + #else +--- a/Kconfig.sources ++++ b/Kconfig.sources +@@ -9,9 +9,6 @@ source "$BACKPORT_DIR/drivers/net/wirele + source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig" + source "$BACKPORT_DIR/drivers/net/usb/Kconfig" + +-source "$BACKPORT_DIR/drivers/ssb/Kconfig" +-source "$BACKPORT_DIR/drivers/bcma/Kconfig" +- + source "$BACKPORT_DIR/net/nfc/Kconfig" + + source "$BACKPORT_DIR/drivers/media/Kconfig" +--- a/Makefile.kernel ++++ b/Makefile.kernel +@@ -38,8 +38,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/ + #obj-$(CPTCFG_WLAN += drivers/net/wireless/ + obj-$(CPTCFG_BT) += net/bluetooth/ + obj-$(CPTCFG_BT) += drivers/bluetooth/ +-obj-$(CPTCFG_SSB) += drivers/ssb/ +-obj-$(CPTCFG_BCMA) += drivers/bcma/ + obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/ + obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/ + obj-$(CPTCFG_NFC) += net/nfc/ diff --git a/package/kernel/mac80211/patches/070-ath_common_config.patch b/package/kernel/mac80211/patches/070-ath_common_config.patch new file mode 100644 index 0000000..c6e9cd8 --- /dev/null +++ b/package/kernel/mac80211/patches/070-ath_common_config.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/Kconfig ++++ b/drivers/net/wireless/ath/Kconfig +@@ -6,6 +6,7 @@ menuconfig ATH_CARDS + tristate "Atheros Wireless Cards" + depends on m + depends on CFG80211 && (!UML || BROKEN) ++ select ATH_COMMON + ---help--- + This will enable the support for the Atheros wireless drivers. + ath5k, ath9k, ath9k_htc and ar9170 drivers share some common code, this option diff --git a/package/kernel/mac80211/patches/080-disable_clk_backport.patch b/package/kernel/mac80211/patches/080-disable_clk_backport.patch new file mode 100644 index 0000000..3765591 --- /dev/null +++ b/package/kernel/mac80211/patches/080-disable_clk_backport.patch @@ -0,0 +1,20 @@ +--- a/compat/compat-3.6.c ++++ b/compat/compat-3.6.c +@@ -147,17 +147,3 @@ int sg_alloc_table_from_pages(struct sg_ + return 0; + } + EXPORT_SYMBOL_GPL(sg_alloc_table_from_pages); +- +-/* whoopsie ! */ +-#ifndef CONFIG_COMMON_CLK +-int clk_enable(struct clk *clk) +-{ +- return 0; +-} +-EXPORT_SYMBOL_GPL(clk_enable); +- +-void clk_disable(struct clk *clk) +-{ +-} +-EXPORT_SYMBOL_GPL(clk_disable); +-#endif diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch new file mode 100644 index 0000000..02f46c7 --- /dev/null +++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch @@ -0,0 +1,376 @@ +--- a/net/mac80211/Kconfig ++++ b/net/mac80211/Kconfig +@@ -5,8 +5,6 @@ config MAC80211 + depends on CRYPTO + depends on CRYPTO_ARC4 + depends on CRYPTO_AES +- select BPAUTO_CRYPTO_CCM +- depends on CRYPTO_GCM + depends on CRC32 + ---help--- + This option enables the hardware independent IEEE 802.11 +--- a/net/mac80211/Makefile ++++ b/net/mac80211/Makefile +@@ -16,9 +16,7 @@ mac80211-y := \ + michael.o \ + tkip.o \ + aes_ccm.o \ +- aes_gcm.o \ + aes_cmac.o \ +- aes_gmac.o \ + cfg.o \ + ethtool.o \ + rx.o \ +--- a/net/mac80211/aes_ccm.c ++++ b/net/mac80211/aes_ccm.c +@@ -13,89 +13,132 @@ + #include + #include + #include ++#include + + #include + #include "key.h" + #include "aes_ccm.h" + +-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +- u8 *data, size_t data_len, u8 *mic, +- size_t mic_len) ++static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0, ++ u8 *a, u8 *b) + { +- struct scatterlist sg[3]; ++ int i; ++ ++ crypto_cipher_encrypt_one(tfm, b, b_0); ++ ++ /* Extra Authenticate-only data (always two AES blocks) */ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ aad[i] ^= b[i]; ++ crypto_cipher_encrypt_one(tfm, b, aad); ++ ++ aad += AES_BLOCK_SIZE; ++ ++ for (i = 0; i < AES_BLOCK_SIZE; i++) ++ aad[i] ^= b[i]; ++ crypto_cipher_encrypt_one(tfm, a, aad); + +- char aead_req_data[sizeof(struct aead_request) + +- crypto_aead_reqsize(tfm)] +- __aligned(__alignof__(struct aead_request)); +- struct aead_request *aead_req = (void *) aead_req_data; ++ /* Mask out bits from auth-only-b_0 */ ++ b_0[0] &= 0x07; + +- memset(aead_req, 0, sizeof(aead_req_data)); ++ /* S_0 is used to encrypt T (= MIC) */ ++ b_0[14] = 0; ++ b_0[15] = 0; ++ crypto_cipher_encrypt_one(tfm, s_0, b_0); ++} + +- sg_init_table(sg, 3); +- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); +- sg_set_buf(&sg[1], data, data_len); +- sg_set_buf(&sg[2], mic, mic_len); + +- aead_request_set_tfm(aead_req, tfm); +- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); +- aead_request_set_ad(aead_req, sg[0].length); ++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len) ++{ ++ int i, j, last_len, num_blocks; ++ u8 b[AES_BLOCK_SIZE]; ++ u8 s_0[AES_BLOCK_SIZE]; ++ u8 e[AES_BLOCK_SIZE]; ++ u8 *pos, *cpos; ++ ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); ++ last_len = data_len % AES_BLOCK_SIZE; ++ aes_ccm_prepare(tfm, b_0, aad, s_0, b, b); ++ ++ /* Process payload blocks */ ++ pos = data; ++ cpos = data; ++ for (j = 1; j <= num_blocks; j++) { ++ int blen = (j == num_blocks && last_len) ? ++ last_len : AES_BLOCK_SIZE; ++ ++ /* Authentication followed by encryption */ ++ for (i = 0; i < blen; i++) ++ b[i] ^= pos[i]; ++ crypto_cipher_encrypt_one(tfm, b, b); ++ ++ b_0[14] = (j >> 8) & 0xff; ++ b_0[15] = j & 0xff; ++ crypto_cipher_encrypt_one(tfm, e, b_0); ++ for (i = 0; i < blen; i++) ++ *cpos++ = *pos++ ^ e[i]; ++ } + +- crypto_aead_encrypt(aead_req); ++ for (i = 0; i < mic_len; i++) ++ mic[i] = b[i] ^ s_0[i]; + } + +-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, ++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, + u8 *data, size_t data_len, u8 *mic, + size_t mic_len) + { +- struct scatterlist sg[3]; +- char aead_req_data[sizeof(struct aead_request) + +- crypto_aead_reqsize(tfm)] +- __aligned(__alignof__(struct aead_request)); +- struct aead_request *aead_req = (void *) aead_req_data; +- +- if (data_len == 0) +- return -EINVAL; +- +- memset(aead_req, 0, sizeof(aead_req_data)); +- +- sg_init_table(sg, 3); +- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); +- sg_set_buf(&sg[1], data, data_len); +- sg_set_buf(&sg[2], mic, mic_len); +- +- aead_request_set_tfm(aead_req, tfm); +- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); +- aead_request_set_ad(aead_req, sg[0].length); ++ int i, j, last_len, num_blocks; ++ u8 *pos, *cpos; ++ u8 a[AES_BLOCK_SIZE]; ++ u8 b[AES_BLOCK_SIZE]; ++ u8 s_0[AES_BLOCK_SIZE]; ++ ++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); ++ last_len = data_len % AES_BLOCK_SIZE; ++ aes_ccm_prepare(tfm, b_0, aad, s_0, a, b); ++ ++ /* Process payload blocks */ ++ cpos = data; ++ pos = data; ++ for (j = 1; j <= num_blocks; j++) { ++ int blen = (j == num_blocks && last_len) ? ++ last_len : AES_BLOCK_SIZE; ++ ++ /* Decryption followed by authentication */ ++ b_0[14] = (j >> 8) & 0xff; ++ b_0[15] = j & 0xff; ++ crypto_cipher_encrypt_one(tfm, b, b_0); ++ for (i = 0; i < blen; i++) { ++ *pos = *cpos++ ^ b[i]; ++ a[i] ^= *pos++; ++ } ++ crypto_cipher_encrypt_one(tfm, a, a); ++ } ++ ++ for (i = 0; i < mic_len; i++) { ++ if ((mic[i] ^ s_0[i]) != a[i]) ++ return -1; ++ } + +- return crypto_aead_decrypt(aead_req); ++ return 0; + } + +-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], +- size_t key_len, +- size_t mic_len) ++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], ++ size_t key_len, ++ size_t mic_len) + { +- struct crypto_aead *tfm; +- int err; ++ struct crypto_cipher *tfm; + +- tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); +- if (IS_ERR(tfm)) +- return tfm; +- +- err = crypto_aead_setkey(tfm, key, key_len); +- if (err) +- goto free_aead; +- err = crypto_aead_setauthsize(tfm, mic_len); +- if (err) +- goto free_aead; ++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); ++ if (!IS_ERR(tfm)) ++ crypto_cipher_setkey(tfm, key, key_len); + + return tfm; +- +-free_aead: +- crypto_free_aead(tfm); +- return ERR_PTR(err); + } + +-void ieee80211_aes_key_free(struct crypto_aead *tfm) ++ ++void ieee80211_aes_key_free(struct crypto_cipher *tfm) + { +- crypto_free_aead(tfm); ++ crypto_free_cipher(tfm); + } +--- a/net/mac80211/aes_ccm.h ++++ b/net/mac80211/aes_ccm.h +@@ -12,15 +12,15 @@ + + #include + +-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], +- size_t key_len, +- size_t mic_len); +-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, ++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], ++ size_t key_len, ++ size_t mic_len); ++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, + u8 *data, size_t data_len, u8 *mic, + size_t mic_len); +-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, ++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, + u8 *data, size_t data_len, u8 *mic, + size_t mic_len); +-void ieee80211_aes_key_free(struct crypto_aead *tfm); ++void ieee80211_aes_key_free(struct crypto_cipher *tfm); + + #endif /* AES_CCM_H */ +--- a/net/mac80211/aes_gcm.h ++++ b/net/mac80211/aes_gcm.h +@@ -11,12 +11,28 @@ + + #include + +-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +- u8 *data, size_t data_len, u8 *mic); +-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +- u8 *data, size_t data_len, u8 *mic); +-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], +- size_t key_len); +-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm); ++static inline void ++ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) ++{ ++} ++ ++static inline int ++ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline struct crypto_aead * ++ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len) ++{ ++ return NULL; ++} ++ ++static inline void ++ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) ++{ ++} + + #endif /* AES_GCM_H */ +--- a/net/mac80211/aes_gmac.h ++++ b/net/mac80211/aes_gmac.h +@@ -11,10 +11,22 @@ + + #include + +-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], +- size_t key_len); +-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, +- const u8 *data, size_t data_len, u8 *mic); +-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm); ++static inline struct crypto_aead * ++ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len) ++{ ++ return NULL; ++} ++ ++static inline int ++ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, ++ const u8 *data, size_t data_len, u8 *mic) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void ++ieee80211_aes_gmac_key_free(struct crypto_aead *tfm) ++{ ++} + + #endif /* AES_GMAC_H */ +--- a/net/mac80211/key.h ++++ b/net/mac80211/key.h +@@ -84,7 +84,7 @@ struct ieee80211_key { + * Management frames. + */ + u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; +- struct crypto_aead *tfm; ++ struct crypto_cipher *tfm; + u32 replays; /* dot11RSNAStatsCCMPReplays */ + } ccmp; + struct { +--- a/net/mac80211/wpa.c ++++ b/net/mac80211/wpa.c +@@ -307,7 +307,8 @@ ieee80211_crypto_tkip_decrypt(struct iee + } + + +-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) ++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, ++ u16 data_len) + { + __le16 mask_fc; + int a4_included, mgmt; +@@ -337,14 +338,8 @@ static void ccmp_special_blocks(struct s + else + qos_tid = 0; + +- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC +- * mode authentication are not allowed to collide, yet both are derived +- * from this vector b_0. We only set L := 1 here to indicate that the +- * data size can be represented in (L+1) bytes. The CCM layer will take +- * care of storing the data length in the top (L+1) bytes and setting +- * and clearing the other bits as is required to derive the two IVs. +- */ +- b_0[0] = 0x1; ++ /* First block, b_0 */ ++ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ + + /* Nonce: Nonce Flags | A2 | PN + * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) +@@ -352,6 +347,8 @@ static void ccmp_special_blocks(struct s + b_0[1] = qos_tid | (mgmt << 4); + memcpy(&b_0[2], hdr->addr2, ETH_ALEN); + memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); ++ /* l(m) */ ++ put_unaligned_be16(data_len, &b_0[14]); + + /* AAD (extra authenticate-only data) / masked 802.11 header + * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ +@@ -463,7 +460,7 @@ static int ccmp_encrypt_skb(struct ieee8 + return 0; + + pos += IEEE80211_CCMP_HDR_LEN; +- ccmp_special_blocks(skb, pn, b_0, aad); ++ ccmp_special_blocks(skb, pn, b_0, aad, len); + ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, + skb_put(skb, mic_len), mic_len); + +@@ -534,7 +531,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee + u8 aad[2 * AES_BLOCK_SIZE]; + u8 b_0[AES_BLOCK_SIZE]; + /* hardware didn't decrypt/verify MIC */ +- ccmp_special_blocks(skb, pn, b_0, aad); ++ ccmp_special_blocks(skb, pn, b_0, aad, data_len); + + if (ieee80211_aes_ccm_decrypt( + key->u.ccmp.tfm, b_0, aad, diff --git a/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch new file mode 100644 index 0000000..d1d9fbd --- /dev/null +++ b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch @@ -0,0 +1,12 @@ +Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects + +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -846,7 +846,6 @@ static int ieee80211_stop_ap(struct wiph + sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; + + __sta_info_flush(sdata, true); +- ieee80211_free_keys(sdata, true); + + sdata->vif.bss_conf.enable_beacon = false; + sdata->vif.bss_conf.ssid_len = 0; diff --git a/package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch b/package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch new file mode 100644 index 0000000..ffd8807 --- /dev/null +++ b/package/kernel/mac80211/patches/120-cfg80211_allow_perm_addr_change.patch @@ -0,0 +1,43 @@ +--- a/net/wireless/sysfs.c ++++ b/net/wireless/sysfs.c +@@ -24,18 +24,35 @@ static inline struct cfg80211_registered + return container_of(dev, struct cfg80211_registered_device, wiphy.dev); + } + +-#define SHOW_FMT(name, fmt, member) \ ++#define SHOW_FMT(name, fmt, member, mode) \ + static ssize_t name ## _show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \ + } \ +-static DEVICE_ATTR_RO(name) ++static DEVICE_ATTR_##mode(name) + +-SHOW_FMT(index, "%d", wiphy_idx); +-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); +-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); ++static ssize_t macaddress_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ u8 mac[ETH_ALEN]; ++ ++ if (!mac_pton(buf, mac)) ++ return -EINVAL; ++ ++ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') ++ return -EINVAL; ++ ++ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN); ++ ++ return strnlen(buf, len); ++} ++ ++SHOW_FMT(index, "%d", wiphy_idx, RO); ++SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW); ++SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO); + + static ssize_t name_show(struct device *dev, + struct device_attribute *attr, diff --git a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch new file mode 100644 index 0000000..cafed72 --- /dev/null +++ b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch @@ -0,0 +1,67 @@ +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -285,7 +285,7 @@ void ieee80211_restart_hw(struct ieee802 + } + EXPORT_SYMBOL(ieee80211_restart_hw); + +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + static int ieee80211_ifa_changed(struct notifier_block *nb, + unsigned long data, void *arg) + { +@@ -344,7 +344,7 @@ static int ieee80211_ifa_changed(struct + } + #endif + +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + static int ieee80211_ifa6_changed(struct notifier_block *nb, + unsigned long data, void *arg) + { +@@ -1081,14 +1081,14 @@ int ieee80211_register_hw(struct ieee802 + + rtnl_unlock(); + +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + local->ifa_notifier.notifier_call = ieee80211_ifa_changed; + result = register_inetaddr_notifier(&local->ifa_notifier); + if (result) + goto fail_ifa; + #endif + +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; + result = register_inet6addr_notifier(&local->ifa6_notifier); + if (result) +@@ -1097,13 +1097,13 @@ int ieee80211_register_hw(struct ieee802 + + return 0; + +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + fail_ifa6: +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + unregister_inetaddr_notifier(&local->ifa_notifier); + #endif + #endif +-#if defined(CONFIG_INET) || defined(CONFIG_IPV6) ++#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6) + fail_ifa: + #endif + rtnl_lock(); +@@ -1131,10 +1131,10 @@ void ieee80211_unregister_hw(struct ieee + tasklet_kill(&local->tx_pending_tasklet); + tasklet_kill(&local->tasklet); + +-#ifdef CONFIG_INET ++#ifdef __disabled__CONFIG_INET + unregister_inetaddr_notifier(&local->ifa_notifier); + #endif +-#if IS_ENABLED(CONFIG_IPV6) ++#if IS_ENABLED(__disabled__CONFIG_IPV6) + unregister_inet6addr_notifier(&local->ifa6_notifier); + #endif + diff --git a/package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch new file mode 100644 index 0000000..21516ff --- /dev/null +++ b/package/kernel/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch @@ -0,0 +1,38 @@ +--- a/drivers/net/wireless/ath/ath5k/initvals.c ++++ b/drivers/net/wireless/ath/ath5k/initvals.c +@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini + { AR5K_IMR, 0 }, + { AR5K_IER, AR5K_IER_DISABLE }, + { AR5K_BSR, 0, AR5K_INI_READ }, ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + { AR5K_TXCFG, AR5K_DMASIZE_128B }, + { AR5K_RXCFG, AR5K_DMASIZE_128B }, ++#else ++ /* WAR for AR71xx PCI bug */ ++ { AR5K_TXCFG, AR5K_DMASIZE_128B }, ++ { AR5K_RXCFG, AR5K_DMASIZE_4B }, ++#endif + { AR5K_CFG, AR5K_INIT_CFG }, + { AR5K_TOPS, 8 }, + { AR5K_RXNOFRM, 8 }, +--- a/drivers/net/wireless/ath/ath5k/dma.c ++++ b/drivers/net/wireless/ath/ath5k/dma.c +@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah) + * guess we can tweak it and see how it goes ;-) + */ + if (ah->ah_version != AR5K_AR5210) { ++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79) + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); ++#else ++ /* WAR for AR71xx PCI bug */ ++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, ++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); ++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, ++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B); ++#endif + } + + /* Pre-enable interrupts on 5211/5212*/ diff --git a/package/kernel/mac80211/patches/210-ap_scan.patch b/package/kernel/mac80211/patches/210-ap_scan.patch new file mode 100644 index 0000000..2980f8b --- /dev/null +++ b/package/kernel/mac80211/patches/210-ap_scan.patch @@ -0,0 +1,11 @@ +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -1981,7 +1981,7 @@ static int ieee80211_scan(struct wiphy * + * the frames sent while scanning on other channel will be + * lost) + */ +- if (sdata->u.ap.beacon && ++ if (0 && sdata->u.ap.beacon && + (!(wiphy->features & NL80211_FEATURE_AP_SCAN) || + !(req->flags & NL80211_SCAN_FLAG_AP))) + return -EOPNOTSUPP; diff --git a/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch new file mode 100644 index 0000000..bddb15a --- /dev/null +++ b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch @@ -0,0 +1,31 @@ +From: Felix Fietkau +Date: Sun, 7 Jun 2015 13:53:35 +0200 +Subject: [PATCH] ath9k: force rx_clear when disabling rx + +This makes stopping Rx more reliable and should reduce the frequency of +Rx related DMA stop warnings + +Cc: stable@vger.kernel.org +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath + + ath9k_ani_reset(ah, is_scanning); + +- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); ++ REG_CLR_BIT(ah, AR_DIAG_SW, ++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); + } + EXPORT_SYMBOL(ath9k_hw_startpcureceive); + + void ath9k_hw_abortpcurecv(struct ath_hw *ah) + { +- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); ++ REG_SET_BIT(ah, AR_DIAG_SW, ++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); + + ath9k_hw_disable_mib_counters(ah); + } diff --git a/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch new file mode 100644 index 0000000..33b21e6 --- /dev/null +++ b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch @@ -0,0 +1,121 @@ +From: Felix Fietkau +Date: Thu, 2 Jul 2015 15:20:56 +0200 +Subject: [PATCH] ath9k: limit retries for powersave response frames + +In some cases, the channel might be busy enough that an ath9k AP's +response to PS-Poll frames might be too slow and the station has already +gone to sleep. To avoid wasting too much airtime on this, limit the +number of retries on such frames and ensure that no sample rate gets +used. + +Signed-off-by: Felix Fietkau +--- + +--- a/drivers/net/wireless/ath/ath9k/xmit.c ++++ b/drivers/net/wireless/ath/ath9k/xmit.c +@@ -136,10 +136,25 @@ static void ath_send_bar(struct ath_atx_ + } + + static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta, +- struct ath_buf *bf) ++ struct ath_buf *bf, bool ps) + { ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu); ++ ++ if (ps) { ++ /* Clear the first rate to avoid using a sample rate for PS frames */ ++ info->control.rates[0].idx = -1; ++ info->control.rates[0].count = 0; ++ } ++ + ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates, + ARRAY_SIZE(bf->rates)); ++ if (!ps) ++ return; ++ ++ if (bf->rates[0].count > 2) ++ bf->rates[0].count = 2; ++ ++ bf->rates[1].idx = -1; + } + + static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, +@@ -1419,7 +1434,7 @@ ath_tx_form_burst(struct ath_softc *sc, + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) + break; + +- ath_set_rates(tid->an->vif, tid->an->sta, bf); ++ ath_set_rates(tid->an->vif, tid->an->sta, bf, false); + } while (1); + } + +@@ -1450,7 +1465,7 @@ static bool ath_tx_sched_aggr(struct ath + return false; + } + +- ath_set_rates(tid->an->vif, tid->an->sta, bf); ++ ath_set_rates(tid->an->vif, tid->an->sta, bf, false); + if (aggr) + last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf, + tid_q, &aggr_len); +@@ -1632,7 +1647,7 @@ void ath9k_release_buffered_frames(struc + + __skb_unlink(bf->bf_mpdu, tid_q); + list_add_tail(&bf->list, &bf_q); +- ath_set_rates(tid->an->vif, tid->an->sta, bf); ++ ath_set_rates(tid->an->vif, tid->an->sta, bf, true); + if (bf_isampdu(bf)) { + ath_tx_addto_baw(sc, tid, bf); + bf->bf_state.bf_type &= ~BUF_AGGR; +@@ -2278,7 +2293,7 @@ int ath_tx_start(struct ieee80211_hw *hw + struct ath_txq *txq = txctl->txq; + struct ath_atx_tid *tid = NULL; + struct ath_buf *bf; +- bool queue, skip_uapsd = false, ps_resp; ++ bool queue, ps_resp; + int q, ret; + + if (vif) +@@ -2325,13 +2340,13 @@ int ath_tx_start(struct ieee80211_hw *hw + if (!txctl->an) + txctl->an = &avp->mcast_node; + queue = true; +- skip_uapsd = true; ++ ps_resp = false; + } + + if (txctl->an && queue) + tid = ath_get_skb_tid(sc, txctl->an, skb); + +- if (!skip_uapsd && ps_resp) { ++ if (ps_resp) { + ath_txq_unlock(sc, txq); + txq = sc->tx.uapsdq; + ath_txq_lock(sc, txq); +@@ -2369,7 +2384,7 @@ int ath_tx_start(struct ieee80211_hw *hw + if (txctl->paprd) + bf->bf_state.bfs_paprd_timestamp = jiffies; + +- ath_set_rates(vif, sta, bf); ++ ath_set_rates(vif, sta, bf, ps_resp); + ath_tx_send_normal(sc, txq, tid, skb); + + out: +@@ -2408,7 +2423,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw + break; + + bf->bf_lastbf = bf; +- ath_set_rates(vif, NULL, bf); ++ ath_set_rates(vif, NULL, bf, false); + ath_buf_set_rate(sc, bf, &info, fi->framelen, false); + duration += info.rates[0].PktDuration; + if (bf_tail) +@@ -2911,7 +2926,7 @@ int ath9k_tx99_send(struct ath_softc *sc + return -EINVAL; + } + +- ath_set_rates(sc->tx99_vif, NULL, bf); ++ ath_set_rates(sc->tx99_vif, NULL, bf, false); + + ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr); + ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum); diff --git a/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch b/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch new file mode 100644 index 0000000..944b8e7 --- /dev/null +++ b/package/kernel/mac80211/patches/302-ath9k-fix-phyerror-codes.patch @@ -0,0 +1,108 @@ +From: Zefir Kurtisi +Date: Tue, 20 Oct 2015 14:19:26 +0200 +Subject: [PATCH] ath9k: fix phyerror codes + +Some of the ath9k_phyerr enums were wrong from the +beginning (and even before). Most of the time the +codes were used for counters to be displayed over +debugfs, which made this a non-functional issue. + +Some (e.g. ATH9K_PHYERR_FALSE_RADAR_EXT) are used +for radar detection and require the correct code +to work as intended. + +This patch includes: +a) fixes + ATH9K_PHYERR_FALSE_RADAR_EXT: 24 => 36 + ATH9K_PHYERR_CCK_LENGTH_ILLEGAL: 32 => 28 + ATH9K_PHYERR_CCK_POWER_DROP: 33 => 29 + ATH9K_PHYERR_HT_CRC_ERROR: 34 => 32 + ATH9K_PHYERR_HT_LENGTH_ILLEGAL: 35 => 33 + ATH9K_PHYERR_HT_RATE_ILLEGAL: 36 => 34 + +b) extensions + ATH9K_PHYERR_CCK_BLOCKER = 24 + ATH9K_PHYERR_HT_ZLF = 35 + ATH9K_PHYERR_GREEN_FIELD = 37 + +Aside from the correction and completion made in +the enum, the patch also extends the display of +the related counters in the debugfs. + +Signed-off-by: Zefir Kurtisi +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath9k/common-debug.c ++++ b/drivers/net/wireless/ath/ath9k/common-debug.c +@@ -207,6 +207,7 @@ static ssize_t read_file_phy_err(struct + PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR); + PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE); + PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR); ++ + PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING); + PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); + PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); +@@ -214,17 +215,24 @@ static ssize_t read_file_phy_err(struct + PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP); + PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE); + PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART); +- PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); ++ ++ PHY_ERR("CCK-BLOCKER ERR", ATH9K_PHYERR_CCK_BLOCKER); + PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING); + PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC); + PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL); +- PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); +- PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); + PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); + PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP); ++ PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE); ++ PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART); ++ + PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR); + PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); + PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL); ++ PHY_ERR("HT-ZLF ERR", ATH9K_PHYERR_HT_ZLF); ++ ++ PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT); ++ PHY_ERR("GREEN-FIELD ERR", ATH9K_PHYERR_GREEN_FIELD); ++ PHY_ERR("SPECTRAL ERR", ATH9K_PHYERR_SPECTRAL); + + if (len > size) + len = size; +--- a/drivers/net/wireless/ath/ath9k/mac.h ++++ b/drivers/net/wireless/ath/ath9k/mac.h +@@ -209,21 +209,25 @@ enum ath9k_phyerr { + ATH9K_PHYERR_OFDM_POWER_DROP = 21, + ATH9K_PHYERR_OFDM_SERVICE = 22, + ATH9K_PHYERR_OFDM_RESTART = 23, +- ATH9K_PHYERR_FALSE_RADAR_EXT = 24, + ++ ATH9K_PHYERR_CCK_BLOCKER = 24, + ATH9K_PHYERR_CCK_TIMING = 25, + ATH9K_PHYERR_CCK_HEADER_CRC = 26, + ATH9K_PHYERR_CCK_RATE_ILLEGAL = 27, ++ ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 28, ++ ATH9K_PHYERR_CCK_POWER_DROP = 29, + ATH9K_PHYERR_CCK_SERVICE = 30, + ATH9K_PHYERR_CCK_RESTART = 31, +- ATH9K_PHYERR_CCK_LENGTH_ILLEGAL = 32, +- ATH9K_PHYERR_CCK_POWER_DROP = 33, + +- ATH9K_PHYERR_HT_CRC_ERROR = 34, +- ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35, +- ATH9K_PHYERR_HT_RATE_ILLEGAL = 36, ++ ATH9K_PHYERR_HT_CRC_ERROR = 32, ++ ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 33, ++ ATH9K_PHYERR_HT_RATE_ILLEGAL = 34, ++ ATH9K_PHYERR_HT_ZLF = 35, ++ ++ ATH9K_PHYERR_FALSE_RADAR_EXT = 36, ++ ATH9K_PHYERR_GREEN_FIELD = 37, ++ ATH9K_PHYERR_SPECTRAL = 38, + +- ATH9K_PHYERR_SPECTRAL = 38, + ATH9K_PHYERR_MAX = 39, + }; + diff --git a/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch b/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch new file mode 100644 index 0000000..dea65bb --- /dev/null +++ b/package/kernel/mac80211/patches/303-ath10k-enable-adaptive-CCA.patch @@ -0,0 +1,239 @@ +From: Maharaja +Date: Wed, 21 Oct 2015 11:49:18 +0300 +Subject: [PATCH] ath10k: enable adaptive CCA + +European Union has made it mandatory that all devices working in 2.4 GHz +has to adhere to the ETSI specification (ETSI EN 300 328 V1.9.1) +beginnig this year. The standard basically speaks about interferences +in 2.4Ghz band. +For example, when 802.11 device detects interference, TX must be stopped +as long as interference is present. + +Adaptive CCA is a feature, when enabled the device learns from the +environment and configures CCA levels adaptively. This will improve +detecting interferences and the device can stop trasmissions till the +interference is present eventually leading to good performances in +varying interference conditions. + +The patch includes code for enabling adaptive CCA for 10.2.4 firmware on +QCA988X. + +Signed-off-by: Maharaja +Signed-off-by: Manikanta Pubbisetty +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -151,6 +151,7 @@ static const char *const ath10k_core_fw_ + [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad", + [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", + [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", ++ [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", + }; + + static unsigned int ath10k_core_get_fw_feature_str(char *buf, +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -497,6 +497,9 @@ enum ath10k_fw_features { + */ + ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10, + ++ /* Firmware Supports Adaptive CCA*/ ++ ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11, ++ + /* keep last */ + ATH10K_FW_FEATURE_COUNT, + }; +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -3905,6 +3905,18 @@ static int ath10k_start(struct ieee80211 + goto err_core_stop; + } + ++ if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA, ++ ar->fw_features)) { ++ ret = ath10k_wmi_pdev_enable_adaptive_cca(ar, 1, ++ WMI_CCA_DETECT_LEVEL_AUTO, ++ WMI_CCA_DETECT_MARGIN_AUTO); ++ if (ret) { ++ ath10k_warn(ar, "failed to enable adaptive cca: %d\n", ++ ret); ++ goto err_core_stop; ++ } ++ } ++ + ret = ath10k_wmi_pdev_set_param(ar, + ar->wmi.pdev_param->ani_enable, 1); + if (ret) { +--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h ++++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h +@@ -182,6 +182,10 @@ struct wmi_ops { + void (*fw_stats_fill)(struct ath10k *ar, + struct ath10k_fw_stats *fw_stats, + char *buf); ++ struct sk_buff *(*gen_pdev_enable_adaptive_cca)(struct ath10k *ar, ++ u8 enable, ++ u32 detect_level, ++ u32 detect_margin); + }; + + int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); +@@ -1302,4 +1306,25 @@ ath10k_wmi_fw_stats_fill(struct ath10k * + ar->wmi.ops->fw_stats_fill(ar, fw_stats, buf); + return 0; + } ++ ++static inline int ++ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, ++ u32 detect_level, u32 detect_margin) ++{ ++ struct sk_buff *skb; ++ ++ if (!ar->wmi.ops->gen_pdev_enable_adaptive_cca) ++ return -EOPNOTSUPP; ++ ++ skb = ar->wmi.ops->gen_pdev_enable_adaptive_cca(ar, enable, ++ detect_level, ++ detect_margin); ++ ++ if (IS_ERR(skb)) ++ return PTR_ERR(skb); ++ ++ return ath10k_wmi_cmd_send(ar, skb, ++ ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); ++} ++ + #endif +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -148,6 +148,7 @@ static struct wmi_cmd_map wmi_cmd_map = + .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID, + .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID, + .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, ++ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, + .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, +@@ -313,6 +314,7 @@ static struct wmi_cmd_map wmi_10x_cmd_ma + .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID, + .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID, + .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, ++ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, + .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, +@@ -477,6 +479,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd + .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, + .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, + .pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, ++ .pdev_enable_adaptive_cca_cmdid = WMI_10_2_SET_CCA_PARAMS, + .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, +@@ -1407,6 +1410,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_m + .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID, + .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, + .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED, ++ .pdev_enable_adaptive_cca_cmdid = WMI_CMD_UNSUPPORTED, + .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED, + .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED, +@@ -6996,6 +7000,28 @@ unlock: + buf[len] = 0; + } + ++static struct sk_buff * ++ath10k_wmi_op_gen_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, ++ u32 detect_level, u32 detect_margin) ++{ ++ struct wmi_pdev_set_adaptive_cca_params *cmd; ++ struct sk_buff *skb; ++ ++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); ++ if (!skb) ++ return ERR_PTR(-ENOMEM); ++ ++ cmd = (struct wmi_pdev_set_adaptive_cca_params *)skb->data; ++ cmd->enable = __cpu_to_le32(enable); ++ cmd->cca_detect_level = __cpu_to_le32(detect_level); ++ cmd->cca_detect_margin = __cpu_to_le32(detect_margin); ++ ++ ath10k_dbg(ar, ATH10K_DBG_WMI, ++ "wmi pdev set adaptive cca params enable:%d detection level:%d detection margin:%d\n", ++ enable, detect_level, detect_margin); ++ return skb; ++} ++ + static const struct wmi_ops wmi_ops = { + .rx = ath10k_wmi_op_rx, + .map_svc = wmi_main_svc_map, +@@ -7059,6 +7085,7 @@ static const struct wmi_ops wmi_ops = { + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ + /* .gen_adaptive_qcs not implemented */ ++ /* .gen_pdev_enable_adaptive_cca not implemented */ + }; + + static const struct wmi_ops wmi_10_1_ops = { +@@ -7125,6 +7152,7 @@ static const struct wmi_ops wmi_10_1_ops + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ + /* .gen_adaptive_qcs not implemented */ ++ /* .gen_pdev_enable_adaptive_cca not implemented */ + }; + + static const struct wmi_ops wmi_10_2_ops = { +@@ -7188,6 +7216,7 @@ static const struct wmi_ops wmi_10_2_ops + .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, + .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, ++ /* .gen_pdev_enable_adaptive_cca not implemented */ + }; + + static const struct wmi_ops wmi_10_2_4_ops = { +@@ -7251,6 +7280,8 @@ static const struct wmi_ops wmi_10_2_4_o + .gen_delba_send = ath10k_wmi_op_gen_delba_send, + .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config, + .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, ++ .gen_pdev_enable_adaptive_cca = ++ ath10k_wmi_op_gen_pdev_enable_adaptive_cca, + /* .gen_bcn_tmpl not implemented */ + /* .gen_prb_tmpl not implemented */ + /* .gen_p2p_go_bcn_ie not implemented */ +--- a/drivers/net/wireless/ath/ath10k/wmi.h ++++ b/drivers/net/wireless/ath/ath10k/wmi.h +@@ -772,6 +772,7 @@ struct wmi_cmd_map { + u32 mu_cal_start_cmdid; + u32 set_cca_params_cmdid; + u32 pdev_bss_chan_info_request_cmdid; ++ u32 pdev_enable_adaptive_cca_cmdid; + }; + + /* +@@ -1381,6 +1382,9 @@ enum wmi_10_2_cmd_id { + WMI_10_2_VDEV_ATF_REQUEST_CMDID, + WMI_10_2_PEER_ATF_REQUEST_CMDID, + WMI_10_2_PDEV_GET_TEMPERATURE_CMDID, ++ WMI_10_2_MU_CAL_START_CMDID, ++ WMI_10_2_SET_LTEU_CONFIG_CMDID, ++ WMI_10_2_SET_CCA_PARAMS, + WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1, + }; + +@@ -6094,6 +6098,15 @@ enum wmi_txbf_conf { + WMI_TXBF_CONF_AFTER_ASSOC, + }; + ++#define WMI_CCA_DETECT_LEVEL_AUTO 0 ++#define WMI_CCA_DETECT_MARGIN_AUTO 0 ++ ++struct wmi_pdev_set_adaptive_cca_params { ++ __le32 enable; ++ __le32 cca_detect_level; ++ __le32 cca_detect_margin; ++} __packed; ++ + struct ath10k; + struct ath10k_vif; + struct ath10k_fw_stats_pdev; diff --git a/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch b/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch new file mode 100644 index 0000000..e4ccac3 --- /dev/null +++ b/package/kernel/mac80211/patches/304-ath10k-add-FW-API-support-to-test-mode.patch @@ -0,0 +1,331 @@ +From: Alan Liu +Date: Wed, 28 Oct 2015 21:38:32 +0200 +Subject: [PATCH] ath10k: add FW API support to test mode + +Add WMI-TLV and FW API support in ath10k testmode. +Ath10k can get right wmi command format from UTF image +to communicate UTF firmware. + +Signed-off-by: Alan Liu +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -569,8 +569,8 @@ static int ath10k_download_fw(struct ath + } + break; + case ATH10K_FIRMWARE_MODE_UTF: +- data = ar->testmode.utf->data; +- data_len = ar->testmode.utf->size; ++ data = ar->testmode.utf_firmware_data; ++ data_len = ar->testmode.utf_firmware_len; + mode_name = "utf"; + break; + default: +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -817,9 +817,12 @@ struct ath10k { + struct { + /* protected by conf_mutex */ + const struct firmware *utf; ++ char utf_version[32]; ++ const void *utf_firmware_data; ++ size_t utf_firmware_len; + DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT); + enum ath10k_fw_wmi_op_version orig_wmi_op_version; +- ++ enum ath10k_fw_wmi_op_version op_version; + /* protected by data_lock */ + bool utf_monitor; + } testmode; +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -94,6 +94,7 @@ enum qca6174_chip_id_rev { + #define ATH10K_FW_API5_FILE "firmware-5.bin" + + #define ATH10K_FW_UTF_FILE "utf.bin" ++#define ATH10K_FW_UTF_API2_FILE "utf-2.bin" + + /* includes also the null byte */ + #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" +--- a/drivers/net/wireless/ath/ath10k/testmode.c ++++ b/drivers/net/wireless/ath/ath10k/testmode.c +@@ -139,11 +139,181 @@ static int ath10k_tm_cmd_get_version(str + return cfg80211_testmode_reply(skb); + } + +-static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ++static int ath10k_tm_fetch_utf_firmware_api_2(struct ath10k *ar) ++{ ++ size_t len, magic_len, ie_len; ++ struct ath10k_fw_ie *hdr; ++ char filename[100]; ++ __le32 *version; ++ const u8 *data; ++ int ie_id, ret; ++ ++ snprintf(filename, sizeof(filename), "%s/%s", ++ ar->hw_params.fw.dir, ATH10K_FW_UTF_API2_FILE); ++ ++ /* load utf firmware image */ ++ ret = request_firmware(&ar->testmode.utf, filename, ar->dev); ++ if (ret) { ++ ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", ++ filename, ret); ++ return ret; ++ } ++ ++ data = ar->testmode.utf->data; ++ len = ar->testmode.utf->size; ++ ++ /* FIXME: call release_firmware() in error cases */ ++ ++ /* magic also includes the null byte, check that as well */ ++ magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1; ++ ++ if (len < magic_len) { ++ ath10k_err(ar, "utf firmware file is too small to contain magic\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) { ++ ath10k_err(ar, "invalid firmware magic\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ /* jump over the padding */ ++ magic_len = ALIGN(magic_len, 4); ++ ++ len -= magic_len; ++ data += magic_len; ++ ++ /* loop elements */ ++ while (len > sizeof(struct ath10k_fw_ie)) { ++ hdr = (struct ath10k_fw_ie *)data; ++ ++ ie_id = le32_to_cpu(hdr->id); ++ ie_len = le32_to_cpu(hdr->len); ++ ++ len -= sizeof(*hdr); ++ data += sizeof(*hdr); ++ ++ if (len < ie_len) { ++ ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n", ++ ie_id, len, ie_len); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ switch (ie_id) { ++ case ATH10K_FW_IE_FW_VERSION: ++ if (ie_len > sizeof(ar->testmode.utf_version) - 1) ++ break; ++ ++ memcpy(ar->testmode.utf_version, data, ie_len); ++ ar->testmode.utf_version[ie_len] = '\0'; ++ ++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, ++ "testmode found fw utf version %s\n", ++ ar->testmode.utf_version); ++ break; ++ case ATH10K_FW_IE_TIMESTAMP: ++ /* ignore timestamp, but don't warn about it either */ ++ break; ++ case ATH10K_FW_IE_FW_IMAGE: ++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, ++ "testmode found fw image ie (%zd B)\n", ++ ie_len); ++ ++ ar->testmode.utf_firmware_data = data; ++ ar->testmode.utf_firmware_len = ie_len; ++ break; ++ case ATH10K_FW_IE_WMI_OP_VERSION: ++ if (ie_len != sizeof(u32)) ++ break; ++ version = (__le32 *)data; ++ ar->testmode.op_version = le32_to_cpup(version); ++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode found fw ie wmi op version %d\n", ++ ar->testmode.op_version); ++ break; ++ default: ++ ath10k_warn(ar, "Unknown testmode FW IE: %u\n", ++ le32_to_cpu(hdr->id)); ++ break; ++ } ++ /* jump over the padding */ ++ ie_len = ALIGN(ie_len, 4); ++ ++ len -= ie_len; ++ data += ie_len; ++ } ++ ++ if (!ar->testmode.utf_firmware_data || !ar->testmode.utf_firmware_len) { ++ ath10k_err(ar, "No ATH10K_FW_IE_FW_IMAGE found\n"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ release_firmware(ar->testmode.utf); ++ ++ return ret; ++} ++ ++static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar) + { + char filename[100]; + int ret; + ++ snprintf(filename, sizeof(filename), "%s/%s", ++ ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); ++ ++ /* load utf firmware image */ ++ ret = request_firmware(&ar->testmode.utf, filename, ar->dev); ++ if (ret) { ++ ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", ++ filename, ret); ++ return ret; ++ } ++ ++ /* We didn't find FW UTF API 1 ("utf.bin") does not advertise ++ * firmware features. Do an ugly hack where we force the firmware ++ * features to match with 10.1 branch so that wmi.c will use the ++ * correct WMI interface. ++ */ ++ ++ ar->testmode.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; ++ ar->testmode.utf_firmware_data = ar->testmode.utf->data; ++ ar->testmode.utf_firmware_len = ar->testmode.utf->size; ++ ++ return 0; ++} ++ ++static int ath10k_tm_fetch_firmware(struct ath10k *ar) ++{ ++ int ret; ++ ++ ret = ath10k_tm_fetch_utf_firmware_api_2(ar); ++ if (ret == 0) { ++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using fw utf api 2"); ++ return 0; ++ } ++ ++ ret = ath10k_tm_fetch_utf_firmware_api_1(ar); ++ if (ret) { ++ ath10k_err(ar, "failed to fetch utf firmware binary: %d", ret); ++ return ret; ++ } ++ ++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode using utf api 1"); ++ ++ return 0; ++} ++ ++static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[]) ++{ ++ const char *ver; ++ int ret; ++ + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n"); + + mutex_lock(&ar->conf_mutex); +@@ -165,36 +335,27 @@ static int ath10k_tm_cmd_utf_start(struc + goto err; + } + +- snprintf(filename, sizeof(filename), "%s/%s", +- ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); +- +- /* load utf firmware image */ +- ret = request_firmware(&ar->testmode.utf, filename, ar->dev); ++ ret = ath10k_tm_fetch_firmware(ar); + if (ret) { +- ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", +- filename, ret); ++ ath10k_err(ar, "failed to fetch UTF firmware: %d", ret); + goto err; + } + + spin_lock_bh(&ar->data_lock); +- + ar->testmode.utf_monitor = true; +- + spin_unlock_bh(&ar->data_lock); +- + BUILD_BUG_ON(sizeof(ar->fw_features) != + sizeof(ar->testmode.orig_fw_features)); + + memcpy(ar->testmode.orig_fw_features, ar->fw_features, + sizeof(ar->fw_features)); + ar->testmode.orig_wmi_op_version = ar->wmi.op_version; +- +- /* utf.bin firmware image does not advertise firmware features. Do +- * an ugly hack where we force the firmware features so that wmi.c +- * will use the correct WMI interface. +- */ + memset(ar->fw_features, 0, sizeof(ar->fw_features)); +- ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1; ++ ++ ar->wmi.op_version = ar->testmode.op_version; ++ ++ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode wmi version %d\n", ++ ar->wmi.op_version); + + ret = ath10k_hif_power_up(ar); + if (ret) { +@@ -212,7 +373,12 @@ static int ath10k_tm_cmd_utf_start(struc + + ar->state = ATH10K_STATE_UTF; + +- ath10k_info(ar, "UTF firmware started\n"); ++ if (strlen(ar->testmode.utf_version) > 0) ++ ver = ar->testmode.utf_version; ++ else ++ ver = "API 1"; ++ ++ ath10k_info(ar, "UTF firmware %s started\n", ver); + + mutex_unlock(&ar->conf_mutex); + +--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c ++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c +@@ -23,6 +23,7 @@ + #include "wmi-ops.h" + #include "wmi-tlv.h" + #include "p2p.h" ++#include "testmode.h" + + /***************/ + /* TLV helpers */ +@@ -419,6 +420,7 @@ static void ath10k_wmi_tlv_op_rx(struct + { + struct wmi_cmd_hdr *cmd_hdr; + enum wmi_tlv_event_id id; ++ bool consumed; + + cmd_hdr = (struct wmi_cmd_hdr *)skb->data; + id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); +@@ -428,6 +430,18 @@ static void ath10k_wmi_tlv_op_rx(struct + + trace_ath10k_wmi_event(ar, id, skb->data, skb->len); + ++ consumed = ath10k_tm_event_wmi(ar, id, skb); ++ ++ /* Ready event must be handled normally also in UTF mode so that we ++ * know the UTF firmware has booted, others we are just bypass WMI ++ * events to testmode. ++ */ ++ if (consumed && id != WMI_TLV_READY_EVENTID) { ++ ath10k_dbg(ar, ATH10K_DBG_WMI, ++ "wmi tlv testmode consumed 0x%x\n", id); ++ goto out; ++ } ++ + switch (id) { + case WMI_TLV_MGMT_RX_EVENTID: + ath10k_wmi_event_mgmt_rx(ar, skb); diff --git a/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch b/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch new file mode 100644 index 0000000..7deb19c --- /dev/null +++ b/package/kernel/mac80211/patches/305-ath10k-add-fw_stats-support-to-10.4-firmware.patch @@ -0,0 +1,468 @@ +From: Manikanta Pubbisetty +Date: Wed, 28 Oct 2015 21:38:33 +0200 +Subject: [PATCH] ath10k: add fw_stats support to 10.4 firmware + +This patch adds support for getting firmware debug stats in 10.4 fw. + +Signed-off-by: Manikanta Pubbisetty +Signed-off-by: Tamizh chelvam +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -214,6 +214,7 @@ struct ath10k_fw_stats_pdev { + s32 hw_queued; + s32 hw_reaped; + s32 underrun; ++ u32 hw_paused; + s32 tx_abort; + s32 mpdus_requed; + u32 tx_ko; +@@ -226,6 +227,16 @@ struct ath10k_fw_stats_pdev { + u32 pdev_resets; + u32 phy_underrun; + u32 txop_ovf; ++ u32 seq_posted; ++ u32 seq_failed_queueing; ++ u32 seq_completed; ++ u32 seq_restarted; ++ u32 mu_seq_posted; ++ u32 mpdus_sw_flush; ++ u32 mpdus_hw_filter; ++ u32 mpdus_truncated; ++ u32 mpdus_ack_failed; ++ u32 mpdus_expired; + + /* PDEV RX stats */ + s32 mid_ppdu_route_change; +@@ -242,6 +253,7 @@ struct ath10k_fw_stats_pdev { + s32 phy_errs; + s32 phy_err_drop; + s32 mpdu_errs; ++ s32 rx_ovfl_errs; + }; + + struct ath10k_fw_stats { +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -2479,6 +2479,47 @@ void ath10k_wmi_pull_pdev_stats_tx(const + dst->txop_ovf = __le32_to_cpu(src->txop_ovf); + } + ++static void ++ath10k_wmi_10_4_pull_pdev_stats_tx(const struct wmi_10_4_pdev_stats_tx *src, ++ struct ath10k_fw_stats_pdev *dst) ++{ ++ dst->comp_queued = __le32_to_cpu(src->comp_queued); ++ dst->comp_delivered = __le32_to_cpu(src->comp_delivered); ++ dst->msdu_enqued = __le32_to_cpu(src->msdu_enqued); ++ dst->mpdu_enqued = __le32_to_cpu(src->mpdu_enqued); ++ dst->wmm_drop = __le32_to_cpu(src->wmm_drop); ++ dst->local_enqued = __le32_to_cpu(src->local_enqued); ++ dst->local_freed = __le32_to_cpu(src->local_freed); ++ dst->hw_queued = __le32_to_cpu(src->hw_queued); ++ dst->hw_reaped = __le32_to_cpu(src->hw_reaped); ++ dst->underrun = __le32_to_cpu(src->underrun); ++ dst->tx_abort = __le32_to_cpu(src->tx_abort); ++ dst->mpdus_requed = __le32_to_cpu(src->mpdus_requed); ++ dst->tx_ko = __le32_to_cpu(src->tx_ko); ++ dst->data_rc = __le32_to_cpu(src->data_rc); ++ dst->self_triggers = __le32_to_cpu(src->self_triggers); ++ dst->sw_retry_failure = __le32_to_cpu(src->sw_retry_failure); ++ dst->illgl_rate_phy_err = __le32_to_cpu(src->illgl_rate_phy_err); ++ dst->pdev_cont_xretry = __le32_to_cpu(src->pdev_cont_xretry); ++ dst->pdev_tx_timeout = __le32_to_cpu(src->pdev_tx_timeout); ++ dst->pdev_resets = __le32_to_cpu(src->pdev_resets); ++ dst->phy_underrun = __le32_to_cpu(src->phy_underrun); ++ dst->txop_ovf = __le32_to_cpu(src->txop_ovf); ++ dst->hw_paused = __le32_to_cpu(src->hw_paused); ++ dst->seq_posted = __le32_to_cpu(src->seq_posted); ++ dst->seq_failed_queueing = ++ __le32_to_cpu(src->seq_failed_queueing); ++ dst->seq_completed = __le32_to_cpu(src->seq_completed); ++ dst->seq_restarted = __le32_to_cpu(src->seq_restarted); ++ dst->mu_seq_posted = __le32_to_cpu(src->mu_seq_posted); ++ dst->mpdus_sw_flush = __le32_to_cpu(src->mpdus_sw_flush); ++ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); ++ dst->mpdus_truncated = __le32_to_cpu(src->mpdus_truncated); ++ dst->mpdus_ack_failed = __le32_to_cpu(src->mpdus_ack_failed); ++ dst->mpdus_hw_filter = __le32_to_cpu(src->mpdus_hw_filter); ++ dst->mpdus_expired = __le32_to_cpu(src->mpdus_expired); ++} ++ + void ath10k_wmi_pull_pdev_stats_rx(const struct wmi_pdev_stats_rx *src, + struct ath10k_fw_stats_pdev *dst) + { +@@ -2789,6 +2830,86 @@ static int ath10k_wmi_10_2_4_op_pull_fw_ + return 0; + } + ++static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, ++ struct sk_buff *skb, ++ struct ath10k_fw_stats *stats) ++{ ++ const struct wmi_10_2_stats_event *ev = (void *)skb->data; ++ u32 num_pdev_stats; ++ u32 num_pdev_ext_stats; ++ u32 num_vdev_stats; ++ u32 num_peer_stats; ++ int i; ++ ++ if (!skb_pull(skb, sizeof(*ev))) ++ return -EPROTO; ++ ++ num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); ++ num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); ++ num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); ++ num_peer_stats = __le32_to_cpu(ev->num_peer_stats); ++ ++ for (i = 0; i < num_pdev_stats; i++) { ++ const struct wmi_10_4_pdev_stats *src; ++ struct ath10k_fw_stats_pdev *dst; ++ ++ src = (void *)skb->data; ++ if (!skb_pull(skb, sizeof(*src))) ++ return -EPROTO; ++ ++ dst = kzalloc(sizeof(*dst), GFP_ATOMIC); ++ if (!dst) ++ continue; ++ ++ ath10k_wmi_pull_pdev_stats_base(&src->base, dst); ++ ath10k_wmi_10_4_pull_pdev_stats_tx(&src->tx, dst); ++ ath10k_wmi_pull_pdev_stats_rx(&src->rx, dst); ++ dst->rx_ovfl_errs = __le32_to_cpu(src->rx_ovfl_errs); ++ ath10k_wmi_pull_pdev_stats_extra(&src->extra, dst); ++ ++ list_add_tail(&dst->list, &stats->pdevs); ++ } ++ ++ for (i = 0; i < num_pdev_ext_stats; i++) { ++ const struct wmi_10_2_pdev_ext_stats *src; ++ ++ src = (void *)skb->data; ++ if (!skb_pull(skb, sizeof(*src))) ++ return -EPROTO; ++ ++ /* FIXME: expose values to userspace ++ * ++ * Note: Even though this loop seems to do nothing it is ++ * required to parse following sub-structures properly. ++ */ ++ } ++ ++ /* fw doesn't implement vdev stats */ ++ ++ for (i = 0; i < num_peer_stats; i++) { ++ const struct wmi_10_4_peer_stats *src; ++ struct ath10k_fw_stats_peer *dst; ++ ++ src = (void *)skb->data; ++ if (!skb_pull(skb, sizeof(*src))) ++ return -EPROTO; ++ ++ dst = kzalloc(sizeof(*dst), GFP_ATOMIC); ++ if (!dst) ++ continue; ++ ++ ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); ++ dst->peer_rssi = __le32_to_cpu(src->peer_rssi); ++ dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); ++ dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); ++ /* FIXME: expose 10.4 specific values */ ++ ++ list_add_tail(&dst->list, &stats->peers); ++ } ++ ++ return 0; ++} ++ + void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb) + { + ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); +@@ -4935,6 +5056,9 @@ static void ath10k_wmi_10_4_op_rx(struct + ath10k_dbg(ar, ATH10K_DBG_WMI, + "received event id %d not implemented\n", id); + break; ++ case WMI_10_4_UPDATE_STATS_EVENTID: ++ ath10k_wmi_event_update_stats(ar, skb); ++ break; + default: + ath10k_warn(ar, "Unknown eventid: %d\n", id); + break; +@@ -7022,6 +7146,90 @@ ath10k_wmi_op_gen_pdev_enable_adaptive_c + return skb; + } + ++void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, ++ struct ath10k_fw_stats *fw_stats, ++ char *buf) ++{ ++ u32 len = 0; ++ u32 buf_len = ATH10K_FW_STATS_BUF_SIZE; ++ const struct ath10k_fw_stats_pdev *pdev; ++ const struct ath10k_fw_stats_vdev *vdev; ++ const struct ath10k_fw_stats_peer *peer; ++ size_t num_peers; ++ size_t num_vdevs; ++ ++ spin_lock_bh(&ar->data_lock); ++ ++ pdev = list_first_entry_or_null(&fw_stats->pdevs, ++ struct ath10k_fw_stats_pdev, list); ++ if (!pdev) { ++ ath10k_warn(ar, "failed to get pdev stats\n"); ++ goto unlock; ++ } ++ ++ num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); ++ num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); ++ ++ ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); ++ ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); ++ ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); ++ ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "HW paused", pdev->hw_paused); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "Seqs posted", pdev->seq_posted); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "Seqs failed queueing", pdev->seq_failed_queueing); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "Seqs completed", pdev->seq_completed); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "Seqs restarted", pdev->seq_restarted); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "MU Seqs posted", pdev->mu_seq_posted); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "MPDUs SW flushed", pdev->mpdus_sw_flush); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "MPDUs HW filtered", pdev->mpdus_hw_filter); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "MPDUs truncated", pdev->mpdus_truncated); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "MPDUs receive no ACK", pdev->mpdus_ack_failed); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "MPDUs expired", pdev->mpdus_expired); ++ ++ ath10k_wmi_fw_pdev_rx_stats_fill(pdev, buf, &len); ++ len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", ++ "Num Rx Overflow errors", pdev->rx_ovfl_errs); ++ ++ len += scnprintf(buf + len, buf_len - len, "\n"); ++ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", ++ "ath10k VDEV stats", num_vdevs); ++ len += scnprintf(buf + len, buf_len - len, "%30s\n\n", ++ "================="); ++ ++ list_for_each_entry(vdev, &fw_stats->vdevs, list) { ++ ath10k_wmi_fw_vdev_stats_fill(vdev, buf, &len); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "\n"); ++ len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", ++ "ath10k PEER stats", num_peers); ++ len += scnprintf(buf + len, buf_len - len, "%30s\n\n", ++ "================="); ++ ++ list_for_each_entry(peer, &fw_stats->peers, list) { ++ ath10k_wmi_fw_peer_stats_fill(peer, buf, &len); ++ } ++ ++unlock: ++ spin_unlock_bh(&ar->data_lock); ++ ++ if (len >= buf_len) ++ buf[len - 1] = 0; ++ else ++ buf[len] = 0; ++} ++ + static const struct wmi_ops wmi_ops = { + .rx = ath10k_wmi_op_rx, + .map_svc = wmi_main_svc_map, +@@ -7292,6 +7500,7 @@ static const struct wmi_ops wmi_10_4_ops + .rx = ath10k_wmi_10_4_op_rx, + .map_svc = wmi_10_4_svc_map, + ++ .pull_fw_stats = ath10k_wmi_10_4_op_pull_fw_stats, + .pull_scan = ath10k_wmi_op_pull_scan_ev, + .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev, + .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev, +@@ -7341,9 +7550,11 @@ static const struct wmi_ops wmi_10_4_ops + .gen_addba_send = ath10k_wmi_op_gen_addba_send, + .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, + .gen_delba_send = ath10k_wmi_op_gen_delba_send, ++ .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, + + /* shared with 10.2 */ + .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc, ++ .gen_request_stats = ath10k_wmi_op_gen_request_stats, + }; + + int ath10k_wmi_attach(struct ath10k *ar) +--- a/drivers/net/wireless/ath/ath10k/wmi.h ++++ b/drivers/net/wireless/ath/ath10k/wmi.h +@@ -3866,6 +3866,111 @@ struct wmi_pdev_stats_tx { + __le32 txop_ovf; + } __packed; + ++struct wmi_10_4_pdev_stats_tx { ++ /* Num HTT cookies queued to dispatch list */ ++ __le32 comp_queued; ++ ++ /* Num HTT cookies dispatched */ ++ __le32 comp_delivered; ++ ++ /* Num MSDU queued to WAL */ ++ __le32 msdu_enqued; ++ ++ /* Num MPDU queue to WAL */ ++ __le32 mpdu_enqued; ++ ++ /* Num MSDUs dropped by WMM limit */ ++ __le32 wmm_drop; ++ ++ /* Num Local frames queued */ ++ __le32 local_enqued; ++ ++ /* Num Local frames done */ ++ __le32 local_freed; ++ ++ /* Num queued to HW */ ++ __le32 hw_queued; ++ ++ /* Num PPDU reaped from HW */ ++ __le32 hw_reaped; ++ ++ /* Num underruns */ ++ __le32 underrun; ++ ++ /* HW Paused. */ ++ __le32 hw_paused; ++ ++ /* Num PPDUs cleaned up in TX abort */ ++ __le32 tx_abort; ++ ++ /* Num MPDUs requed by SW */ ++ __le32 mpdus_requed; ++ ++ /* excessive retries */ ++ __le32 tx_ko; ++ ++ /* data hw rate code */ ++ __le32 data_rc; ++ ++ /* Scheduler self triggers */ ++ __le32 self_triggers; ++ ++ /* frames dropped due to excessive sw retries */ ++ __le32 sw_retry_failure; ++ ++ /* illegal rate phy errors */ ++ __le32 illgl_rate_phy_err; ++ ++ /* wal pdev continuous xretry */ ++ __le32 pdev_cont_xretry; ++ ++ /* wal pdev tx timeouts */ ++ __le32 pdev_tx_timeout; ++ ++ /* wal pdev resets */ ++ __le32 pdev_resets; ++ ++ /* frames dropped due to non-availability of stateless TIDs */ ++ __le32 stateless_tid_alloc_failure; ++ ++ __le32 phy_underrun; ++ ++ /* MPDU is more than txop limit */ ++ __le32 txop_ovf; ++ ++ /* Number of Sequences posted */ ++ __le32 seq_posted; ++ ++ /* Number of Sequences failed queueing */ ++ __le32 seq_failed_queueing; ++ ++ /* Number of Sequences completed */ ++ __le32 seq_completed; ++ ++ /* Number of Sequences restarted */ ++ __le32 seq_restarted; ++ ++ /* Number of MU Sequences posted */ ++ __le32 mu_seq_posted; ++ ++ /* Num MPDUs flushed by SW, HWPAUSED,SW TXABORT(Reset,channel change) */ ++ __le32 mpdus_sw_flush; ++ ++ /* Num MPDUs filtered by HW, all filter condition (TTL expired) */ ++ __le32 mpdus_hw_filter; ++ ++ /* Num MPDUs truncated by PDG ++ * (TXOP, TBTT, PPDU_duration based on rate, dyn_bw) ++ */ ++ __le32 mpdus_truncated; ++ ++ /* Num MPDUs that was tried but didn't receive ACK or BA */ ++ __le32 mpdus_ack_failed; ++ ++ /* Num MPDUs that was dropped due to expiry. */ ++ __le32 mpdus_expired; ++} __packed; ++ + struct wmi_pdev_stats_rx { + /* Cnts any change in ring routing mid-ppdu */ + __le32 mid_ppdu_route_change; +@@ -4039,6 +4144,16 @@ struct wmi_10_2_pdev_stats { + struct wmi_pdev_stats_extra extra; + } __packed; + ++struct wmi_10_4_pdev_stats { ++ struct wmi_pdev_stats_base base; ++ struct wmi_10_4_pdev_stats_tx tx; ++ struct wmi_pdev_stats_rx rx; ++ __le32 rx_ovfl_errs; ++ struct wmi_pdev_stats_mem mem; ++ __le32 sram_free_size; ++ struct wmi_pdev_stats_extra extra; ++} __packed; ++ + /* + * VDEV statistics + * TODO: add all VDEV stats here +@@ -4080,6 +4195,23 @@ struct wmi_10_2_4_peer_stats { + __le32 unknown_value; /* FIXME: what is this word? */ + } __packed; + ++struct wmi_10_4_peer_stats { ++ struct wmi_mac_addr peer_macaddr; ++ __le32 peer_rssi; ++ __le32 peer_rssi_seq_num; ++ __le32 peer_tx_rate; ++ __le32 peer_rx_rate; ++ __le32 current_per; ++ __le32 retries; ++ __le32 tx_rate_count; ++ __le32 max_4ms_frame_len; ++ __le32 total_sub_frames; ++ __le32 tx_bytes; ++ __le32 num_pkt_loss_overflow[4]; ++ __le32 num_pkt_loss_excess_retry[4]; ++ __le32 peer_rssi_changed; ++} __packed; ++ + struct wmi_10_2_pdev_ext_stats { + __le32 rx_rssi_comb; + __le32 rx_rssi[4]; +@@ -6201,5 +6333,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(str + char *buf); + size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); + size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); ++void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, ++ struct ath10k_fw_stats *fw_stats, ++ char *buf); + + #endif /* _WMI_H_ */ diff --git a/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch b/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch new file mode 100644 index 0000000..58db2b2 --- /dev/null +++ b/package/kernel/mac80211/patches/306-ath10k-use-local-memory-instead-of-shadow-descriptor.patch @@ -0,0 +1,60 @@ +From: Rajkumar Manoharan +Date: Fri, 23 Oct 2015 18:01:03 +0530 +Subject: [PATCH] ath10k: use local memory instead of shadow descriptor + in ce_send + +Currently to avoid uncached memory access while filling up copy engine +descriptors, shadow descriptors are used. This can be optimized further +by removing shadow descriptors. To achieve that first shadow ring +dependency in ce_send is removed by creating local copy of the +descriptor on stack and make a one-shot copy into the "uncached" +descriptor. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/ce.c ++++ b/drivers/net/wireless/ath/ath10k/ce.c +@@ -274,7 +274,7 @@ int ath10k_ce_send_nolock(struct ath10k_ + { + struct ath10k *ar = ce_state->ar; + struct ath10k_ce_ring *src_ring = ce_state->src_ring; +- struct ce_desc *desc, *sdesc; ++ struct ce_desc *desc, sdesc; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; + unsigned int write_index = src_ring->write_index; +@@ -294,7 +294,6 @@ int ath10k_ce_send_nolock(struct ath10k_ + + desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space, + write_index); +- sdesc = CE_SRC_RING_TO_DESC(src_ring->shadow_base, write_index); + + desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA); + +@@ -303,11 +302,11 @@ int ath10k_ce_send_nolock(struct ath10k_ + if (flags & CE_SEND_FLAG_BYTE_SWAP) + desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; + +- sdesc->addr = __cpu_to_le32(buffer); +- sdesc->nbytes = __cpu_to_le16(nbytes); +- sdesc->flags = __cpu_to_le16(desc_flags); ++ sdesc.addr = __cpu_to_le32(buffer); ++ sdesc.nbytes = __cpu_to_le16(nbytes); ++ sdesc.flags = __cpu_to_le16(desc_flags); + +- *desc = *sdesc; ++ *desc = sdesc; + + src_ring->per_transfer_context[write_index] = per_transfer_context; + +@@ -614,7 +613,7 @@ int ath10k_ce_completed_send_next_nolock + if (read_index == sw_index) + return -EIO; + +- sbase = src_ring->shadow_base; ++ sbase = src_ring->base_addr_owner_space; + sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); + + /* Return data from completed source descriptor */ diff --git a/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch b/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch new file mode 100644 index 0000000..a61a334 --- /dev/null +++ b/package/kernel/mac80211/patches/307-ath10k-remove-send-completion-validation-in-diag-rea.patch @@ -0,0 +1,49 @@ +From: Rajkumar Manoharan +Date: Fri, 23 Oct 2015 18:01:04 +0530 +Subject: [PATCH] ath10k: remove send completion validation in diag + read/write + +CE diag window access is serialized (it has to be by design) so +there's no way to get a different send completion. so there's no +need for post completion validation. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -920,16 +920,6 @@ static int ath10k_pci_diag_read_mem(stru + } + } + +- if (nbytes != completed_nbytes) { +- ret = -EIO; +- goto done; +- } +- +- if (buf != (u32)address) { +- ret = -EIO; +- goto done; +- } +- + i = 0; + while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, +@@ -1094,16 +1084,6 @@ static int ath10k_pci_diag_write_mem(str + } + } + +- if (nbytes != completed_nbytes) { +- ret = -EIO; +- goto done; +- } +- +- if (buf != ce_data) { +- ret = -EIO; +- goto done; +- } +- + i = 0; + while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, + &completed_nbytes, diff --git a/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch b/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch new file mode 100644 index 0000000..e758665 --- /dev/null +++ b/package/kernel/mac80211/patches/308-ath10k-cleanup-copy-engine-send-completion.patch @@ -0,0 +1,165 @@ +From: Rajkumar Manoharan +Date: Fri, 23 Oct 2015 18:01:05 +0530 +Subject: [PATCH] ath10k: cleanup copy engine send completion + +The physical address necessary to unmap DMA ('bufferp') is stored +in ath10k_skb_cb as 'paddr'. ath10k doesn't rely on the meta/transfer_id +when handling send completion (htc ep id is stored in sk_buff control +buffer). So the unused output arguments {bufferp, nbytesp and transfer_idp} +are removed from CE send completion. This change is needed before removing +the shadow copy of copy engine (CE) descriptors in follow up patch. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/ce.c ++++ b/drivers/net/wireless/ath/ath10k/ce.c +@@ -578,17 +578,13 @@ int ath10k_ce_revoke_recv_next(struct at + * The caller takes responsibility for any necessary locking. + */ + int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, +- void **per_transfer_contextp, +- u32 *bufferp, +- unsigned int *nbytesp, +- unsigned int *transfer_idp) ++ void **per_transfer_contextp) + { + struct ath10k_ce_ring *src_ring = ce_state->src_ring; + u32 ctrl_addr = ce_state->ctrl_addr; + struct ath10k *ar = ce_state->ar; + unsigned int nentries_mask = src_ring->nentries_mask; + unsigned int sw_index = src_ring->sw_index; +- struct ce_desc *sdesc, *sbase; + unsigned int read_index; + + if (src_ring->hw_index == sw_index) { +@@ -613,15 +609,6 @@ int ath10k_ce_completed_send_next_nolock + if (read_index == sw_index) + return -EIO; + +- sbase = src_ring->base_addr_owner_space; +- sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); +- +- /* Return data from completed source descriptor */ +- *bufferp = __le32_to_cpu(sdesc->addr); +- *nbytesp = __le16_to_cpu(sdesc->nbytes); +- *transfer_idp = MS(__le16_to_cpu(sdesc->flags), +- CE_DESC_FLAGS_META_DATA); +- + if (per_transfer_contextp) + *per_transfer_contextp = + src_ring->per_transfer_context[sw_index]; +@@ -696,10 +683,7 @@ int ath10k_ce_cancel_send_next(struct at + } + + int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, +- void **per_transfer_contextp, +- u32 *bufferp, +- unsigned int *nbytesp, +- unsigned int *transfer_idp) ++ void **per_transfer_contextp) + { + struct ath10k *ar = ce_state->ar; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); +@@ -707,9 +691,7 @@ int ath10k_ce_completed_send_next(struct + + spin_lock_bh(&ar_pci->ce_lock); + ret = ath10k_ce_completed_send_next_nolock(ce_state, +- per_transfer_contextp, +- bufferp, nbytesp, +- transfer_idp); ++ per_transfer_contextp); + spin_unlock_bh(&ar_pci->ce_lock); + + return ret; +--- a/drivers/net/wireless/ath/ath10k/ce.h ++++ b/drivers/net/wireless/ath/ath10k/ce.h +@@ -192,16 +192,10 @@ int ath10k_ce_completed_recv_next(struct + * Pops 1 completed send buffer from Source ring. + */ + int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, +- void **per_transfer_contextp, +- u32 *bufferp, +- unsigned int *nbytesp, +- unsigned int *transfer_idp); ++ void **per_transfer_contextp); + + int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, +- void **per_transfer_contextp, +- u32 *bufferp, +- unsigned int *nbytesp, +- unsigned int *transfer_idp); ++ void **per_transfer_contextp); + + /*==================CE Engine Initialization=======================*/ + +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -910,9 +910,8 @@ static int ath10k_pci_diag_read_mem(stru + goto done; + + i = 0; +- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, +- &completed_nbytes, +- &id) != 0) { ++ while (ath10k_ce_completed_send_next_nolock(ce_diag, ++ NULL) != 0) { + mdelay(1); + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { + ret = -EBUSY; +@@ -1073,9 +1072,8 @@ static int ath10k_pci_diag_write_mem(str + goto done; + + i = 0; +- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, +- &completed_nbytes, +- &id) != 0) { ++ while (ath10k_ce_completed_send_next_nolock(ce_diag, ++ NULL) != 0) { + mdelay(1); + + if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { +@@ -1139,13 +1137,9 @@ static void ath10k_pci_htc_tx_cb(struct + struct ath10k *ar = ce_state->ar; + struct sk_buff_head list; + struct sk_buff *skb; +- u32 ce_data; +- unsigned int nbytes; +- unsigned int transfer_id; + + __skb_queue_head_init(&list); +- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, +- &nbytes, &transfer_id) == 0) { ++ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { + /* no need to call tx completion for NULL pointers */ + if (skb == NULL) + continue; +@@ -1215,12 +1209,8 @@ static void ath10k_pci_htt_tx_cb(struct + { + struct ath10k *ar = ce_state->ar; + struct sk_buff *skb; +- u32 ce_data; +- unsigned int nbytes; +- unsigned int transfer_id; + +- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data, +- &nbytes, &transfer_id) == 0) { ++ while (ath10k_ce_completed_send_next(ce_state, (void **)&skb) == 0) { + /* no need to call tx completion for NULL pointers */ + if (!skb) + continue; +@@ -1796,12 +1786,8 @@ err_dma: + static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) + { + struct bmi_xfer *xfer; +- u32 ce_data; +- unsigned int nbytes; +- unsigned int transfer_id; + +- if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer, &ce_data, +- &nbytes, &transfer_id)) ++ if (ath10k_ce_completed_send_next(ce_state, (void **)&xfer)) + return; + + xfer->tx_done = true; diff --git a/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch b/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch new file mode 100644 index 0000000..5bd8833 --- /dev/null +++ b/package/kernel/mac80211/patches/309-ath10k-remove-shadow-copy-of-CE-descriptors-for-sour.patch @@ -0,0 +1,90 @@ +From: Rajkumar Manoharan +Date: Fri, 23 Oct 2015 18:01:06 +0530 +Subject: [PATCH] ath10k: remove shadow copy of CE descriptors for source + ring + +For the messages from host to target, shadow copy of CE descriptors +are maintained in source ring. Before writing actual CE descriptor, +first shadow copy is filled and then it is copied to CE address space. +To optimize in download path and to reduce d-cache pressure, removing +shadow copy of CE descriptors. This will also reduce driver memory +consumption by 33KB during on device probing. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/ce.c ++++ b/drivers/net/wireless/ath/ath10k/ce.c +@@ -921,27 +921,6 @@ ath10k_ce_alloc_src_ring(struct ath10k * + src_ring->base_addr_ce_space_unaligned, + CE_DESC_RING_ALIGN); + +- /* +- * Also allocate a shadow src ring in regular +- * mem to use for faster access. +- */ +- src_ring->shadow_base_unaligned = +- kmalloc((nentries * sizeof(struct ce_desc) + +- CE_DESC_RING_ALIGN), GFP_KERNEL); +- if (!src_ring->shadow_base_unaligned) { +- dma_free_coherent(ar->dev, +- (nentries * sizeof(struct ce_desc) + +- CE_DESC_RING_ALIGN), +- src_ring->base_addr_owner_space, +- src_ring->base_addr_ce_space); +- kfree(src_ring); +- return ERR_PTR(-ENOMEM); +- } +- +- src_ring->shadow_base = PTR_ALIGN( +- src_ring->shadow_base_unaligned, +- CE_DESC_RING_ALIGN); +- + return src_ring; + } + +@@ -1120,7 +1099,6 @@ void ath10k_ce_free_pipe(struct ath10k * + struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; + + if (ce_state->src_ring) { +- kfree(ce_state->src_ring->shadow_base_unaligned); + dma_free_coherent(ar->dev, + (ce_state->src_ring->nentries * + sizeof(struct ce_desc) + +--- a/drivers/net/wireless/ath/ath10k/ce.h ++++ b/drivers/net/wireless/ath/ath10k/ce.h +@@ -100,12 +100,6 @@ struct ath10k_ce_ring { + + /* CE address space */ + u32 base_addr_ce_space; +- /* +- * Start of shadow copy of descriptors, within regular memory. +- * Aligned to descriptor-size boundary. +- */ +- void *shadow_base_unaligned; +- struct ce_desc *shadow_base; + + /* keep last */ + void *per_transfer_context[0]; +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -1594,7 +1594,6 @@ static void ath10k_pci_tx_pipe_cleanup(s + struct ath10k_pci *ar_pci; + struct ath10k_ce_pipe *ce_pipe; + struct ath10k_ce_ring *ce_ring; +- struct ce_desc *ce_desc; + struct sk_buff *skb; + int i; + +@@ -1609,10 +1608,6 @@ static void ath10k_pci_tx_pipe_cleanup(s + if (!pci_pipe->buf_sz) + return; + +- ce_desc = ce_ring->shadow_base; +- if (WARN_ON(!ce_desc)) +- return; +- + for (i = 0; i < ce_ring->nentries; i++) { + skb = ce_ring->per_transfer_context[i]; + if (!skb) diff --git a/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch b/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch new file mode 100644 index 0000000..cc79dd7 --- /dev/null +++ b/package/kernel/mac80211/patches/310-ath10k-remove-supported-chain-mask.patch @@ -0,0 +1,77 @@ +From: Rajkumar Manoharan +Date: Tue, 27 Oct 2015 17:51:11 +0530 +Subject: [PATCH] ath10k: remove supported chain mask + +Removing supported chainmask fields as it can be always derived +from num_rf_chains. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/core.h ++++ b/drivers/net/wireless/ath/ath10k/core.h +@@ -745,8 +745,6 @@ struct ath10k { + int num_started_vdevs; + + /* Protected by conf-mutex */ +- u8 supp_tx_chainmask; +- u8 supp_rx_chainmask; + u8 cfg_tx_chainmask; + u8 cfg_rx_chainmask; + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -3736,13 +3736,8 @@ static int ath10k_get_antenna(struct iee + + mutex_lock(&ar->conf_mutex); + +- if (ar->cfg_tx_chainmask) { +- *tx_ant = ar->cfg_tx_chainmask; +- *rx_ant = ar->cfg_rx_chainmask; +- } else { +- *tx_ant = ar->supp_tx_chainmask; +- *rx_ant = ar->supp_rx_chainmask; +- } ++ *tx_ant = ar->cfg_tx_chainmask; ++ *rx_ant = ar->cfg_rx_chainmask; + + mutex_unlock(&ar->conf_mutex); + +@@ -3884,9 +3879,7 @@ static int ath10k_start(struct ieee80211 + } + } + +- if (ar->cfg_tx_chainmask) +- __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, +- ar->cfg_rx_chainmask); ++ __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); + + /* + * By default FW set ARP frames ac to voice (6). In that case ARP +@@ -7169,8 +7162,8 @@ int ath10k_mac_register(struct ath10k *a + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT); + +- ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; +- ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; ++ ar->hw->wiphy->available_antennas_rx = ar->cfg_rx_chainmask; ++ ar->hw->wiphy->available_antennas_tx = ar->cfg_tx_chainmask; + + if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) + ar->hw->wiphy->interface_modes |= +--- a/drivers/net/wireless/ath/ath10k/wmi.c ++++ b/drivers/net/wireless/ath/ath10k/wmi.c +@@ -4460,8 +4460,10 @@ static void ath10k_wmi_event_service_rea + ar->num_rf_chains = ar->max_spatial_stream; + } + +- ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1; +- ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1; ++ if (!ar->cfg_tx_chainmask) { ++ ar->cfg_tx_chainmask = (1 << ar->num_rf_chains) - 1; ++ ar->cfg_rx_chainmask = (1 << ar->num_rf_chains) - 1; ++ } + + if (strlen(ar->hw->wiphy->fw_version) == 0) { + snprintf(ar->hw->wiphy->fw_version, diff --git a/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch b/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch new file mode 100644 index 0000000..b4ca9ca --- /dev/null +++ b/package/kernel/mac80211/patches/311-ath10k-fill-HT-VHT-MCS-rateset-only-for-configured-c.patch @@ -0,0 +1,37 @@ +From: Rajkumar Manoharan +Date: Tue, 27 Oct 2015 17:51:12 +0530 +Subject: [PATCH] ath10k: fill HT/VHT MCS rateset only for configured + chainmask + +HT/VHT MCS rateset should be filled only for configured chainmask +rather that max supported chainmask. Fix that by checking configured +chainmask while filling HT/VHT MCS rate map. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -6984,7 +6984,7 @@ static struct ieee80211_sta_vht_cap ath1 + + mcs_map = 0; + for (i = 0; i < 8; i++) { +- if (i < ar->num_rf_chains) ++ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) + mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2); + else + mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2); +@@ -7051,8 +7051,10 @@ static struct ieee80211_sta_ht_cap ath10 + if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) + ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; + +- for (i = 0; i < ar->num_rf_chains; i++) +- ht_cap.mcs.rx_mask[i] = 0xFF; ++ for (i = 0; i < ar->num_rf_chains; i++) { ++ if (ar->cfg_rx_chainmask & BIT(i)) ++ ht_cap.mcs.rx_mask[i] = 0xFF; ++ } + + ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; + diff --git a/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch b/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch new file mode 100644 index 0000000..ea79b1a --- /dev/null +++ b/package/kernel/mac80211/patches/312-ath10k-move-static-HT-VHT-capability-setup-functions.patch @@ -0,0 +1,314 @@ +From: Rajkumar Manoharan +Date: Tue, 27 Oct 2015 17:51:13 +0530 +Subject: [PATCH] ath10k: move static HT/VHT capability setup functions + +Move HT and VHT capabiltity setup static functions to avoid +forward declaration. + +Signed-off-by: Rajkumar Manoharan +Signed-off-by: Kalle Valo +--- + +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -3757,6 +3757,146 @@ static void ath10k_check_chain_mask(stru + dbg, cm); + } + ++static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) ++{ ++ int nsts = ar->vht_cap_info; ++ ++ nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; ++ nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ ++ /* If firmware does not deliver to host number of space-time ++ * streams supported, assume it support up to 4 BF STS and return ++ * the value for VHT CAP: nsts-1) ++ */ ++ if (nsts == 0) ++ return 3; ++ ++ return nsts; ++} ++ ++static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) ++{ ++ int sound_dim = ar->vht_cap_info; ++ ++ sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; ++ sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ ++ /* If the sounding dimension is not advertised by the firmware, ++ * let's use a default value of 1 ++ */ ++ if (sound_dim == 0) ++ return 1; ++ ++ return sound_dim; ++} ++ ++static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) ++{ ++ struct ieee80211_sta_vht_cap vht_cap = {0}; ++ u16 mcs_map; ++ u32 val; ++ int i; ++ ++ vht_cap.vht_supported = 1; ++ vht_cap.cap = ar->vht_cap_info; ++ ++ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | ++ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { ++ val = ath10k_mac_get_vht_cap_bf_sts(ar); ++ val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; ++ ++ vht_cap.cap |= val; ++ } ++ ++ if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | ++ IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { ++ val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); ++ val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; ++ val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; ++ ++ vht_cap.cap |= val; ++ } ++ ++ mcs_map = 0; ++ for (i = 0; i < 8; i++) { ++ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) ++ mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i * 2); ++ else ++ mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); ++ } ++ ++ vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); ++ vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); ++ ++ return vht_cap; ++} ++ ++static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) ++{ ++ int i; ++ struct ieee80211_sta_ht_cap ht_cap = {0}; ++ ++ if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) ++ return ht_cap; ++ ++ ht_cap.ht_supported = 1; ++ ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ++ ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; ++ ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; ++ ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; ++ ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; ++ ++ if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) ++ ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; ++ ++ if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) ++ ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ++ ++ if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { ++ u32 smps; ++ ++ smps = WLAN_HT_CAP_SM_PS_DYNAMIC; ++ smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; ++ ++ ht_cap.cap |= smps; ++ } ++ ++ if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) ++ ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; ++ ++ if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { ++ u32 stbc; ++ ++ stbc = ar->ht_cap_info; ++ stbc &= WMI_HT_CAP_RX_STBC; ++ stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; ++ stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; ++ stbc &= IEEE80211_HT_CAP_RX_STBC; ++ ++ ht_cap.cap |= stbc; ++ } ++ ++ if (ar->ht_cap_info & WMI_HT_CAP_LDPC) ++ ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; ++ ++ if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) ++ ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; ++ ++ /* max AMSDU is implicitly taken from vht_cap_info */ ++ if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) ++ ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; ++ ++ for (i = 0; i < ar->num_rf_chains; i++) { ++ if (ar->cfg_rx_chainmask & BIT(i)) ++ ht_cap.mcs.rx_mask[i] = 0xFF; ++ } ++ ++ ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; ++ ++ return ht_cap; ++} ++ + static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) + { + int ret; +@@ -4068,39 +4208,6 @@ static u32 get_nss_from_chainmask(u16 ch + return 1; + } + +-static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) +-{ +- int nsts = ar->vht_cap_info; +- +- nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; +- nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; +- +- /* If firmware does not deliver to host number of space-time +- * streams supported, assume it support up to 4 BF STS and return +- * the value for VHT CAP: nsts-1) +- * */ +- if (nsts == 0) +- return 3; +- +- return nsts; +-} +- +-static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar) +-{ +- int sound_dim = ar->vht_cap_info; +- +- sound_dim &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; +- sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; +- +- /* If the sounding dimension is not advertised by the firmware, +- * let's use a default value of 1 +- */ +- if (sound_dim == 0) +- return 1; +- +- return sound_dim; +-} +- + static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif) + { + u32 value = 0; +@@ -6954,113 +7061,6 @@ static const struct ieee80211_iface_comb + }, + }; + +-static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) +-{ +- struct ieee80211_sta_vht_cap vht_cap = {0}; +- u16 mcs_map; +- u32 val; +- int i; +- +- vht_cap.vht_supported = 1; +- vht_cap.cap = ar->vht_cap_info; +- +- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | +- IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) { +- val = ath10k_mac_get_vht_cap_bf_sts(ar); +- val <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; +- val &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; +- +- vht_cap.cap |= val; +- } +- +- if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | +- IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) { +- val = ath10k_mac_get_vht_cap_bf_sound_dim(ar); +- val <<= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; +- val &= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; +- +- vht_cap.cap |= val; +- } +- +- mcs_map = 0; +- for (i = 0; i < 8; i++) { +- if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) +- mcs_map |= IEEE80211_VHT_MCS_SUPPORT_0_9 << (i*2); +- else +- mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i*2); +- } +- +- vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); +- vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); +- +- return vht_cap; +-} +- +-static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) +-{ +- int i; +- struct ieee80211_sta_ht_cap ht_cap = {0}; +- +- if (!(ar->ht_cap_info & WMI_HT_CAP_ENABLED)) +- return ht_cap; +- +- ht_cap.ht_supported = 1; +- ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; +- ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; +- ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; +- ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40; +- ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT; +- +- if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI) +- ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; +- +- if (ar->ht_cap_info & WMI_HT_CAP_HT40_SGI) +- ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; +- +- if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS) { +- u32 smps; +- +- smps = WLAN_HT_CAP_SM_PS_DYNAMIC; +- smps <<= IEEE80211_HT_CAP_SM_PS_SHIFT; +- +- ht_cap.cap |= smps; +- } +- +- if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) +- ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; +- +- if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { +- u32 stbc; +- +- stbc = ar->ht_cap_info; +- stbc &= WMI_HT_CAP_RX_STBC; +- stbc >>= WMI_HT_CAP_RX_STBC_MASK_SHIFT; +- stbc <<= IEEE80211_HT_CAP_RX_STBC_SHIFT; +- stbc &= IEEE80211_HT_CAP_RX_STBC; +- +- ht_cap.cap |= stbc; +- } +- +- if (ar->ht_cap_info & WMI_HT_CAP_LDPC) +- ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; +- +- if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) +- ht_cap.cap |= IEEE80211_HT_CAP_LSIG_TXOP_PROT; +- +- /* max AMSDU is implicitly taken from vht_cap_info */ +- if (ar->vht_cap_info & WMI_VHT_CAP_MAX_MPDU_LEN_MASK) +- ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; +- +- for (i = 0; i < ar->num_rf_chains; i++) { +- if (ar->cfg_rx_chainmask & BIT(i)) +- ht_cap.mcs.rx_mask[i] = 0xFF; +- } +- +- ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; +- +- return ht_cap; +-} +- + static void ath10k_get_arvif_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) + { diff --git a/package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch b/package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch new file mode 100644 index 0000000..7424ca4 --- /dev/null +++ b/package/kernel/mac80211/patches/313-mac80211-fix-crash-on-mesh-local-link-ID-generation-.patch @@ -0,0 +1,42 @@ +From: Matthias Schiffer +Date: Sat, 24 Oct 2015 21:25:51 +0200 +Subject: [PATCH] mac80211: fix crash on mesh local link ID generation with + VIFs + +llid_in_use needs to be limited to stations of the same VIF, otherwise it +will cause a NULL deref as the sta_info of non-mesh-VIFs don't have +sta->mesh set. + +Steps to reproduce: + + modprobe mac80211_hwsim channels=2 + iw phy phy0 interface add ibss0 type ibss + iw phy phy0 interface add mesh0 type mp + iw phy phy1 interface add ibss1 type ibss + iw phy phy1 interface add mesh1 type mp + ip link set ibss0 up + ip link set mesh0 up + ip link set ibss1 up + ip link set mesh1 up + iw dev ibss0 ibss join foo 2412 + iw dev ibss1 ibss join foo 2412 + # Ensure that ibss0 and ibss1 are actually associated; I often need to + # leave and join the cell on ibss1 a second time. + iw dev mesh0 mesh join bar + iw dev mesh1 mesh join bar # crash + +Signed-off-by: Matthias Schiffer +--- + +--- a/net/mac80211/mesh_plink.c ++++ b/net/mac80211/mesh_plink.c +@@ -686,6 +686,9 @@ static bool llid_in_use(struct ieee80211 + + rcu_read_lock(); + list_for_each_entry_rcu(sta, &local->sta_list, list) { ++ if (sdata != sta->sdata) ++ continue; ++ + if (!memcmp(&sta->mesh->llid, &llid, sizeof(llid))) { + in_use = true; + break; diff --git a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch new file mode 100644 index 0000000..72e9a41 --- /dev/null +++ b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch @@ -0,0 +1,30 @@ +--- a/drivers/net/wireless/ath/Makefile ++++ b/drivers/net/wireless/ath/Makefile +@@ -13,10 +13,10 @@ ath-objs := main.o \ + regd.o \ + hw.o \ + key.o \ ++ debug.o \ + dfs_pattern_detector.o \ + dfs_pri_detector.o + +-ath-$(CPTCFG_ATH_DEBUG) += debug.o + ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o + + ccflags-y += -D__CHECK_ENDIAN__ +--- a/drivers/net/wireless/ath/ath.h ++++ b/drivers/net/wireless/ath/ath.h +@@ -318,13 +318,6 @@ void _ath_dbg(struct ath_common *common, + #endif /* CPTCFG_ATH_DEBUG */ + + /** Returns string describing opmode, or NULL if unknown mode. */ +-#ifdef CPTCFG_ATH_DEBUG + const char *ath_opmode_to_string(enum nl80211_iftype opmode); +-#else +-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode) +-{ +- return "UNKNOWN"; +-} +-#endif + + #endif /* ATH_H */ diff --git a/package/kernel/mac80211/patches/401-ath9k_blink_default.patch b/package/kernel/mac80211/patches/401-ath9k_blink_default.patch new file mode 100644 index 0000000..4a997f1 --- /dev/null +++ b/package/kernel/mac80211/patches/401-ath9k_blink_default.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -45,7 +45,7 @@ int ath9k_modparam_nohwcrypt; + module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); + MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); + +-int ath9k_led_blink; ++int ath9k_led_blink = 1; + module_param_named(blink, ath9k_led_blink, int, 0444); + MODULE_PARM_DESC(blink, "Enable LED blink on activity"); + diff --git a/package/kernel/mac80211/patches/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/402-ath_regd_optional.patch new file mode 100644 index 0000000..1000cd8 --- /dev/null +++ b/package/kernel/mac80211/patches/402-ath_regd_optional.patch @@ -0,0 +1,69 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -341,6 +341,10 @@ ath_reg_apply_beaconing_flags(struct wip + struct ieee80211_channel *ch; + unsigned int i; + ++#ifdef CPTCFG_ATH_USER_REGD ++ return; ++#endif ++ + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!wiphy->bands[band]) + continue; +@@ -374,6 +378,10 @@ ath_reg_apply_ir_flags(struct wiphy *wip + { + struct ieee80211_supported_band *sband; + ++#ifdef CPTCFG_ATH_USER_REGD ++ return; ++#endif ++ + sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + if (!sband) + return; +@@ -402,6 +410,10 @@ static void ath_reg_apply_radar_flags(st + struct ieee80211_channel *ch; + unsigned int i; + ++#ifdef CPTCFG_ATH_USER_REGD ++ return; ++#endif ++ + if (!wiphy->bands[IEEE80211_BAND_5GHZ]) + return; + +@@ -633,6 +645,11 @@ ath_regd_init_wiphy(struct ath_regulator + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; ++ ++#ifdef CPTCFG_ATH_USER_REGD ++ return 0; ++#endif ++ + wiphy->regulatory_flags |= REGULATORY_STRICT_REG | + REGULATORY_CUSTOM_REG; + +--- a/drivers/net/wireless/ath/Kconfig ++++ b/drivers/net/wireless/ath/Kconfig +@@ -22,6 +22,9 @@ menuconfig ATH_CARDS + + if ATH_CARDS + ++config ATH_USER_REGD ++ bool "Do not enforce EEPROM regulatory restrictions" ++ + config ATH_DEBUG + bool "Atheros wireless debugging" + ---help--- +--- a/.local-symbols ++++ b/.local-symbols +@@ -140,6 +140,7 @@ RTL8187_LEDS= + ATH_COMMON= + ATH_CARDS= + ATH_DEBUG= ++ATH_USER_REGD= + ATH_TRACEPOINTS= + ATH_REG_DYNAMIC_USER_REG_HINTS= + ATH_REG_DYNAMIC_USER_CERT_TESTING= diff --git a/package/kernel/mac80211/patches/403-world_regd_fixup.patch b/package/kernel/mac80211/patches/403-world_regd_fixup.patch new file mode 100644 index 0000000..2b04309 --- /dev/null +++ b/package/kernel/mac80211/patches/403-world_regd_fixup.patch @@ -0,0 +1,84 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -43,7 +43,8 @@ static int __ath_regd_init(struct ath_re + NL80211_RRF_NO_OFDM) + + /* We allow IBSS on these on a case by case basis by regulatory domain */ +-#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\ ++#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\ ++ REG_RULE(5260-10, 5350+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) + #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\ + NL80211_RRF_NO_IR) +@@ -61,57 +62,56 @@ static int __ath_regd_init(struct ath_re + #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ + ATH9K_5GHZ_5725_5850 + ++#define REGD_RULES(...) \ ++ .reg_rules = { __VA_ARGS__ }, \ ++ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ })) ++ + /* Can be used for: + * 0x60, 0x61, 0x62 */ + static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = { +- .n_reg_rules = 5, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH9K_2GHZ_ALL, + ATH9K_5GHZ_ALL, +- } ++ ) + }; + + /* Can be used by 0x63 and 0x65 */ + static const struct ieee80211_regdomain ath_world_regdom_63_65 = { +- .n_reg_rules = 4, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH9K_2GHZ_CH01_11, + ATH9K_2GHZ_CH12_13, + ATH9K_5GHZ_NO_MIDBAND, +- } ++ ) + }; + + /* Can be used by 0x64 only */ + static const struct ieee80211_regdomain ath_world_regdom_64 = { +- .n_reg_rules = 3, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH9K_2GHZ_CH01_11, + ATH9K_5GHZ_NO_MIDBAND, +- } ++ ) + }; + + /* Can be used by 0x66 and 0x69 */ + static const struct ieee80211_regdomain ath_world_regdom_66_69 = { +- .n_reg_rules = 3, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH9K_2GHZ_CH01_11, + ATH9K_5GHZ_ALL, +- } ++ ) + }; + + /* Can be used by 0x67, 0x68, 0x6A and 0x6C */ + static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = { +- .n_reg_rules = 4, + .alpha2 = "99", +- .reg_rules = { ++ REGD_RULES( + ATH9K_2GHZ_CH01_11, + ATH9K_2GHZ_CH12_13, + ATH9K_5GHZ_ALL, +- } ++ ) + }; + + static bool dynamic_country_user_possible(struct ath_regulatory *reg) diff --git a/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch new file mode 100644 index 0000000..ca11199 --- /dev/null +++ b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch @@ -0,0 +1,19 @@ +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -2480,6 +2480,8 @@ void regulatory_hint_country_ie(struct w + enum environment_cap env = ENVIRON_ANY; + struct regulatory_request *request = NULL, *lr; + ++ return; ++ + /* IE len must be evenly divisible by 2 */ + if (country_ie_len & 0x01) + return; +@@ -2686,6 +2688,7 @@ static void restore_regulatory_settings( + + void regulatory_hint_disconnect(void) + { ++ return; + REG_DBG_PRINT("All devices are disconnected, going to restore regulatory settings\n"); + restore_regulatory_settings(false); + } diff --git a/package/kernel/mac80211/patches/405-ath_regd_us.patch b/package/kernel/mac80211/patches/405-ath_regd_us.patch new file mode 100644 index 0000000..cc55877 --- /dev/null +++ b/package/kernel/mac80211/patches/405-ath_regd_us.patch @@ -0,0 +1,26 @@ +--- a/drivers/net/wireless/ath/regd_common.h ++++ b/drivers/net/wireless/ath/regd_common.h +@@ -32,6 +32,7 @@ enum EnumRd { + FCC2_WORLD = 0x21, + FCC2_ETSIC = 0x22, + FCC6_WORLD = 0x23, ++ FCC3_FCCA_2 = 0x2A, + FRANCE_RES = 0x31, + FCC3_FCCA = 0x3A, + FCC3_WORLD = 0x3B, +@@ -167,6 +168,7 @@ static struct reg_dmn_pair_mapping regDo + {FCC2_WORLD, CTL_FCC, CTL_ETSI}, + {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, + {FCC3_FCCA, CTL_FCC, CTL_FCC}, ++ {FCC3_FCCA_2, CTL_FCC, CTL_FCC}, + {FCC3_WORLD, CTL_FCC, CTL_ETSI}, + {FCC4_FCCA, CTL_FCC, CTL_FCC}, + {FCC5_FCCA, CTL_FCC, CTL_FCC}, +@@ -463,6 +465,7 @@ static struct country_code_to_enum_rd al + {CTRY_UAE, NULL1_WORLD, "AE"}, + {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, + {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, ++ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"}, + /* This "PS" is for US public safety actually... to support this we + * would need to assign new special alpha2 to CRDA db as with the world + * regdomain and use another alpha2 */ diff --git a/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch b/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch new file mode 100644 index 0000000..6336f1f --- /dev/null +++ b/package/kernel/mac80211/patches/406-ath_relax_default_regd.patch @@ -0,0 +1,47 @@ +--- a/drivers/net/wireless/ath/regd.c ++++ b/drivers/net/wireless/ath/regd.c +@@ -114,10 +114,22 @@ static const struct ieee80211_regdomain + ) + }; + ++static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) ++{ ++ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; ++} ++ ++static bool is_default_regd(struct ath_regulatory *reg) ++{ ++ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT; ++} ++ + static bool dynamic_country_user_possible(struct ath_regulatory *reg) + { + if (config_enabled(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING)) + return true; ++ if (is_default_regd(reg)) ++ return true; + + switch (reg->country_code) { + case CTRY_UNITED_STATES: +@@ -202,11 +214,6 @@ static inline bool is_wwr_sku(u16 regd) + (regd == WORLD)); + } + +-static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) +-{ +- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; +-} +- + bool ath_is_world_regd(struct ath_regulatory *reg) + { + return is_wwr_sku(ath_regd_get_eepromRD(reg)); +@@ -650,6 +657,9 @@ ath_regd_init_wiphy(struct ath_regulator + return 0; + #endif + ++ if (is_default_regd(reg)) ++ return 0; ++ + wiphy->regulatory_flags |= REGULATORY_STRICT_REG | + REGULATORY_CUSTOM_REG; + diff --git a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch new file mode 100644 index 0000000..1a62484 --- /dev/null +++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -722,6 +722,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_AP) }, + { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + static const struct ieee80211_iface_limit wds_limits[] = { diff --git a/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch new file mode 100644 index 0000000..2a5ab3d --- /dev/null +++ b/package/kernel/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch @@ -0,0 +1,46 @@ +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw + goto end; + } + +- /* Don't allow other interfaces if one ad-hoc is configured. +- * TODO: Fix the problems with ad-hoc and multiple other interfaces. +- * We would need to operate the HW in ad-hoc mode to allow TSF updates +- * for the IBSS, but this breaks with additional AP or STA interfaces +- * at the moment. */ +- if (ah->num_adhoc_vifs || +- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { ++ /* Don't allow more than one ad-hoc interface */ ++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) { + ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n"); + ret = -ELNRNG; + goto end; +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -1965,7 +1965,7 @@ ath5k_beacon_send(struct ath5k_hw *ah) + } + + if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + +- ah->num_mesh_vifs > 1) || ++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) || + ah->opmode == NL80211_IFTYPE_MESH_POINT) { + u64 tsf = ath5k_hw_get_tsf64(ah); + u32 tsftu = TSF_TO_TU(tsf); +@@ -2051,7 +2051,7 @@ ath5k_beacon_update_timers(struct ath5k_ + + intval = ah->bintval & AR5K_BEACON_PERIOD; + if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +- + ah->num_mesh_vifs > 1) { ++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) { + intval /= ATH_BCBUF; /* staggered multi-bss beacons */ + if (intval < 15) + ATH5K_WARN(ah, "intval %u is too low, min 15\n", +@@ -2518,6 +2518,7 @@ static const struct ieee80211_iface_limi + BIT(NL80211_IFTYPE_MESH_POINT) | + #endif + BIT(NL80211_IFTYPE_AP) }, ++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, + }; + + static const struct ieee80211_iface_combination if_comb = { diff --git a/package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch b/package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch new file mode 100644 index 0000000..414f495 --- /dev/null +++ b/package/kernel/mac80211/patches/420-ath5k_disable_fast_cc.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath5k/reset.c ++++ b/drivers/net/wireless/ath/ath5k/reset.c +@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + tsf_lo = 0; + mode = 0; + ++#if 0 + /* + * Sanity check for fast flag + * Fast channel change only available +@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum + */ + if (fast && (ah->ah_radio != AR5K_RF2413) && + (ah->ah_radio != AR5K_RF5413)) ++#endif + fast = false; + + /* Disable sleep clock operation diff --git a/package/kernel/mac80211/patches/430-add_ath5k_platform.patch b/package/kernel/mac80211/patches/430-add_ath5k_platform.patch new file mode 100644 index 0000000..b213e2a --- /dev/null +++ b/package/kernel/mac80211/patches/430-add_ath5k_platform.patch @@ -0,0 +1,33 @@ +--- /dev/null ++++ b/include/linux/ath5k_platform.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) 2008 Atheros Communications Inc. ++ * Copyright (c) 2009 Gabor Juhos ++ * Copyright (c) 2009 Imre Kaloz ++ * Copyright (c) 2010 Daniel Golle ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#ifndef _LINUX_ATH5K_PLATFORM_H ++#define _LINUX_ATH5K_PLATFORM_H ++ ++#define ATH5K_PLAT_EEP_MAX_WORDS 2048 ++ ++struct ath5k_platform_data { ++ u16 *eeprom_data; ++ u8 *macaddr; ++}; ++ ++#endif /* _LINUX_ATH5K_PLATFORM_H */ diff --git a/package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch b/package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch new file mode 100644 index 0000000..cdc9315 --- /dev/null +++ b/package/kernel/mac80211/patches/431-add_platform_eeprom_support_to_ath5k.patch @@ -0,0 +1,56 @@ +--- a/drivers/net/wireless/ath/ath5k/pci.c ++++ b/drivers/net/wireless/ath/ath5k/pci.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include "../ath.h" + #include "ath5k.h" + #include "debug.h" +@@ -72,7 +73,7 @@ static void ath5k_pci_read_cachesize(str + } + + /* +- * Read from eeprom ++ * Read from eeprom or platform_data + */ + static bool + ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) +@@ -80,6 +81,19 @@ ath5k_pci_eeprom_read(struct ath_common + struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; + u32 status, timeout; + ++ struct ath5k_platform_data *pdata = NULL; ++ ++ if (ah->pdev) ++ pdata = ah->pdev->dev.platform_data; ++ ++ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) { ++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS) ++ return false; ++ ++ *data = pdata->eeprom_data[offset]; ++ return true; ++ } ++ + /* + * Initialize EEPROM access + */ +@@ -123,6 +137,16 @@ static int ath5k_pci_eeprom_read_mac(str + u16 data; + int octet; + ++ struct ath5k_platform_data *pdata = NULL; ++ ++ if (ah->pdev) ++ pdata = ah->pdev->dev.platform_data; ++ ++ if (pdata && pdata->macaddr) { ++ memcpy(mac, pdata->macaddr, ETH_ALEN); ++ return 0; ++ } ++ + AR5K_EEPROM_READ(0x20, data); + + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { diff --git a/package/kernel/mac80211/patches/432-ath5k_add_pciids.patch b/package/kernel/mac80211/patches/432-ath5k_add_pciids.patch new file mode 100644 index 0000000..d82f800 --- /dev/null +++ b/package/kernel/mac80211/patches/432-ath5k_add_pciids.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath5k/pci.c ++++ b/drivers/net/wireless/ath/ath5k/pci.c +@@ -48,6 +48,8 @@ static const struct pci_device_id ath5k_ + { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ + { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ + { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ ++ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */ ++ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */ + { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */ + { 0 } + }; diff --git a/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch new file mode 100644 index 0000000..924b62e --- /dev/null +++ b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch @@ -0,0 +1,143 @@ +This adds a bwmode debugfs file which can be used to set alternate +channel operating bandwidths. Only tested with AR5413 and only at +5 and 20 mhz channels. + +Signed-off-by: Pat Erley +--- +Other devices will need to be added to the switch in write_file_bwmode + +drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ + 1 files changed, 86 insertions(+), 0 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/debug.c ++++ b/drivers/net/wireless/ath/ath5k/debug.c +@@ -823,6 +823,97 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++/* debugfs: bwmode */ ++ ++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[15]; ++ unsigned int len = 0; ++ ++ int cur_ah_bwmode = ah->ah_bwmode_debug; ++ ++#define print_selected(MODE, LABEL) \ ++ if (cur_ah_bwmode == MODE) \ ++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \ ++ else \ ++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \ ++ len += snprintf(buf+len, sizeof(buf)-len, " "); ++ ++ print_selected(AR5K_BWMODE_5MHZ, "5"); ++ print_selected(AR5K_BWMODE_10MHZ, "10"); ++ print_selected(AR5K_BWMODE_DEFAULT, "20"); ++ print_selected(AR5K_BWMODE_40MHZ, "40"); ++#undef print_selected ++ ++ len += snprintf(buf+len, sizeof(buf)-len, "\n"); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_bwmode(struct file *file, ++ const char __user *userbuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath5k_hw *ah = file->private_data; ++ char buf[3]; ++ int bw = 20; ++ int tobwmode = AR5K_BWMODE_DEFAULT; ++ ++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) ++ return -EFAULT; ++ ++ /* TODO: Add check for active interface */ ++ ++ if(strncmp(buf, "5", 1) == 0 ) { ++ tobwmode = AR5K_BWMODE_5MHZ; ++ bw = 5; ++ } else if ( strncmp(buf, "10", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_10MHZ; ++ bw = 10; ++ } else if ( strncmp(buf, "20", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_DEFAULT; ++ bw = 20; ++ } else if ( strncmp(buf, "40", 2) == 0 ) { ++ tobwmode = AR5K_BWMODE_40MHZ; ++ bw = 40; ++ } else ++ return -EINVAL; ++ ++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n", ++ bw, tobwmode); ++ ++ switch (ah->ah_radio) { ++ /* TODO: only define radios that actually support 5/10mhz channels */ ++ case AR5K_RF5413: ++ case AR5K_RF5110: ++ case AR5K_RF5111: ++ case AR5K_RF5112: ++ case AR5K_RF2413: ++ case AR5K_RF2316: ++ case AR5K_RF2317: ++ case AR5K_RF2425: ++ if(ah->ah_bwmode_debug != tobwmode) { ++ mutex_lock(&ah->lock); ++ ah->ah_bwmode = tobwmode; ++ ah->ah_bwmode_debug = tobwmode; ++ mutex_unlock(&ah->lock); ++ } ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ return count; ++} ++ ++static const struct file_operations fops_bwmode = { ++ .read = read_file_bwmode, ++ .write = write_file_bwmode, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; + + /* debugfs: queues etc */ + +@@ -1010,6 +1101,9 @@ ath5k_debug_init_device(struct ath5k_hw + debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah, + &fops_beacon); + ++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah, ++ &fops_bwmode); ++ + debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset); + + debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah, +--- a/drivers/net/wireless/ath/ath5k/ath5k.h ++++ b/drivers/net/wireless/ath/ath5k/ath5k.h +@@ -1372,6 +1372,7 @@ struct ath5k_hw { + u8 ah_coverage_class; + bool ah_ack_bitrate_high; + u8 ah_bwmode; ++ u8 ah_bwmode_debug; + bool ah_short_slot; + + /* Antenna Control */ +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru + return -EINVAL; + } + ++ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT) ++ ah->ah_bwmode = ah->ah_bwmode_debug; ++ + /* + * To switch channels clear any pending DMA operations; + * wait long enough for the RX fifo to drain, reset the diff --git a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch new file mode 100644 index 0000000..a7f9d9f --- /dev/null +++ b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch @@ -0,0 +1,65 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1301,6 +1301,53 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); + } + ++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ struct ath_common *common = ath9k_hw_common(ah); ++ int bytes = 0; ++ int pos = *ppos; ++ int size = 4096; ++ u16 val; ++ int i; ++ ++ if (AR_SREV_9300_20_OR_LATER(ah)) ++ size = 16384; ++ ++ if (*ppos < 0) ++ return -EINVAL; ++ ++ if (count > size - *ppos) ++ count = size - *ppos; ++ ++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) { ++ void *from = &val; ++ ++ if (!common->bus_ops->eeprom_read(common, i, &val)) ++ val = 0xffff; ++ ++ if (*ppos % 2) { ++ from++; ++ bytes = 1; ++ } else if (count == 1) { ++ bytes = 1; ++ } else { ++ bytes = 2; ++ } ++ copy_to_user(user_buf, from, bytes); ++ user_buf += bytes; ++ } ++ return *ppos - pos; ++} ++ ++static const struct file_operations fops_eeprom = { ++ .read = read_file_eeprom, ++ .open = simple_open, ++ .owner = THIS_MODULE ++}; ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1320,6 +1367,8 @@ int ath9k_init_debug(struct ath_hw *ah) + ath9k_tx99_init_debug(sc); + ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); + ++ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, ++ &fops_eeprom); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch new file mode 100644 index 0000000..143545c --- /dev/null +++ b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch @@ -0,0 +1,32 @@ +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -1038,23 +1038,23 @@ static int __init ath9k_init(void) + { + int error; + +- error = ath_pci_init(); ++ error = ath_ahb_init(); + if (error < 0) { +- pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; + goto err_out; + } + +- error = ath_ahb_init(); ++ error = ath_pci_init(); + if (error < 0) { ++ pr_err("No PCI devices found, driver not installed\n"); + error = -ENODEV; +- goto err_pci_exit; ++ goto err_ahb_exit; + } + + return 0; + +- err_pci_exit: +- ath_pci_exit(); ++ err_ahb_exit: ++ ath_ahb_exit(); + err_out: + return error; + } diff --git a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch new file mode 100644 index 0000000..d2a3b96 --- /dev/null +++ b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch @@ -0,0 +1,18 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -390,13 +390,8 @@ static void ath9k_hw_init_config(struct + + ah->config.rx_intr_mitigation = true; + +- if (AR_SREV_9300_20_OR_LATER(ah)) { +- ah->config.rimt_last = 500; +- ah->config.rimt_first = 2000; +- } else { +- ah->config.rimt_last = 250; +- ah->config.rimt_first = 700; +- } ++ ah->config.rimt_last = 250; ++ ah->config.rimt_first = 500; + + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) + ah->config.pll_pwrsave = 7; diff --git a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch new file mode 100644 index 0000000..d4104f0 --- /dev/null +++ b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -87,7 +87,7 @@ int ath_descdma_setup(struct ath_softc * + (_l) &= ((_sz) - 1); \ + } while (0) + +-#define ATH_RXBUF 512 ++#define ATH_RXBUF 256 + #define ATH_TXBUF 512 + #define ATH_TXBUF_RESERVE 5 + #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch new file mode 100644 index 0000000..5ecf528 --- /dev/null +++ b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch @@ -0,0 +1,125 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1348,6 +1348,52 @@ static const struct file_operations fops + .owner = THIS_MODULE + }; + ++ ++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08x\n", common->chan_bw); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ unsigned long chan_bw; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &chan_bw)) ++ return -EINVAL; ++ ++ common->chan_bw = chan_bw; ++ if (!test_bit(ATH_OP_INVALID, &common->op_flags)) ++ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL); ++ ++ return count; ++} ++ ++static const struct file_operations fops_chanbw = { ++ .read = read_file_chan_bw, ++ .write = write_file_chan_bw, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1369,6 +1415,8 @@ int ath9k_init_debug(struct ath_hw *ah) + + debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_eeprom); ++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++ sc, &fops_chanbw); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, +--- a/drivers/net/wireless/ath/ath.h ++++ b/drivers/net/wireless/ath/ath.h +@@ -151,6 +151,7 @@ struct ath_common { + int debug_mask; + enum ath_device_state state; + unsigned long op_flags; ++ u32 chan_bw; + + struct ath_ani ani; + +--- a/drivers/net/wireless/ath/ath9k/common.c ++++ b/drivers/net/wireless/ath/ath9k/common.c +@@ -296,11 +296,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke + /* + * Update internal channel flags. + */ +-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, ++static void ath9k_cmn_update_ichannel(struct ath_common *common, ++ struct ath9k_channel *ichan, + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *chan = chandef->chan; + u16 flags = 0; ++ int width; + + ichan->channel = chan->center_freq; + ichan->chan = chan; +@@ -308,7 +310,19 @@ static void ath9k_cmn_update_ichannel(st + if (chan->band == IEEE80211_BAND_5GHZ) + flags |= CHANNEL_5GHZ; + +- switch (chandef->width) { ++ switch (common->chan_bw) { ++ case 5: ++ width = NL80211_CHAN_WIDTH_5; ++ break; ++ case 10: ++ width = NL80211_CHAN_WIDTH_10; ++ break; ++ default: ++ width = chandef->width; ++ break; ++ } ++ ++ switch (width) { + case NL80211_CHAN_WIDTH_5: + flags |= CHANNEL_QUARTER; + break; +@@ -341,10 +355,11 @@ struct ath9k_channel *ath9k_cmn_get_chan + struct cfg80211_chan_def *chandef) + { + struct ieee80211_channel *curchan = chandef->chan; ++ struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *channel; + + channel = &ah->channels[curchan->hw_value]; +- ath9k_cmn_update_ichannel(channel, chandef); ++ ath9k_cmn_update_ichannel(common, channel, chandef); + + return channel; + } diff --git a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch new file mode 100644 index 0000000..c84d1bc --- /dev/null +++ b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch @@ -0,0 +1,30 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -651,6 +651,7 @@ int ath9k_hw_init(struct ath_hw *ah) + + /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ + switch (ah->hw_version.devid) { ++ case AR9300_DEVID_INVALID: + case AR5416_DEVID_PCI: + case AR5416_DEVID_PCIE: + case AR5416_AR9100_DEVID: +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -36,6 +36,7 @@ + + #define ATHEROS_VENDOR_ID 0x168c + ++#define AR9300_DEVID_INVALID 0xabcd + #define AR5416_DEVID_PCI 0x0023 + #define AR5416_DEVID_PCIE 0x0024 + #define AR9160_DEVID_PCI 0x0027 +--- a/drivers/net/wireless/ath/ath9k/pci.c ++++ b/drivers/net/wireless/ath/ath9k/pci.c +@@ -751,6 +751,7 @@ static const struct pci_device_id ath_pc + .driver_data = ATH9K_PCI_BT_ANT_DIV }, + #endif + ++ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */ + { 0 } + }; + diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch new file mode 100644 index 0000000..be7bd58 --- /dev/null +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -0,0 +1,160 @@ +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -2361,6 +2361,7 @@ struct cfg80211_qos_map { + * (as advertised by the nl80211 feature flag.) + * @get_tx_power: store the current TX power into the dbm variable; + * return 0 if successful ++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary + * + * @set_wds_peer: set the WDS peer for a WDS interface + * +@@ -2617,6 +2618,7 @@ struct cfg80211_ops { + enum nl80211_tx_power_setting type, int mbm); + int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, + int *dbm); ++ int (*set_antenna_gain)(struct wiphy *wiphy, int dbi); + + int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1250,6 +1250,7 @@ enum ieee80211_smps_mode { + * + * @power_level: requested transmit power (in dBm), backward compatibility + * value only that is set to the minimum of all interfaces ++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi) + * + * @chandef: the channel definition to tune to + * @radar_enabled: whether radar detection is enabled +@@ -1270,6 +1271,7 @@ enum ieee80211_smps_mode { + struct ieee80211_conf { + u32 flags; + int power_level, dynamic_ps_timeout; ++ int max_antenna_gain; + + u16 listen_interval; + u8 ps_dtim_period; +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -1783,6 +1783,9 @@ enum nl80211_commands { + * between scans. The scan plans are executed sequentially. + * Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan. + * ++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce ++ * transmit power to stay within regulatory limits. u32, dBi. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -2157,6 +2160,8 @@ enum nl80211_attrs { + NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS, + NL80211_ATTR_SCHED_SCAN_PLANS, + ++ NL80211_ATTR_WIPHY_ANTENNA_GAIN, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2206,6 +2206,19 @@ static int ieee80211_get_tx_power(struct + return 0; + } + ++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi) ++{ ++ struct ieee80211_local *local = wiphy_priv(wiphy); ++ ++ if (dbi < 0) ++ return -EINVAL; ++ ++ local->user_antenna_gain = dbi; ++ ieee80211_hw_config(local, 0); ++ ++ return 0; ++} ++ + static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr) + { +@@ -3849,6 +3862,7 @@ const struct cfg80211_ops mac80211_confi + .set_wiphy_params = ieee80211_set_wiphy_params, + .set_tx_power = ieee80211_set_tx_power, + .get_tx_power = ieee80211_get_tx_power, ++ .set_antenna_gain = ieee80211_set_antenna_gain, + .set_wds_peer = ieee80211_set_wds_peer, + .rfkill_poll = ieee80211_rfkill_poll, + CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1321,6 +1321,7 @@ struct ieee80211_local { + int dynamic_ps_forced_timeout; + + int user_power_level; /* in dBm, for all interfaces */ ++ int user_antenna_gain; /* in dBi */ + + enum ieee80211_smps_mode smps_mode; + +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -93,7 +93,7 @@ static u32 ieee80211_hw_conf_chan(struct + struct ieee80211_sub_if_data *sdata; + struct cfg80211_chan_def chandef = {}; + u32 changed = 0; +- int power; ++ int power, max_power; + u32 offchannel_flag; + + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; +@@ -150,6 +150,12 @@ static u32 ieee80211_hw_conf_chan(struct + } + rcu_read_unlock(); + ++ max_power = chandef.chan->max_reg_power; ++ if (local->user_antenna_gain > 0) { ++ max_power -= local->user_antenna_gain; ++ power = min(power, max_power); ++ } ++ + if (local->hw.conf.power_level != power) { + changed |= IEEE80211_CONF_CHANGE_POWER; + local->hw.conf.power_level = power; +@@ -580,6 +586,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + IEEE80211_RADIOTAP_MCS_HAVE_BW; + local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; ++ local->user_antenna_gain = 0; + local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES; + local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN; + local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -403,6 +403,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 }, + [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 }, + [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, ++ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, + }; + + /* policy for the key attributes */ +@@ -2220,6 +2221,20 @@ static int nl80211_set_wiphy(struct sk_b + if (result) + return result; + } ++ ++ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { ++ int idx, dbi = 0; ++ ++ if (!rdev->ops->set_antenna_gain) ++ return -EOPNOTSUPP; ++ ++ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN; ++ dbi = nla_get_u32(info->attrs[idx]); ++ ++ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi); ++ if (result) ++ return result; ++ } + + if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && + info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) { diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch new file mode 100644 index 0000000..89e3c97 --- /dev/null +++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch @@ -0,0 +1,251 @@ +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -813,6 +813,9 @@ static inline int ath9k_dump_btcoex(stru + void ath_init_leds(struct ath_softc *sc); + void ath_deinit_leds(struct ath_softc *sc); + void ath_fill_led_pin(struct ath_softc *sc); ++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name, ++ const char *trigger, bool active_low); ++ + #else + static inline void ath_init_leds(struct ath_softc *sc) + { +@@ -952,6 +955,13 @@ void ath_ant_comb_scan(struct ath_softc + + #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ + ++struct ath_led { ++ struct list_head list; ++ struct ath_softc *sc; ++ const struct gpio_led *gpio; ++ struct led_classdev cdev; ++}; ++ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +@@ -1003,9 +1013,8 @@ struct ath_softc { + spinlock_t chan_lock; + + #ifdef CPTCFG_MAC80211_LEDS +- bool led_registered; +- char led_name[32]; +- struct led_classdev led_cdev; ++ const char *led_default_trigger; ++ struct list_head leds; + #endif + + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -24,45 +24,102 @@ + static void ath_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) + { +- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); +- u32 val = (brightness == LED_OFF); ++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev); ++ struct ath_softc *sc = led->sc; + +- if (sc->sc_ah->config.led_active_high) +- val = !val; ++ ath9k_ps_wakeup(sc); ++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio, ++ (brightness != LED_OFF) ^ led->gpio->active_low); ++ ath9k_ps_restore(sc); ++} ++ ++static int ath_add_led(struct ath_softc *sc, struct ath_led *led) ++{ ++ const struct gpio_led *gpio = led->gpio; ++ int ret; ++ ++ led->cdev.name = gpio->name; ++ led->cdev.default_trigger = gpio->default_trigger; ++ led->cdev.brightness_set = ath_led_brightness; + +- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); ++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev); ++ if (ret < 0) ++ return ret; ++ ++ led->sc = sc; ++ list_add(&led->list, &sc->leds); ++ ++ /* Configure gpio for output */ ++ ath9k_hw_cfg_output(sc->sc_ah, gpio->gpio, ++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ++ ++ /* LED off */ ++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); ++ ++ return 0; ++} ++ ++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name, ++ const char *trigger, bool active_low) ++{ ++ struct ath_led *led; ++ struct gpio_led *gpio; ++ char *_name; ++ int ret; ++ ++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1, ++ GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->gpio = gpio = (struct gpio_led *) (led + 1); ++ _name = (char *) (led->gpio + 1); ++ ++ strcpy(_name, name); ++ gpio->name = _name; ++ gpio->gpio = gpio_num; ++ gpio->active_low = active_low; ++ gpio->default_trigger = trigger; ++ ++ ret = ath_add_led(sc, led); ++ if (unlikely(ret < 0)) ++ kfree(led); ++ ++ return ret; + } + + void ath_deinit_leds(struct ath_softc *sc) + { +- if (!sc->led_registered) +- return; ++ struct ath_led *led; + +- ath_led_brightness(&sc->led_cdev, LED_OFF); +- led_classdev_unregister(&sc->led_cdev); ++ while (!list_empty(&sc->leds)) { ++ led = list_first_entry(&sc->leds, struct ath_led, list); ++ list_del(&led->list); ++ ath_led_brightness(&led->cdev, LED_OFF); ++ led_classdev_unregister(&led->cdev); ++ kfree(led); ++ } + } + + void ath_init_leds(struct ath_softc *sc) + { +- int ret; ++ char led_name[32]; ++ const char *trigger; ++ ++ INIT_LIST_HEAD(&sc->leds); + + if (AR_SREV_9100(sc->sc_ah)) + return; + +- if (!ath9k_led_blink) +- sc->led_cdev.default_trigger = +- ieee80211_get_radio_led_name(sc->hw); +- +- snprintf(sc->led_name, sizeof(sc->led_name), +- "ath9k-%s", wiphy_name(sc->hw->wiphy)); +- sc->led_cdev.name = sc->led_name; +- sc->led_cdev.brightness_set = ath_led_brightness; ++ snprintf(led_name, sizeof(led_name), "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); + +- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); +- if (ret < 0) +- return; ++ if (ath9k_led_blink) ++ trigger = sc->led_default_trigger; ++ else ++ trigger = ieee80211_get_radio_led_name(sc->hw); + +- sc->led_registered = true; ++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1); + } + + void ath_fill_led_pin(struct ath_softc *sc) +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -950,7 +950,7 @@ int ath9k_init_device(u16 devid, struct + + #ifdef CPTCFG_MAC80211_LEDS + /* must be initialized before ieee80211_register_hw */ +- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, ++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, + ARRAY_SIZE(ath9k_tpt_blink)); + #endif +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1393,6 +1393,61 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + ++#ifdef CONFIG_MAC80211_LEDS ++ ++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ char buf[32], *str, *name, *c; ++ ssize_t len; ++ unsigned int gpio; ++ bool active_low = false; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, ubuf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ name = strchr(buf, ','); ++ if (!name) ++ return -EINVAL; ++ ++ *(name++) = 0; ++ if (!*name) ++ return -EINVAL; ++ ++ c = strchr(name, '\n'); ++ if (c) ++ *c = 0; ++ ++ str = buf; ++ if (*str == '!') { ++ str++; ++ active_low = true; ++ } ++ ++ if (kstrtouint(str, 0, &gpio) < 0) ++ return -EINVAL; ++ ++ if (gpio >= sc->sc_ah->caps.num_gpio_pins) ++ return -EINVAL; ++ ++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0) ++ return -EINVAL; ++ ++ return count; ++} ++ ++static const struct file_operations fops_gpio_led = { ++ .write = write_file_gpio_led, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++#endif ++ + + int ath9k_init_debug(struct ath_hw *ah) + { +@@ -1417,6 +1472,10 @@ int ath9k_init_debug(struct ath_hw *ah) + &fops_eeprom); + debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_chanbw); ++#ifdef CONFIG_MAC80211_LEDS ++ debugfs_create_file("gpio_led", S_IWUSR, ++ sc->debug.debugfs_phy, sc, &fops_gpio_led); ++#endif + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, diff --git a/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch b/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch new file mode 100644 index 0000000..dc33cd0 --- /dev/null +++ b/package/kernel/mac80211/patches/531-ath9k_extra_platform_leds.patch @@ -0,0 +1,71 @@ +--- a/include/linux/ath9k_platform.h ++++ b/include/linux/ath9k_platform.h +@@ -41,6 +41,9 @@ struct ath9k_platform_data { + int (*external_reset)(void); + + bool use_eeprom; ++ ++ int num_leds; ++ const struct gpio_led *leds; + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -15,6 +15,7 @@ + */ + + #include "ath9k.h" ++#include + + /********************************/ + /* LED functions */ +@@ -88,6 +89,24 @@ int ath_create_gpio_led(struct ath_softc + return ret; + } + ++static int ath_create_platform_led(struct ath_softc *sc, ++ const struct gpio_led *gpio) ++{ ++ struct ath_led *led; ++ int ret; ++ ++ led = kzalloc(sizeof(*led), GFP_KERNEL); ++ if (!led) ++ return -ENOMEM; ++ ++ led->gpio = gpio; ++ ret = ath_add_led(sc, led); ++ if (ret < 0) ++ kfree(led); ++ ++ return ret; ++} ++ + void ath_deinit_leds(struct ath_softc *sc) + { + struct ath_led *led; +@@ -103,8 +122,10 @@ void ath_deinit_leds(struct ath_softc *s + + void ath_init_leds(struct ath_softc *sc) + { ++ struct ath9k_platform_data *pdata = sc->dev->platform_data; + char led_name[32]; + const char *trigger; ++ int i; + + INIT_LIST_HEAD(&sc->leds); + +@@ -120,6 +141,12 @@ void ath_init_leds(struct ath_softc *sc) + trigger = ieee80211_get_radio_led_name(sc->hw); + + ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1); ++ ++ if (!pdata) ++ return; ++ ++ for (i = 0; i < pdata->num_leds; i++) ++ ath_create_platform_led(sc, &pdata->leds[i]); + } + + void ath_fill_led_pin(struct ath_softc *sc) diff --git a/package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch b/package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch new file mode 100644 index 0000000..e899903 --- /dev/null +++ b/package/kernel/mac80211/patches/540-ath9k_reduce_ani_interval.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/ath9k/ani.h ++++ b/drivers/net/wireless/ath/ath9k/ani.h +@@ -42,7 +42,7 @@ + #define ATH9K_ANI_PERIOD 300 + + /* in ms */ +-#define ATH9K_ANI_POLLINTERVAL 1000 ++#define ATH9K_ANI_POLLINTERVAL 300 + + #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0 + #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20 diff --git a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch new file mode 100644 index 0000000..3c5e9f5 --- /dev/null +++ b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch @@ -0,0 +1,28 @@ +--- a/drivers/net/wireless/ath/ath9k/mac.c ++++ b/drivers/net/wireless/ath/ath9k/mac.c +@@ -695,7 +695,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw + { + #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ + struct ath_common *common = ath9k_hw_common(ah); +- u32 mac_status, last_mac_status = 0; ++ u32 mac_status = 0, last_mac_status = 0; + int i; + + /* Enable access to the DMA observation bus */ +@@ -725,6 +725,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw + } + + if (i == 0) { ++ if (!AR_SREV_9300_20_OR_LATER(ah) && ++ (mac_status & 0x700) == 0) { ++ /* ++ * DMA is idle but the MAC is still stuck ++ * processing events ++ */ ++ *reset = true; ++ return true; ++ } ++ + ath_err(common, + "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n", + AH_RX_STOP_DMA_TIMEOUT / 1000, diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch new file mode 100644 index 0000000..9758d5f --- /dev/null +++ b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch @@ -0,0 +1,139 @@ +--- a/drivers/net/wireless/ath/ath9k/debug.c ++++ b/drivers/net/wireless/ath/ath9k/debug.c +@@ -1449,6 +1449,50 @@ static const struct file_operations fops + #endif + + ++static ssize_t read_file_diag(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[32]; ++ unsigned int len; ++ ++ len = sprintf(buf, "0x%08lx\n", ah->diag); ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static ssize_t write_file_diag(struct file *file, const char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ath_softc *sc = file->private_data; ++ struct ath_hw *ah = sc->sc_ah; ++ unsigned long diag; ++ char buf[32]; ++ ssize_t len; ++ ++ len = min(count, sizeof(buf) - 1); ++ if (copy_from_user(buf, user_buf, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &diag)) ++ return -EINVAL; ++ ++ ah->diag = diag; ++ ath9k_hw_update_diag(ah); ++ ++ return count; ++} ++ ++static const struct file_operations fops_diag = { ++ .read = read_file_diag, ++ .write = write_file_diag, ++ .open = simple_open, ++ .owner = THIS_MODULE, ++ .llseek = default_llseek, ++}; ++ ++ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +@@ -1476,6 +1520,8 @@ int ath9k_init_debug(struct ath_hw *ah) + debugfs_create_file("gpio_led", S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_gpio_led); + #endif ++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++ sc, &fops_diag); + debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, + read_file_dma); + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -519,6 +519,12 @@ enum { + ATH9K_RESET_COLD, + }; + ++enum { ++ ATH_DIAG_DISABLE_RX, ++ ATH_DIAG_DISABLE_TX, ++ ATH_DIAG_TRIGGER_ERROR, ++}; ++ + struct ath9k_hw_version { + u32 magic; + u16 devid; +@@ -804,6 +810,8 @@ struct ath_hw { + u32 rfkill_polarity; + u32 ah_flags; + ++ unsigned long diag; ++ + bool reset_power_on; + bool htc_reset_init; + +@@ -1066,6 +1074,7 @@ void ath9k_hw_check_nav(struct ath_hw *a + bool ath9k_hw_check_alive(struct ath_hw *ah); + + bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); ++void ath9k_hw_update_diag(struct ath_hw *ah); + + /* Generic hw timer primitives */ + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -1809,6 +1809,20 @@ u32 ath9k_hw_get_tsf_offset(struct times + } + EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); + ++void ath9k_hw_update_diag(struct ath_hw *ah) ++{ ++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); ++ ++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag)) ++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++ else ++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK); ++} ++EXPORT_SYMBOL(ath9k_hw_update_diag); ++ + int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + struct ath9k_hw_cal_data *caldata, bool fastcc) + { +@@ -2017,6 +2031,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ar9003_hw_disable_phy_restart(ah); + + ath9k_hw_apply_gpio_override(ah); ++ ath9k_hw_update_diag(ah); + + if (AR_SREV_9565(ah) && common->bt_ant_diversity) + REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); +--- a/drivers/net/wireless/ath/ath9k/main.c ++++ b/drivers/net/wireless/ath/ath9k/main.c +@@ -533,6 +533,11 @@ irqreturn_t ath_isr(int irq, void *dev) + if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) + return IRQ_HANDLED; + ++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) { ++ status |= ATH9K_INT_FATAL; ++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag); ++ } ++ + /* + * If there are no status bits set, then this interrupt was not + * for me (should have been caught above). diff --git a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch new file mode 100644 index 0000000..fa8eca5 --- /dev/null +++ b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch @@ -0,0 +1,186 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.h ++++ b/drivers/net/wireless/ath/ath9k/hw.h +@@ -720,6 +720,7 @@ struct ath_spec_scan { + * @config_pci_powersave: + * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC + * ++ * @get_adc_entropy: get entropy from the raw ADC I/Q output + * @spectral_scan_config: set parameters for spectral scan and enable/disable it + * @spectral_scan_trigger: trigger a spectral scan run + * @spectral_scan_wait: wait for a spectral scan run to finish +@@ -742,6 +743,7 @@ struct ath_hw_ops { + struct ath_hw_antcomb_conf *antconf); + void (*antdiv_comb_conf_set)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); ++ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len); + void (*spectral_scan_config)(struct ath_hw *ah, + struct ath_spec_scan *param); + void (*spectral_scan_trigger)(struct ath_hw *ah); +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -1998,6 +1998,26 @@ void ar9003_hw_init_rate_txpower(struct + } + } + ++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0); ++ ++ memset(buf, 0, len); ++ for (i = 0; i < len; i++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9); ++ udelay(1); ++ } ++ } ++} ++ + void ar9003_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +@@ -2034,6 +2054,7 @@ void ar9003_hw_attach_phy_ops(struct ath + priv_ops->set_radar_params = ar9003_hw_set_radar_params; + priv_ops->fast_chan_change = ar9003_hw_fast_chan_change; + ++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy; + ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; + ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; + ops->spectral_scan_config = ar9003_hw_spectral_scan_config; +--- a/drivers/net/wireless/ath/ath9k/init.c ++++ b/drivers/net/wireless/ath/ath9k/init.c +@@ -710,7 +710,8 @@ static void ath9k_init_txpower_limits(st + if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) + ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); + +- ah->curchan = curchan; ++ if (curchan) ++ ah->curchan = curchan; + } + + static const struct ieee80211_iface_limit if_limits[] = { +@@ -910,6 +911,18 @@ static void ath9k_set_hw_capab(struct at + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); + } + ++static void ath_get_initial_entropy(struct ath_softc *sc) ++{ ++ struct ath_hw *ah = sc->sc_ah; ++ char buf[256]; ++ ++ /* reuse last channel initialized by the tx power test */ ++ ath9k_hw_reset(ah, ah->curchan, NULL, false); ++ ++ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf)); ++ add_device_randomness(buf, sizeof(buf)); ++} ++ + int ath9k_init_device(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +@@ -955,6 +968,8 @@ int ath9k_init_device(u16 devid, struct + ARRAY_SIZE(ath9k_tpt_blink)); + #endif + ++ ath_get_initial_entropy(sc); ++ + /* Register with mac80211 */ + error = ieee80211_register_hw(hw); + if (error) +--- a/drivers/net/wireless/ath/ath9k/hw-ops.h ++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h +@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp + ath9k_hw_ops(ah)->tx99_set_txpower(ah, power); + } + ++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah, ++ u8 *buf, size_t len) ++{ ++ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len); ++} ++ + #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT + + static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -1327,9 +1327,30 @@ void ar5008_hw_init_rate_txpower(struct + } + } + ++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len) ++{ ++ int i, j; ++ ++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); ++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); ++ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0); ++ ++ memset(buf, 0, len); ++ for (i = 0; i < len; i++) { ++ for (j = 0; j < 4; j++) { ++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC); ++ ++ buf[i] <<= 2; ++ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8); ++ udelay(1); ++ } ++ } ++} ++ + int ar5008_hw_attach_phy_ops(struct ath_hw *ah) + { + struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); ++ struct ath_hw_ops *ops = ath9k_hw_ops(ah); + static const u32 ar5416_cca_regs[6] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, +@@ -1344,6 +1365,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ + if (ret) + return ret; + ++ ops->get_adc_entropy = ar5008_hw_get_adc_entropy; ++ + priv_ops->rf_set_freq = ar5008_hw_set_channel; + priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; + +--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h ++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h +@@ -20,6 +20,12 @@ + #define PHY_AGC_CLR 0x10000000 + #define RFSILENT_BB 0x00002000 + ++#define AR_PHY_TEST_BBB_OBS_SEL 0x780000 ++#define AR_PHY_TEST_BBB_OBS_SEL_S 19 ++ ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23 ++#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S) ++ + #define AR_PHY_TURBO 0x9804 + #define AR_PHY_FC_TURBO_MODE 0x00000001 + #define AR_PHY_FC_TURBO_SHORT 0x00000002 +@@ -36,6 +42,9 @@ + + #define AR_PHY_TEST2 0x9808 + ++#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00 ++#define AR_PHY_TEST2_RX_OBS_SEL_S 10 ++ + #define AR_PHY_TIMING2 0x9810 + #define AR_PHY_TIMING3 0x9814 + #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +@@ -390,6 +399,8 @@ + #define AR_PHY_RFBUS_GRANT 0x9C20 + #define AR_PHY_RFBUS_GRANT_EN 0x00000001 + ++#define AR_PHY_TST_ADC 0x9C24 ++ + #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 + #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 + diff --git a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch new file mode 100644 index 0000000..3f46226 --- /dev/null +++ b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch @@ -0,0 +1,79 @@ +--- a/drivers/net/wireless/ath/ath9k/hw.c ++++ b/drivers/net/wireless/ath/ath9k/hw.c +@@ -246,6 +246,19 @@ void ath9k_hw_get_channel_centers(struct + centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); + } + ++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah) ++{ ++ /* On AR9330 and AR9340 devices, some PHY registers must be ++ * tuned to gain better stability/performance. These registers ++ * might be changed while doing wlan reset so the registers must ++ * be reprogrammed after each reset. ++ */ ++ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20)); ++ REG_RMW(ah, AR_PHY_USB_CTRL2, ++ (1 << 21) | (0xf << 22), ++ (1 << 21) | (0x3 << 22)); ++} ++ + /******************/ + /* Chip Revisions */ + /******************/ +@@ -1387,6 +1400,9 @@ static bool ath9k_hw_set_reset(struct at + if (AR_SREV_9100(ah)) + udelay(50); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1486,6 +1502,9 @@ static bool ath9k_hw_chip_reset(struct a + ar9003_hw_internal_regulator_apply(ah); + ath9k_hw_init_pll(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return true; + } + +@@ -1787,8 +1806,14 @@ static int ath9k_hw_do_fastcc(struct ath + if (AR_SREV_9271(ah)) + ar9002_hw_load_ani_reg(ah, chan); + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + fail: ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return -EINVAL; + } + +@@ -2042,6 +2067,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ath9k_hw_set_radar_params(ah); + } + ++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) ++ ath9k_hw_disable_pll_lock_detect(ah); ++ + return 0; + } + EXPORT_SYMBOL(ath9k_hw_reset); +--- a/drivers/net/wireless/ath/ath9k/phy.h ++++ b/drivers/net/wireless/ath/ath9k/phy.h +@@ -48,6 +48,9 @@ + #define AR_PHY_PLL_CONTROL 0x16180 + #define AR_PHY_PLL_MODE 0x16184 + ++#define AR_PHY_USB_CTRL1 0x16c84 ++#define AR_PHY_USB_CTRL2 0x16c88 ++ + enum ath9k_ant_div_comb_lna_conf { + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, + ATH_ANT_DIV_COMB_LNA2, diff --git a/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch new file mode 100644 index 0000000..3d24ccd --- /dev/null +++ b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch @@ -0,0 +1,155 @@ +--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +@@ -956,55 +956,6 @@ static bool ar5008_hw_ani_control_new(st + * on == 0 means more noise imm + */ + u32 on = param ? 1 : 0; +- /* +- * make register setting for default +- * (weak sig detect ON) come from INI file +- */ +- int m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- int m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- int m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- int m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- int m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- int m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- int m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- int m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- int m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- int m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); + + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c +@@ -41,20 +41,6 @@ static const int cycpwrThr1_table[] = + /* level: 0 1 2 3 4 5 6 7 8 */ + { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */ + +-/* +- * register values to turn OFDM weak signal detection OFF +- */ +-static const int m1ThreshLow_off = 127; +-static const int m2ThreshLow_off = 127; +-static const int m1Thresh_off = 127; +-static const int m2Thresh_off = 127; +-static const int m2CountThr_off = 31; +-static const int m2CountThrLow_off = 63; +-static const int m1ThreshLowExt_off = 127; +-static const int m2ThreshLowExt_off = 127; +-static const int m1ThreshExt_off = 127; +-static const int m2ThreshExt_off = 127; +- + static const u8 ofdm2pwr[] = { + ALL_TARGET_LEGACY_6_24, + ALL_TARGET_LEGACY_6_24, +@@ -1089,11 +1075,6 @@ static bool ar9003_hw_ani_control(struct + struct ath_common *common = ath9k_hw_common(ah); + struct ath9k_channel *chan = ah->curchan; + struct ar5416AniState *aniState = &ah->ani; +- int m1ThreshLow, m2ThreshLow; +- int m1Thresh, m2Thresh; +- int m2CountThr, m2CountThrLow; +- int m1ThreshLowExt, m2ThreshLowExt; +- int m1ThreshExt, m2ThreshExt; + s32 value, value2; + + switch (cmd & ah->ani_function) { +@@ -1107,61 +1088,6 @@ static bool ar9003_hw_ani_control(struct + */ + u32 on = param ? 1 : 0; + +- if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) +- goto skip_ws_det; +- +- m1ThreshLow = on ? +- aniState->iniDef.m1ThreshLow : m1ThreshLow_off; +- m2ThreshLow = on ? +- aniState->iniDef.m2ThreshLow : m2ThreshLow_off; +- m1Thresh = on ? +- aniState->iniDef.m1Thresh : m1Thresh_off; +- m2Thresh = on ? +- aniState->iniDef.m2Thresh : m2Thresh_off; +- m2CountThr = on ? +- aniState->iniDef.m2CountThr : m2CountThr_off; +- m2CountThrLow = on ? +- aniState->iniDef.m2CountThrLow : m2CountThrLow_off; +- m1ThreshLowExt = on ? +- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; +- m2ThreshLowExt = on ? +- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; +- m1ThreshExt = on ? +- aniState->iniDef.m1ThreshExt : m1ThreshExt_off; +- m2ThreshExt = on ? +- aniState->iniDef.m2ThreshExt : m2ThreshExt_off; +- +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +- m1ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +- m2ThreshLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M1_THRESH, +- m1Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2_THRESH, +- m2Thresh); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR, +- AR_PHY_SFCORR_M2COUNT_THR, +- m2CountThr); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +- m2CountThrLow); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, +- m1ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, +- m2ThreshLowExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M1_THRESH, +- m1ThreshExt); +- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +- AR_PHY_SFCORR_EXT_M2_THRESH, +- m2ThreshExt); +-skip_ws_det: + if (on) + REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, + AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); diff --git a/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch new file mode 100644 index 0000000..15863a6 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch @@ -0,0 +1,66 @@ +From 7a69da907de668fb22a30ae218062d6f081864ea Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sat, 17 Aug 2013 19:31:41 +0200 +Subject: [PATCH] rt2x00: rt2800lib: move rt2800_drv_data declaration into + rt2800lib.h + +The rt2800_drv_data structure contains driver specific +information. Move the declaration into the rt2800lib.h +header which is a more logical place for it. Also fix +the comment style to avoid checkpatch warning. + +The patch contains no functional changes, it is in +preparation for the next patch. + +Signed-off-by: Gabor Juhos +--- +Changes since v1: --- +--- + drivers/net/wireless/rt2x00/rt2800.h | 13 ------------- + drivers/net/wireless/rt2x00/rt2800lib.h | 11 +++++++++++ + 2 files changed, 11 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/rt2x00/rt2800lib.h +@@ -20,6 +20,20 @@ + #ifndef RT2800LIB_H + #define RT2800LIB_H + ++#include "rt2800.h" ++ ++/* RT2800 driver data structure */ ++struct rt2800_drv_data { ++ u8 calibration_bw20; ++ u8 calibration_bw40; ++ u8 bbp25; ++ u8 bbp26; ++ u8 txmixer_gain_24g; ++ u8 txmixer_gain_5g; ++ unsigned int tbtt_tick; ++ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); ++}; ++ + struct rt2800_ops { + void (*register_read)(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 *value); +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -2969,18 +2969,4 @@ enum rt2800_eeprom_word { + #define WCID_END 222 + #define STA_IDS_SIZE (WCID_END - WCID_START + 2) + +-/* +- * RT2800 driver data structure +- */ +-struct rt2800_drv_data { +- u8 calibration_bw20; +- u8 calibration_bw40; +- u8 bbp25; +- u8 bbp26; +- u8 txmixer_gain_24g; +- u8 txmixer_gain_5g; +- unsigned int tbtt_tick; +- DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); +-}; +- + #endif /* RT2800_H */ diff --git a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch new file mode 100644 index 0000000..9165eec --- /dev/null +++ b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch @@ -0,0 +1,80 @@ +From a7f268af31dddf763fe3dbe9cbf96ea77e0540e0 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sat, 17 Aug 2013 19:31:41 +0200 +Subject: [PATCH] rt2x00: rt2800lib: introduce RT2800_HAS_HIGH_SHARED_MEM flag + +Some chipsets have more than 16KB of shared memory. +Introduce a new rt2800 specific flag to indicate that +and add a helper function which helps to check the +presence of the new flag. + +Also enable the new flag for the RT3593 chipset which +has 24KB of shared memory. The flag can also be used +for other chipsets, but none of those has been tested +yet. + +Signed-off-by: Gabor Juhos +--- +Changes since v1: + - don't enable the new flag for RT3071 and RT5592 +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++++ + drivers/net/wireless/rt2x00/rt2800lib.h | 13 +++++++++++++ + 2 files changed, 17 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7721,6 +7721,7 @@ static int rt2800_probe_rt(struct rt2x00 + + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) + { ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + int retval; + u32 reg; + +@@ -7728,6 +7729,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (retval) + return retval; + ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); ++ + /* + * Allocate eeprom data. + */ +--- a/drivers/net/wireless/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/rt2x00/rt2800lib.h +@@ -22,6 +22,10 @@ + + #include "rt2800.h" + ++enum rt2800_flag { ++ RT2800_HAS_HIGH_SHARED_MEM, ++}; ++ + /* RT2800 driver data structure */ + struct rt2800_drv_data { + u8 calibration_bw20; +@@ -32,6 +36,8 @@ struct rt2800_drv_data { + u8 txmixer_gain_5g; + unsigned int tbtt_tick; + DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); ++ ++ unsigned long rt2800_flags; + }; + + struct rt2800_ops { +@@ -64,6 +70,13 @@ struct rt2800_ops { + __le32 *(*drv_get_txwi)(struct queue_entry *entry); + }; + ++static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); ++} ++ + static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 *value) diff --git a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch new file mode 100644 index 0000000..5671515 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch @@ -0,0 +1,531 @@ +From 250a1b520cd7fdc0df4fc3fedea9066913f49ecf Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sat, 17 Aug 2013 19:31:42 +0200 +Subject: [PATCH] rt2x00: rt2800: serialize shared memory access + +The shared memory of the rt2800 devices is accessible +through the register offset range between 0x4000 and +0x8000. The size of this range is 16KB only and on +devices which have more than 16KB of shared memory either +the low or the high part of the memory is accessible at a +time. + +Serialize all accesses to the shared memory by a mutex, +in order to avoid concurrent use of that. + +Signed-off-by: Gabor Juhos +--- +Changes since v1: --- +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 55 +++++++++++++++++++++++++++++- + drivers/net/wireless/rt2x00/rt2800lib.h | 32 +++++++++++++++++ + drivers/net/wireless/rt2x00/rt2800mmio.c | 26 ++++++++++++++ + drivers/net/wireless/rt2x00/rt2800mmio.h | 4 +++ + drivers/net/wireless/rt2x00/rt2800pci.c | 14 ++++++++ + drivers/net/wireless/rt2x00/rt2800soc.c | 3 ++ + drivers/net/wireless/rt2x00/rt2800usb.c | 31 +++++++++++++++++ + 7 files changed, 164 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -451,11 +451,13 @@ void rt2800_mcu_request(struct rt2x00_de + rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); + rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); + + reg = 0; + rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); + rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + mutex_unlock(&rt2x00dev->csr_mutex); +@@ -674,7 +676,9 @@ int rt2800_load_firmware(struct rt2x00_d + * Wait for device to stabilize. + */ + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); ++ rt2800_shared_mem_unlock(rt2x00dev); + if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) + break; + msleep(1); +@@ -694,10 +698,16 @@ int rt2800_load_firmware(struct rt2x00_d + /* + * Initialize firmware. + */ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++ rt2800_shared_mem_unlock(rt2x00dev); ++ + if (rt2x00_is_usb(rt2x00dev)) { ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); ++ rt2800_shared_mem_unlock(rt2x00dev); ++ + rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); + } + msleep(1); +@@ -1035,8 +1045,10 @@ void rt2800_write_beacon(struct queue_en + + beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); + ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); ++ rt2800_shared_mem_unlock(rt2x00dev); + __set_bit(ENTRY_BCN_ENABLED, &entry->flags); + + /* +@@ -1066,6 +1078,8 @@ static inline void rt2800_clear_beacon_r + + beacon_base = rt2800_hw_beacon_base(rt2x00dev, index); + ++ rt2800_shared_mem_lock(rt2x00dev); ++ + /* + * For the Beacon base registers we only need to clear + * the whole TXWI which (when set to 0) will invalidate +@@ -1073,6 +1087,8 @@ static inline void rt2800_clear_beacon_r + */ + for (i = 0; i < txwi_desc_size; i += sizeof(__le32)) + rt2800_register_write(rt2x00dev, beacon_base + i, 0); ++ ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + void rt2800_clear_beacon(struct queue_entry *entry) +@@ -1261,7 +1277,9 @@ static void rt2800_delete_wcid_attr(stru + { + u32 offset; + offset = MAC_WCID_ATTR_ENTRY(wcid); ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write(rt2x00dev, offset, 0); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev, +@@ -1274,11 +1292,13 @@ static void rt2800_config_wcid_attr_bssi + * The BSS Idx numbers is split in a main value of 3 bits, + * and a extended field for adding one additional bit to the value. + */ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7)); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, + (bssidx & 0x8) >> 3); + rt2800_register_write(rt2x00dev, offset, reg); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, +@@ -1291,6 +1311,7 @@ static void rt2800_config_wcid_attr_ciph + + offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); + ++ rt2800_shared_mem_lock(rt2x00dev); + if (crypto->cmd == SET_KEY) { + rt2800_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, +@@ -1315,6 +1336,7 @@ static void rt2800_config_wcid_attr_ciph + rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); + rt2800_register_write(rt2x00dev, offset, reg); + } ++ rt2800_shared_mem_unlock(rt2x00dev); + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + +@@ -1324,8 +1346,11 @@ static void rt2800_config_wcid_attr_ciph + (crypto->cipher == CIPHER_AES)) + iveiv_entry.iv[3] |= 0x20; + iveiv_entry.iv[3] |= key->keyidx << 6; ++ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_multiwrite(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, +@@ -1348,8 +1373,11 @@ int rt2800_config_shared_key(struct rt2x + sizeof(key_entry.rx_mic)); + + offset = SHARED_KEY_ENTRY(key->hw_key_idx); ++ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_multiwrite(rt2x00dev, offset, + &key_entry, sizeof(key_entry)); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + /* +@@ -1364,10 +1392,12 @@ int rt2800_config_shared_key(struct rt2x + + offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); + ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_read(rt2x00dev, offset, ®); + rt2x00_set_field32(®, field, + (crypto->cmd == SET_KEY) * crypto->cipher); + rt2800_register_write(rt2x00dev, offset, reg); ++ rt2800_shared_mem_unlock(rt2x00dev); + + /* + * Update WCID information +@@ -1405,8 +1435,11 @@ int rt2800_config_pairwise_key(struct rt + sizeof(key_entry.rx_mic)); + + offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); ++ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_multiwrite(rt2x00dev, offset, + &key_entry, sizeof(key_entry)); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + /* +@@ -4884,14 +4917,19 @@ static int rt2800_init_registers(struct + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ ++ rt2800_shared_mem_lock(rt2x00dev); + for (i = 0; i < 4; i++) + rt2800_register_write(rt2x00dev, + SHARED_KEY_MODE_ENTRY(i), 0); ++ rt2800_shared_mem_unlock(rt2x00dev); + + for (i = 0; i < 256; i++) { + rt2800_config_wcid(rt2x00dev, NULL, i); + rt2800_delete_wcid_attr(rt2x00dev, i); ++ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + /* +@@ -5017,8 +5055,10 @@ static int rt2800_wait_bbp_ready(struct + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++ rt2800_shared_mem_unlock(rt2x00dev); + msleep(1); + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { +@@ -6714,11 +6754,19 @@ int rt2800_enable_radio(struct rt2x00_de + /* + * Send signal during boot time to initialize firmware. + */ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +- if (rt2x00_is_usb(rt2x00dev)) ++ rt2800_shared_mem_unlock(rt2x00dev); ++ ++ if (rt2x00_is_usb(rt2x00dev)) { ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); ++ rt2800_shared_mem_unlock(rt2x00dev); ++ } ++ + rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); ++ + msleep(1); + + /* +@@ -7725,6 +7773,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + int retval; + u32 reg; + ++ rt2800_shared_mem_init_lock(rt2x00dev); ++ + retval = rt2800_probe_rt(rt2x00dev); + if (retval) + return retval; +@@ -7808,8 +7858,11 @@ void rt2800_get_key_seq(struct ieee80211 + return; + + offset = MAC_IVEIV_ENTRY(key->hw_key_idx); ++ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); ++ rt2800_shared_mem_unlock(rt2x00dev); + + memcpy(&seq->tkip.iv16, &iveiv_entry.iv[0], 2); + memcpy(&seq->tkip.iv32, &iveiv_entry.iv[4], 4); +--- a/drivers/net/wireless/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/rt2x00/rt2800lib.h +@@ -38,6 +38,11 @@ struct rt2800_drv_data { + DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); + + unsigned long rt2800_flags; ++ ++ union { ++ spinlock_t spin; ++ struct mutex mutex; ++ } shmem_lock; + }; + + struct rt2800_ops { +@@ -68,6 +73,10 @@ 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); ++ ++ void (*shmem_init_lock)(struct rt2x00_dev *rt2x00dev); ++ void (*shmem_lock)(struct rt2x00_dev *rt2x00dev); ++ void (*shmem_unlock)(struct rt2x00_dev *rt2x00dev); + }; + + static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev) +@@ -77,6 +86,29 @@ static inline bool rt2800_has_high_share + return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + } + ++static inline void rt2800_shared_mem_init_lock(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ rt2800ops->shmem_init_lock(rt2x00dev); ++} ++ ++static inline void rt2800_shared_mem_lock(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ if (rt2800_has_high_shared_mem(rt2x00dev)) ++ rt2800ops->shmem_lock(rt2x00dev); ++} ++ ++static inline void rt2800_shared_mem_unlock(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; ++ ++ if (rt2800_has_high_shared_mem(rt2x00dev)) ++ rt2800ops->shmem_unlock(rt2x00dev); ++} ++ + static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 *value) +--- a/drivers/net/wireless/rt2x00/rt2800mmio.c ++++ b/drivers/net/wireless/rt2x00/rt2800mmio.c +@@ -820,8 +820,10 @@ int rt2800mmio_init_registers(struct rt2 + rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); + rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); + rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); ++ rt2800_shared_mem_unlock(rt2x00dev); + + if (rt2x00_is_pcie(rt2x00dev) && + (rt2x00_rt(rt2x00dev, RT3090) || +@@ -865,6 +867,30 @@ int rt2800mmio_enable_radio(struct rt2x0 + } + EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio); + ++void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ spin_lock_init(&drv_data->shmem_lock.spin); ++} ++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_init_lock); ++ ++void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ spin_lock_bh(&drv_data->shmem_lock.spin); ++} ++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_lock); ++ ++void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ spin_unlock_bh(&drv_data->shmem_lock.spin); ++} ++EXPORT_SYMBOL_GPL(rt2800mmio_shmem_unlock); ++ + MODULE_AUTHOR(DRV_PROJECT); + MODULE_VERSION(DRV_VERSION); + MODULE_DESCRIPTION("rt2800 MMIO library"); +--- a/drivers/net/wireless/rt2x00/rt2800mmio.h ++++ b/drivers/net/wireless/rt2x00/rt2800mmio.h +@@ -160,4 +160,8 @@ int rt2800mmio_init_registers(struct rt2 + /* Device state switch handlers. */ + int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev); + ++void rt2800mmio_shmem_init_lock(struct rt2x00_dev *rt2x00dev); ++void rt2800mmio_shmem_lock(struct rt2x00_dev *rt2x00dev); ++void rt2800mmio_shmem_unlock(struct rt2x00_dev *rt2x00dev); ++ + #endif /* RT2800MMIO_H */ +--- a/drivers/net/wireless/rt2x00/rt2800pci.c ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -69,7 +69,9 @@ static void rt2800pci_mcu_status(struct + return; + + for (i = 0; i < 200; i++) { ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); ++ rt2800_shared_mem_unlock(rt2x00dev); + + if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || + (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || +@@ -83,8 +85,10 @@ static void rt2800pci_mcu_status(struct + if (i == 200) + rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n"); + ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ rt2800_shared_mem_unlock(rt2x00dev); + } + + static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) +@@ -184,6 +188,8 @@ static int rt2800pci_write_firmware(stru + */ + reg = 0; + rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); ++ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg); + + /* +@@ -197,6 +203,7 @@ static int rt2800pci_write_firmware(stru + + rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0); + rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++ rt2800_shared_mem_unlock(rt2x00dev); + + return 0; + } +@@ -213,8 +220,10 @@ static int rt2800pci_enable_radio(struct + return retval; + + /* After resume MCU_BOOT_SIGNAL will trash these. */ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); + rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ rt2800_shared_mem_unlock(rt2x00dev); + + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02); + rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); +@@ -233,10 +242,12 @@ static int rt2800pci_set_state(struct rt + 0, 0x02); + rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); + } else if (state == STATE_SLEEP) { ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, + 0xffffffff); + rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, + 0xffffffff); ++ rt2800_shared_mem_unlock(rt2x00dev); + rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, + 0xff, 0x01); + } +@@ -337,6 +348,9 @@ static const struct rt2800_ops rt2800pci + .drv_write_firmware = rt2800pci_write_firmware, + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, ++ .shmem_init_lock = rt2800mmio_shmem_init_lock, ++ .shmem_lock = rt2800mmio_shmem_lock, ++ .shmem_unlock = rt2800mmio_shmem_unlock, + }; + + static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { +--- a/drivers/net/wireless/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/rt2x00/rt2800soc.c +@@ -176,6 +176,9 @@ static const struct rt2800_ops rt2800soc + .drv_write_firmware = rt2800soc_write_firmware, + .drv_init_registers = rt2800mmio_init_registers, + .drv_get_txwi = rt2800mmio_get_txwi, ++ .shmem_init_lock = rt2800mmio_shmem_init_lock, ++ .shmem_lock = rt2800mmio_shmem_lock, ++ .shmem_unlock = rt2800mmio_shmem_unlock, + }; + + static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { +--- a/drivers/net/wireless/rt2x00/rt2800usb.c ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -51,6 +51,27 @@ static bool rt2800usb_hwcrypt_disabled(s + return modparam_nohwcrypt; + } + ++static void rt2800usb_shmem_init_lock(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ mutex_init(&drv_data->shmem_lock.mutex); ++} ++ ++static void rt2800usb_shmem_lock(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ mutex_lock(&drv_data->shmem_lock.mutex); ++} ++ ++static void rt2800usb_shmem_unlock(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ mutex_unlock(&drv_data->shmem_lock.mutex); ++} ++ + /* + * Queue handlers. + */ +@@ -299,8 +320,10 @@ static int rt2800usb_write_firmware(stru + data + offset, length); + } + ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2800_shared_mem_unlock(rt2x00dev); + + /* + * Send firmware request to device to load firmware, +@@ -315,7 +338,10 @@ static int rt2800usb_write_firmware(stru + } + + msleep(10); ++ ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++ rt2800_shared_mem_unlock(rt2x00dev); + + return 0; + } +@@ -333,8 +359,10 @@ static int rt2800usb_init_registers(stru + if (rt2800_wait_csr_ready(rt2x00dev)) + return -EBUSY; + ++ rt2800_shared_mem_lock(rt2x00dev); + rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); + rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); ++ rt2800_shared_mem_unlock(rt2x00dev); + + reg = 0; + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); +@@ -863,6 +891,9 @@ static const struct rt2800_ops rt2800usb + .drv_write_firmware = rt2800usb_write_firmware, + .drv_init_registers = rt2800usb_init_registers, + .drv_get_txwi = rt2800usb_get_txwi, ++ .shmem_init_lock = rt2800usb_shmem_init_lock, ++ .shmem_lock = rt2800usb_shmem_lock, ++ .shmem_unlock = rt2800usb_shmem_unlock, + }; + + static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { diff --git a/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch new file mode 100644 index 0000000..b8c1914 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0004-rt2x00-rt2800lib-fix-beacon-generation-on-RT3593.patch @@ -0,0 +1,131 @@ +From dcfe3dd46242050f100162dce2bcad24d2c942c6 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sat, 17 Aug 2013 19:31:42 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix beacon generation on RT3593 + +On the RT3593 chipset, the beacon registers are located +in the high 8KB part of the shared memory. + +The high part of the shared memory is only accessible +if it is explicitly selected. Add a helper function +in order to be able to control the SHR_MSEL bit in +the PBF_SYS_CTRL register. Also add a few more helper +functions and use those to select the correct part of +the shared memory before and after accessing the beacon +registers. + +The base addresses of the beacon registers are also +different from the actually used values, so fix the +'rt2800_hw_beacon_base' function to return the correct +values. + +Signed-off-by: Gabor Juhos +--- +Changes since v1: --- +--- + drivers/net/wireless/rt2x00/rt2800.h | 3 +++ + drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -574,6 +574,7 @@ + #define PBF_SYS_CTRL 0x0400 + #define PBF_SYS_CTRL_READY FIELD32(0x00000080) + #define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) ++#define PBF_SYS_CTRL_SHR_MSEL FIELD32(0x00080000) + + /* + * HOST-MCU shared memory +@@ -2026,6 +2027,8 @@ struct mac_iveiv_entry { + (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ + (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) + ++#define HW_BEACON_BASE_HIGH(__index) (0x4000 + (__index) * 512) ++ + #define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64) + + /* +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -82,6 +82,39 @@ static inline bool rt2800_is_305x_soc(st + return false; + } + ++static inline void rt2800_shared_mem_select(struct rt2x00_dev *rt2x00dev, ++ bool high) ++{ ++ u32 reg; ++ ++ if (WARN_ON_ONCE(!rt2800_has_high_shared_mem(rt2x00dev))) ++ return; ++ ++ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); ++ rt2x00_set_field32(®, PBF_SYS_CTRL_SHR_MSEL, high); ++ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); ++} ++ ++static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return true; ++ ++ return false; ++} ++ ++static inline void rt2800_select_beacon_mem(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2800_beacon_uses_high_mem(rt2x00dev)) ++ rt2800_shared_mem_select(rt2x00dev, true); ++} ++ ++static inline void rt2800_deselect_beacon_mem(struct rt2x00_dev *rt2x00dev) ++{ ++ if (rt2800_beacon_uses_high_mem(rt2x00dev)) ++ rt2800_shared_mem_select(rt2x00dev, false); ++} ++ + static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u8 value) + { +@@ -948,6 +981,9 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry); + static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, + unsigned int index) + { ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ return HW_BEACON_BASE_HIGH(index); ++ + return HW_BEACON_BASE(index); + } + +@@ -1046,8 +1082,12 @@ void rt2800_write_beacon(struct queue_en + beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); + + rt2800_shared_mem_lock(rt2x00dev); ++ ++ rt2800_select_beacon_mem(rt2x00dev); + rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, + entry->skb->len + padding_len); ++ rt2800_deselect_beacon_mem(rt2x00dev); ++ + rt2800_shared_mem_unlock(rt2x00dev); + __set_bit(ENTRY_BCN_ENABLED, &entry->flags); + +@@ -1080,6 +1120,8 @@ static inline void rt2800_clear_beacon_r + + rt2800_shared_mem_lock(rt2x00dev); + ++ rt2800_select_beacon_mem(rt2x00dev); ++ + /* + * For the Beacon base registers we only need to clear + * the whole TXWI which (when set to 0) will invalidate +@@ -1088,6 +1130,8 @@ static inline void rt2800_clear_beacon_r + for (i = 0; i < txwi_desc_size; i += sizeof(__le32)) + rt2800_register_write(rt2x00dev, beacon_base + i, 0); + ++ rt2800_deselect_beacon_mem(rt2x00dev); ++ + rt2800_shared_mem_unlock(rt2x00dev); + } + diff --git a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch new file mode 100644 index 0000000..d04998a --- /dev/null +++ b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch @@ -0,0 +1,62 @@ +From a058825fa7b53fab3b003d8928b60e5b686b3421 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 4 Aug 2013 14:36:11 +0200 +Subject: [PATCH] rt2x00: rt2800lib: add hw_beacon_count field to struct + rt2800_drv_data + +Some chipsets can handle more than 8 beacons at once. +Add a new field to the rt2800_drv_data structure which +will hold the number of supported beacons of the given +chipset. + +Update the rt2x00_init_registers function to get the +beacon count from the new field instead of using a +hardcoded value. + +In order to keep the current behaviour, initialize the +new field with the actually used value. + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++- + drivers/net/wireless/rt2x00/rt2800lib.h | 1 + + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -4614,6 +4614,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); + */ + static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) + { ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + u32 reg; + u16 eeprom; + unsigned int i; +@@ -4979,7 +4980,7 @@ static int rt2800_init_registers(struct + /* + * Clear all beacons + */ +- for (i = 0; i < 8; i++) ++ for (i = 0; i < drv_data->hw_beacon_count; i++) + rt2800_clear_beacon_register(rt2x00dev, i); + + if (rt2x00_is_usb(rt2x00dev)) { +@@ -7826,6 +7827,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (rt2x00_rt(rt2x00dev, RT3593)) + __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + ++ drv_data->hw_beacon_count = 8; ++ + /* + * Allocate eeprom data. + */ +--- a/drivers/net/wireless/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/rt2x00/rt2800lib.h +@@ -35,6 +35,7 @@ struct rt2800_drv_data { + u8 txmixer_gain_24g; + u8 txmixer_gain_5g; + unsigned int tbtt_tick; ++ unsigned int hw_beacon_count; + DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); + + unsigned long rt2800_flags; diff --git a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch new file mode 100644 index 0000000..f5231f0 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch @@ -0,0 +1,67 @@ +From 1bfa43ca8f30be53ce4fa79cfc3e219642a812b6 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Mon, 2 Sep 2013 10:58:32 +0200 +Subject: [PATCH] rt2x00: rt2800lib: init additional beacon offset registers + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++ + drivers/net/wireless/rt2x00/rt2800lib.c | 24 ++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -629,6 +629,20 @@ + */ + #define PBF_DBG 0x043c + ++/* BCN_OFFSET2 */ ++#define BCN_OFFSET2 0x0444 ++#define BCN_OFFSET2_BCN8 FIELD32(0x000000ff) ++#define BCN_OFFSET2_BCN9 FIELD32(0x0000ff00) ++#define BCN_OFFSET2_BCN10 FIELD32(0x00ff0000) ++#define BCN_OFFSET2_BCN11 FIELD32(0xff000000) ++ ++/* BCN_OFFSET3 */ ++#define BCN_OFFSET3 0x0448 ++#define BCN_OFFSET3_BCN12 FIELD32(0x000000ff) ++#define BCN_OFFSET3_BCN13 FIELD32(0x0000ff00) ++#define BCN_OFFSET3_BCN14 FIELD32(0x00ff0000) ++#define BCN_OFFSET3_BCN15 FIELD32(0xff000000) ++ + /* + * RF registers + */ +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -4626,6 +4626,30 @@ static int rt2800_init_registers(struct + if (ret) + return ret; + ++ if (drv_data->hw_beacon_count == 16) { ++ rt2800_register_read(rt2x00dev, BCN_OFFSET2, ®); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN8, ++ rt2800_get_beacon_offset(rt2x00dev, 8)); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN9, ++ rt2800_get_beacon_offset(rt2x00dev, 9)); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN10, ++ rt2800_get_beacon_offset(rt2x00dev, 10)); ++ rt2x00_set_field32(®, BCN_OFFSET2_BCN11, ++ rt2800_get_beacon_offset(rt2x00dev, 11)); ++ rt2800_register_write(rt2x00dev, BCN_OFFSET2, reg); ++ ++ rt2800_register_read(rt2x00dev, BCN_OFFSET3, ®); ++ rt2x00_set_field32(®, BCN_OFFSET3_BCN12, ++ rt2800_get_beacon_offset(rt2x00dev, 12)); ++ rt2x00_set_field32(®, BCN_OFFSET3_BCN13, ++ rt2800_get_beacon_offset(rt2x00dev, 13)); ++ rt2x00_set_field32(®, BCN_OFFSET3_BCN14, ++ rt2800_get_beacon_offset(rt2x00dev, 14)); ++ rt2x00_set_field32(®, BCN_OFFSET3_BCN15, ++ rt2800_get_beacon_offset(rt2x00dev, 15)); ++ rt2800_register_write(rt2x00dev, BCN_OFFSET3, reg); ++ } ++ + rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); + rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + diff --git a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch new file mode 100644 index 0000000..4b21eae --- /dev/null +++ b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch @@ -0,0 +1,24 @@ +From 9bea8b61f6025cd633bd5ac71be258620b49bcb3 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Mon, 2 Sep 2013 11:00:06 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix max supported beacon count for RT3593 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7851,7 +7851,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (rt2x00_rt(rt2x00dev, RT3593)) + __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + +- drv_data->hw_beacon_count = 8; ++ if (rt2x00_rt(rt2x00dev, RT3593)) ++ drv_data->hw_beacon_count = 16; ++ else ++ drv_data->hw_beacon_count = 8; + + /* + * Allocate eeprom data. diff --git a/package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch b/package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch new file mode 100644 index 0000000..8a10c6e --- /dev/null +++ b/package/kernel/mac80211/patches/600-0008-rt2x00-allow-to-build-rt2800soc-module-for-RT3883.patch @@ -0,0 +1,30 @@ +From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/Kconfig ++++ b/drivers/net/wireless/rt2x00/Kconfig +@@ -210,7 +210,7 @@ endif + config RT2800SOC + tristate "Ralink WiSoC support" + depends on m +- depends on SOC_RT288X || SOC_RT305X ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 + select RT2X00_LIB_SOC + select RT2X00_LIB_MMIO + select RT2X00_LIB_CRYPTO +@@ -245,7 +245,7 @@ config RT2X00_LIB_PCI + + config RT2X00_LIB_SOC + tristate "RT2x00 SoC support" +- depends on SOC_RT288X || SOC_RT305X ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 + depends on m + select RT2X00_LIB + diff --git a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch new file mode 100644 index 0000000..e77cd86 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch @@ -0,0 +1,20 @@ +From 4f16582c93a71eba9d389e0f0a8aa9099a9587cd Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: enable support for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7821,6 +7821,7 @@ static int rt2800_probe_rt(struct rt2x00 + case RT3390: + case RT3572: + case RT3593: ++ case RT3883: + case RT5390: + case RT5392: + case RT5592: diff --git a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch new file mode 100644 index 0000000..780c1dd --- /dev/null +++ b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch @@ -0,0 +1,112 @@ +From ecb394ccf248d8652c463133c4f404458a57a9c1 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add rf_vals for RF3853 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800.h | 4 +- + drivers/net/wireless/rt2x00/rt2800lib.c | 65 +++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -48,7 +48,8 @@ + * RF2853 2.4G/5G 3T3R + * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) + * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) +- * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) ++ * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593) ++ * RF3853 2.4G/5G 3T3R(RT3883/RT3662) + * RF5592 2.4G/5G 2T2R + * RF3070 2.4G 1T1R + * RF5360 2.4G 1T1R +@@ -72,6 +73,7 @@ + #define RF5592 0x000f + #define RF3070 0x3070 + #define RF3290 0x3290 ++#define RF3853 0x3853 + #define RF5360 0x5360 + #define RF5362 0x5362 + #define RF5370 0x5370 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7441,6 +7441,66 @@ static const struct rf_channel rf_vals_3 + {173, 0x61, 0, 9}, + }; + ++static const struct rf_channel rf_vals_3853[] = { ++ {1, 241, 6, 2}, ++ {2, 241, 6, 7}, ++ {3, 242, 6, 2}, ++ {4, 242, 6, 7}, ++ {5, 243, 6, 2}, ++ {6, 243, 6, 7}, ++ {7, 244, 6, 2}, ++ {8, 244, 6, 7}, ++ {9, 245, 6, 2}, ++ {10, 245, 6, 7}, ++ {11, 246, 6, 2}, ++ {12, 246, 6, 7}, ++ {13, 247, 6, 2}, ++ {14, 248, 6, 4}, ++ ++ {36, 0x56, 8, 4}, ++ {38, 0x56, 8, 6}, ++ {40, 0x56, 8, 8}, ++ {44, 0x57, 8, 0}, ++ {46, 0x57, 8, 2}, ++ {48, 0x57, 8, 4}, ++ {52, 0x57, 8, 8}, ++ {54, 0x57, 8, 10}, ++ {56, 0x58, 8, 0}, ++ {60, 0x58, 8, 4}, ++ {62, 0x58, 8, 6}, ++ {64, 0x58, 8, 8}, ++ ++ {100, 0x5b, 8, 8}, ++ {102, 0x5b, 8, 10}, ++ {104, 0x5c, 8, 0}, ++ {108, 0x5c, 8, 4}, ++ {110, 0x5c, 8, 6}, ++ {112, 0x5c, 8, 8}, ++ {114, 0x5c, 8, 10}, ++ {116, 0x5d, 8, 0}, ++ {118, 0x5d, 8, 2}, ++ {120, 0x5d, 8, 4}, ++ {124, 0x5d, 8, 8}, ++ {126, 0x5d, 8, 10}, ++ {128, 0x5e, 8, 0}, ++ {132, 0x5e, 8, 4}, ++ {134, 0x5e, 8, 6}, ++ {136, 0x5e, 8, 8}, ++ {140, 0x5f, 8, 0}, ++ ++ {149, 0x5f, 8, 9}, ++ {151, 0x5f, 8, 11}, ++ {153, 0x60, 8, 1}, ++ {157, 0x60, 8, 5}, ++ {159, 0x60, 8, 7}, ++ {161, 0x60, 8, 9}, ++ {165, 0x61, 8, 1}, ++ {167, 0x61, 8, 3}, ++ {169, 0x61, 8, 5}, ++ {171, 0x61, 8, 7}, ++ {173, 0x61, 8, 9}, ++}; ++ + static const struct rf_channel rf_vals_5592_xtal20[] = { + /* Channel, N, K, mod, R */ + {1, 482, 4, 10, 3}, +@@ -7668,6 +7728,11 @@ static int rt2800_probe_hw_mode(struct r + spec->channels = rf_vals_3x; + break; + ++ case RF3853: ++ spec->num_channels = ARRAY_SIZE(rf_vals_3853); ++ spec->channels = rf_vals_3853; ++ break; ++ + case RF5592: + rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); + if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { diff --git a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch new file mode 100644 index 0000000..858dece --- /dev/null +++ b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch @@ -0,0 +1,28 @@ +From f8e3fcf18e1f2d7f9e6a9680c5452da090f33d88 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 1 Aug 2013 14:40:44 +0200 +Subject: [PATCH] rt2x00: rt2800lib: enable VCO calibration for RF3853 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -4378,6 +4378,7 @@ void rt2800_vco_calibration(struct rt2x0 + case RF3053: + case RF3070: + case RF3290: ++ case RF3853: + case RF5360: + case RF5362: + case RF5370: +@@ -7847,6 +7848,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3053: + case RF3070: + case RF3290: ++ case RF3853: + case RF5360: + case RF5362: + case RF5370: diff --git a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch new file mode 100644 index 0000000..ed82e44 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch @@ -0,0 +1,235 @@ +From 6e3a17190815c6aa4dc53c2cfe9125fb1154f187 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:27 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add channel configuration function for + RF3853 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 208 +++++++++++++++++++++++++++++++ + 1 file changed, 208 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -2625,6 +2625,211 @@ static void rt2800_config_channel_rf3053 + } + } + ++static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_conf *conf, ++ struct rf_channel *rf, ++ struct channel_info *info) ++{ ++ u8 rfcsr; ++ u8 bbp; ++ u8 pwr1, pwr2, pwr3; ++ ++ const bool txbf_enabled = false; /* TODO */ ++ ++ /* TODO: add band selection */ ++ ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40); ++ else if (rf->channel < 132) ++ rt2800_rfcsr_write(rt2x00dev, 6, 0x80); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40); ++ ++ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); ++ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); ++ ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x46); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48); ++ ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 12, 0x52); ++ ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12); ++ ++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); ++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); ++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); ++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); ++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); ++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); ++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); ++ ++ switch (rt2x00dev->default_ant.tx_chain_num) { ++ case 3: ++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); ++ /* fallthrough */ ++ case 2: ++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); ++ /* fallthrough */ ++ case 1: ++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); ++ break; ++ } ++ ++ switch (rt2x00dev->default_ant.rx_chain_num) { ++ case 3: ++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); ++ /* fallthrough */ ++ case 2: ++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); ++ /* fallthrough */ ++ case 1: ++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); ++ break; ++ } ++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); ++ ++ rt2800_adjust_freq_offset(rt2x00dev); ++ ++ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); ++ if (!conf_is_ht40(conf)) ++ rfcsr &= ~(0x06); ++ else ++ rfcsr |= 0x06; ++ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); ++ ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 31, 0xa0); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80); ++ ++ if (conf_is_ht40(conf)) ++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8); ++ ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20); ++ ++ /* loopback RF_BS */ ++ rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr); ++ if (rf->channel <= 14) ++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1); ++ else ++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0); ++ rt2800_rfcsr_write(rt2x00dev, 36, rfcsr); ++ ++ if (rf->channel <= 14) ++ rfcsr = 0x23; ++ else if (rf->channel < 100) ++ rfcsr = 0x36; ++ else if (rf->channel < 132) ++ rfcsr = 0x32; ++ else ++ rfcsr = 0x30; ++ ++ if (txbf_enabled) ++ rfcsr |= 0x40; ++ ++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); ++ ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b); ++ ++ if (rf->channel <= 14) ++ rfcsr = 0xbb; ++ else if (rf->channel < 100) ++ rfcsr = 0xeb; ++ else if (rf->channel < 132) ++ rfcsr = 0xb3; ++ else ++ rfcsr = 0x9b; ++ rt2800_rfcsr_write(rt2x00dev, 45, rfcsr); ++ ++ if (rf->channel <= 14) ++ rfcsr = 0x8e; ++ else ++ rfcsr = 0x8a; ++ ++ if (txbf_enabled) ++ rfcsr |= 0x20; ++ ++ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); ++ ++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86); ++ ++ rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 51, 0x75); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51); ++ ++ rt2800_rfcsr_read(rt2x00dev, 52, &rfcsr); ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x45); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05); ++ ++ if (rf->channel <= 14) { ++ pwr1 = info->default_power1 & 0x1f; ++ pwr2 = info->default_power2 & 0x1f; ++ pwr3 = info->default_power3 & 0x1f; ++ } else { ++ pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) | ++ (info->default_power1 & 0x7); ++ pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) | ++ (info->default_power2 & 0x7); ++ pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) | ++ (info->default_power3 & 0x7); ++ } ++ ++ rt2800_rfcsr_write(rt2x00dev, 53, pwr1); ++ rt2800_rfcsr_write(rt2x00dev, 54, pwr2); ++ rt2800_rfcsr_write(rt2x00dev, 55, pwr3); ++ ++ rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n", ++ rf->channel, pwr1, pwr2, pwr3); ++ ++ bbp = (info->default_power1 >> 5) | ++ ((info->default_power2 & 0xe0) >> 1); ++ rt2800_bbp_write(rt2x00dev, 109, bbp); ++ ++ rt2800_bbp_read(rt2x00dev, 110, &bbp); ++ bbp &= 0x0f; ++ bbp |= (info->default_power3 & 0xe0) >> 1; ++ rt2800_bbp_write(rt2x00dev, 110, bbp); ++ ++ rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr); ++ if (rf->channel <= 14) ++ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e); ++ ++ /* Enable RF tuning */ ++ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); ++ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); ++ ++ udelay(2000); ++ ++ rt2800_bbp_read(rt2x00dev, 49, &bbp); ++ /* clear update flag */ ++ rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe); ++ rt2800_bbp_write(rt2x00dev, 49, bbp); ++ ++ /* TODO: add calibration for TxBF */ ++} ++ + #define POWER_BOUND 0x27 + #define POWER_BOUND_5G 0x2b + +@@ -3237,6 +3442,9 @@ static void rt2800_config_channel(struct + case RF3322: + rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); + break; ++ case RF3853: ++ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info); ++ break; + case RF3070: + case RF5360: + case RF5362: diff --git a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch new file mode 100644 index 0000000..33cbc4c --- /dev/null +++ b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch @@ -0,0 +1,20 @@ +From afd38ae82226551bf879b6c7c4b620c271fee9d2 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 1 Aug 2013 14:42:05 +0200 +Subject: [PATCH] rt2x00: rt2800lib: enable RF3853 support + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7406,6 +7406,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF3290: + case RF3320: + case RF3322: ++ case RF3853: + case RF5360: + case RF5362: + case RF5370: diff --git a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch new file mode 100644 index 0000000..c3a4798 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch @@ -0,0 +1,77 @@ +From 0094872a5e8e4664c6ea1b2dfa487063d39ae363 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add MAC register initialization for + RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800.h | 14 ++++++++++++++ + drivers/net/wireless/rt2x00/rt2800lib.c | 19 ++++++++++++++++--- + 2 files changed, 30 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -1588,6 +1588,20 @@ + #define TX_PWR_CFG_9_STBC7_CH2 FIELD32(0x00000f00) + + /* ++ * TX_TXBF_CFG: ++ */ ++#define TX_TXBF_CFG_0 0x138c ++#define TX_TXBF_CFG_1 0x13a4 ++#define TX_TXBF_CFG_2 0x13a8 ++#define TX_TXBF_CFG_3 0x13ac ++ ++/* ++ * TX_FBK_CFG_3S: ++ */ ++#define TX_FBK_CFG_3S_0 0x13c4 ++#define TX_FBK_CFG_3S_1 0x13c8 ++ ++/* + * RX_FILTER_CFG: RX configuration register. + */ + #define RX_FILTER_CFG 0x1400 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -4981,6 +4981,12 @@ static int rt2800_init_registers(struct + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x00000000); + } ++ } else if (rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000); ++ 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, RT5592)) { +@@ -5011,9 +5017,11 @@ static int rt2800_init_registers(struct + + rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); +- if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || +- rt2x00_rt(rt2x00dev, RT2883) || +- rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) ++ if (rt2x00_rt(rt2x00dev, RT3883)) ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 3); ++ else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || ++ rt2x00_rt(rt2x00dev, RT2883) || ++ rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); +@@ -5166,6 +5174,11 @@ static int rt2800_init_registers(struct + reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; + rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg); + ++ if (rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008); ++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413); ++ } ++ + rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®); + rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, diff --git a/package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch b/package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch new file mode 100644 index 0000000..837c025 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0015-rt2x00-rt2800soc-fix-rt2800soc_disable_radio-for-RT3.patch @@ -0,0 +1,30 @@ +From 6c2d32478159fffff0b85abb6817a21bb2338231 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:27 +0100 +Subject: [PATCH] rt2x00: rt2800soc: fix rt2800soc_disable_radio for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800soc.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/rt2x00/rt2800soc.c +@@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(s + + static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev) + { ++ u32 reg; ++ + rt2800_disable_radio(rt2x00dev); + rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); +- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); ++ ++ reg = 0; ++ if (rt2x00_rt(rt2x00dev, RT3883)) ++ rt2x00_set_field32(®, TX_PIN_CFG_RFTR_EN, 1); ++ ++ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg); + } + + static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev, diff --git a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch new file mode 100644 index 0000000..e647777 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch @@ -0,0 +1,71 @@ +From 84833056aa7dd25f5b097e31c78f2a0914c5160c Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:26 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add BBP register initialization for + RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -5784,6 +5784,47 @@ static void rt2800_init_bbp_3593(struct + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + } + ++static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev) ++{ ++ rt2800_init_bbp_early(rt2x00dev); ++ ++ rt2800_bbp_write(rt2x00dev, 4, 0x50); ++ rt2800_bbp_write(rt2x00dev, 47, 0x48); ++ ++ rt2800_bbp_write(rt2x00dev, 86, 0x46); ++ rt2800_bbp_write(rt2x00dev, 88, 0x90); ++ ++ rt2800_bbp_write(rt2x00dev, 92, 0x02); ++ ++ rt2800_bbp_write(rt2x00dev, 103, 0xc0); ++ rt2800_bbp_write(rt2x00dev, 104, 0x92); ++ rt2800_bbp_write(rt2x00dev, 105, 0x34); ++ rt2800_bbp_write(rt2x00dev, 106, 0x12); ++ rt2800_bbp_write(rt2x00dev, 120, 0x50); ++ rt2800_bbp_write(rt2x00dev, 137, 0x0f); ++ rt2800_bbp_write(rt2x00dev, 163, 0x9d); ++ ++ /* Set ITxBF timeout to 0x9C40=1000msec */ ++ rt2800_bbp_write(rt2x00dev, 179, 0x02); ++ rt2800_bbp_write(rt2x00dev, 180, 0x00); ++ rt2800_bbp_write(rt2x00dev, 182, 0x40); ++ rt2800_bbp_write(rt2x00dev, 180, 0x01); ++ rt2800_bbp_write(rt2x00dev, 182, 0x9c); ++ ++ rt2800_bbp_write(rt2x00dev, 179, 0x00); ++ ++ /* Reprogram the inband interface to put right values in RXWI */ ++ rt2800_bbp_write(rt2x00dev, 142, 0x04); ++ rt2800_bbp_write(rt2x00dev, 143, 0x3b); ++ rt2800_bbp_write(rt2x00dev, 142, 0x06); ++ rt2800_bbp_write(rt2x00dev, 143, 0xa0); ++ rt2800_bbp_write(rt2x00dev, 142, 0x07); ++ rt2800_bbp_write(rt2x00dev, 143, 0xa1); ++ rt2800_bbp_write(rt2x00dev, 142, 0x08); ++ rt2800_bbp_write(rt2x00dev, 143, 0xa2); ++ rt2800_bbp_write(rt2x00dev, 148, 0xc8); ++} ++ + static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) + { + int ant, div_mode; +@@ -6002,6 +6043,9 @@ static void rt2800_init_bbp(struct rt2x0 + case RT3593: + rt2800_init_bbp_3593(rt2x00dev); + return; ++ case RT3883: ++ rt2800_init_bbp_3883(rt2x00dev); ++ return; + case RT5390: + case RT5392: + rt2800_init_bbp_53xx(rt2x00dev); diff --git a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch new file mode 100644 index 0000000..0fec3cd --- /dev/null +++ b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch @@ -0,0 +1,178 @@ +From 99c659cf345640fd0f733cbcaf4583cc2c868ec0 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Mon, 29 Apr 2013 13:21:48 +0200 +Subject: [PATCH] rt2x00: rt2800lib: add RFCSR initialization for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800.h | 1 + + drivers/net/wireless/rt2x00/rt2800lib.c | 141 +++++++++++++++++++++++++++++++ + 2 files changed, 142 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -2171,6 +2171,7 @@ struct mac_iveiv_entry { + /* + * RFCSR 2: + */ ++#define RFCSR2_RESCAL_BP FIELD8(0x40) + #define RFCSR2_RESCAL_EN FIELD8(0x80) + + /* +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -6819,6 +6819,144 @@ static void rt2800_init_rfcsr_3593(struc + /* TODO: enable stream mode support */ + } + ++static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 rfcsr; ++ ++ /* TODO: get the actual ECO value from the SoC */ ++ const unsigned int eco = 5; ++ ++ rt2800_rf_init_calibration(rt2x00dev, 2); ++ ++ rt2800_rfcsr_write(rt2x00dev, 0, 0xe0); ++ rt2800_rfcsr_write(rt2x00dev, 1, 0x03); ++ rt2800_rfcsr_write(rt2x00dev, 2, 0x50); ++ rt2800_rfcsr_write(rt2x00dev, 3, 0x20); ++ rt2800_rfcsr_write(rt2x00dev, 4, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 5, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40); ++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 8, 0x5b); ++ rt2800_rfcsr_write(rt2x00dev, 9, 0x08); ++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48); ++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a); ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12); ++ rt2800_rfcsr_write(rt2x00dev, 14, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 16, 0x00); ++ ++ /* RFCSR 17 will be initialized later based on the ++ * frequency offset stored in the EEPROM ++ */ ++ ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x40); ++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 21, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0xc0); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 26, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20); ++ rt2800_rfcsr_write(rt2x00dev, 35, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 37, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 38, 0x86); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x23); ++ rt2800_rfcsr_write(rt2x00dev, 40, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 41, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 43, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93); ++ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); ++ rt2800_rfcsr_write(rt2x00dev, 46, 0x60); ++ rt2800_rfcsr_write(rt2x00dev, 47, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 48, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e); ++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86); ++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51); ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05); ++ rt2800_rfcsr_write(rt2x00dev, 53, 0x76); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0x76); ++ rt2800_rfcsr_write(rt2x00dev, 55, 0x76); ++ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb); ++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e); ++ rt2800_rfcsr_write(rt2x00dev, 58, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 59, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 60, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 61, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 62, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 63, 0x00); ++ ++ /* TODO: rx filter calibration? */ ++ ++ rt2800_bbp_write(rt2x00dev, 137, 0x0f); ++ ++ rt2800_bbp_write(rt2x00dev, 163, 0x9d); ++ ++ rt2800_bbp_write(rt2x00dev, 105, 0x05); ++ ++ rt2800_bbp_write(rt2x00dev, 179, 0x02); ++ rt2800_bbp_write(rt2x00dev, 180, 0x00); ++ rt2800_bbp_write(rt2x00dev, 182, 0x40); ++ rt2800_bbp_write(rt2x00dev, 180, 0x01); ++ rt2800_bbp_write(rt2x00dev, 182, 0x9c); ++ ++ rt2800_bbp_write(rt2x00dev, 179, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 142, 0x04); ++ rt2800_bbp_write(rt2x00dev, 143, 0x3b); ++ rt2800_bbp_write(rt2x00dev, 142, 0x06); ++ rt2800_bbp_write(rt2x00dev, 143, 0xa0); ++ rt2800_bbp_write(rt2x00dev, 142, 0x07); ++ rt2800_bbp_write(rt2x00dev, 143, 0xa1); ++ rt2800_bbp_write(rt2x00dev, 142, 0x08); ++ rt2800_bbp_write(rt2x00dev, 143, 0xa2); ++ rt2800_bbp_write(rt2x00dev, 148, 0xc8); ++ ++ if (eco == 5) { ++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8); ++ rt2800_rfcsr_write(rt2x00dev, 33, 0x32); ++ } ++ ++ rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0); ++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); ++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); ++ msleep(1); ++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0); ++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); ++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); ++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); ++ rfcsr |= 0xc0; ++ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr); ++ rfcsr |= 0x20; ++ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 46, &rfcsr); ++ rfcsr |= 0x20; ++ rt2800_rfcsr_write(rt2x00dev, 46, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr); ++ rfcsr &= ~0xee; ++ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); ++} ++ + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) + { + rt2800_rf_init_calibration(rt2x00dev, 2); +@@ -7050,6 +7188,9 @@ static void rt2800_init_rfcsr(struct rt2 + case RT3390: + rt2800_init_rfcsr_3390(rt2x00dev); + break; ++ case RT3883: ++ rt2800_init_rfcsr_3883(rt2x00dev); ++ break; + case RT3572: + rt2800_init_rfcsr_3572(rt2x00dev); + break; diff --git a/package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch b/package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch new file mode 100644 index 0000000..57af961 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0018-rt2x00-rt2800lib-use-the-extended-EEPROM-map-for-RT3.patch @@ -0,0 +1,22 @@ +From 86022438ffeb1b87dfcd018bf477fdbb43076691 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 8 May 2013 19:35:33 +0200 +Subject: [PATCH] rt2x00: rt2800lib: use the extended EEPROM map for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -342,7 +342,8 @@ static unsigned int rt2800_eeprom_word_i + wiphy_name(rt2x00dev->hw->wiphy), word)) + return 0; + +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + map = rt2800_eeprom_map_ext; + else + map = rt2800_eeprom_map; diff --git a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch new file mode 100644 index 0000000..c9d1e06 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch @@ -0,0 +1,21 @@ +From 4cf5403f02fa65dc2207f61d223cffa9ae50e907 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 1 Aug 2013 14:48:21 +0200 +Subject: [PATCH] rt2x00: rt2800lib: force rf type to RF3853 on RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7587,6 +7587,8 @@ static int rt2800_init_eeprom(struct rt2 + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); ++ else if (rt2x00_rt(rt2x00dev, RT3883)) ++ rf = RF3853; + else + rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + diff --git a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch new file mode 100644 index 0000000..12b9c33 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch @@ -0,0 +1,136 @@ +From 269f19c848a2380db03a3f207cafb88e28d71c53 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:28 +0100 +Subject: [PATCH] rt2x00: rt2800lib: add channel configuration code for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 72 +++++++++++++++++++++++++++++-- + 1 file changed, 69 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3405,6 +3405,36 @@ static char rt2800_txpower_to_dev(struct + return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); + } + ++static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev, ++ struct rf_channel *rf) ++{ ++ u8 bbp; ++ ++ bbp = (rf->channel > 14) ? 0x48 : 0x38; ++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp); ++ ++ rt2800_bbp_write(rt2x00dev, 69, 0x12); ++ ++ if (rf->channel <= 14) { ++ rt2800_bbp_write(rt2x00dev, 70, 0x0a); ++ } else { ++ /* Disable CCK packet detection */ ++ rt2800_bbp_write(rt2x00dev, 70, 0x00); ++ } ++ ++ rt2800_bbp_write(rt2x00dev, 73, 0x10); ++ ++ if (rf->channel > 14) { ++ rt2800_bbp_write(rt2x00dev, 62, 0x1d); ++ rt2800_bbp_write(rt2x00dev, 63, 0x1d); ++ rt2800_bbp_write(rt2x00dev, 64, 0x1d); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 62, 0x2d); ++ rt2800_bbp_write(rt2x00dev, 63, 0x2d); ++ rt2800_bbp_write(rt2x00dev, 64, 0x2d); ++ } ++} ++ + static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, +@@ -3423,6 +3453,12 @@ static void rt2800_config_channel(struct + rt2800_txpower_to_dev(rt2x00dev, rf->channel, + info->default_power3); + ++ switch (rt2x00dev->chip.rt) { ++ case RT3883: ++ rt3883_bbp_adjust(rt2x00dev, rf); ++ break; ++ } ++ + switch (rt2x00dev->chip.rf) { + case RF2020: + case RF3020: +@@ -3506,6 +3542,15 @@ static void rt2800_config_channel(struct + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 77, 0x98); ++ } else if (rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); ++ ++ if (rt2x00dev->default_ant.rx_chain_num > 1) ++ rt2800_bbp_write(rt2x00dev, 86, 0x46); ++ else ++ rt2800_bbp_write(rt2x00dev, 86, 0); + } else { + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +@@ -3518,6 +3563,7 @@ static void rt2800_config_channel(struct + !rt2x00_rt(rt2x00dev, RT5392)) { + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { + rt2800_bbp_write(rt2x00dev, 82, 0x62); ++ rt2800_bbp_write(rt2x00dev, 82, 0x62); + rt2800_bbp_write(rt2x00dev, 75, 0x46); + } else { + if (rt2x00_rt(rt2x00dev, RT3593)) +@@ -3526,19 +3572,22 @@ static void rt2800_config_channel(struct + rt2800_bbp_write(rt2x00dev, 82, 0x84); + rt2800_bbp_write(rt2x00dev, 75, 0x50); + } +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + rt2800_bbp_write(rt2x00dev, 83, 0x8a); + } + + } else { + if (rt2x00_rt(rt2x00dev, RT3572)) + rt2800_bbp_write(rt2x00dev, 82, 0x94); +- else if (rt2x00_rt(rt2x00dev, RT3593)) ++ else if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + rt2800_bbp_write(rt2x00dev, 82, 0x82); + else + rt2800_bbp_write(rt2x00dev, 82, 0xf2); + +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + rt2800_bbp_write(rt2x00dev, 83, 0x9a); + + if (rt2x00_has_cap_external_lna_a(rt2x00dev)) +@@ -3660,6 +3709,23 @@ static void rt2800_config_channel(struct + + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + ++ usleep_range(1000, 1500); ++ } ++ ++ if (rt2x00_rt(rt2x00dev, RT3883)) { ++ if (!conf_is_ht40(conf)) ++ rt2800_bbp_write(rt2x00dev, 105, 0x34); ++ else ++ rt2800_bbp_write(rt2x00dev, 105, 0x04); ++ ++ /* AGC init */ ++ if (rf->channel <= 14) ++ reg = 0x2e + rt2x00dev->lna_gain; ++ else ++ reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3); ++ ++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); ++ + usleep_range(1000, 1500); + } + diff --git a/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch new file mode 100644 index 0000000..3f40b4e --- /dev/null +++ b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch @@ -0,0 +1,30 @@ +From e37d93abaabe3ab72b0332a18092acc162307274 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Mon, 30 Sep 2013 13:57:26 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix txpower_to_dev function for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3392,13 +3392,15 @@ static char rt2800_txpower_to_dev(struct + unsigned int channel, + char txpower) + { +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC); + + if (channel <= 14) + return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); + +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + return clamp_t(char, txpower, MIN_A_TXPOWER_3593, + MAX_A_TXPOWER_3593); + else diff --git a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch new file mode 100644 index 0000000..52baeec --- /dev/null +++ b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch @@ -0,0 +1,23 @@ +From c4d79e344bd580d85821390d49f92dced7d8e125 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:29 +0100 +Subject: [PATCH] rt2x00: rt2800lib: use correct txpower calculation function + for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -4611,7 +4611,8 @@ static void rt2800_config_txpower(struct + struct ieee80211_channel *chan, + int power_level) + { +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level); + else + rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level); diff --git a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch new file mode 100644 index 0000000..b9dafc6 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch @@ -0,0 +1,33 @@ +From caea0671cd8fd9ade4f5969cbe0ee545e94ae105 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sat, 24 Aug 2013 11:49:55 +0200 +Subject: [PATCH] rt2x00: rt2800lib: hardcode txmixer gain values to zero for + RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7469,7 +7469,8 @@ static u8 rt2800_get_txmixer_gain_24g(st + { + u16 word; + +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + return 0; + + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); +@@ -7483,7 +7484,8 @@ static u8 rt2800_get_txmixer_gain_5g(str + { + u16 word; + +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + return 0; + + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); diff --git a/package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch b/package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch new file mode 100644 index 0000000..53435aa --- /dev/null +++ b/package/kernel/mac80211/patches/600-0024-rt2x00-rt2800lib-use-correct-RT-XWI-size-for-RT3883.patch @@ -0,0 +1,20 @@ +From 11c40fb47c4a4dd6ad060c2ae127ced89ffb9fe1 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 18 Apr 2013 14:33:33 +0200 +Subject: [PATCH] rt2x00: rt2800lib: use correct [RT]XWI size for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -558,6 +558,7 @@ void rt2800_get_txwi_rxwi_size(struct rt + { + switch (rt2x00dev->chip.rt) { + case RT3593: ++ case RT3883: + *txwi_size = TXWI_DESC_SIZE_4WORDS; + *rxwi_size = RXWI_DESC_SIZE_5WORDS; + break; diff --git a/package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch b/package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch new file mode 100644 index 0000000..08f3f88 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0025-rt2x00-rt2800lib-use-correct-beacon-base-for-RT3883.patch @@ -0,0 +1,22 @@ +From b403bdfa00665ce6b53583bdb837ffad0b91c09f Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:29 +0100 +Subject: [PATCH] rt2x00: rt2800lib: use correct beacon base for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -983,7 +983,8 @@ EXPORT_SYMBOL_GPL(rt2800_txdone_entry); + static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, + unsigned int index) + { +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + return HW_BEACON_BASE_HIGH(index); + + return HW_BEACON_BASE(index); diff --git a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch new file mode 100644 index 0000000..f09f803 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch @@ -0,0 +1,22 @@ +From 74b7eaf75fc6eb86292056ef705e543f9cd6086b Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 18 Aug 2013 09:57:58 +0200 +Subject: [PATCH] rt2x00: rt2800lib: use correct beacon count for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -8402,7 +8402,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (rt2x00_rt(rt2x00dev, RT3593)) + __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + drv_data->hw_beacon_count = 16; + else + drv_data->hw_beacon_count = 8; diff --git a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch new file mode 100644 index 0000000..f7d23fc --- /dev/null +++ b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch @@ -0,0 +1,22 @@ +From fa5ad9c025610c22048add2f0ad03f62b6ca1e74 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Mon, 30 Sep 2013 16:53:33 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix antenna configuration for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -1937,7 +1937,8 @@ void rt2800_config_ant(struct rt2x00_dev + rt2800_bbp_write(rt2x00dev, 3, r3); + rt2800_bbp_write(rt2x00dev, 1, r1); + +- if (rt2x00_rt(rt2x00dev, RT3593)) { ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) { + if (ant->rx_chain_num == 1) + rt2800_bbp_write(rt2x00dev, 86, 0x00); + else diff --git a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch new file mode 100644 index 0000000..4da750e --- /dev/null +++ b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch @@ -0,0 +1,32 @@ +From 6d668fef3a1baa60bdd715ee062ddb6333d2647c Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Mon, 30 Sep 2013 16:58:23 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix LNA gain configuration for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -1960,7 +1960,8 @@ static void rt2800_config_lna_gain(struc + rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); + } else if (libconf->rf.channel <= 128) { +- if (rt2x00_rt(rt2x00dev, RT3593)) { ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) { + rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, + EEPROM_EXT_LNA2_A1); +@@ -1970,7 +1971,8 @@ static void rt2800_config_lna_gain(struc + EEPROM_RSSI_BG2_LNA_A1); + } + } else { +- if (rt2x00_rt(rt2x00dev, RT3593)) { ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) { + rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, + EEPROM_EXT_LNA2_A2); diff --git a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch new file mode 100644 index 0000000..628b237 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch @@ -0,0 +1,44 @@ +From c49b2d829aa1c816a46a577cdec6d2ff14d9f06e Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Tue, 1 Oct 2013 15:40:08 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix VGC setup for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -4811,7 +4811,8 @@ static u8 rt2800_get_default_vgc(struct + else + vgc = 0x2e + rt2x00dev->lna_gain; + } else { /* 5GHZ band */ +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; + else if (rt2x00_rt(rt2x00dev, RT5592)) + vgc = 0x24 + (2 * rt2x00dev->lna_gain); +@@ -4831,7 +4832,8 @@ static inline void rt2800_set_vgc(struct + { + if (qual->vgc_level != vgc_level) { + if (rt2x00_rt(rt2x00dev, RT3572) || +- rt2x00_rt(rt2x00dev, RT3593)) { ++ rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) { + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, + vgc_level); + } else if (rt2x00_rt(rt2x00dev, RT5592)) { +@@ -4878,6 +4880,11 @@ void rt2800_link_tuner(struct rt2x00_dev + } + break; + ++ case RT3883: ++ if (qual->rssi > -65) ++ vgc += 0x10; ++ break; ++ + case RT5592: + if (qual->rssi > -65) + vgc += 0x20; diff --git a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch new file mode 100644 index 0000000..216b8b6 --- /dev/null +++ b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch @@ -0,0 +1,42 @@ +From 1616650aea676541d4dc8adc6f4219856d193c8b Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Tue, 1 Oct 2013 17:27:57 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix EEPROM LNA validation for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7606,7 +7606,8 @@ static int rt2800_validate_eeprom(struct + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); +- if (!rt2x00_rt(rt2x00dev, RT3593)) { ++ if (!rt2x00_rt(rt2x00dev, RT3593) && ++ !rt2x00_rt(rt2x00dev, RT3883)) { + if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, +@@ -7626,7 +7627,8 @@ static int rt2800_validate_eeprom(struct + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); +- if (!rt2x00_rt(rt2x00dev, RT3593)) { ++ if (!rt2x00_rt(rt2x00dev, RT3593) && ++ !rt2x00_rt(rt2x00dev, RT3883)) { + if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, +@@ -7634,7 +7636,8 @@ static int rt2800_validate_eeprom(struct + } + rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + +- if (rt2x00_rt(rt2x00dev, RT3593)) { ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) { + rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word); + if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 || + rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff) diff --git a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch new file mode 100644 index 0000000..515086f --- /dev/null +++ b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch @@ -0,0 +1,22 @@ +From e3871034a0e7c8a95152dc3eafbcc4535398cbdc Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 2 Oct 2013 10:11:59 +0200 +Subject: [PATCH] rt2x00: rt2800lib: fix txpower compensation for RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3981,6 +3981,9 @@ static u8 rt2800_compensate_txpower(stru + if (rt2x00_rt(rt2x00dev, RT3593)) + return min_t(u8, txpower, 0xc); + ++ if (rt2x00_rt(rt2x00dev, RT3883)) ++ return min_t(u8, txpower, 0xf); ++ + if (rt2x00_has_cap_power_limit(rt2x00dev)) { + /* + * Check if eirp txpower exceed txpower_limit. diff --git a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch new file mode 100644 index 0000000..77e3f1b --- /dev/null +++ b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch @@ -0,0 +1,23 @@ +From f6734ec72da936989a8ce4186b3ede28fbc47836 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 18 Aug 2013 21:57:34 +0200 +Subject: [PATCH] rt2x00: rt2800lib: enable RT2800_HAS_HIGH_SHARED_MEM for + RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -8415,7 +8415,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (retval) + return retval; + +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + + if (rt2x00_rt(rt2x00dev, RT3593) || diff --git a/package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch b/package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch new file mode 100644 index 0000000..dc06e6a --- /dev/null +++ b/package/kernel/mac80211/patches/600-0033-rt2x00-rt2800lib-use-high-memory-for-beacons-on-RT38.patch @@ -0,0 +1,22 @@ +From f1acfc2f397e86548ae1b479c198d4bef57050f6 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 29 Sep 2013 18:10:34 +0200 +Subject: [PATCH] rt2x00: rt2800lib: use high memory for beacons on RT3883 + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -97,7 +97,8 @@ static inline void rt2800_shared_mem_sel + + static inline bool rt2800_beacon_uses_high_mem(struct rt2x00_dev *rt2x00dev) + { +- if (rt2x00_rt(rt2x00dev, RT3593)) ++ if (rt2x00_rt(rt2x00dev, RT3593) || ++ rt2x00_rt(rt2x00dev, RT3883)) + return true; + + return false; diff --git a/package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch b/package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch new file mode 100644 index 0000000..71f7bba --- /dev/null +++ b/package/kernel/mac80211/patches/600-0034-rt2x00-rt2800mmio-add-a-workaround-for-spurious-TX_F.patch @@ -0,0 +1,136 @@ +From 5e67d4f8a46d19748b501c2ef86de3f50d3cfd51 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 24 Mar 2013 19:26:27 +0100 +Subject: [PATCH] rt2x00: rt2800mmio: add a workaround for spurious + TX_FIFO_STATUS interrupts + +Signed-off-by: Gabor Juhos +--- + drivers/net/wireless/rt2x00/rt2800mmio.c | 72 +++++++++++++++++++++++++----- + drivers/net/wireless/rt2x00/rt2x00.h | 5 +++ + 2 files changed, 65 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800mmio.c ++++ b/drivers/net/wireless/rt2x00/rt2800mmio.c +@@ -415,9 +415,9 @@ void rt2800mmio_autowake_tasklet(unsigne + } + EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet); + +-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) ++static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev, ++ u32 status) + { +- u32 status; + int i; + + /* +@@ -438,29 +438,77 @@ static void rt2800mmio_txstatus_interrup + * Since we have only one producer and one consumer we don't + * need to lock the kfifo. + */ +- for (i = 0; i < rt2x00dev->tx->limit; i++) { +- rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); +- +- if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) +- break; +- ++ i = 0; ++ do { + if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) { +- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); ++ rt2x00_warn(rt2x00dev, ++ "TX status FIFO overrun, drop TX status report\n"); + break; + } +- } ++ ++ if (++i >= rt2x00dev->tx->limit) ++ break; ++ ++ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); ++ } while (rt2x00_get_field32(status, TX_STA_FIFO_VALID)); + + /* Schedule the tasklet for processing the tx status. */ + tasklet_schedule(&rt2x00dev->txstatus_tasklet); + } + ++#define RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES 4 ++ ++static bool rt2800mmio_txstatus_is_spurious(struct rt2x00_dev *rt2x00dev, ++ u32 txstatus) ++{ ++ if (likely(rt2x00_get_field32(txstatus, TX_STA_FIFO_VALID))) { ++ rt2x00dev->txstatus_irq_retries = 0; ++ return false; ++ } ++ ++ rt2x00dev->txstatus_irq_retries++; ++ ++ /* Ensure that we don't go into an infinite IRQ loop. */ ++ if (rt2x00dev->txstatus_irq_retries >= ++ RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES) { ++ rt2x00_warn(rt2x00dev, ++ "%u spurious TX_FIFO_STATUS interrupt(s)\n", ++ rt2x00dev->txstatus_irq_retries); ++ rt2x00dev->txstatus_irq_retries = 0; ++ return false; ++ } ++ ++ return true; ++} ++ + irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance) + { + struct rt2x00_dev *rt2x00dev = dev_instance; + u32 reg, mask; ++ u32 txstatus = 0; + +- /* Read status and ACK all interrupts */ ++ /* Read status */ + rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); ++ ++ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { ++ /* Due to unknown reason the hardware generates a ++ * TX_FIFO_STATUS interrupt before the TX_STA_FIFO ++ * register contain valid data. Read the TX status ++ * here to see if we have to process the actual ++ * request. ++ */ ++ rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &txstatus); ++ if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) { ++ /* Remove the TX_FIFO_STATUS bit so it won't be ++ * processed in this turn. The hardware will ++ * generate another IRQ for us. ++ */ ++ rt2x00_set_field32(®, ++ INT_SOURCE_CSR_TX_FIFO_STATUS, 0); ++ } ++ } ++ ++ /* ACK interrupts */ + rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + + if (!reg) +@@ -477,7 +525,7 @@ irqreturn_t rt2800mmio_interrupt(int irq + mask = ~reg; + + if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { +- rt2800mmio_txstatus_interrupt(rt2x00dev); ++ rt2800mmio_txstatus_interrupt(rt2x00dev, txstatus); + /* + * Never disable the TX_FIFO_STATUS interrupt. + */ +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -989,6 +989,11 @@ struct rt2x00_dev { + int rf_channel; + + /* ++ * Counter for tx status irq retries (rt2800pci). ++ */ ++ unsigned int txstatus_irq_retries; ++ ++ /* + * Protect the interrupt mask register. + */ + spinlock_t irqmask_lock; diff --git a/package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch b/package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch new file mode 100644 index 0000000..08c8fa6 --- /dev/null +++ b/package/kernel/mac80211/patches/601-rt2x00-set_pci_mwi.patch @@ -0,0 +1,13 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00pci.c ++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c +@@ -94,8 +94,10 @@ int rt2x00pci_probe(struct pci_dev *pci_ + + pci_set_master(pci_dev); + ++#ifdef CONFIG_PCI_SET_MWI + if (pci_set_mwi(pci_dev)) + rt2x00_probe_err("MWI not available\n"); ++#endif + + if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) { + rt2x00_probe_err("PCI DMA not supported\n"); diff --git a/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch b/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch new file mode 100644 index 0000000..8c71075 --- /dev/null +++ b/package/kernel/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch @@ -0,0 +1,32 @@ +--- /dev/null ++++ b/include/linux/rt2x00_platform.h +@@ -0,0 +1,19 @@ ++/* ++ * Platform data definition for the rt2x00 driver ++ * ++ * Copyright (C) 2011 Gabor Juhos ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef _RT2X00_PLATFORM_H ++#define _RT2X00_PLATFORM_H ++ ++struct rt2x00_platform_data { ++ char *eeprom_file_name; ++}; ++ ++#endif /* _RT2X00_PLATFORM_H */ +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + diff --git a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch new file mode 100644 index 0000000..1255d75 --- /dev/null +++ b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch @@ -0,0 +1,301 @@ +--- a/.local-symbols ++++ b/.local-symbols +@@ -314,6 +314,7 @@ RT2X00_LIB_FIRMWARE= + RT2X00_LIB_CRYPTO= + RT2X00_LIB_LEDS= + RT2X00_LIB_DEBUGFS= ++RT2X00_LIB_EEPROM= + RT2X00_DEBUG= + WL_MEDIATEK= + MT7601U= +--- a/drivers/net/wireless/rt2x00/Kconfig ++++ b/drivers/net/wireless/rt2x00/Kconfig +@@ -69,6 +69,7 @@ config RT2800PCI + select RT2X00_LIB_MMIO + select RT2X00_LIB_PCI + select RT2X00_LIB_FIRMWARE ++ select RT2X00_LIB_EEPROM + select RT2X00_LIB_CRYPTO + depends on CRC_CCITT + depends on EEPROM_93CX6 +@@ -215,6 +216,7 @@ config RT2800SOC + select RT2X00_LIB_MMIO + select RT2X00_LIB_CRYPTO + select RT2X00_LIB_FIRMWARE ++ select RT2X00_LIB_EEPROM + select RT2800_LIB + select RT2800_LIB_MMIO + ---help--- +@@ -265,6 +267,9 @@ config RT2X00_LIB_FIRMWARE + config RT2X00_LIB_CRYPTO + bool + ++config RT2X00_LIB_EEPROM ++ boolean ++ + config RT2X00_LIB_LEDS + bool + default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n) +--- a/drivers/net/wireless/rt2x00/Makefile ++++ b/drivers/net/wireless/rt2x00/Makefile +@@ -7,6 +7,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) + + rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o + rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o + rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o ++rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o + + obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o + obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o +--- a/drivers/net/wireless/rt2x00/rt2800lib.h ++++ b/drivers/net/wireless/rt2x00/rt2800lib.h +@@ -46,6 +46,8 @@ struct rt2800_drv_data { + } shmem_lock; + }; + ++#include "rt2800.h" ++ + struct rt2800_ops { + void (*register_read)(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 *value); +@@ -179,6 +181,15 @@ static inline int rt2800_read_eeprom(str + { + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + ++ if (rt2x00dev->eeprom_file) { ++ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, ++ EEPROM_SIZE); ++ return 0; ++ } ++ ++ if (!rt2800ops->read_eeprom) ++ return -EINVAL; ++ + return rt2800ops->read_eeprom(rt2x00dev); + } + +--- a/drivers/net/wireless/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/rt2x00/rt2800soc.c +@@ -102,19 +102,6 @@ static int rt2800soc_set_device_state(st + return retval; + } + +-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev) +-{ +- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); +- +- if (!base_addr) +- return -ENOMEM; +- +- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); +- +- iounmap(base_addr); +- return 0; +-} +- + /* Firmware functions */ + static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) + { +@@ -178,7 +165,6 @@ static const struct rt2800_ops rt2800soc + .register_multiread = rt2x00mmio_register_multiread, + .register_multiwrite = rt2x00mmio_register_multiwrite, + .regbusy_read = rt2x00mmio_regbusy_read, +- .read_eeprom = rt2800soc_read_eeprom, + .hwcrypt_disabled = rt2800soc_hwcrypt_disabled, + .drv_write_firmware = rt2800soc_write_firmware, + .drv_init_registers = rt2800mmio_init_registers, +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -697,6 +697,7 @@ enum rt2x00_capability_flags { + REQUIRE_HT_TX_DESC, + REQUIRE_PS_AUTOWAKE, + REQUIRE_DELAYED_RFKILL, ++ REQUIRE_EEPROM_FILE, + + /* + * Capabilities +@@ -966,6 +967,11 @@ struct rt2x00_dev { + const struct firmware *fw; + + /* ++ * EEPROM image. ++ */ ++ const struct firmware *eeprom_file; ++ ++ /* + * FIFO for storing tx status reports between isr and tasklet. + */ + DECLARE_KFIFO_PTR(txstatus_fifo, u32); +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -1334,6 +1334,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de + INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); + INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep); + ++ retval = rt2x00lib_load_eeprom_file(rt2x00dev); ++ if (retval) ++ goto exit; ++ + /* + * Let the driver probe the device to detect the capabilities. + */ +@@ -1474,6 +1478,11 @@ void rt2x00lib_remove_dev(struct rt2x00_ + * Free the driver data. + */ + kfree(rt2x00dev->drv_data); ++ ++ /* ++ * Free EEPROM image. ++ */ ++ rt2x00lib_free_eeprom_file(rt2x00dev); + } + EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); + +--- /dev/null ++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c +@@ -0,0 +1,111 @@ ++/* ++ Copyright (C) 2004 - 2009 Ivo van Doorn ++ Copyright (C) 2004 - 2009 Gertjan van Wingerde ++ ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the ++ Free Software Foundation, Inc., ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/* ++ Module: rt2x00lib ++ Abstract: rt2x00 eeprom file loading routines. ++ */ ++ ++#include ++#include ++ ++#include "rt2x00.h" ++#include "rt2x00lib.h" ++ ++static const char * ++rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data; ++ ++ if (pdata && pdata->eeprom_file_name) ++ return pdata->eeprom_file_name; ++ ++ return NULL ++} ++ ++static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ const struct firmware *ee; ++ const char *ee_name; ++ int retval; ++ ++ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev); ++ if (!ee_name) { ++ rt2x00_err(rt2x00dev, ++ "Invalid EEPROM filename.\n" ++ "Please file bug report to %s.\n", DRV_PROJECT); ++ return -EINVAL; ++ } ++ ++ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name); ++ ++ retval = request_firmware(&ee, ee_name, rt2x00dev->dev); ++ if (retval) { ++ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n"); ++ return retval; ++ } ++ ++ if (!ee || !ee->size || !ee->data) { ++ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n"); ++ retval = -ENOENT; ++ goto err_exit; ++ } ++ ++ if (ee->size != rt2x00dev->ops->eeprom_size) { ++ rt2x00_err(rt2x00dev, ++ "EEPROM file size is invalid, it should be %d bytes\n", ++ rt2x00dev->ops->eeprom_size); ++ retval = -EINVAL; ++ goto err_release_ee; ++ } ++ ++ rt2x00dev->eeprom_file = ee; ++ return 0; ++ ++err_release_ee: ++ release_firmware(ee); ++err_exit: ++ return retval; ++} ++ ++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ int retval; ++ ++ if (!rt2x00lib_get_eeprom_file_name(rt2x00dev)) ++ return 0; ++ ++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags); ++ ++ if (!rt2x00dev->eeprom_file) { ++ retval = rt2x00lib_request_eeprom_file(rt2x00dev); ++ if (retval) ++ return retval; ++ } ++ ++ return 0; ++} ++ ++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ release_firmware(rt2x00dev->eeprom_file); ++ rt2x00dev->eeprom_file = NULL; ++} +--- a/drivers/net/wireless/rt2x00/rt2x00lib.h ++++ b/drivers/net/wireless/rt2x00/rt2x00lib.h +@@ -320,6 +320,22 @@ static inline void rt2x00lib_free_firmwa + #endif /* CPTCFG_RT2X00_LIB_FIRMWARE */ + + /* ++ * EEPROM file handlers. ++ */ ++#ifdef CPTCFG_RT2X00_LIB_EEPROM ++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev); ++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev); ++#else ++static inline int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++ return 0; ++} ++static inline void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev) ++{ ++} ++#endif /* CPTCFG_RT2X00_LIB_EEPROM */ ++ ++/* + * Debugfs handlers. + */ + #ifdef CPTCFG_RT2X00_LIB_DEBUGFS +--- a/drivers/net/wireless/rt2x00/rt2x00soc.c ++++ b/drivers/net/wireless/rt2x00/rt2x00soc.c +@@ -92,6 +92,7 @@ int rt2x00soc_probe(struct platform_devi + rt2x00dev->hw = hw; + rt2x00dev->irq = platform_get_irq(pdev, 0); + rt2x00dev->name = pdev->dev.driver->name; ++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags); + + rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); + diff --git a/package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch b/package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch new file mode 100644 index 0000000..4bc6f37 --- /dev/null +++ b/package/kernel/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch @@ -0,0 +1,33 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c +@@ -26,6 +26,7 @@ + + #include + #include ++#include + + #include "rt2x00.h" + #include "rt2x00lib.h" +@@ -34,11 +35,21 @@ static const char * + rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) + { + struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data; ++#ifdef CONFIG_OF ++ struct device_node *np; ++ const char *eep; ++#endif + + if (pdata && pdata->eeprom_file_name) + return pdata->eeprom_file_name; + +- return NULL ++#ifdef CONFIG_OF ++ np = rt2x00dev->dev->of_node; ++ if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0) ++ return eep; ++#endif ++ ++ return NULL; + } + + static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev) diff --git a/package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch b/package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch new file mode 100644 index 0000000..75f0415 --- /dev/null +++ b/package/kernel/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch @@ -0,0 +1,101 @@ +From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 17 Mar 2013 00:55:04 +0100 +Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside + OF + +Signed-off-by: John Crispin +--- + drivers/net/wireless/rt2x00/Kconfig | 1 + + drivers/net/wireless/rt2x00/rt2800pci.c | 44 ++++++++++++++++++++++++++----- + 2 files changed, 39 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/rt2x00/Kconfig ++++ b/drivers/net/wireless/rt2x00/Kconfig +@@ -219,6 +219,7 @@ config RT2800SOC + select RT2X00_LIB_EEPROM + select RT2800_LIB + select RT2800_LIB_MMIO ++ select MTD if SOC_RT288X || SOC_RT305X + ---help--- + This adds support for Ralink WiSoC devices. + Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. +--- a/drivers/net/wireless/rt2x00/rt2x00eeprom.c ++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c +@@ -26,11 +26,66 @@ + + #include + #include ++#include ++#include + #include + + #include "rt2x00.h" + #include "rt2x00lib.h" + ++static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev) ++{ ++ int ret = -EINVAL; ++#ifdef CONFIG_OF ++ static struct firmware mtd_fw; ++ struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL; ++ size_t retlen, len = rt2x00dev->ops->eeprom_size; ++ int size, offset = 0; ++ struct mtd_info *mtd; ++ const char *part; ++ const __be32 *list; ++ phandle phandle; ++ ++ list = of_get_property(np, "ralink,mtd-eeprom", &size); ++ if (!list) { ++ dev_err(rt2x00dev->dev, "failed to load eeprom property\n"); ++ return -ENOENT; ++ } ++ ++ phandle = be32_to_cpup(list++); ++ if (phandle) ++ mtd_np = of_find_node_by_phandle(phandle); ++ if (!mtd_np) { ++ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n"); ++ return -EINVAL; ++ } ++ ++ part = of_get_property(mtd_np, "label", NULL); ++ if (!part) ++ part = mtd_np->name; ++ ++ mtd = get_mtd_device_nm(part); ++ if (IS_ERR(mtd)) { ++ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part); ++ return PTR_ERR(mtd); ++ } ++ ++ if (size > sizeof(*list)) ++ offset = be32_to_cpup(list); ++ ++ ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom); ++ put_mtd_device(mtd); ++ ++ if (!ret) { ++ rt2x00dev->eeprom_file = &mtd_fw; ++ mtd_fw.size = len; ++ mtd_fw.data = rt2x00dev->eeprom; ++ } ++#endif ++ ++ return ret; ++} ++ + static const char * + rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) + { +@@ -58,6 +113,9 @@ static int rt2x00lib_request_eeprom_file + const char *ee_name; + int retval; + ++ if (!rt2800lib_read_eeprom_mtd(rt2x00dev)) ++ return 0; ++ + ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev); + if (!ee_name) { + rt2x00_err(rt2x00dev, diff --git a/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch new file mode 100644 index 0000000..76269f2 --- /dev/null +++ b/package/kernel/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -0,0 +1,47 @@ +--- a/include/linux/rt2x00_platform.h ++++ b/include/linux/rt2x00_platform.h +@@ -14,6 +14,9 @@ + + struct rt2x00_platform_data { + char *eeprom_file_name; ++ ++ int disable_2ghz; ++ int disable_5ghz; + }; + + #endif /* _RT2X00_PLATFORM_H */ +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -940,6 +940,22 @@ static int rt2x00lib_probe_hw_modes(stru + unsigned int num_rates; + unsigned int i; + ++ if (rt2x00dev->dev->platform_data) { ++ struct rt2x00_platform_data *pdata; ++ ++ pdata = rt2x00dev->dev->platform_data; ++ if (pdata->disable_2ghz) ++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ; ++ if (pdata->disable_5ghz) ++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ; ++ } ++ ++ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) { ++ rt2x00_err(rt2x00dev, "No supported bands\n"); ++ return -EINVAL; ++ } ++ ++ + num_rates = 0; + if (spec->supported_rates & SUPPORT_RATE_CCK) + num_rates += 4; +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -405,6 +405,7 @@ struct hw_mode_spec { + unsigned int supported_bands; + #define SUPPORT_BAND_2GHZ 0x00000001 + #define SUPPORT_BAND_5GHZ 0x00000002 ++#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ) + + unsigned int supported_rates; + #define SUPPORT_RATE_CCK 0x00000001 diff --git a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch new file mode 100644 index 0000000..0177c80 --- /dev/null +++ b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch @@ -0,0 +1,63 @@ +--- a/include/linux/rt2x00_platform.h ++++ b/include/linux/rt2x00_platform.h +@@ -14,6 +14,7 @@ + + struct rt2x00_platform_data { + char *eeprom_file_name; ++ const u8 *mac_address; + + int disable_2ghz; + int disable_5ghz; +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -931,6 +931,18 @@ static void rt2x00lib_rate(struct ieee80 + entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE; + } + ++const u8 *rt2x00lib_get_mac_address(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2x00_platform_data *pdata; ++ ++ pdata = rt2x00dev->dev->platform_data; ++ if (!pdata) ++ return NULL; ++ ++ return pdata->mac_address; ++} ++EXPORT_SYMBOL_GPL(rt2x00lib_get_mac_address); ++ + static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, + struct hw_mode_spec *spec) + { +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -1412,6 +1412,7 @@ static inline void rt2x00debug_dump_fram + */ + u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, + struct ieee80211_vif *vif); ++const u8 *rt2x00lib_get_mac_address(struct rt2x00_dev *rt2x00dev); + + /* + * Interrupt context handlers. +--- a/drivers/net/wireless/rt2x00/rt61pci.c ++++ b/drivers/net/wireless/rt2x00/rt61pci.c +@@ -2390,6 +2390,7 @@ static int rt61pci_validate_eeprom(struc + u32 reg; + u16 word; + u8 *mac; ++ const u8 *pdata_mac; + s8 value; + + rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®); +@@ -2410,7 +2411,11 @@ static int rt61pci_validate_eeprom(struc + /* + * Start validation of the data that has been read. + */ ++ pdata_mac = rt2x00lib_get_mac_address(rt2x00dev); + mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); ++ if (pdata_mac) ++ memcpy(mac, pdata_mac, 6); ++ + if (!is_valid_ether_addr(mac)) { + eth_random_addr(mac); + rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac); diff --git a/package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch b/package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch new file mode 100644 index 0000000..63a8641 --- /dev/null +++ b/package/kernel/mac80211/patches/609-rt2x00-allow_disabling_bands_through_dts.patch @@ -0,0 +1,27 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include "rt2x00.h" + #include "rt2x00lib.h" +@@ -951,6 +952,16 @@ static int rt2x00lib_probe_hw_modes(stru + struct ieee80211_rate *rates; + unsigned int num_rates; + unsigned int i; ++#ifdef CONFIG_OF ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int enabled; ++ if (!of_property_read_u32(np, "ralink,2ghz", ++ &enabled) && !enabled) ++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ; ++ if (!of_property_read_u32(np, "ralink,5ghz", ++ &enabled) && !enabled) ++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ; ++#endif /* CONFIG_OF */ + + if (rt2x00dev->dev->platform_data) { + struct rt2x00_platform_data *pdata; diff --git a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch new file mode 100644 index 0000000..d6ea384 --- /dev/null +++ b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch @@ -0,0 +1,211 @@ +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3528,11 +3528,18 @@ static void rt2800_config_channel(struct + /* + * Change BBP settings + */ ++ + if (rt2x00_rt(rt2x00dev, RT3352)) { ++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); ++ + rt2800_bbp_write(rt2x00dev, 27, 0x0); + rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 27, 0x20); + rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); ++ rt2800_bbp_write(rt2x00dev, 86, 0x38); ++ rt2800_bbp_write(rt2x00dev, 83, 0x6a); + } else if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rf->channel > 14) { + /* Disable CCK Packet detection on 5GHz */ +@@ -6594,6 +6601,12 @@ static void rt2800_init_rfcsr_3290(struc + + static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) + { ++ int tx0_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX0, ++ &rt2x00dev->cap_flags); ++ int tx1_int_pa = test_bit(CAPABILITY_INTERNAL_PA_TX1, ++ &rt2x00dev->cap_flags); ++ u8 rfcsr; ++ + rt2800_rf_init_calibration(rt2x00dev, 30); + + rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); +@@ -6629,15 +6642,30 @@ static void rt2800_init_rfcsr_3352(struc + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + rt2800_rfcsr_write(rt2x00dev, 32, 0x80); + rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 34, 0x01); ++ rfcsr = 0x01; ++ if (!tx0_int_pa) ++ rt2x00_set_field8(&rfcsr, RFCSR34_TX0_EXT_PA, 1); ++ if (!tx1_int_pa) ++ rt2x00_set_field8(&rfcsr, RFCSR34_TX1_EXT_PA, 1); ++ rt2800_rfcsr_write(rt2x00dev, 34, rfcsr); + rt2800_rfcsr_write(rt2x00dev, 35, 0x03); + rt2800_rfcsr_write(rt2x00dev, 36, 0xbd); + rt2800_rfcsr_write(rt2x00dev, 37, 0x3c); + rt2800_rfcsr_write(rt2x00dev, 38, 0x5f); + rt2800_rfcsr_write(rt2x00dev, 39, 0xc5); + rt2800_rfcsr_write(rt2x00dev, 40, 0x33); +- rt2800_rfcsr_write(rt2x00dev, 41, 0x5b); +- rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); ++ rfcsr = 0x52; ++ if (tx0_int_pa) { ++ rt2x00_set_field8(&rfcsr, RFCSR41_BIT1, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR41_BIT4, 1); ++ } ++ rt2800_rfcsr_write(rt2x00dev, 41, rfcsr); ++ rfcsr = 0x52; ++ if (tx1_int_pa) { ++ rt2x00_set_field8(&rfcsr, RFCSR42_BIT1, 1); ++ rt2x00_set_field8(&rfcsr, RFCSR42_BIT4, 1); ++ } ++ rt2800_rfcsr_write(rt2x00dev, 42, rfcsr); + rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); +@@ -6645,15 +6673,20 @@ static void rt2800_init_rfcsr_3352(struc + rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); + rt2800_rfcsr_write(rt2x00dev, 48, 0x14); + rt2800_rfcsr_write(rt2x00dev, 49, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 50, 0x2d); +- rt2800_rfcsr_write(rt2x00dev, 51, 0x7f); +- rt2800_rfcsr_write(rt2x00dev, 52, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 53, 0x52); +- rt2800_rfcsr_write(rt2x00dev, 54, 0x1b); +- rt2800_rfcsr_write(rt2x00dev, 55, 0x7f); +- rt2800_rfcsr_write(rt2x00dev, 56, 0x00); +- rt2800_rfcsr_write(rt2x00dev, 57, 0x52); +- rt2800_rfcsr_write(rt2x00dev, 58, 0x1b); ++ rfcsr = 0x2d; ++ if (!tx0_int_pa) ++ rt2x00_set_field8(&rfcsr, RFCSR50_TX0_EXT_PA, 1); ++ if (!tx1_int_pa) ++ rt2x00_set_field8(&rfcsr, RFCSR50_TX1_EXT_PA, 1); ++ rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); ++ rt2800_rfcsr_write(rt2x00dev, 51, (tx0_int_pa ? 0x7f : 0x52)); ++ rt2800_rfcsr_write(rt2x00dev, 52, (tx0_int_pa ? 0x00 : 0xc0)); ++ rt2800_rfcsr_write(rt2x00dev, 53, (tx0_int_pa ? 0x52 : 0xd2)); ++ rt2800_rfcsr_write(rt2x00dev, 54, (tx0_int_pa ? 0x1b : 0xc0)); ++ rt2800_rfcsr_write(rt2x00dev, 55, (tx1_int_pa ? 0x7f : 0x52)); ++ rt2800_rfcsr_write(rt2x00dev, 56, (tx1_int_pa ? 0x00 : 0xc0)); ++ rt2800_rfcsr_write(rt2x00dev, 57, (tx0_int_pa ? 0x52 : 0x49)); ++ rt2800_rfcsr_write(rt2x00dev, 58, (tx1_int_pa ? 0x1b : 0xc0)); + rt2800_rfcsr_write(rt2x00dev, 59, 0x00); + rt2800_rfcsr_write(rt2x00dev, 60, 0x00); + rt2800_rfcsr_write(rt2x00dev, 61, 0x00); +@@ -7674,6 +7707,7 @@ static int rt2800_init_eeprom(struct rt2 + * RT53xx: defined in "EEPROM_CHIP_ID" field + */ + if (rt2x00_rt(rt2x00dev, RT3290) || ++ rt2x00_rt(rt2x00dev, RT3352) || + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +@@ -7769,7 +7803,8 @@ static int rt2800_init_eeprom(struct rt2 + /* + * Detect if this device has Bluetooth co-existence. + */ +- if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) ++ if (!rt2x00_rt(rt2x00dev, RT3352) && ++ rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) + __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); + + /* +@@ -7798,6 +7833,22 @@ static int rt2800_init_eeprom(struct rt2 + EIRP_MAX_TX_POWER_LIMIT) + __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); + ++ /* ++ * Detect if device uses internal or external PA ++ */ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ ++ if (rt2x00_rt(rt2x00dev, RT3352)) { ++ if (!rt2x00_get_field16(eeprom, ++ EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352)) ++ __set_bit(CAPABILITY_INTERNAL_PA_TX0, ++ &rt2x00dev->cap_flags); ++ if (!rt2x00_get_field16(eeprom, ++ EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352)) ++ __set_bit(CAPABILITY_INTERNAL_PA_TX1, ++ &rt2x00dev->cap_flags); ++ } ++ + return 0; + } + +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -2335,6 +2335,12 @@ struct mac_iveiv_entry { + #define RFCSR36_RF_BS FIELD8(0x80) + + /* ++ * RFCSR 34: ++ */ ++#define RFCSR34_TX0_EXT_PA FIELD8(0x04) ++#define RFCSR34_TX1_EXT_PA FIELD8(0x08) ++ ++/* + * RFCSR 38: + */ + #define RFCSR38_RX_LO1_EN FIELD8(0x20) +@@ -2346,6 +2352,18 @@ struct mac_iveiv_entry { + #define RFCSR39_RX_LO2_EN FIELD8(0x80) + + /* ++ * RFCSR 41: ++ */ ++#define RFCSR41_BIT1 FIELD8(0x01) ++#define RFCSR41_BIT4 FIELD8(0x08) ++ ++/* ++ * RFCSR 42: ++ */ ++#define RFCSR42_BIT1 FIELD8(0x01) ++#define RFCSR42_BIT4 FIELD8(0x08) ++ ++/* + * RFCSR 49: + */ + #define RFCSR49_TX FIELD8(0x3f) +@@ -2358,6 +2376,8 @@ struct mac_iveiv_entry { + * RFCSR 50: + */ + #define RFCSR50_TX FIELD8(0x3f) ++#define RFCSR50_TX0_EXT_PA FIELD8(0x02) ++#define RFCSR50_TX1_EXT_PA FIELD8(0x10) + #define RFCSR50_EP FIELD8(0xc0) + /* bits for RT3593 */ + #define RFCSR50_TX_LO1_EN FIELD8(0x20) +@@ -2505,6 +2525,8 @@ enum rt2800_eeprom_word { + * INTERNAL_TX_ALC: 0: disable, 1: enable + * BT_COEXIST: 0: disable, 1: enable + * DAC_TEST: 0: disable, 1: enable ++ * EXTERNAL_TX0_PA: 0: disable, 1: enable (only on RT3352) ++ * EXTERNAL_TX1_PA: 0: disable, 1: enable (only on RT3352) + */ + #define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001) + #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002) +@@ -2521,6 +2543,8 @@ enum rt2800_eeprom_word { + #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000) + #define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000) + #define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000) ++#define EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352 FIELD16(0x4000) ++#define EEPROM_NIC_CONF1_EXTERNAL_TX1_PA_3352 FIELD16(0x8000) + + /* + * EEPROM frequency +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -717,6 +717,8 @@ enum rt2x00_capability_flags { + CAPABILITY_DOUBLE_ANTENNA, + CAPABILITY_BT_COEXIST, + CAPABILITY_VCO_RECALIBRATION, ++ CAPABILITY_INTERNAL_PA_TX0, ++ CAPABILITY_INTERNAL_PA_TX1, + }; + + /* diff --git a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch new file mode 100644 index 0000000..41a8294 --- /dev/null +++ b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch @@ -0,0 +1,106 @@ +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -8185,6 +8185,27 @@ static const struct rf_channel rf_vals_5 + {196, 83, 0, 12, 1}, + }; + ++/* ++ * RF value list for rt3xxx with Xtal20MHz ++ * Supports: 2.4 GHz (all) (RF3322) ++ */ ++static const struct rf_channel rf_vals_xtal20mhz_3x[] = { ++ {1, 0xE2, 2, 0x14}, ++ {2, 0xE3, 2, 0x14}, ++ {3, 0xE4, 2, 0x14}, ++ {4, 0xE5, 2, 0x14}, ++ {5, 0xE6, 2, 0x14}, ++ {6, 0xE7, 2, 0x14}, ++ {7, 0xE8, 2, 0x14}, ++ {8, 0xE9, 2, 0x14}, ++ {9, 0xEA, 2, 0x14}, ++ {10, 0xEB, 2, 0x14}, ++ {11, 0xEC, 2, 0x14}, ++ {12, 0xED, 2, 0x14}, ++ {13, 0xEE, 2, 0x14}, ++ {14, 0xF0, 2, 0x18}, ++}; ++ + static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + { + struct hw_mode_spec *spec = &rt2x00dev->spec; +@@ -8271,7 +8292,10 @@ static int rt2800_probe_hw_mode(struct r + case RF5390: + case RF5392: + spec->num_channels = 14; +- spec->channels = rf_vals_3x; ++ if (spec->clk_is_20mhz) ++ spec->channels = rf_vals_xtal20mhz_3x; ++ else ++ spec->channels = rf_vals_3x; + break; + + case RF3052: +@@ -8455,6 +8479,19 @@ static int rt2800_probe_rt(struct rt2x00 + return 0; + } + ++int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev) ++{ ++ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data; ++ struct hw_mode_spec *spec = &rt2x00dev->spec; ++ ++ if (!pdata) ++ return -EINVAL; ++ ++ spec->clk_is_20mhz = pdata->clk_is_20mhz; ++ ++ return 0; ++} ++ + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) + { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +@@ -8497,6 +8534,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + + /* ++ * Probe SoC clock. ++ */ ++ if (rt2x00_is_soc(rt2x00dev)) { ++ retval = rt2800_probe_clk(rt2x00dev); ++ if (retval) ++ return retval; ++ } ++ ++ /* + * Initialize hw specifications. + */ + retval = rt2800_probe_hw_mode(rt2x00dev); +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -400,6 +400,7 @@ static inline struct rt2x00_intf* vif_to + * @channels: Device/chipset specific channel values (See &struct rf_channel). + * @channels_info: Additional information for channels (See &struct channel_info). + * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap). ++ * @clk_is_20mhz: External crystal of WiSoC is 20MHz instead of 40MHz + */ + struct hw_mode_spec { + unsigned int supported_bands; +@@ -416,6 +417,7 @@ struct hw_mode_spec { + const struct channel_info *channels_info; + + struct ieee80211_sta_ht_cap ht; ++ int clk_is_20mhz; + }; + + /* +--- a/include/linux/rt2x00_platform.h ++++ b/include/linux/rt2x00_platform.h +@@ -18,6 +18,7 @@ struct rt2x00_platform_data { + + int disable_2ghz; + int disable_5ghz; ++ int clk_is_20mhz; + }; + + #endif /* _RT2X00_PLATFORM_H */ diff --git a/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch new file mode 100644 index 0000000..1970efc --- /dev/null +++ b/package/kernel/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -0,0 +1,33 @@ +From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 17 Mar 2013 00:03:31 +0100 +Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC + +This patch ads the match table to allow loading the wmac support from a +devicetree. + +Signed-off-by: John Crispin +--- + drivers/net/wireless/rt2x00/rt2800pci.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2800soc.c ++++ b/drivers/net/wireless/rt2x00/rt2800soc.c +@@ -237,10 +237,17 @@ static int rt2800soc_probe(struct platfo + return rt2x00soc_probe(pdev, &rt2800soc_ops); + } + ++static const struct of_device_id rt2880_wmac_match[] = { ++ { .compatible = "ralink,rt2880-wmac" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_wmac_match); ++ + static struct platform_driver rt2800soc_driver = { + .driver = { + .name = "rt2800_wmac", + .mod_name = KBUILD_MODNAME, ++ .of_match_table = rt2880_wmac_match, + }, + .probe = rt2800soc_probe, + .remove = rt2x00soc_remove, diff --git a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch new file mode 100644 index 0000000..9f11862 --- /dev/null +++ b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch @@ -0,0 +1,29 @@ +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include "rt2x00.h" + #include "rt2800lib.h" +@@ -8481,13 +8482,14 @@ static int rt2800_probe_rt(struct rt2x00 + + int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev) + { +- struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data; + struct hw_mode_spec *spec = &rt2x00dev->spec; ++ struct clk *clk = clk_get(rt2x00dev->dev, NULL); + +- if (!pdata) +- return -EINVAL; ++ if (IS_ERR(clk)) ++ return PTR_ERR(clk); + +- spec->clk_is_20mhz = pdata->clk_is_20mhz; ++ if (clk_get_rate(clk) == 20000000) ++ spec->clk_is_20mhz = 1; + + return 0; + } diff --git a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch new file mode 100644 index 0000000..9679d71 --- /dev/null +++ b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch @@ -0,0 +1,276 @@ +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -74,6 +74,7 @@ + #define RF3070 0x3070 + #define RF3290 0x3290 + #define RF3853 0x3853 ++#define RF5350 0x5350 + #define RF5360 0x5360 + #define RF5362 0x5362 + #define RF5370 0x5370 +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3014,6 +3014,13 @@ static void rt2800_config_channel_rf53xx + + rt2800_rfcsr_write(rt2x00dev, 59, + r59_non_bt[idx]); ++ } else if (rt2x00_rt(rt2x00dev, RT5350)) { ++ static const char r59_non_bt[] = {0x0b, 0x0b, ++ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, ++ 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06}; ++ ++ rt2800_rfcsr_write(rt2x00dev, 59, ++ r59_non_bt[idx]); + } + } + } +@@ -3492,6 +3499,7 @@ static void rt2800_config_channel(struct + rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info); + break; + case RF3070: ++ case RF5350: + case RF5360: + case RF5362: + case RF5370: +@@ -3510,6 +3518,7 @@ static void rt2800_config_channel(struct + if (rt2x00_rf(rt2x00dev, RF3070) || + rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || ++ rt2x00_rf(rt2x00dev, RF5350) || + rt2x00_rf(rt2x00dev, RF5360) || + rt2x00_rf(rt2x00dev, RF5362) || + rt2x00_rf(rt2x00dev, RF5370) || +@@ -3788,7 +3797,8 @@ static void rt2800_config_channel(struct + /* + * Clear update flag + */ +- if (rt2x00_rt(rt2x00dev, RT3352)) { ++ if (rt2x00_rt(rt2x00dev, RT3352) || ++ rt2x00_rt(rt2x00dev, RT5350)) { + rt2800_bbp_read(rt2x00dev, 49, &bbp); + rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); + rt2800_bbp_write(rt2x00dev, 49, bbp); +@@ -4674,6 +4684,7 @@ void rt2800_vco_calibration(struct rt2x0 + case RF3070: + case RF3290: + case RF3853: ++ case RF5350: + case RF5360: + case RF5362: + case RF5370: +@@ -5087,6 +5098,8 @@ static int rt2800_init_registers(struct + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); ++ } else if (rt2x00_rt(rt2x00dev, RT5350)) { ++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + } else { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +@@ -5742,9 +5755,13 @@ static void rt2800_init_bbp_3352(struct + + rt2800_bbp_write(rt2x00dev, 82, 0x62); + +- rt2800_bbp_write(rt2x00dev, 83, 0x6a); +- +- rt2800_bbp_write(rt2x00dev, 84, 0x99); ++ if (rt2x00_rt(rt2x00dev, RT5350)) { ++ rt2800_bbp_write(rt2x00dev, 83, 0x7a); ++ rt2800_bbp_write(rt2x00dev, 84, 0x9a); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 83, 0x6a); ++ rt2800_bbp_write(rt2x00dev, 84, 0x99); ++ } + + rt2800_bbp_write(rt2x00dev, 86, 0x38); + +@@ -5758,9 +5775,13 @@ static void rt2800_init_bbp_3352(struct + + rt2800_bbp_write(rt2x00dev, 104, 0x92); + +- rt2800_bbp_write(rt2x00dev, 105, 0x34); +- +- rt2800_bbp_write(rt2x00dev, 106, 0x05); ++ if (rt2x00_rt(rt2x00dev, RT5350)) { ++ rt2800_bbp_write(rt2x00dev, 105, 0x3c); ++ rt2800_bbp_write(rt2x00dev, 106, 0x03); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 105, 0x34); ++ rt2800_bbp_write(rt2x00dev, 106, 0x05); ++ } + + rt2800_bbp_write(rt2x00dev, 120, 0x50); + +@@ -5785,6 +5806,13 @@ static void rt2800_init_bbp_3352(struct + rt2800_bbp_write(rt2x00dev, 143, 0xa2); + + rt2800_bbp_write(rt2x00dev, 148, 0xc8); ++ ++ if (rt2x00_rt(rt2x00dev, RT5350)) { ++ rt2800_bbp_write(rt2x00dev, 150, 0x40); /* Antenna Software OFDM */ ++ rt2800_bbp_write(rt2x00dev, 151, 0x30); /* Antenna Software CCK */ ++ rt2800_bbp_write(rt2x00dev, 152, 0xa3); ++ rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */ ++ } + } + + static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) +@@ -6126,6 +6154,7 @@ static void rt2800_init_bbp(struct rt2x0 + rt2800_init_bbp_3290(rt2x00dev); + break; + case RT3352: ++ case RT5350: + rt2800_init_bbp_3352(rt2x00dev); + break; + case RT3390: +@@ -7077,6 +7106,76 @@ static void rt2800_init_rfcsr_3883(struc + rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); + } + ++static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev) ++{ ++ rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); ++ rt2800_rfcsr_write(rt2x00dev, 1, 0x23); ++ rt2800_rfcsr_write(rt2x00dev, 2, 0x50); ++ rt2800_rfcsr_write(rt2x00dev, 3, 0x08); ++ rt2800_rfcsr_write(rt2x00dev, 4, 0x49); ++ rt2800_rfcsr_write(rt2x00dev, 5, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); ++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); ++ rt2800_rfcsr_write(rt2x00dev, 9, 0x02); ++ rt2800_rfcsr_write(rt2x00dev, 10, 0x53); ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); ++ rt2800_rfcsr_write(rt2x00dev, 12, 0x46); ++ if(rt2x00dev->spec.clk_is_20mhz) ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x1f); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); ++ rt2800_rfcsr_write(rt2x00dev, 14, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 16, 0xc0); ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x03); ++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 21, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 25, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 26, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 27, 0x03); ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0xd0); ++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 34, 0x07); ++ rt2800_rfcsr_write(rt2x00dev, 35, 0x12); ++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 37, 0x08); ++ rt2800_rfcsr_write(rt2x00dev, 38, 0x85); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); ++ rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); ++ rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); ++ rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); ++ rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); ++ rt2800_rfcsr_write(rt2x00dev, 44, 0x0c); ++ rt2800_rfcsr_write(rt2x00dev, 45, 0xa6); ++ rt2800_rfcsr_write(rt2x00dev, 46, 0x73); ++ rt2800_rfcsr_write(rt2x00dev, 47, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 48, 0x10); ++ rt2800_rfcsr_write(rt2x00dev, 49, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 50, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 51, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 52, 0x38); ++ rt2800_rfcsr_write(rt2x00dev, 53, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 54, 0x38); ++ rt2800_rfcsr_write(rt2x00dev, 55, 0x43); ++ rt2800_rfcsr_write(rt2x00dev, 56, 0x82); ++ rt2800_rfcsr_write(rt2x00dev, 57, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 58, 0x39); ++ rt2800_rfcsr_write(rt2x00dev, 59, 0x0b); ++ rt2800_rfcsr_write(rt2x00dev, 60, 0x45); ++ rt2800_rfcsr_write(rt2x00dev, 61, 0xd1); ++ rt2800_rfcsr_write(rt2x00dev, 62, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 63, 0x00); ++} ++ + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) + { + rt2800_rf_init_calibration(rt2x00dev, 2); +@@ -7317,6 +7416,9 @@ static void rt2800_init_rfcsr(struct rt2 + case RT3593: + rt2800_init_rfcsr_3593(rt2x00dev); + break; ++ case RT5350: ++ rt2800_init_rfcsr_5350(rt2x00dev); ++ break; + case RT5390: + rt2800_init_rfcsr_5390(rt2x00dev); + break; +@@ -7576,6 +7678,12 @@ static int rt2800_validate_eeprom(struct + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); + rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); ++ } else if (rt2x00_rt(rt2x00dev, RT5350)) { ++ rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 1); ++ rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1); ++ rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF3320); ++ rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); ++ rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); + } else if (rt2x00_rt(rt2x00dev, RT2860) || + rt2x00_rt(rt2x00dev, RT2872)) { + /* +@@ -7714,6 +7822,8 @@ static int rt2800_init_eeprom(struct rt2 + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + else if (rt2x00_rt(rt2x00dev, RT3883)) + rf = RF3853; ++ else if (rt2x00_rt(rt2x00dev, RT5350)) ++ rf = RF5350; + else + rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + +@@ -7733,6 +7843,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF3320: + case RF3322: + case RF3853: ++ case RF5350: + case RF5360: + case RF5362: + case RF5370: +@@ -8286,6 +8397,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3290: + case RF3320: + case RF3322: ++ case RF5350: + case RF5360: + case RF5362: + case RF5370: +@@ -8425,6 +8537,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3070: + case RF3290: + case RF3853: ++ case RF5350: + case RF5360: + case RF5362: + case RF5370: +@@ -8465,6 +8578,7 @@ static int rt2800_probe_rt(struct rt2x00 + case RT3572: + case RT3593: + case RT3883: ++ case RT5350: + case RT5390: + case RT5392: + case RT5592: +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -169,6 +169,7 @@ struct rt2x00_chip { + #define RT3572 0x3572 + #define RT3593 0x3593 + #define RT3883 0x3883 /* WSOC */ ++#define RT5350 0x5350 /* WSOC 2.4GHz */ + #define RT5390 0x5390 /* 2.4GHz */ + #define RT5392 0x5392 /* 2.4GHz */ + #define RT5592 0x5592 diff --git a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch new file mode 100644 index 0000000..b085c5e --- /dev/null +++ b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch @@ -0,0 +1,40 @@ +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + #include "rt2x00.h" + #include "rt2800lib.h" +@@ -7933,6 +7934,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); + ++ { ++ struct device_node *np = rt2x00dev->dev->of_node; ++ unsigned int led_polarity; ++ ++ /* Allow overriding polarity from OF */ ++ if (!of_property_read_u32(np, "ralink,led-polarity", ++ &led_polarity)) ++ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY, ++ led_polarity); ++ } ++ + rt2x00dev->led_mcu_reg = eeprom; + #endif /* CPTCFG_RT2X00_LIB_LEDS */ + +--- a/drivers/net/wireless/rt2x00/rt2x00leds.c ++++ b/drivers/net/wireless/rt2x00/rt2x00leds.c +@@ -109,6 +109,9 @@ static int rt2x00leds_register_led(struc + led->led_dev.name = name; + led->led_dev.brightness = LED_OFF; + ++ if (rt2x00_is_soc(rt2x00dev)) ++ led->led_dev.brightness_set(&led->led_dev, LED_OFF); ++ + retval = led_classdev_register(device, &led->led_dev); + if (retval) { + rt2x00_err(rt2x00dev, "Failed to register led handler\n"); diff --git a/package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch b/package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch new file mode 100644 index 0000000..2dbfd10 --- /dev/null +++ b/package/kernel/mac80211/patches/620-rt2x00-add-AP+STA-support.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -1283,7 +1283,7 @@ static inline void rt2x00lib_set_if_comb + */ + if_limit = &rt2x00dev->if_limits_ap; + if_limit->max = rt2x00dev->ops->max_ap_intf; +- if_limit->types = BIT(NL80211_IFTYPE_AP); ++ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION); + #ifdef CPTCFG_MAC80211_MESH + if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); + #endif diff --git a/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch new file mode 100644 index 0000000..259cb1f --- /dev/null +++ b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch @@ -0,0 +1,15 @@ +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -7817,10 +7817,11 @@ static int rt2800_init_eeprom(struct rt2 + * RT53xx: defined in "EEPROM_CHIP_ID" field + */ + if (rt2x00_rt(rt2x00dev, RT3290) || +- rt2x00_rt(rt2x00dev, RT3352) || + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); ++ else if (rt2x00_rt(rt2x00dev, RT3352)) ++ rf = RF3322; + else if (rt2x00_rt(rt2x00dev, RT3883)) + rf = RF3853; + else if (rt2x00_rt(rt2x00dev, RT5350)) diff --git a/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch new file mode 100644 index 0000000..77d63fe --- /dev/null +++ b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch @@ -0,0 +1,29 @@ +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -2321,6 +2321,8 @@ struct mac_iveiv_entry { + #define RFCSR30_RX_H20M FIELD8(0x04) + #define RFCSR30_RX_VCM FIELD8(0x18) + #define RFCSR30_RF_CALIBRATION FIELD8(0x80) ++#define RF3322_RFCSR30_TX_H20M FIELD8(0x01) ++#define RF3322_RFCSR30_RX_H20M FIELD8(0x02) + + /* + * RFCSR 31: +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -3527,8 +3527,13 @@ static void rt2800_config_channel(struct + rt2x00_rf(rt2x00dev, RF5390) || + rt2x00_rf(rt2x00dev, RF5392)) { + rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +- rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0); +- rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0); ++ if(rt2x00_rf(rt2x00dev, RF3322)) { ++ rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_TX_H20M, conf_is_ht40(conf)); ++ rt2x00_set_field8(&rfcsr, RF3322_RFCSR30_RX_H20M, conf_is_ht40(conf)); ++ } else { ++ rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, conf_is_ht40(conf)); ++ rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, conf_is_ht40(conf)); ++ } + rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); diff --git a/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch new file mode 100644 index 0000000..9903aa5 --- /dev/null +++ b/package/kernel/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/mwl8k.c ++++ b/drivers/net/wireless/mwl8k.c +@@ -5679,6 +5679,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw") + MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API)); + + static const struct pci_device_id mwl8k_pci_id_table[] = { ++ { PCI_VDEVICE(MARVELL, 0x2a02), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, }, + { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, }, diff --git a/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch new file mode 100644 index 0000000..3b8b756 --- /dev/null +++ b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/wireless/libertas/cfg.c ++++ b/drivers/net/wireless/libertas/cfg.c +@@ -2083,6 +2083,8 @@ struct wireless_dev *lbs_cfg_alloc(struc + goto err_wiphy_new; + } + ++ set_wiphy_dev(wdev->wiphy, dev); ++ + lbs_deb_leave(LBS_DEB_CFG80211); + return wdev; + +--- a/drivers/net/wireless/libertas/main.c ++++ b/drivers/net/wireless/libertas/main.c +@@ -987,6 +987,7 @@ struct lbs_private *lbs_add_card(void *c + goto err_adapter; + } + ++ dev_net_set(dev, wiphy_net(wdev->wiphy)); + dev->ieee80211_ptr = wdev; + dev->ml_priv = priv; + SET_NETDEV_DEV(dev, dmdev); diff --git a/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch new file mode 100644 index 0000000..dace56b --- /dev/null +++ b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/libertas/cfg.c ++++ b/drivers/net/wireless/libertas/cfg.c +@@ -2173,6 +2173,8 @@ int lbs_cfg_register(struct lbs_private + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + wdev->wiphy->reg_notifier = lbs_reg_notifier; + ++ memcpy(wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN); ++ + ret = wiphy_register(wdev->wiphy); + if (ret < 0) + pr_err("cannot register wiphy device\n"); diff --git a/package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch b/package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch new file mode 100644 index 0000000..3993c6e --- /dev/null +++ b/package/kernel/mac80211/patches/805-b43-gpio-mask-module-option.patch @@ -0,0 +1,37 @@ +--- a/drivers/net/wireless/b43/b43.h ++++ b/drivers/net/wireless/b43/b43.h +@@ -839,6 +839,7 @@ struct b43_wldev { + bool qos_enabled; /* TRUE, if QoS is used. */ + bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ + bool use_pio; /* TRUE if next init should use PIO */ ++ int gpiomask; /* GPIO LED mask as a module parameter */ + + /* PHY/Radio device. */ + struct b43_phy phy; +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -76,6 +76,11 @@ MODULE_FIRMWARE("b43/ucode16_mimo.fw"); + MODULE_FIRMWARE("b43/ucode5.fw"); + MODULE_FIRMWARE("b43/ucode9.fw"); + ++static int modparam_gpiomask = 0x000F; ++module_param_named(gpiomask, modparam_gpiomask, int, 0444); ++MODULE_PARM_DESC(gpiomask, ++ "GPIO mask for LED control (default 0x000F)"); ++ + static int modparam_bad_frames_preempt; + module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); + MODULE_PARM_DESC(bad_frames_preempt, +@@ -2883,10 +2888,10 @@ static int b43_gpio_init(struct b43_wlde + u32 mask, set; + + b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0); +- b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF); ++ b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask); + + mask = 0x0000001F; +- set = 0x0000000F; ++ set = modparam_gpiomask; + if (dev->dev->chip_id == 0x4301) { + mask |= 0x0060; + set |= 0x0060; diff --git a/package/kernel/mac80211/patches/810-b43_no_pio.patch b/package/kernel/mac80211/patches/810-b43_no_pio.patch new file mode 100644 index 0000000..d99f3ce --- /dev/null +++ b/package/kernel/mac80211/patches/810-b43_no_pio.patch @@ -0,0 +1,86 @@ +--- a/drivers/net/wireless/b43/Makefile ++++ b/drivers/net/wireless/b43/Makefile +@@ -17,7 +17,7 @@ b43-$(CPTCFG_B43_PHY_AC) += phy_ac.o + b43-y += sysfs.o + b43-y += xmit.o + b43-y += dma.o +-b43-y += pio.o ++b43-$(CPTCFG_B43_PIO) += pio.o + b43-y += rfkill.o + b43-y += ppr.o + b43-$(CPTCFG_B43_LEDS) += leds.o +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -2009,10 +2009,12 @@ static void b43_do_interrupt_thread(stru + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3], + dma_reason[4], dma_reason[5]); ++#ifdef CPTCFG_B43_PIO + b43err(dev->wl, "This device does not support DMA " + "on your system. It will now be switched to PIO.\n"); + /* Fall back to PIO transfers if we get fatal DMA errors! */ + dev->use_pio = true; ++#endif + b43_controller_restart(dev, "DMA error"); + return; + } +--- a/drivers/net/wireless/b43/pio.h ++++ b/drivers/net/wireless/b43/pio.h +@@ -150,7 +150,7 @@ static inline void b43_piorx_write32(str + b43_write32(q->dev, q->mmio_base + offset, value); + } + +- ++#ifdef CPTCFG_B43_PIO + int b43_pio_init(struct b43_wldev *dev); + void b43_pio_free(struct b43_wldev *dev); + +@@ -161,5 +161,37 @@ void b43_pio_rx(struct b43_pio_rxqueue * + + void b43_pio_tx_suspend(struct b43_wldev *dev); + void b43_pio_tx_resume(struct b43_wldev *dev); ++#else ++static inline int b43_pio_init(struct b43_wldev *dev) ++{ ++ return 0; ++} ++ ++static inline void b43_pio_free(struct b43_wldev *dev) ++{ ++} ++ ++static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) ++{ ++ return 0; ++} ++ ++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, ++ const struct b43_txstatus *status) ++{ ++} ++ ++static inline void b43_pio_rx(struct b43_pio_rxqueue *q) ++{ ++} ++ ++static inline void b43_pio_tx_suspend(struct b43_wldev *dev) ++{ ++} ++ ++static inline void b43_pio_tx_resume(struct b43_wldev *dev) ++{ ++} ++#endif /* CPTCFG_B43_PIO */ + + #endif /* B43_PIO_H_ */ +--- a/drivers/net/wireless/b43/Kconfig ++++ b/drivers/net/wireless/b43/Kconfig +@@ -118,7 +118,7 @@ config B43_BCMA_PIO + default y + + config B43_PIO +- bool ++ bool "Broadcom 43xx PIO support" + depends on B43 && B43_SSB + select SSB_BLOCKIO + default y diff --git a/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch new file mode 100644 index 0000000..4f06d8e --- /dev/null +++ b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch @@ -0,0 +1,131 @@ +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -1649,7 +1649,7 @@ static void b43_write_beacon_template(st + len, ram_offset, shm_size_offset, rate); + + /* Write the PHY TX control parameters. */ +- antenna = B43_ANTENNA_DEFAULT; ++ antenna = dev->tx_antenna; + antenna = b43_antenna_to_phyctl(antenna); + ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); + /* We can't send beacons with short preamble. Would get PHY errors. */ +@@ -3301,8 +3301,8 @@ static int b43_chip_init(struct b43_wlde + + /* Select the antennae */ + if (phy->ops->set_rx_antenna) +- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT); +- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); ++ phy->ops->set_rx_antenna(dev, dev->rx_antenna); ++ b43_mgmtframe_txantenna(dev, dev->tx_antenna); + + if (phy->type == B43_PHYTYPE_B) { + value16 = b43_read16(dev, 0x005E); +@@ -4002,7 +4002,6 @@ static int b43_op_config(struct ieee8021 + struct b43_wldev *dev = wl->current_dev; + struct b43_phy *phy = &dev->phy; + struct ieee80211_conf *conf = &hw->conf; +- int antenna; + int err = 0; + + mutex_lock(&wl->mutex); +@@ -4045,11 +4044,9 @@ static int b43_op_config(struct ieee8021 + } + + /* Antennas for RX and management frame TX. */ +- antenna = B43_ANTENNA_DEFAULT; +- b43_mgmtframe_txantenna(dev, antenna); +- antenna = B43_ANTENNA_DEFAULT; ++ b43_mgmtframe_txantenna(dev, dev->tx_antenna); + if (phy->ops->set_rx_antenna) +- phy->ops->set_rx_antenna(dev, antenna); ++ phy->ops->set_rx_antenna(dev, dev->rx_antenna); + + if (wl->radio_enabled != phy->radio_on) { + if (wl->radio_enabled) { +@@ -5210,6 +5207,47 @@ static int b43_op_get_survey(struct ieee + return 0; + } + ++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) ++{ ++ struct b43_wl *wl = hw_to_b43_wl(hw); ++ struct b43_wldev *dev = wl->current_dev; ++ ++ if (tx_ant == 1 && rx_ant == 1) { ++ dev->tx_antenna = B43_ANTENNA0; ++ dev->rx_antenna = B43_ANTENNA0; ++ } ++ else if (tx_ant == 2 && rx_ant == 2) { ++ dev->tx_antenna = B43_ANTENNA1; ++ dev->rx_antenna = B43_ANTENNA1; ++ } ++ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) { ++ dev->tx_antenna = B43_ANTENNA_DEFAULT; ++ dev->rx_antenna = B43_ANTENNA_DEFAULT; ++ } ++ else { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++ ++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) ++{ ++ struct b43_wl *wl = hw_to_b43_wl(hw); ++ struct b43_wldev *dev = wl->current_dev; ++ ++ switch (dev->tx_antenna) { ++ case B43_ANTENNA0: ++ *tx_ant = 1; *rx_ant = 1; break; ++ case B43_ANTENNA1: ++ *tx_ant = 2; *rx_ant = 2; break; ++ case B43_ANTENNA_DEFAULT: ++ *tx_ant = 3; *rx_ant = 3; break; ++ } ++ return 0; ++} ++ + static const struct ieee80211_ops b43_hw_ops = { + .tx = b43_op_tx, + .conf_tx = b43_op_conf_tx, +@@ -5231,6 +5269,8 @@ static const struct ieee80211_ops b43_hw + .sw_scan_complete = b43_op_sw_scan_complete_notifier, + .get_survey = b43_op_get_survey, + .rfkill_poll = b43_rfkill_poll, ++ .set_antenna = b43_op_set_antenna, ++ .get_antenna = b43_op_get_antenna, + }; + + /* Hard-reset the chip. Do not call this directly. +@@ -5539,6 +5579,8 @@ static int b43_one_core_attach(struct b4 + if (!wldev) + goto out; + ++ wldev->rx_antenna = B43_ANTENNA_DEFAULT; ++ wldev->tx_antenna = B43_ANTENNA_DEFAULT; + wldev->use_pio = b43_modparam_pio; + wldev->dev = dev; + wldev->wl = wl; +@@ -5629,6 +5671,9 @@ static struct b43_wl *b43_wireless_init( + + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + ++ hw->wiphy->available_antennas_rx = 0x3; ++ hw->wiphy->available_antennas_tx = 0x3; ++ + wl->hw_registred = false; + hw->max_rates = 2; + SET_IEEE80211_DEV(hw, dev->dev); +--- a/drivers/net/wireless/b43/b43.h ++++ b/drivers/net/wireless/b43/b43.h +@@ -840,6 +840,8 @@ struct b43_wldev { + bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ + bool use_pio; /* TRUE if next init should use PIO */ + int gpiomask; /* GPIO LED mask as a module parameter */ ++ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */ ++ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */ + + /* PHY/Radio device. */ + struct b43_phy phy; diff --git a/package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch b/package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch new file mode 100644 index 0000000..9c51ac6 --- /dev/null +++ b/package/kernel/mac80211/patches/841-b43-reduce-number-of-RX-slots.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/b43/dma.h ++++ b/drivers/net/wireless/b43/dma.h +@@ -169,7 +169,7 @@ struct b43_dmadesc_generic { + + /* DMA engine tuning knobs */ + #define B43_TXRING_SLOTS 256 +-#define B43_RXRING_SLOTS 256 ++#define B43_RXRING_SLOTS 32 + #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) + #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) + diff --git a/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch b/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch new file mode 100644 index 0000000..ab06b6e --- /dev/null +++ b/package/kernel/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch @@ -0,0 +1,17 @@ +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -2900,6 +2900,14 @@ static int b43_gpio_init(struct b43_wlde + } else if (dev->dev->chip_id == 0x5354) { + /* Don't allow overtaking buttons GPIOs */ + set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */ ++ } else if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM47162 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5356 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5357 || ++ dev->dev->chip_id == BCMA_CHIP_ID_BCM53572) { ++ /* just use gpio 0 and 1 for 2.4 GHz wifi led */ ++ set &= 0x3; ++ mask &= 0x3; + } + + if (0 /* FIXME: conditional unknown */ ) { diff --git a/package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch b/package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch new file mode 100644 index 0000000..9d1d419 --- /dev/null +++ b/package/kernel/mac80211/patches/847-b43-always-take-overlapping-devs.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -118,7 +118,7 @@ static int b43_modparam_pio = 0; + module_param_named(pio, b43_modparam_pio, int, 0644); + MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); + +-static int modparam_allhwsupport = !IS_ENABLED(CPTCFG_BRCMSMAC); ++static int modparam_allhwsupport = 1; + module_param_named(allhwsupport, modparam_allhwsupport, int, 0444); + MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)"); + diff --git a/package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch b/package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch new file mode 100644 index 0000000..185c427 --- /dev/null +++ b/package/kernel/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch @@ -0,0 +1,27 @@ +--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c ++++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c +@@ -58,19 +58,12 @@ + (((c) < 149) ? 3 : 4)))) + + #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0) +-#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \ +- NL80211_RRF_NO_IR) ++#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, 0) + +-#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \ +- NL80211_RRF_DFS | \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \ +- NL80211_RRF_DFS | \ +- NL80211_RRF_NO_IR) +-#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \ +- NL80211_RRF_NO_IR) ++#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, 0) ++#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, 0) + + static const struct ieee80211_regdomain brcms_regdom_x2 = { + .n_reg_rules = 6, diff --git a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch new file mode 100644 index 0000000..d60d3fa --- /dev/null +++ b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch @@ -0,0 +1,97 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 8 Jun 2015 16:11:40 +0200 +Subject: [PATCH] brcmfmac: register wiphy(s) during module_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is needed by OpenWrt which expects all PHYs to be created after +module loads successfully. + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +@@ -1236,6 +1236,7 @@ static int __init brcmfmac_module_init(v + #endif + if (!schedule_work(&brcmf_driver_work)) + return -EBUSY; ++ flush_work(&brcmf_driver_work); + + return 0; + } +--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +@@ -420,6 +420,7 @@ struct brcmf_fw { + u16 bus_nr; + void (*done)(struct device *dev, const struct firmware *fw, + void *nvram_image, u32 nvram_len); ++ struct completion *completion; + }; + + static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) +@@ -455,6 +456,8 @@ static void brcmf_fw_request_nvram_done( + goto fail; + + fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length); ++ if (fwctx->completion) ++ complete(fwctx->completion); + kfree(fwctx); + return; + +@@ -462,6 +465,8 @@ fail: + brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); + release_firmware(fwctx->code); + device_release_driver(fwctx->dev); ++ if (fwctx->completion) ++ complete(fwctx->completion); + kfree(fwctx); + } + +@@ -477,6 +482,8 @@ static void brcmf_fw_request_code_done(c + /* only requested code so done here */ + if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { + fwctx->done(fwctx->dev, fw, NULL, 0); ++ if (fwctx->completion) ++ complete(fwctx->completion); + kfree(fwctx); + return; + } +@@ -494,6 +501,8 @@ static void brcmf_fw_request_code_done(c + fail: + brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); + device_release_driver(fwctx->dev); ++ if (fwctx->completion) ++ complete(fwctx->completion); + kfree(fwctx); + } + +@@ -505,6 +514,8 @@ int brcmf_fw_get_firmwares_pcie(struct d + u16 domain_nr, u16 bus_nr) + { + struct brcmf_fw *fwctx; ++ struct completion completion; ++ int err; + + brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); + if (!fw_cb || !code) +@@ -525,9 +536,17 @@ int brcmf_fw_get_firmwares_pcie(struct d + fwctx->domain_nr = domain_nr; + fwctx->bus_nr = bus_nr; + +- return request_firmware_nowait(THIS_MODULE, true, code, dev, ++ init_completion(&completion); ++ fwctx->completion = &completion; ++ ++ err = request_firmware_nowait(THIS_MODULE, true, code, dev, + GFP_KERNEL, fwctx, + brcmf_fw_request_code_done); ++ if (!err) ++ wait_for_completion_timeout(fwctx->completion, ++ msecs_to_jiffies(5000)); ++ fwctx->completion = NULL; ++ return err; + } + + int brcmf_fw_get_firmwares(struct device *dev, u16 flags, diff --git a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch new file mode 100644 index 0000000..43582f6 --- /dev/null +++ b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -0,0 +1,50 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 9 Jul 2015 00:07:59 +0200 +Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +@@ -609,9 +609,37 @@ static struct wireless_dev *brcmf_cfg802 + u32 *flags, + struct vif_params *params) + { ++ struct net_device *dev; + struct wireless_dev *wdev; + int err; + ++ /* ++ * There is a bug with in-firmware BSS management. When adding virtual ++ * interface brcmfmac first tells firmware to create new BSS and then ++ * it creates new struct net_device. ++ * ++ * If creating/registering netdev(ice) fails, BSS remains in some bugged ++ * state. It conflicts with existing BSSes by overtaking their auth ++ * requests. ++ * ++ * It results in one BSS (addresss X) sending beacons and another BSS ++ * (address Y) replying to authentication requests. This makes interface ++ * unusable as AP. ++ * ++ * To workaround this bug we may try to guess if register_netdev(ice) ++ * will fail. The most obvious case is using interface name that already ++ * exists. This is actually quite likely with brcmfmac & some user space ++ * scripts as brcmfmac doesn't allow deleting virtual interfaces. ++ * So this bug can be triggered even by something trivial like: ++ * iw dev wlan0 delete ++ * iw phy phy0 interface add wlan0 type __ap ++ */ ++ dev = dev_get_by_name(&init_net, name); ++ if (dev) { ++ dev_put(dev); ++ return ERR_PTR(-EEXIST); ++ } ++ + brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); + err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); + if (err) { diff --git a/package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch b/package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch new file mode 100644 index 0000000..e6b2d7b --- /dev/null +++ b/package/kernel/mac80211/patches/910-00-rt2x00-enable-rt2800soc-for-mt7620.patch @@ -0,0 +1,20 @@ +--- a/drivers/net/wireless/rt2x00/Kconfig ++++ b/drivers/net/wireless/rt2x00/Kconfig +@@ -211,7 +211,7 @@ endif + config RT2800SOC + tristate "Ralink WiSoC support" + depends on m +- depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 + select RT2X00_LIB_SOC + select RT2X00_LIB_MMIO + select RT2X00_LIB_CRYPTO +@@ -248,7 +248,7 @@ config RT2X00_LIB_PCI + + config RT2X00_LIB_SOC + tristate "RT2x00 SoC support" +- depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 ++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620 + depends on m + select RT2X00_LIB + diff --git a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch new file mode 100644 index 0000000..b0536ce --- /dev/null +++ b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch @@ -0,0 +1,1202 @@ +--- a/drivers/net/wireless/rt2x00/rt2800.h ++++ b/drivers/net/wireless/rt2x00/rt2800.h +@@ -81,6 +81,7 @@ + #define RF5372 0x5372 + #define RF5390 0x5390 + #define RF5392 0x5392 ++#define RF7620 0x7620 + + /* + * Chipset revisions. +@@ -656,6 +657,14 @@ + #define RF_CSR_CFG_BUSY FIELD32(0x00020000) + + /* ++ * mt7620 RF registers (reversed order) ++ */ ++#define RF_CSR_CFG_DATA_MT7620 FIELD32(0x0000ff00) ++#define RF_CSR_CFG_REGNUM_MT7620 FIELD32(0x03ff0000) ++#define RF_CSR_CFG_WRITE_MT7620 FIELD32(0x00000010) ++#define RF_CSR_CFG_BUSY_MT7620 FIELD32(0x00000001) ++ ++/* + * EFUSE_CSR: RT30x0 EEPROM + */ + #define EFUSE_CTRL 0x0580 +@@ -1039,6 +1048,11 @@ + #define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) + + /* ++ * mt7620 ++ */ ++#define MIMO_PS_CFG 0x1210 ++ ++/* + * EDCA_AC0_CFG: + */ + #define EDCA_AC0_CFG 0x1300 +@@ -1218,6 +1232,8 @@ + #define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) + #define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) + #define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) ++#define TX_PIN_CFG_RFRX_EN FIELD32(0x00100000) /* mt7620 */ ++#define TX_PIN_CFG_RFRX_POL FIELD32(0x00200000) /* mt7620 */ + #define TX_PIN_CFG_PA_PE_A2_EN FIELD32(0x01000000) + #define TX_PIN_CFG_PA_PE_G2_EN FIELD32(0x02000000) + #define TX_PIN_CFG_PA_PE_A2_POL FIELD32(0x04000000) +@@ -1564,6 +1580,17 @@ + #define TX_PWR_CFG_4_EXT_STBC4_CH2 FIELD32(0x0000000f) + #define TX_PWR_CFG_4_EXT_STBC6_CH2 FIELD32(0x00000f00) + ++/* mt7620 */ ++#define TX0_RF_GAIN_CORRECT 0x13a0 ++#define TX1_RF_GAIN_CORRECT 0x13a4 ++#define TX0_RF_GAIN_ATTEN 0x13a8 ++#define TX1_RF_GAIN_ATTEN 0x13ac ++#define TX_ALG_CFG_0 0x13b0 ++#define TX_ALG_CFG_1 0x13b4 ++#define TX0_BB_GAIN_ATTEN 0x13c0 ++#define TX1_BB_GAIN_ATTEN 0x13c4 ++#define TX_ALC_VGA3 0x13c8 ++ + /* TX_PWR_CFG_7 */ + #define TX_PWR_CFG_7 0x13d4 + #define TX_PWR_CFG_7_OFDM54_CH0 FIELD32(0x0000000f) +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -61,6 +61,8 @@ + rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) + #define WAIT_FOR_RFCSR(__dev, __reg) \ + rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) ++#define WAIT_FOR_RFCSR_MT7620(__dev, __reg) \ ++ rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY_MT7620, (__reg)) + #define WAIT_FOR_RF(__dev, __reg) \ + rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) + #define WAIT_FOR_MCU(__dev, __reg) \ +@@ -186,19 +188,55 @@ static void rt2800_rfcsr_write(struct rt + * Wait until the RFCSR becomes available, afterwards we + * can safely write the new data into the register. + */ +- if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { +- reg = 0; +- rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); +- rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); +- rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); +- rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); ++ switch (rt2x00dev->chip.rf) { ++ case RF7620: ++ if (WAIT_FOR_RFCSR_MT7620(rt2x00dev, ®)) { ++ reg = 0; ++ rt2x00_set_field32(®, RF_CSR_CFG_DATA_MT7620, value); ++ rt2x00_set_field32(®, RF_CSR_CFG_REGNUM_MT7620, word); ++ rt2x00_set_field32(®, RF_CSR_CFG_WRITE_MT7620, 1); ++ rt2x00_set_field32(®, RF_CSR_CFG_BUSY_MT7620, 1); ++ ++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); ++ } ++ break; ++ ++ default: ++ if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { ++ reg = 0; ++ rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); ++ rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); ++ rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); ++ rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); + +- rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); ++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); ++ } ++ break; + } + + mutex_unlock(&rt2x00dev->csr_mutex); + } + ++static void rt2800_rfcsr_write_bank(struct rt2x00_dev *rt2x00dev, const u8 bank, ++ const unsigned int reg, const u8 value) ++{ ++ rt2800_rfcsr_write(rt2x00dev, (reg | (bank << 6)), value); ++} ++ ++static void rt2800_rfcsr_write_chanreg(struct rt2x00_dev *rt2x00dev, ++ const unsigned int reg, const u8 value) ++{ ++ rt2800_rfcsr_write_bank(rt2x00dev, 4, reg, value); ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, reg, value); ++} ++ ++static void rt2800_rfcsr_write_dccal(struct rt2x00_dev *rt2x00dev, ++ const unsigned int reg, const u8 value) ++{ ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, reg, value); ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, reg, value); ++} ++ + static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev, + const unsigned int word, u8 *value) + { +@@ -214,22 +252,47 @@ static void rt2800_rfcsr_read(struct rt2 + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. + */ +- if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { +- reg = 0; +- rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); +- rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); +- rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); ++ switch (rt2x00dev->chip.rf) { ++ case RF7620: ++ if (WAIT_FOR_RFCSR_MT7620(rt2x00dev, ®)) { ++ reg = 0; ++ rt2x00_set_field32(®, RF_CSR_CFG_REGNUM_MT7620, word); ++ rt2x00_set_field32(®, RF_CSR_CFG_WRITE_MT7620, 0); ++ rt2x00_set_field32(®, RF_CSR_CFG_BUSY_MT7620, 1); + +- rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); ++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); + +- WAIT_FOR_RFCSR(rt2x00dev, ®); +- } ++ WAIT_FOR_RFCSR_MT7620(rt2x00dev, ®); ++ } + +- *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); ++ *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA_MT7620); ++ break; ++ ++ default: ++ if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { ++ reg = 0; ++ rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); ++ rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); ++ rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); ++ ++ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); ++ ++ WAIT_FOR_RFCSR(rt2x00dev, ®); ++ } ++ ++ *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); ++ break; ++ } + + mutex_unlock(&rt2x00dev->csr_mutex); + } + ++static void rt2800_rfcsr_read_bank(struct rt2x00_dev *rt2x00dev, const u8 bank, ++ const unsigned int reg, u8 *value) ++{ ++ rt2800_rfcsr_read(rt2x00dev, (reg | (bank << 6)), value); ++} ++ + static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev, + const unsigned int word, const u32 value) + { +@@ -566,6 +629,16 @@ void rt2800_get_txwi_rxwi_size(struct rt + *rxwi_size = RXWI_DESC_SIZE_5WORDS; + break; + ++ case RT5390: ++ if ( rt2x00dev->chip.rf == RF7620 ) { ++ *txwi_size = TXWI_DESC_SIZE_5WORDS; ++ *rxwi_size = RXWI_DESC_SIZE_6WORDS; ++ } else { ++ *txwi_size = TXWI_DESC_SIZE_4WORDS; ++ *rxwi_size = RXWI_DESC_SIZE_4WORDS; ++ } ++ break; ++ + case RT5592: + *txwi_size = TXWI_DESC_SIZE_5WORDS; + *rxwi_size = RXWI_DESC_SIZE_6WORDS; +@@ -3302,6 +3375,312 @@ static void rt2800_config_channel_rf55xx + rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F); + } + ++typedef struct mt7620_freqconfig { ++ u8 Channel; ++ u8 Rdiv; ++ u16 N; ++ u8 K; ++ u8 D; ++ u32 Ksd; ++} mt7620_freqconfig; ++ ++mt7620_freqconfig mt7620_chanconfig[] = ++{ ++ /* 2.4 to 2.483 GHz ++ * CH Rdiv N K D Ksd */ ++ { 0, 0, 0, 0, 0, 0 }, ++ { 1, 3, 0x50, 0, 0, 0x19999 }, ++ { 2, 3, 0x50, 0, 0, 0x24444 }, ++ { 3, 3, 0x50, 0, 0, 0x2EEEE }, ++ { 4, 3, 0x50, 0, 0, 0x39999 }, ++ { 5, 3, 0x51, 0, 0, 0x04444 }, ++ { 6, 3, 0x51, 0, 0, 0x0EEEE }, ++ { 7, 3, 0x51, 0, 0, 0x19999 }, ++ { 8, 3, 0x51, 0, 0, 0x24444 }, ++ { 9, 3, 0x51, 0, 0, 0x2EEEE }, ++ { 10, 3, 0x51, 0, 0, 0x39999 }, ++ { 11, 3, 0x52, 0, 0, 0x04444 }, ++ { 12, 3, 0x52, 0, 0, 0x0EEEE }, ++ { 13, 3, 0x52, 0, 0, 0x19999 }, ++ { 14, 3, 0x52, 0, 0, 0x33333 }, ++}; ++ ++static void rt2800_config_channel_rf7620(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_conf *conf, ++ struct rf_channel *rf, ++ struct channel_info *info) ++{ ++ int i; ++ u8 bbp; ++ u8 rfcsr; ++ u8 txrx_agc_fc; ++ u32 reg; ++ u16 eeprom, target_power; ++ u32 mac_sys_ctrl, mac_status; ++ u32 tx_pin = 0x00150F0F; ++ struct hw_mode_spec *spec = &rt2x00dev->spec; ++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; ++ ++ /* Frequeny plan setting */ ++ /* ++ * Rdiv setting ++ * R13[1:0] ++ */ ++ rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); ++ rfcsr = rfcsr & (~0x03); ++ if (spec->clk_is_20mhz) ++ rfcsr |= (mt7620_chanconfig[rf->channel].Rdiv & 0x3); ++ rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); ++ ++ /* ++ * N setting ++ * R21[0], R20[7:0] ++ */ ++ rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr); ++ rfcsr = (mt7620_chanconfig[rf->channel].N & 0x00ff); ++ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr); ++ rfcsr = rfcsr & (~0x01); ++ rfcsr |= ((mt7620_chanconfig[rf->channel].N & 0x0100) >> 8); ++ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); ++ ++ /* ++ * K setting ++ * R16[3:0] (RF PLL freq selection) ++ */ ++ rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr); ++ rfcsr = rfcsr & (~0x0f); ++ rfcsr |= (mt7620_chanconfig[rf->channel].K & 0x0f); ++ rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); ++ ++ /* ++ * D setting ++ * R22[2:0] (D=15, R22[2:0]=<111>) ++ */ ++ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr); ++ rfcsr = rfcsr & (~0x07); ++ rfcsr |= (mt7620_chanconfig[rf->channel].D & 0x07); ++ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); ++ ++ /* ++ * Ksd setting ++ * Ksd: R19<1:0>,R18<7:0>,R17<7:0> ++ */ ++ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); ++ rfcsr = (mt7620_chanconfig[rf->channel].Ksd & 0x000000ff); ++ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr); ++ rfcsr = ((mt7620_chanconfig[rf->channel].Ksd & 0x0000ff00) >> 8); ++ rt2800_rfcsr_write(rt2x00dev, 18, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 19, &rfcsr); ++ rfcsr = rfcsr & (~0x03); ++ rfcsr |= ((mt7620_chanconfig[rf->channel].Ksd & 0x00030000) >> 16); ++ rt2800_rfcsr_write(rt2x00dev, 19, rfcsr); ++ ++ /* Default: XO=20MHz , SDM mode */ ++ rt2800_rfcsr_read(rt2x00dev, 16, &rfcsr); ++ rfcsr = rfcsr & (~0xE0); ++ rfcsr |= 0x80; ++ rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr); ++ rfcsr |= 0x80; ++ rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); ++ if (rt2x00dev->default_ant.tx_chain_num == 1) ++ rfcsr &= (~0x2); ++ else ++ rfcsr |= 0x2; ++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); ++ if (rt2x00dev->default_ant.tx_chain_num == 1) ++ rfcsr &= (~0x20); ++ else ++ rfcsr |= 0x20; ++ if (rt2x00dev->default_ant.rx_chain_num == 1) ++ rfcsr &= (~0x02); ++ else ++ rfcsr |= 0x02; ++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); ++ ++ rt2800_rfcsr_read(rt2x00dev, 42, &rfcsr); ++ if (rt2x00dev->default_ant.tx_chain_num == 1) ++ rfcsr &= (~0x40); ++ else ++ rfcsr |= 0x40; ++ rt2800_rfcsr_write(rt2x00dev, 42, rfcsr); ++ ++ /* RF for DC Cal BW */ ++ if (conf_is_ht40(conf)) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 6, 0x10); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 7, 0x10); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 8, 0x04); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x10); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x10); ++ } else { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 6, 0x20); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 7, 0x20); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 8, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x20); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x20); ++ } ++ ++ if (conf_is_ht40(conf)) { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x08); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x08); ++ } else { ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x28); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x28); ++ } ++ ++ rt2800_rfcsr_read(rt2x00dev, 28, &rfcsr); ++ if (conf_is_ht40(conf) && (rf->channel == 11)) ++ rfcsr |= 0x4; ++ else ++ rfcsr &= (~0x4); ++ rt2800_rfcsr_write(rt2x00dev, 28, rfcsr); ++ ++ /*if (bScan == FALSE)*/ ++ if (conf_is_ht40(conf)) { ++ txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, ++ RFCSR24_TX_AGC_FC); ++ } else { ++ txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20, ++ RFCSR24_TX_AGC_FC); ++ } ++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 6, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 6, rfcsr); ++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 7, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 7, rfcsr); ++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 6, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 6, rfcsr); ++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 7, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 7, rfcsr); ++ ++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 58, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 58, rfcsr); ++ rt2800_rfcsr_read_bank(rt2x00dev, 5, 59, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 59, rfcsr); ++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 58, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 58, rfcsr); ++ rt2800_rfcsr_read_bank(rt2x00dev, 7, 59, &rfcsr); ++ rfcsr &= (~0x3F); ++ rfcsr |= txrx_agc_fc; ++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 59, rfcsr); ++ ++ rt2800_register_read(rt2x00dev, TX_ALG_CFG_0, ®); ++ reg = reg & (~0x3F3F); ++ reg |= info->default_power1; ++ reg |= (info->default_power2 << 8); ++ reg |= (0x2F << 16); ++ reg |= (0x2F << 24); ++ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); ++ if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) { ++ /* init base power by e2p target power */ ++ rt2800_eeprom_read(rt2x00dev, 0xD0, &target_power); ++ target_power &= 0x3F; ++ reg = reg & (~0x3F3F); ++ reg |= target_power; ++ reg |= (target_power << 8); ++ } ++ rt2800_register_write(rt2x00dev, TX_ALG_CFG_0, reg); ++ ++ rt2800_register_read(rt2x00dev, TX_ALG_CFG_1, ®); ++ reg = reg & (~0x3F); ++ rt2800_register_write(rt2x00dev, TX_ALG_CFG_1, reg); ++ ++ /*if (bScan == FALSE)*/ ++ /* Save MAC SYS CTRL registers */ ++ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &mac_sys_ctrl); ++ /* Disable Tx/Rx */ ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0); ++ /* Check MAC Tx/Rx idle */ ++ for (i = 0; i < 10000; i++) { ++ rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, &mac_status); ++ if (mac_status & 0x3) ++ udelay(50); ++ else ++ break; ++ } ++ ++ if (i == 10000) ++ rt2x00_warn(rt2x00dev, "Wait MAC Status to MAX !!!\n"); ++ ++ if (rf->channel > 10) { ++ rt2800_bbp_read(rt2x00dev, 30, &bbp); ++ bbp = 0x40; ++ rt2800_bbp_write(rt2x00dev, 30, bbp); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0); ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x7b); ++ } else { ++ rt2800_bbp_read(rt2x00dev, 30, &bbp); ++ bbp = 0x1f; ++ rt2800_bbp_write(rt2x00dev, 30, bbp); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); ++ } ++ ++ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, mac_sys_ctrl); ++ ++ rt2800_rfcsr_write(rt2x00dev, 5, 0x40); ++ rt2800_rfcsr_write(rt2x00dev, 4, 0x0C); ++ ++ /* vcocal_en (initiate VCO calibration (reset after completion)) */ ++ rt2800_rfcsr_read(rt2x00dev, 4, &rfcsr); ++ rfcsr = ((rfcsr & ~0x80) | 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 4, rfcsr); ++ mdelay(2); ++ ++ rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); ++ ++ if (rt2x00dev->default_ant.tx_chain_num == 1) { ++ rt2800_bbp_write(rt2x00dev, 91, 0x07); ++ rt2800_bbp_write(rt2x00dev, 95, 0x1A); ++ rt2800_bbp_write(rt2x00dev, 195, 128); ++ rt2800_bbp_write(rt2x00dev, 196, 0xA0); ++ rt2800_bbp_write(rt2x00dev, 195, 170); ++ rt2800_bbp_write(rt2x00dev, 196, 0x12); ++ rt2800_bbp_write(rt2x00dev, 195, 171); ++ rt2800_bbp_write(rt2x00dev, 196, 0x10); ++ } else { ++ rt2800_bbp_write(rt2x00dev, 91, 0x06); ++ rt2800_bbp_write(rt2x00dev, 95, 0x9A); ++ rt2800_bbp_write(rt2x00dev, 195, 128); ++ rt2800_bbp_write(rt2x00dev, 196, 0xE0); ++ rt2800_bbp_write(rt2x00dev, 195, 170); ++ rt2800_bbp_write(rt2x00dev, 196, 0x30); ++ rt2800_bbp_write(rt2x00dev, 195, 171); ++ rt2800_bbp_write(rt2x00dev, 196, 0x30); ++ } ++ ++ /* On 11A, We should delay and wait RF/BBP to be stable*/ ++ /* and the appropriate time should be 1000 micro seconds */ ++ /* 2005/06/05 - On 11G, We also need this delay time. ++ * Otherwise it's difficult to pass the WHQL.*/ ++ udelay(1000); ++} ++ ++ + static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev, + const unsigned int word, + const u8 value) +@@ -3458,7 +3837,7 @@ static void rt2800_config_channel(struct + struct channel_info *info) + { + u32 reg; +- unsigned int tx_pin; ++ u32 tx_pin; + u8 bbp, rfcsr; + + info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, +@@ -3512,6 +3891,9 @@ static void rt2800_config_channel(struct + case RF5592: + rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info); + break; ++ case RF7620: ++ rt2800_config_channel_rf7620(rt2x00dev, conf, rf, info); ++ break; + default: + rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); + } +@@ -3614,7 +3996,7 @@ static void rt2800_config_channel(struct + else if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) + rt2800_bbp_write(rt2x00dev, 82, 0x82); +- else ++ else if (rt2x00dev->chip.rf != RF7620) + rt2800_bbp_write(rt2x00dev, 82, 0xf2); + + if (rt2x00_rt(rt2x00dev, RT3593) || +@@ -3636,7 +4018,7 @@ static void rt2800_config_channel(struct + if (rt2x00_rt(rt2x00dev, RT3572)) + rt2800_rfcsr_write(rt2x00dev, 8, 0); + +- tx_pin = 0; ++ rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin); + + switch (rt2x00dev->default_ant.tx_chain_num) { + case 3: +@@ -3685,6 +4067,7 @@ static void rt2800_config_channel(struct + + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFRX_EN, 1); /* mt7620 */ + + rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + +@@ -4701,6 +5084,14 @@ void rt2800_vco_calibration(struct rt2x0 + rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); + rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + break; ++ case RF7620: ++ rt2800_rfcsr_read(rt2x00dev, 4, &rfcsr); ++ /* vcocal_en (initiate VCO calibration (reset after completion)) ++ * It should be at the end of RF configuration. */ ++ rfcsr = ((rfcsr & ~0x80) | 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 4, rfcsr); ++ mdelay(1); ++ break; + default: + return; + } +@@ -5101,9 +5492,42 @@ static int rt2800_init_registers(struct + } else if (rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392) || + rt2x00_rt(rt2x00dev, RT5592)) { +- rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); +- rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +- rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); ++ if (rt2x00dev->chip.rf == RF7620) { ++ 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, ++ 0x06060606); ++ rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, ++ 0x0); ++ rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, ++ 0x0); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN, ++ 0x6C6C666C); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN, ++ 0x6C6C666C); ++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT, ++ 0x3630363A); ++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_CORRECT, ++ 0x3630363A); ++ rt2800_register_read(rt2x00dev, TX_ALG_CFG_1, ®); ++ reg = reg & (~0x80000000); ++ rt2800_register_write(rt2x00dev, TX_ALG_CFG_1, reg); ++ } else { ++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, ++ 0x00000404); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, ++ 0x00080606); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, ++ 0x00000000); ++ } + } else if (rt2x00_rt(rt2x00dev, RT5350)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + } else { +@@ -6135,6 +6559,225 @@ static void rt2800_init_bbp_5592(struct + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + } + ++static void rt2800_bbp_glrt_write(struct rt2x00_dev *rt2x00dev, ++ const u8 reg, const u8 value) ++{ ++ rt2800_bbp_write(rt2x00dev, 195, reg); ++ rt2800_bbp_write(rt2x00dev, 196, value); ++} ++ ++static void rt2800_bbp_dcoc_write(struct rt2x00_dev *rt2x00dev, ++ const u8 reg, const u8 value) ++{ ++ rt2800_bbp_write(rt2x00dev, 158, reg); ++ rt2800_bbp_write(rt2x00dev, 159, value); ++} ++ ++static void rt2800_init_bbp_7620(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 bbp; ++ ++ /* Apply Maximum Likelihood Detection (MLD) for 2 stream case */ ++ rt2800_bbp_read(rt2x00dev, 105, &bbp); ++ rt2x00_set_field8(&bbp, BBP105_MLD, ++ rt2x00dev->default_ant.rx_chain_num == 2); ++ rt2800_bbp_write(rt2x00dev, 105, bbp); ++ ++ /* Avoid data loss and CRC errors */ ++ /* MAC interface control (MAC_IF_80M, 1: 80 MHz) */ ++ rt2800_bbp4_mac_if_ctrl(rt2x00dev); ++ ++ /* Fix I/Q swap issue */ ++ rt2800_bbp_read(rt2x00dev, 1, &bbp); ++ bbp |= 0x04; ++ rt2800_bbp_write(rt2x00dev, 1, bbp); ++ ++ /* BBP for G band */ ++ rt2800_bbp_write(rt2x00dev, 3, 0x08); ++ rt2800_bbp_write(rt2x00dev, 4, 0x00); /* rt2800_bbp4_mac_if_ctrl? */ ++ rt2800_bbp_write(rt2x00dev, 6, 0x08); ++ rt2800_bbp_write(rt2x00dev, 14, 0x09); ++ rt2800_bbp_write(rt2x00dev, 15, 0xFF); ++ rt2800_bbp_write(rt2x00dev, 16, 0x01); ++ rt2800_bbp_write(rt2x00dev, 20, 0x06); ++ rt2800_bbp_write(rt2x00dev, 21, 0x00); ++ rt2800_bbp_write(rt2x00dev, 22, 0x00); ++ rt2800_bbp_write(rt2x00dev, 27, 0x00); ++ rt2800_bbp_write(rt2x00dev, 28, 0x00); ++ rt2800_bbp_write(rt2x00dev, 30, 0x00); ++ rt2800_bbp_write(rt2x00dev, 31, 0x48); ++ rt2800_bbp_write(rt2x00dev, 47, 0x40); ++ rt2800_bbp_write(rt2x00dev, 62, 0x00); ++ rt2800_bbp_write(rt2x00dev, 63, 0x00); ++ rt2800_bbp_write(rt2x00dev, 64, 0x00); ++ rt2800_bbp_write(rt2x00dev, 65, 0x2C); ++ rt2800_bbp_write(rt2x00dev, 66, 0x1C); ++ rt2800_bbp_write(rt2x00dev, 67, 0x20); ++ rt2800_bbp_write(rt2x00dev, 68, 0xDD); ++ rt2800_bbp_write(rt2x00dev, 69, 0x10); ++ rt2800_bbp_write(rt2x00dev, 70, 0x05); ++ rt2800_bbp_write(rt2x00dev, 73, 0x18); ++ rt2800_bbp_write(rt2x00dev, 74, 0x0F); ++ rt2800_bbp_write(rt2x00dev, 75, 0x60); ++ rt2800_bbp_write(rt2x00dev, 76, 0x44); ++ rt2800_bbp_write(rt2x00dev, 77, 0x59); ++ rt2800_bbp_write(rt2x00dev, 78, 0x1E); ++ rt2800_bbp_write(rt2x00dev, 79, 0x1C); ++ rt2800_bbp_write(rt2x00dev, 80, 0x0C); ++ rt2800_bbp_write(rt2x00dev, 81, 0x3A); ++ rt2800_bbp_write(rt2x00dev, 82, 0xB6); ++ rt2800_bbp_write(rt2x00dev, 83, 0x9A); ++ rt2800_bbp_write(rt2x00dev, 84, 0x9A); ++ rt2800_bbp_write(rt2x00dev, 86, 0x38); ++ rt2800_bbp_write(rt2x00dev, 88, 0x90); ++ rt2800_bbp_write(rt2x00dev, 91, 0x04); ++ rt2800_bbp_write(rt2x00dev, 92, 0x02); ++ rt2800_bbp_write(rt2x00dev, 95, 0x9A); ++ rt2800_bbp_write(rt2x00dev, 96, 0x00); ++ rt2800_bbp_write(rt2x00dev, 103, 0xC0); ++ rt2800_bbp_write(rt2x00dev, 104, 0x92); ++ /* FIXME BBP105 owerwrite */ ++ rt2800_bbp_write(rt2x00dev, 105, 0x3C); ++ rt2800_bbp_write(rt2x00dev, 106, 0x12); ++ rt2800_bbp_write(rt2x00dev, 109, 0x00); ++ rt2800_bbp_write(rt2x00dev, 134, 0x10); ++ rt2800_bbp_write(rt2x00dev, 135, 0xA6); ++ rt2800_bbp_write(rt2x00dev, 137, 0x04); ++ rt2800_bbp_write(rt2x00dev, 142, 0x30); ++ rt2800_bbp_write(rt2x00dev, 143, 0xF7); ++ rt2800_bbp_write(rt2x00dev, 160, 0xEC); ++ rt2800_bbp_write(rt2x00dev, 161, 0xC4); ++ rt2800_bbp_write(rt2x00dev, 162, 0x77); ++ rt2800_bbp_write(rt2x00dev, 163, 0xF9); ++ rt2800_bbp_write(rt2x00dev, 164, 0x00); ++ rt2800_bbp_write(rt2x00dev, 165, 0x00); ++ rt2800_bbp_write(rt2x00dev, 186, 0x00); ++ rt2800_bbp_write(rt2x00dev, 187, 0x00); ++ rt2800_bbp_write(rt2x00dev, 188, 0x00); ++ rt2800_bbp_write(rt2x00dev, 186, 0x00); ++ rt2800_bbp_write(rt2x00dev, 187, 0x01); ++ rt2800_bbp_write(rt2x00dev, 188, 0x00); ++ rt2800_bbp_write(rt2x00dev, 189, 0x00); ++ ++ rt2800_bbp_write(rt2x00dev, 91, 0x06); ++ rt2800_bbp_write(rt2x00dev, 92, 0x04); ++ rt2800_bbp_write(rt2x00dev, 93, 0x54); ++ rt2800_bbp_write(rt2x00dev, 99, 0x50); ++ rt2800_bbp_write(rt2x00dev, 148, 0x84); ++ rt2800_bbp_write(rt2x00dev, 167, 0x80); ++ rt2800_bbp_write(rt2x00dev, 178, 0xFF); ++ rt2800_bbp_write(rt2x00dev, 106, 0x13); ++ ++ /* BBP for G band GLRT function (BBP_128 ~ BBP_221) */ ++ rt2800_bbp_glrt_write(rt2x00dev, 0, 0x00); ++ rt2800_bbp_glrt_write(rt2x00dev, 1, 0x14); /* ? see above */ ++ rt2800_bbp_glrt_write(rt2x00dev, 2, 0x20); ++ rt2800_bbp_glrt_write(rt2x00dev, 3, 0x0A); ++ rt2800_bbp_glrt_write(rt2x00dev, 10, 0x16); ++ rt2800_bbp_glrt_write(rt2x00dev, 11, 0x06); ++ rt2800_bbp_glrt_write(rt2x00dev, 12, 0x02); ++ rt2800_bbp_glrt_write(rt2x00dev, 13, 0x07); ++ rt2800_bbp_glrt_write(rt2x00dev, 14, 0x05); ++ rt2800_bbp_glrt_write(rt2x00dev, 15, 0x09); ++ rt2800_bbp_glrt_write(rt2x00dev, 16, 0x20); ++ rt2800_bbp_glrt_write(rt2x00dev, 17, 0x08); ++ rt2800_bbp_glrt_write(rt2x00dev, 18, 0x4A); ++ rt2800_bbp_glrt_write(rt2x00dev, 19, 0x00); ++ rt2800_bbp_glrt_write(rt2x00dev, 20, 0x00); ++ rt2800_bbp_glrt_write(rt2x00dev, 128, 0xE0); ++ rt2800_bbp_glrt_write(rt2x00dev, 129, 0x1F); ++ rt2800_bbp_glrt_write(rt2x00dev, 130, 0x4F); ++ rt2800_bbp_glrt_write(rt2x00dev, 131, 0x32); ++ rt2800_bbp_glrt_write(rt2x00dev, 132, 0x08); ++ rt2800_bbp_glrt_write(rt2x00dev, 133, 0x28); ++ rt2800_bbp_glrt_write(rt2x00dev, 134, 0x19); ++ rt2800_bbp_glrt_write(rt2x00dev, 135, 0x0A); ++ rt2800_bbp_glrt_write(rt2x00dev, 138, 0x16); ++ rt2800_bbp_glrt_write(rt2x00dev, 139, 0x10); ++ rt2800_bbp_glrt_write(rt2x00dev, 140, 0x10); ++ rt2800_bbp_glrt_write(rt2x00dev, 141, 0x1A); ++ rt2800_bbp_glrt_write(rt2x00dev, 142, 0x36); ++ rt2800_bbp_glrt_write(rt2x00dev, 143, 0x2C); ++ rt2800_bbp_glrt_write(rt2x00dev, 144, 0x26); ++ rt2800_bbp_glrt_write(rt2x00dev, 145, 0x24); ++ rt2800_bbp_glrt_write(rt2x00dev, 146, 0x42); ++ rt2800_bbp_glrt_write(rt2x00dev, 147, 0x40); ++ rt2800_bbp_glrt_write(rt2x00dev, 148, 0x30); ++ rt2800_bbp_glrt_write(rt2x00dev, 149, 0x29); ++ rt2800_bbp_glrt_write(rt2x00dev, 150, 0x4C); ++ rt2800_bbp_glrt_write(rt2x00dev, 151, 0x46); ++ rt2800_bbp_glrt_write(rt2x00dev, 152, 0x3D); ++ rt2800_bbp_glrt_write(rt2x00dev, 153, 0x40); ++ rt2800_bbp_glrt_write(rt2x00dev, 154, 0x3E); ++ rt2800_bbp_glrt_write(rt2x00dev, 155, 0x38); ++ rt2800_bbp_glrt_write(rt2x00dev, 156, 0x3D); ++ rt2800_bbp_glrt_write(rt2x00dev, 157, 0x2F); ++ rt2800_bbp_glrt_write(rt2x00dev, 158, 0x3C); ++ rt2800_bbp_glrt_write(rt2x00dev, 159, 0x34); ++ rt2800_bbp_glrt_write(rt2x00dev, 160, 0x2C); ++ rt2800_bbp_glrt_write(rt2x00dev, 161, 0x2F); ++ rt2800_bbp_glrt_write(rt2x00dev, 162, 0x3C); ++ rt2800_bbp_glrt_write(rt2x00dev, 163, 0x35); ++ rt2800_bbp_glrt_write(rt2x00dev, 164, 0x2E); ++ rt2800_bbp_glrt_write(rt2x00dev, 165, 0x2F); ++ rt2800_bbp_glrt_write(rt2x00dev, 166, 0x49); ++ rt2800_bbp_glrt_write(rt2x00dev, 167, 0x41); ++ rt2800_bbp_glrt_write(rt2x00dev, 168, 0x36); ++ rt2800_bbp_glrt_write(rt2x00dev, 169, 0x39); ++ rt2800_bbp_glrt_write(rt2x00dev, 170, 0x30); ++ rt2800_bbp_glrt_write(rt2x00dev, 171, 0x30); ++ rt2800_bbp_glrt_write(rt2x00dev, 172, 0x0E); ++ rt2800_bbp_glrt_write(rt2x00dev, 173, 0x0D); ++ rt2800_bbp_glrt_write(rt2x00dev, 174, 0x28); ++ rt2800_bbp_glrt_write(rt2x00dev, 175, 0x21); ++ rt2800_bbp_glrt_write(rt2x00dev, 176, 0x1C); ++ rt2800_bbp_glrt_write(rt2x00dev, 177, 0x16); ++ rt2800_bbp_glrt_write(rt2x00dev, 178, 0x50); ++ rt2800_bbp_glrt_write(rt2x00dev, 179, 0x4A); ++ rt2800_bbp_glrt_write(rt2x00dev, 180, 0x43); ++ rt2800_bbp_glrt_write(rt2x00dev, 181, 0x50); ++ rt2800_bbp_glrt_write(rt2x00dev, 182, 0x10); ++ rt2800_bbp_glrt_write(rt2x00dev, 183, 0x10); ++ rt2800_bbp_glrt_write(rt2x00dev, 184, 0x10); ++ rt2800_bbp_glrt_write(rt2x00dev, 185, 0x10); ++ rt2800_bbp_glrt_write(rt2x00dev, 200, 0x7D); ++ rt2800_bbp_glrt_write(rt2x00dev, 201, 0x14); ++ rt2800_bbp_glrt_write(rt2x00dev, 202, 0x32); ++ rt2800_bbp_glrt_write(rt2x00dev, 203, 0x2C); ++ rt2800_bbp_glrt_write(rt2x00dev, 204, 0x36); ++ rt2800_bbp_glrt_write(rt2x00dev, 205, 0x4C); ++ rt2800_bbp_glrt_write(rt2x00dev, 206, 0x43); ++ rt2800_bbp_glrt_write(rt2x00dev, 207, 0x2C); ++ rt2800_bbp_glrt_write(rt2x00dev, 208, 0x2E); ++ rt2800_bbp_glrt_write(rt2x00dev, 209, 0x36); ++ rt2800_bbp_glrt_write(rt2x00dev, 210, 0x30); ++ rt2800_bbp_glrt_write(rt2x00dev, 211, 0x6E); ++ ++ /* BBP for G band DCOC function */ ++ rt2800_bbp_dcoc_write(rt2x00dev, 140, 0x0C); ++ rt2800_bbp_dcoc_write(rt2x00dev, 141, 0x00); ++ rt2800_bbp_dcoc_write(rt2x00dev, 142, 0x10); ++ rt2800_bbp_dcoc_write(rt2x00dev, 143, 0x10); ++ rt2800_bbp_dcoc_write(rt2x00dev, 144, 0x10); ++ rt2800_bbp_dcoc_write(rt2x00dev, 145, 0x10); ++ rt2800_bbp_dcoc_write(rt2x00dev, 146, 0x08); ++ rt2800_bbp_dcoc_write(rt2x00dev, 147, 0x40); ++ rt2800_bbp_dcoc_write(rt2x00dev, 148, 0x04); ++ rt2800_bbp_dcoc_write(rt2x00dev, 149, 0x04); ++ rt2800_bbp_dcoc_write(rt2x00dev, 150, 0x08); ++ rt2800_bbp_dcoc_write(rt2x00dev, 151, 0x08); ++ rt2800_bbp_dcoc_write(rt2x00dev, 152, 0x03); ++ rt2800_bbp_dcoc_write(rt2x00dev, 153, 0x03); ++ rt2800_bbp_dcoc_write(rt2x00dev, 154, 0x03); ++ rt2800_bbp_dcoc_write(rt2x00dev, 155, 0x02); ++ rt2800_bbp_dcoc_write(rt2x00dev, 156, 0x40); ++ rt2800_bbp_dcoc_write(rt2x00dev, 157, 0x40); ++ rt2800_bbp_dcoc_write(rt2x00dev, 158, 0x64); ++ rt2800_bbp_dcoc_write(rt2x00dev, 159, 0x64); ++ ++ rt2800_bbp4_mac_if_ctrl(rt2x00dev); ++} ++ + static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + { + unsigned int i; +@@ -6177,7 +6820,10 @@ static void rt2800_init_bbp(struct rt2x0 + return; + case RT5390: + case RT5392: +- rt2800_init_bbp_53xx(rt2x00dev); ++ if (rt2x00dev->chip.rf == RF7620) ++ rt2800_init_bbp_7620(rt2x00dev); ++ else ++ rt2800_init_bbp_53xx(rt2x00dev); + break; + case RT5592: + rt2800_init_bbp_5592(rt2x00dev); +@@ -7391,6 +8037,296 @@ static void rt2800_init_rfcsr_5592(struc + rt2800_led_open_drain_enable(rt2x00dev); + } + ++static void rt2800_init_rfcsr_7620(struct rt2x00_dev *rt2x00dev) ++{ ++ u16 freq; ++ u8 rfvalue; ++ struct hw_mode_spec *spec = &rt2x00dev->spec; ++ ++ /* Initialize RF central register to default value */ ++ rt2800_rfcsr_write(rt2x00dev, 0, 0x02); ++ rt2800_rfcsr_write(rt2x00dev, 1, 0x03); ++ rt2800_rfcsr_write(rt2x00dev, 2, 0x33); ++ rt2800_rfcsr_write(rt2x00dev, 3, 0xFF); ++ rt2800_rfcsr_write(rt2x00dev, 4, 0x0C); ++ rt2800_rfcsr_write(rt2x00dev, 5, 0x40); /* Read only */ ++ rt2800_rfcsr_write(rt2x00dev, 6, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 8, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 9, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 10, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x00); ++ /* rt2800_rfcsr_write(rt2x00dev, 12, 0x43); *//* EEPROM */ ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 14, 0x40); ++ rt2800_rfcsr_write(rt2x00dev, 15, 0x22); ++ rt2800_rfcsr_write(rt2x00dev, 16, 0x4C); ++ rt2800_rfcsr_write(rt2x00dev, 17, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 20, 0xA0); ++ rt2800_rfcsr_write(rt2x00dev, 21, 0x12); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x07); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x13); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0xFE); ++ rt2800_rfcsr_write(rt2x00dev, 25, 0x24); ++ rt2800_rfcsr_write(rt2x00dev, 26, 0x7A); ++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0x05); ++ rt2800_rfcsr_write(rt2x00dev, 30, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 31, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 32, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 34, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 35, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 37, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 38, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 40, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 41, 0xD0); ++ rt2800_rfcsr_write(rt2x00dev, 42, 0x5B); ++ rt2800_rfcsr_write(rt2x00dev, 43, 0x00); ++ ++ rt2800_rfcsr_write(rt2x00dev, 11, 0x21); ++ if (spec->clk_is_20mhz) ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x03); ++ else ++ rt2800_rfcsr_write(rt2x00dev, 13, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 14, 0x7C); ++ rt2800_rfcsr_write(rt2x00dev, 16, 0x80); ++ rt2800_rfcsr_write(rt2x00dev, 17, 0x99); ++ rt2800_rfcsr_write(rt2x00dev, 18, 0x99); ++ rt2800_rfcsr_write(rt2x00dev, 19, 0x09); ++ rt2800_rfcsr_write(rt2x00dev, 20, 0x50); ++ rt2800_rfcsr_write(rt2x00dev, 21, 0xB0); ++ rt2800_rfcsr_write(rt2x00dev, 22, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 23, 0x06); ++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 26, 0x5D); ++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00); ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x61); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0xB5); ++ rt2800_rfcsr_write(rt2x00dev, 43, 0x02); ++ ++ rt2800_rfcsr_write(rt2x00dev, 28, 0x62); ++ rt2800_rfcsr_write(rt2x00dev, 29, 0xAD); ++ rt2800_rfcsr_write(rt2x00dev, 39, 0x80); ++ /* RTMP_TEMPERATURE_CALIBRATION */ ++ /* rt2800_rfcsr_write(rt2x00dev, 34, 0x23); */ ++ /* rt2800_rfcsr_write(rt2x00dev, 35, 0x01); */ ++ ++ /* use rt2800_adjust_freq_offset ? */ ++ rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &freq); ++ rfvalue = freq & 0xff; ++ rt2800_rfcsr_write(rt2x00dev, 12, rfvalue); ++ ++ /* Initialize RF channel register to default value */ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 0, 0x03); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 1, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 2, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 3, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 4, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 5, 0x08); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 6, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 7, 0x51); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x16); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x61); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 12, 0x22); ++ /* rt2800_rfcsr_write_chanreg(rt2x00dev, 13, 0x3D); */ /* fails */ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 15, 0x13); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 16, 0x22); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 18, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x01); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x52); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 22, 0x80); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 23, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 24, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 25, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 26, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 27, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x5C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0x6B); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 30, 0x6B); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 31, 0x31); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x5D); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 33, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xE6); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 35, 0x55); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 37, 0xBB); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 39, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 40, 0x03); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 41, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 42, 0x00); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x07); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x68); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xEF); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x07); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xA8); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0x85); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x10); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x07); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6A); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0x85); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x10); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 62, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 63, 0x00); ++ ++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0xC5); ++ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x47); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x71); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x33); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x0E); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 17, 0x23); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 20, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 21, 0x12); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 29, 0xEB); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 32, 0x7D); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 34, 0xD6); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 36, 0x08); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 38, 0xB4); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xB3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xD5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x69); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFF); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xFF); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x1C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x20); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xF7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x09); ++ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 10, 0x51); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x06); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 19, 0xA7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 28, 0x2C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 8, 0x51); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 9, 0x36); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 11, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 14, 0x16); ++ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x6C); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xFC); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x1F); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x66); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x6B); ++ ++ /* Initialize RF channel register for DRQFN */ ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0xD3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0xE3); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0xE5); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x28); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x68); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xF7); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xC7); ++ ++ /* reduce power consumption */ ++/* rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x53); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0x64); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0x4F); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0x64); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0x4F); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x02); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0x64); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0x4F); ++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x02); ++*/ ++ /* Initialize RF DC calibration register to default value */ ++ rt2800_rfcsr_write_dccal(rt2x00dev, 0, 0x47); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 1, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 2, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 6, 0x10); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 7, 0x10); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 8, 0x04); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 9, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 10, 0x07); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 11, 0x01); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 12, 0x07); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 13, 0x07); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 14, 0x07); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 15, 0x20); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 16, 0x22); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 18, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 19, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 20, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 21, 0xF1); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 22, 0x11); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 23, 0x02); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 24, 0x41); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 25, 0x20); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 26, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 27, 0xD7); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 28, 0xA2); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 29, 0x20); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 30, 0x49); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 31, 0x20); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 32, 0x04); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 33, 0xF1); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 34, 0xA1); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 35, 0x01); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 41, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 42, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 43, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 44, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 45, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 46, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 47, 0x3E); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 48, 0x3D); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 49, 0x3E); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 50, 0x3D); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 51, 0x3E); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 52, 0x3D); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 53, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 54, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 55, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 56, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 57, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 58, 0x10); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 59, 0x10); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 60, 0x0A); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 61, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 62, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 63, 0x00); ++ ++ rt2800_rfcsr_write_dccal(rt2x00dev, 3, 0x08); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 4, 0x04); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x20); ++ ++ rt2800_rfcsr_write_dccal(rt2x00dev, 5, 0x00); ++ rt2800_rfcsr_write_dccal(rt2x00dev, 17, 0x7C); ++} ++ + static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) + { + if (rt2800_is_305x_soc(rt2x00dev)) { +@@ -7426,7 +8362,10 @@ static void rt2800_init_rfcsr(struct rt2 + rt2800_init_rfcsr_5350(rt2x00dev); + break; + case RT5390: +- rt2800_init_rfcsr_5390(rt2x00dev); ++ if (rt2x00dev->chip.rf == RF7620) ++ rt2800_init_rfcsr_7620(rt2x00dev); ++ else ++ rt2800_init_rfcsr_5390(rt2x00dev); + break; + case RT5392: + rt2800_init_rfcsr_5392(rt2x00dev); +@@ -7858,6 +8797,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF5390: + case RF5392: + case RF5592: ++ case RF7620: + break; + default: + rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n", +@@ -8422,6 +9362,7 @@ static int rt2800_probe_hw_mode(struct r + case RF5372: + case RF5390: + case RF5392: ++ case RF7620: + spec->num_channels = 14; + if (spec->clk_is_20mhz) + spec->channels = rf_vals_xtal20mhz_3x; +@@ -8562,6 +9503,7 @@ static int rt2800_probe_hw_mode(struct r + case RF5372: + case RF5390: + case RF5392: ++ case RF7620: + __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags); + break; + } diff --git a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch new file mode 100644 index 0000000..af35560 --- /dev/null +++ b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch @@ -0,0 +1,33 @@ +From: Sven Eckelmann +Date: Tue, 18 Nov 2014 12:29:28 +0100 +Subject: [PATCH] ath10k: Don't initialize devices asynchronously + +OpenWrt requires all PHYs to be initialized to create the configuration files +during bootup. ath10k violates this because it delays the creation of the PHY +to a not well defined point in the future. + +Forcing the work to be done immediately works around this problem but may also +delay the boot when firmware images cannot be found. + +Signed-off-by: Sven Eckelmann +--- + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -1844,6 +1844,16 @@ int ath10k_core_register(struct ath10k * + ar->chip_id = chip_id; + queue_work(ar->workqueue, &ar->register_work); + ++ /* OpenWrt requires all PHYs to be initialized to create the ++ * configuration files during bootup. ath10k violates this ++ * because it delays the creation of the PHY to a not well defined ++ * point in the future. ++ * ++ * Forcing the work to be done immediately works around this problem ++ * but may also delay the boot when firmware images cannot be found. ++ */ ++ flush_workqueue(ar->workqueue); ++ + return 0; + } + EXPORT_SYMBOL(ath10k_core_register); diff --git a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch new file mode 100644 index 0000000..f2718c7 --- /dev/null +++ b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch @@ -0,0 +1,37 @@ +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -7092,6 +7092,21 @@ struct ath10k_vif *ath10k_get_arvif(stru + return arvif_iter.arvif; + } + ++#ifdef CPTCFG_MAC80211_LEDS ++static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = { ++ { .throughput = 0 * 1024, .blink_time = 334 }, ++ { .throughput = 1 * 1024, .blink_time = 260 }, ++ { .throughput = 2 * 1024, .blink_time = 220 }, ++ { .throughput = 5 * 1024, .blink_time = 190 }, ++ { .throughput = 10 * 1024, .blink_time = 170 }, ++ { .throughput = 25 * 1024, .blink_time = 150 }, ++ { .throughput = 54 * 1024, .blink_time = 130 }, ++ { .throughput = 120 * 1024, .blink_time = 110 }, ++ { .throughput = 265 * 1024, .blink_time = 80 }, ++ { .throughput = 586 * 1024, .blink_time = 50 }, ++}; ++#endif ++ + int ath10k_mac_register(struct ath10k *ar) + { + static const u32 cipher_suites[] = { +@@ -7317,6 +7332,12 @@ int ath10k_mac_register(struct ath10k *a + ar->hw->wiphy->cipher_suites = cipher_suites; + ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + ++#if CPTCFG_MAC80211_LEDS ++ ieee80211_create_tpt_led_trigger(ar->hw, ++ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, ++ ARRAY_SIZE(ath10k_tpt_blink)); ++#endif ++ + ret = ieee80211_register_hw(ar->hw); + if (ret) { + ath10k_err(ar, "failed to register ieee80211: %d\n", ret); diff --git a/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch new file mode 100644 index 0000000..d487504 --- /dev/null +++ b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch @@ -0,0 +1,20 @@ +--- a/drivers/net/wireless/mwl8k.c ++++ b/drivers/net/wireless/mwl8k.c +@@ -6262,6 +6262,8 @@ static int mwl8k_probe(struct pci_dev *p + + priv->running_bsses = 0; + ++ wait_for_completion(&priv->firmware_loading_complete); ++ + return rc; + + err_stop_firmware: +@@ -6295,8 +6297,6 @@ static void mwl8k_remove(struct pci_dev + return; + priv = hw->priv; + +- wait_for_completion(&priv->firmware_loading_complete); +- + if (priv->fw_state == FW_STATE_ERROR) { + mwl8k_hw_reset(priv); + goto unmap; -- cgit v1.2.3