diff --git a/diff.diff b/diff.diff new file mode 100644 index 0000000000..dc3fac8f10 --- /dev/null +++ b/diff.diff @@ -0,0 +1,4329 @@ +diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk +index dc7eb77986..60267f3c8e 100644 +--- a/package/kernel/linux/modules/crypto.mk ++++ b/package/kernel/linux/modules/crypto.mk +@@ -110,8 +110,8 @@ define KernelPackage/crypto-crc32 + DEPENDS:=+kmod-crypto-hash + KCONFIG:=CONFIG_CRYPTO_CRC32 + HIDDEN:=1 +- FILES:=$(LINUX_DIR)/crypto/crc32_generic.ko@ge4.9 +- AUTOLOAD:=$(call AutoLoad,04,crc32_generic@ge4.9,1) ++ FILES:=$(LINUX_DIR)/crypto/crc32_generic.ko ++ AUTOLOAD:=$(call AutoLoad,04,crc32_generic,1) + $(call AddDepends/crypto) + endef + +@@ -169,7 +169,9 @@ $(eval $(call KernelPackage,crypto-deflate)) + define KernelPackage/crypto-des + TITLE:=DES/3DES cipher CryptoAPI module + KCONFIG:=CONFIG_CRYPTO_DES +- FILES:=$(LINUX_DIR)/crypto/des_generic.ko ++ FILES:= \ ++ $(LINUX_DIR)/crypto/des_generic.ko \ ++ $(LINUX_DIR)/lib/crypto/libdes.ko@ge5.4 + AUTOLOAD:=$(call AutoLoad,09,des_generic) + $(call AddDepends/crypto) + endef +@@ -194,7 +196,8 @@ define KernelPackage/crypto-ecdh + DEPENDS:=+kmod-crypto-kpp + KCONFIG:= CONFIG_CRYPTO_ECDH + FILES:= \ +- $(LINUX_DIR)/crypto/ecdh_generic.ko ++ $(LINUX_DIR)/crypto/ecdh_generic.ko \ ++ $(LINUX_DIR)/crypto/ecc.ko@ge5.2 + AUTOLOAD:=$(call AutoLoad,10,ecdh_generic) + $(call AddDepends/crypto) + endef +@@ -263,12 +266,23 @@ $(eval $(call KernelPackage,crypto-gf128)) + define KernelPackage/crypto-ghash + TITLE:=GHASH digest CryptoAPI module + DEPENDS:=+kmod-crypto-gf128 +kmod-crypto-hash +- KCONFIG:=CONFIG_CRYPTO_GHASH ++ KCONFIG:= \ ++ CONFIG_CRYPTO_GHASH \ ++ CONFIG_CRYPTO_GHASH_ARM_CE + FILES:=$(LINUX_DIR)/crypto/ghash-generic.ko + AUTOLOAD:=$(call AutoLoad,09,ghash-generic) + $(call AddDepends/crypto) + endef + ++define KernelPackage/crypto-ghash/arm-ce ++ FILES+= $(LINUX_DIR)/arch/arm/crypto/ghash-arm-ce.ko ++ AUTOLOAD+=$(call AutoLoad,09,ghash-arm-ce) ++endef ++ ++KernelPackage/crypto-ghash/imx6=$(KernelPackage/crypto-ghash/arm-ce) ++KernelPackage/crypto-ghash/ipq40xx=$(KernelPackage/crypto-ghash/arm-ce) ++KernelPackage/crypto-ghash/mvebu=$(KernelPackage/crypto-ghash/arm-ce) ++ + $(eval $(call KernelPackage,crypto-ghash)) + + +@@ -402,7 +416,6 @@ endef + + $(eval $(call KernelPackage,crypto-hw-talitos)) + +- + define KernelPackage/crypto-iv + TITLE:=CryptoAPI initialization vectors + DEPENDS:=+kmod-crypto-manager +kmod-crypto-rng +kmod-crypto-wq +@@ -417,7 +430,6 @@ endef + + $(eval $(call KernelPackage,crypto-iv)) + +- + define KernelPackage/crypto-kpp + TITLE:=Key-agreement Protocol Primitives + KCONFIG:=CONFIG_CRYPTO_KPP +@@ -656,11 +668,10 @@ define KernelPackage/crypto-rng + CONFIG_CRYPTO_JITTERENTROPY \ + CONFIG_CRYPTO_RNG2 + FILES:= \ +- $(LINUX_DIR)/crypto/drbg.ko@ge4.2 \ +- $(LINUX_DIR)/crypto/jitterentropy_rng.ko@ge4.2 \ +- $(LINUX_DIR)/crypto/krng.ko@lt4.2 \ ++ $(LINUX_DIR)/crypto/drbg.ko \ ++ $(LINUX_DIR)/crypto/jitterentropy_rng.ko \ + $(LINUX_DIR)/crypto/rng.ko +- AUTOLOAD:=$(call AutoLoad,09,drbg@ge4.2 jitterentropy_rng@ge4.2 krng@lt4.2 rng) ++ AUTOLOAD:=$(call AutoLoad,09,drbg jitterentropy_rng rng) + $(call AddDepends/crypto) + endef + +@@ -684,6 +695,8 @@ define KernelPackage/crypto-sha1 + DEPENDS:=+kmod-crypto-hash + KCONFIG:= \ + CONFIG_CRYPTO_SHA1 \ ++ CONFIG_CRYPTO_SHA1_ARM \ ++ CONFIG_CRYPTO_SHA1_ARM_NEON \ + CONFIG_CRYPTO_SHA1_OCTEON \ + CONFIG_CRYPTO_SHA1_SSSE3 + FILES:=$(LINUX_DIR)/crypto/sha1_generic.ko +@@ -691,11 +704,28 @@ define KernelPackage/crypto-sha1 + $(call AddDepends/crypto) + endef + ++define KernelPackage/crypto-sha1/arm ++ FILES+=$(LINUX_DIR)/arch/arm/crypto/sha1-arm.ko ++ AUTOLOAD+=$(call AutoLoad,09,sha1-arm) ++endef ++ ++define KernelPackage/crypto-sha1/arm-neon ++ $(call KernelPackage/crypto-sha1/arm) ++ FILES+=$(LINUX_DIR)/arch/arm/crypto/sha1-arm-neon.ko ++ AUTOLOAD+=$(call AutoLoad,09,sha1-arm-neon) ++endef ++ ++KernelPackage/crypto-sha1/imx6=$(KernelPackage/crypto-sha1/arm-neon) ++KernelPackage/crypto-sha1/ipq40xx=$(KernelPackage/crypto-sha1/arm-neon) ++KernelPackage/crypto-sha1/mvebu/cortexa9=$(KernelPackage/crypto-sha1/arm-neon) ++ + define KernelPackage/crypto-sha1/octeon + FILES+=$(LINUX_DIR)/arch/mips/cavium-octeon/crypto/octeon-sha1.ko + AUTOLOAD+=$(call AutoLoad,09,octeon-sha1) + endef + ++KernelPackage/crypto-sha1/tegra=$(KernelPakcage/crypto-sha1/arm) ++ + define KernelPackage/crypto-sha1/x86/64 + FILES+=$(LINUX_DIR)/arch/x86/crypto/sha1-ssse3.ko + AUTOLOAD+=$(call AutoLoad,09,sha1-ssse3) +@@ -711,7 +741,9 @@ define KernelPackage/crypto-sha256 + CONFIG_CRYPTO_SHA256 \ + CONFIG_CRYPTO_SHA256_OCTEON \ + CONFIG_CRYPTO_SHA256_SSSE3 +- FILES:=$(LINUX_DIR)/crypto/sha256_generic.ko ++ FILES:= \ ++ $(LINUX_DIR)/crypto/sha256_generic.ko \ ++ $(LINUX_DIR)/lib/crypto/libsha256.ko@ge5.4 + AUTOLOAD:=$(call AutoLoad,09,sha256_generic) + $(call AddDepends/crypto) + endef +@@ -734,6 +766,7 @@ define KernelPackage/crypto-sha512 + DEPENDS:=+kmod-crypto-hash + KCONFIG:= \ + CONFIG_CRYPTO_SHA512 \ ++ CONFIG_CRYPTO_SHA512_ARM \ + CONFIG_CRYPTO_SHA512_OCTEON \ + CONFIG_CRYPTO_SHA512_SSSE3 + FILES:=$(LINUX_DIR)/crypto/sha512_generic.ko +@@ -741,11 +774,22 @@ define KernelPackage/crypto-sha512 + $(call AddDepends/crypto) + endef + ++define KernelPackage/crypto-sha512/arm ++ FILES+=$(LINUX_DIR)/arch/arm/crypto/sha512-arm.ko ++ AUTOLOAD+=$(call AutoLoad,09,sha512-arm) ++endef ++ ++KernelPackage/crypto-sha512/imx6=$(KernelPackage/crypto-sha512/arm) ++KernelPackage/crypto-sha512/ipq40xx=$(KernelPackage/crypto-sha512/arm) ++KernelPackage/crypto-sha512/mvebu/cortexa9=$(KernelPackage/crypto-sha512/arm) ++ + define KernelPackage/crypto-sha512/octeon + FILES+=$(LINUX_DIR)/arch/mips/cavium-octeon/crypto/octeon-sha512.ko + AUTOLOAD+=$(call AutoLoad,09,octeon-sha512) + endef + ++KernelPackage/crypto-sha512/tegra=$(KernelPackage/crypto-sha512/arm) ++ + define KernelPackage/crypto-sha512/x86/64 + FILES+=$(LINUX_DIR)/arch/x86/crypto/sha512-ssse3.ko + AUTOLOAD+=$(call AutoLoad,09,sha512-ssse3) +@@ -768,6 +812,7 @@ define KernelPackage/crypto-user + TITLE:=CryptoAPI userspace interface + DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager + KCONFIG:= \ ++ CONFIG_CRYPTO_USER \ + CONFIG_CRYPTO_USER_API \ + CONFIG_CRYPTO_USER_API_AEAD \ + CONFIG_CRYPTO_USER_API_HASH \ +@@ -778,8 +823,9 @@ define KernelPackage/crypto-user + $(LINUX_DIR)/crypto/algif_aead.ko \ + $(LINUX_DIR)/crypto/algif_hash.ko \ + $(LINUX_DIR)/crypto/algif_rng.ko \ +- $(LINUX_DIR)/crypto/algif_skcipher.ko +- AUTOLOAD:=$(call AutoLoad,09,af_alg algif_aead algif_hash algif_rng algif_skcipher) ++ $(LINUX_DIR)/crypto/algif_skcipher.ko \ ++ $(LINUX_DIR)/crypto/crypto_user.ko ++ AUTOLOAD:=$(call AutoLoad,09,af_alg algif_aead algif_hash algif_rng algif_skcipher crypto_user) + $(call AddDepends/crypto) + endef + +diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile +index d26bcb813e..1782bae0f8 100644 +--- a/package/kernel/mac80211/Makefile ++++ b/package/kernel/mac80211/Makefile +@@ -1,4 +1,4 @@ +-# ++# + # Copyright (C) 2007-2015 OpenWrt.org + # + # This is free software, licensed under the GNU General Public License v2. +diff --git a/package/kernel/mac80211/patches/build/100-backports-pci-Include-linux-pci-aspm.h.patch b/package/kernel/mac80211/patches/build/100-backports-pci-Include-linux-pci-aspm.h.patch +new file mode 100644 +index 0000000000..5faeb96748 +--- /dev/null ++++ b/package/kernel/mac80211/patches/build/100-backports-pci-Include-linux-pci-aspm.h.patch +@@ -0,0 +1,24 @@ ++From: Hauke Mehrtens ++Date: Fri, 27 Sep 2019 23:12:08 +0200 ++Subject: [PATCH] backports: pci: Include linux/pci-aspm.h ++ ++In upstream commit 7ce2e76a0420 linux/pci-aspm.h was removed and the ++content included into pci.h. Add an include to have the functions ++defined in linux/pci-aspm.h available when linux/pci.h is included. ++ ++Signed-off-by: Hauke Mehrtens ++--- ++ ++--- a/backport-include/linux/pci.h +++++ b/backport-include/linux/pci.h ++@@ -3,6 +3,10 @@ ++ #include_next ++ #include ++ +++#if LINUX_VERSION_IS_LESS(5,4,0) +++#include +++#endif +++ ++ #ifndef module_pci_driver ++ /** ++ * module_pci_driver() - Helper macro for registering a PCI driver +diff --git a/package/kernel/mac80211/patches/build/101-backport-add-pci_disable_link_state-wrapper-with-ret.patch b/package/kernel/mac80211/patches/build/101-backport-add-pci_disable_link_state-wrapper-with-ret.patch +new file mode 100644 +index 0000000000..a41879184b +--- /dev/null ++++ b/package/kernel/mac80211/patches/build/101-backport-add-pci_disable_link_state-wrapper-with-ret.patch +@@ -0,0 +1,43 @@ ++From: Felix Fietkau ++Date: Mon, 28 Oct 2019 15:20:40 +0100 ++Subject: [PATCH] backport: add pci_disable_link_state wrapper with return code ++ ++The signature of pci_disable_link_state was changed to indicate if the state ++was successfully disabled. Since the old version did not have this, add a ++wrapper which checks the pcie register to determine the return code ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/backport-include/linux/pci.h +++++ b/backport-include/linux/pci.h ++@@ -236,4 +236,29 @@ static inline struct pci_dev *pcie_find_ ++ (PCI_IRQ_LEGACY | PCI_IRQ_MSI | PCI_IRQ_MSIX) ++ #endif ++ +++#if defined(CONFIG_PCI) && LINUX_VERSION_IS_LESS(5,3,0) +++ +++static inline int +++LINUX_BACKPORT(pci_disable_link_state)(struct pci_dev *pdev, int state) +++{ +++ u16 aspmc; +++ +++ pci_disable_link_state(pdev, state); +++ +++ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspmc); +++ if ((state & PCIE_LINK_STATE_L0S) && +++ (aspmc & PCI_EXP_LNKCTL_ASPM_L0S)) +++ return -EPERM; +++ +++ if ((state & PCIE_LINK_STATE_L1) && +++ (aspmc & PCI_EXP_LNKCTL_ASPM_L1)) +++ return -EPERM; +++ +++ return 0; +++} +++ +++#define pci_disable_link_state LINUX_BACKPORT(pci_disable_link_state) +++ +++#endif +++ ++ #endif /* _BACKPORT_LINUX_PCI_H */ +diff --git a/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch +new file mode 100644 +index 0000000000..c486b2251b +--- /dev/null ++++ b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch +@@ -0,0 +1,44 @@ ++From: David Bauer ++Date: Mon, 16 Dec 2019 20:47:06 +0100 ++Subject: [PATCH] rt2x00: add throughput LED trigger ++ ++This adds a (currently missing) throughput LED trigger for the rt2x00 ++driver. Previously, LED triggers had to be assigned to the netdev, which ++was limited to a single VAP. ++ ++Signed-off-by: David Bauer ++Tested-by: Christoph Krapp ++ ++--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++@@ -1140,6 +1140,19 @@ static void rt2x00lib_remove_hw(struct r ++ kfree(rt2x00dev->spec.channels_info); ++ } ++ +++static const struct ieee80211_tpt_blink rt2x00_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 }, +++}; +++ ++ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) ++ { ++ struct hw_mode_spec *spec = &rt2x00dev->spec; ++@@ -1222,6 +1235,10 @@ static int rt2x00lib_probe_hw(struct rt2 ++ ++ #undef RT2X00_TASKLET_INIT ++ +++ ieee80211_create_tpt_led_trigger(rt2x00dev->hw, +++ IEEE80211_TPT_LEDTRIG_FL_RADIO, rt2x00_tpt_blink, +++ ARRAY_SIZE(rt2x00_tpt_blink)); +++ ++ /* ++ * Register HW. ++ */ +diff --git a/package/kernel/mac80211/patches/subsys/368-cfg80211-add-local-BSS-receive-time-to-survey-inform.patch b/package/kernel/mac80211/patches/subsys/368-cfg80211-add-local-BSS-receive-time-to-survey-inform.patch +new file mode 100644 +index 0000000000..e6d384784e +--- /dev/null ++++ b/package/kernel/mac80211/patches/subsys/368-cfg80211-add-local-BSS-receive-time-to-survey-inform.patch +@@ -0,0 +1,77 @@ ++From: Felix Fietkau ++Date: Wed, 28 Aug 2019 12:13:55 +0200 ++Subject: [PATCH] cfg80211: add local BSS receive time to survey information ++ ++This is useful for checking how much airtime is being used up by other ++transmissions on the channel, e.g. by calculating (time_rx - time_bss_rx) ++or (time_busy - time_bss_rx - time_tx) ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/include/net/cfg80211.h +++++ b/include/net/cfg80211.h ++@@ -668,6 +668,7 @@ ieee80211_chandef_max_power(struct cfg80 ++ * @SURVEY_INFO_TIME_RX: receive time was filled in ++ * @SURVEY_INFO_TIME_TX: transmit time was filled in ++ * @SURVEY_INFO_TIME_SCAN: scan time was filled in +++ * @SURVEY_INFO_TIME_BSS_RX: local BSS receive time was filled in ++ * ++ * Used by the driver to indicate which info in &struct survey_info ++ * it has filled in during the get_survey(). ++@@ -681,6 +682,7 @@ enum survey_info_flags { ++ SURVEY_INFO_TIME_RX = BIT(5), ++ SURVEY_INFO_TIME_TX = BIT(6), ++ SURVEY_INFO_TIME_SCAN = BIT(7), +++ SURVEY_INFO_TIME_BSS_RX = BIT(8), ++ }; ++ ++ /** ++@@ -697,6 +699,7 @@ enum survey_info_flags { ++ * @time_rx: amount of time the radio spent receiving data ++ * @time_tx: amount of time the radio spent transmitting data ++ * @time_scan: amount of time the radio spent for scanning +++ * @time_bss_rx: amount of time the radio spent receiving data on a local BSS ++ * ++ * Used by dump_survey() to report back per-channel survey information. ++ * ++@@ -711,6 +714,7 @@ struct survey_info { ++ u64 time_rx; ++ u64 time_tx; ++ u64 time_scan; +++ u64 time_bss_rx; ++ u32 filled; ++ s8 noise; ++ }; ++--- a/include/uapi/linux/nl80211.h +++++ b/include/uapi/linux/nl80211.h ++@@ -3693,6 +3693,8 @@ enum nl80211_user_reg_hint_type { ++ * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan ++ * (on this channel or globally) ++ * @NL80211_SURVEY_INFO_PAD: attribute used for padding for 64-bit alignment +++ * @NL80211_SURVEY_INFO_TIME_BSS_RX: amount of time the radio spent +++ * receiving local BSS data ++ * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number ++ * currently defined ++ * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use ++@@ -3709,6 +3711,7 @@ enum nl80211_survey_info { ++ NL80211_SURVEY_INFO_TIME_TX, ++ NL80211_SURVEY_INFO_TIME_SCAN, ++ NL80211_SURVEY_INFO_PAD, +++ NL80211_SURVEY_INFO_TIME_BSS_RX, ++ ++ /* keep last */ ++ __NL80211_SURVEY_INFO_AFTER_LAST, ++--- a/net/wireless/nl80211.c +++++ b/net/wireless/nl80211.c ++@@ -8367,6 +8367,10 @@ static int nl80211_send_survey(struct sk ++ nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN, ++ survey->time_scan, NL80211_SURVEY_INFO_PAD)) ++ goto nla_put_failure; +++ if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) && +++ nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX, +++ survey->time_bss_rx, NL80211_SURVEY_INFO_PAD)) +++ goto nla_put_failure; ++ ++ nla_nest_end(msg, infoattr); ++ +diff --git a/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch +index 81007b87cc..cf4fdc13e9 100644 +--- a/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch ++++ b/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch +@@ -1,6 +1,6 @@ + --- a/include/net/cfg80211.h + +++ b/include/net/cfg80211.h +-@@ -2968,6 +2968,7 @@ struct cfg80211_external_auth_params { ++@@ -2972,6 +2972,7 @@ struct cfg80211_external_auth_params { + * (as advertised by the nl80211 feature flag.) + * @get_tx_power: store the current TX power into the dbm variable; + * return 0 if successful +@@ -8,7 +8,7 @@ + * + * @set_wds_peer: set the WDS peer for a WDS interface + * +-@@ -3268,6 +3269,7 @@ struct cfg80211_ops { ++@@ -3272,6 +3273,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); +diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile +index db0bf04d0a..921c32c56b 100644 +--- a/package/kernel/mt76/Makefile ++++ b/package/kernel/mt76/Makefile +@@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= + + PKG_SOURCE_URL:=https://github.com/openwrt/mt76 + PKG_SOURCE_PROTO:=git +-PKG_SOURCE_DATE:=2019-08-22 +-PKG_SOURCE_VERSION:=2a0edbb4473b71dfaa4756f7189abf6cb7f7be8b +-PKG_MIRROR_HASH:=a37975c179b929716c40d19fdcd5b131386d7f497eb8cd5d848be74e76d50d21 ++PKG_SOURCE_DATE:=2020-03-10 ++PKG_SOURCE_VERSION:=08054d5ab1350fcb8563feb90e6ab7f8f4a0a1b7 ++PKG_MIRROR_HASH:=b41a3cab1485c68befb1dcb4c1e426d41705db1b2a57851dafd6e8f75eeea3d7 + + PKG_MAINTAINER:=Felix Fietkau + PKG_BUILD_PARALLEL:=1 +@@ -246,12 +246,12 @@ define KernelPackage/mt7603/install + endef + + define KernelPackage/mt7615e/install +- $(INSTALL_DIR) $(1)/lib/firmware ++ $(INSTALL_DIR) $(1)/lib/firmware/mediatek + cp \ + $(PKG_BUILD_DIR)/firmware/mt7615_cr4.bin \ + $(PKG_BUILD_DIR)/firmware/mt7615_n9.bin \ + $(PKG_BUILD_DIR)/firmware/mt7615_rom_patch.bin \ +- $(1)/lib/firmware ++ $(1)/lib/firmware/mediatek + endef + + $(eval $(call KernelPackage,mt76-core)) +@@ -266,4 +266,4 @@ $(eval $(call KernelPackage,mt76x2u)) + $(eval $(call KernelPackage,mt76x2)) + $(eval $(call KernelPackage,mt7603)) + $(eval $(call KernelPackage,mt7615e)) +-$(eval $(call KernelPackage,mt76)) ++$(eval $(call KernelPackage,mt76)) +\ No newline at end of file +diff --git a/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po b/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po +index 86a01d9b55..b462b053e7 100644 +--- a/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po ++++ b/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po +@@ -91,6 +91,9 @@ msgstr "更新失败!" + msgid "No new data!" + msgstr "你已经是最新数据,无需更新!" + ++msgid "Total Records:" ++msgstr "新的总纪录数:" ++ + msgid "Delete All Subscribe Rules" + msgstr "清空所有订阅的规则库" + +diff --git a/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot b/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot +index 934477d415..aba2fce12a 100755 +--- a/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot ++++ b/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot +@@ -19,10 +19,12 @@ run_reboot() + week="*" + fi + sed -i '/reboot/d' /etc/crontabs/root >/dev/null 2>&1 ++ /etc/init.d/cron restart + echo "$minute $hour * * $week sleep 5 && touch /etc/banner && reboot" >> /etc/crontabs/root + echo "Auto REBOOT has started." + else + sed -i '/reboot/d' /etc/crontabs/root >/dev/null 2>&1 ++ /etc/init.d/cron restart + echo "Auto REBOOT has started." + fi + } +diff --git a/package/lean/luci-app-nps/po/zh-cn/nps.po b/package/lean/luci-app-nps/po/zh-cn/nps.po +index 4fb9ad411e..3891bc0c89 100644 +--- a/package/lean/luci-app-nps/po/zh-cn/nps.po ++++ b/package/lean/luci-app-nps/po/zh-cn/nps.po +@@ -26,4 +26,19 @@ msgid "Nps is running." + msgstr "Nps 运行中" + + msgid "Nps is not running." +-msgstr "Nps 未运行" +\ No newline at end of file ++msgstr "Nps 未运行" ++ ++msgid "Basic Setting" ++msgstr "基本设置" ++ ++msgid "Protocol Type" ++msgstr "协议类型" ++ ++msgid "Server" ++msgstr "服务端地址" ++ ++msgid "TCP Protocol" ++msgstr "TCP" ++ ++msgid "KCP Protocol" ++msgstr "KCP" +diff --git a/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm b/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm +index 67aad5f534..778de53bf2 100644 +--- a/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm ++++ b/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm +@@ -221,7 +221,7 @@ + var others = serverPart[1].split('?'); + var port = others[0] + var queryParam = {} +- if(others.length > 0) { ++ if(others.length > 1) { + var queryParams = others[1] + var queryArray = queryParams.split('&') + for (i = 0; i < queryArray.length; i++) { +diff --git a/package/lean/npc/Makefile b/package/lean/npc/Makefile +index e3b3527868..bb97ff1f91 100644 +--- a/package/lean/npc/Makefile ++++ b/package/lean/npc/Makefile +@@ -7,7 +7,7 @@ + include $(TOPDIR)/rules.mk + + PKG_NAME:=npc +-PKG_VERSION:=0.26.4 ++PKG_VERSION:=0.26.5 + PKG_RELEASE:=2 + + ifeq ($(ARCH),mipsel) +diff --git a/package/libs/openssl/Config.in b/package/libs/openssl/Config.in +index 42d3845081..ecfd2834b6 100644 +--- a/package/libs/openssl/Config.in ++++ b/package/libs/openssl/Config.in +@@ -38,7 +38,7 @@ config OPENSSL_WITH_ASM + + config OPENSSL_WITH_SSE2 + bool +- default y if !TARGET_x86_legacy && !TARGET_x86_geode ++ default y if x86_64 || i386 && !TARGET_x86_legacy + prompt "Enable use of x86 SSE2 instructions" + depends on OPENSSL_WITH_ASM && x86_64 || i386 + help +@@ -248,6 +248,7 @@ config OPENSSL_ENGINE + + config OPENSSL_ENGINE_BUILTIN + bool "Build chosen engines into libcrypto" ++ default y + depends on OPENSSL_ENGINE + help + This builds all chosen engines into libcrypto.so, instead of building +@@ -257,6 +258,7 @@ config OPENSSL_ENGINE_BUILTIN + + config OPENSSL_ENGINE_BUILTIN_AFALG + bool ++ default y + prompt "Acceleration support through AF_ALG sockets engine" + depends on OPENSSL_ENGINE_BUILTIN && KERNEL_AIO + select PACKAGE_libopenssl-conf +diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile +index 627f2bf62f..5c154a9054 100644 +--- a/package/libs/openssl/Makefile ++++ b/package/libs/openssl/Makefile +@@ -11,7 +11,7 @@ PKG_NAME:=openssl + PKG_BASE:=1.1.1 + PKG_BUGFIX:=e-dev + PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX) +-PKG_RELEASE:=1 ++PKG_RELEASE:=2 + + PKG_SOURCE_PROTO:=git + PKG_SOURCE_URL:=https://github.com/openssl/openssl.git +diff --git a/target/linux/generic/backport-4.14/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch b/target/linux/generic/backport-4.14/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch +new file mode 100644 +index 0000000000..ba0d137096 +--- /dev/null ++++ b/target/linux/generic/backport-4.14/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch +@@ -0,0 +1,71 @@ ++From 82afdcd4ec3c8ca6551cbf7c43c09e2fd240487a Mon Sep 17 00:00:00 2001 ++From: Hangbin Liu ++Date: Tue, 10 Mar 2020 15:27:37 +0800 ++Subject: [PATCH] ipv6/addrconf: call ipv6_mc_up() for non-Ethernet interface ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Rafał found an issue that for non-Ethernet interface, if we down and up ++frequently, the memory will be consumed slowly. ++ ++The reason is we add allnodes/allrouters addressed in multicast list in ++ipv6_add_dev(). When link down, we call ipv6_mc_down(), store all multicast ++addresses via mld_add_delrec(). But when link up, we don't call ipv6_mc_up() ++for non-Ethernet interface to remove the addresses. This makes idev->mc_tomb ++getting bigger and bigger. The call stack looks like: ++ ++addrconf_notify(NETDEV_REGISTER) ++ ipv6_add_dev ++ ipv6_dev_mc_inc(ff01::1) ++ ipv6_dev_mc_inc(ff02::1) ++ ipv6_dev_mc_inc(ff02::2) ++ ++addrconf_notify(NETDEV_UP) ++ addrconf_dev_config ++ /* Alas, we support only Ethernet autoconfiguration. */ ++ return; ++ ++addrconf_notify(NETDEV_DOWN) ++ addrconf_ifdown ++ ipv6_mc_down ++ igmp6_group_dropped(ff02::2) ++ mld_add_delrec(ff02::2) ++ igmp6_group_dropped(ff02::1) ++ igmp6_group_dropped(ff01::1) ++ ++After investigating, I can't found a rule to disable multicast on ++non-Ethernet interface. In RFC2460, the link could be Ethernet, PPP, ATM, ++tunnels, etc. In IPv4, it doesn't check the dev type when calls ip_mc_up() ++in inetdev_event(). Even for IPv6, we don't check the dev type and call ++ipv6_add_dev(), ipv6_dev_mc_inc() after register device. ++ ++So I think it's OK to fix this memory consumer by calling ipv6_mc_up() for ++non-Ethernet interface. ++ ++v2: Also check IFF_MULTICAST flag to make sure the interface supports ++ multicast ++ ++Reported-by: Rafał Miłecki ++Tested-by: Rafał Miłecki ++Fixes: 74235a25c673 ("[IPV6] addrconf: Fix IPv6 on tuntap tunnels") ++Fixes: 1666d49e1d41 ("mld: do not remove mld souce list info when set link down") ++Signed-off-by: Hangbin Liu ++Signed-off-by: David S. Miller ++--- ++ net/ipv6/addrconf.c | 4 ++++ ++ 1 file changed, 4 insertions(+) ++ ++--- a/net/ipv6/addrconf.c +++++ b/net/ipv6/addrconf.c ++@@ -3223,6 +3223,10 @@ static void addrconf_dev_config(struct n ++ (dev->type != ARPHRD_TUNNEL) && ++ (dev->type != ARPHRD_NONE)) { ++ /* Alas, we support only Ethernet autoconfiguration. */ +++ idev = __in6_dev_get(dev); +++ if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP && +++ dev->flags & IFF_MULTICAST) +++ ipv6_mc_up(idev); ++ return; ++ } ++ +diff --git a/target/linux/generic/backport-4.19/410-mtd-fix-calculating-partition-end-address.patch b/target/linux/generic/backport-4.19/410-mtd-fix-calculating-partition-end-address.patch +new file mode 100644 +index 0000000000..4027bfd714 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/410-mtd-fix-calculating-partition-end-address.patch +@@ -0,0 +1,28 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Mon, 9 Mar 2020 08:30:19 +0100 ++Subject: [PATCH] mtd: fix calculating partition end address ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This fixes check for partitions that don't start at beginning of their ++parents. Missing partition's offset in formula could result in forcing ++read-only incorrectly. ++ ++Fixes: 6750f61a13a0 ("mtd: improve calculating partition boundaries when checking for alignment") ++Signed-off-by: Rafał Miłecki ++--- ++ drivers/mtd/mtdpart.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/drivers/mtd/mtdpart.c +++++ b/drivers/mtd/mtdpart.c ++@@ -538,7 +538,7 @@ static struct mtd_part *allocate_partiti ++ part->name); ++ } ++ ++- tmp = part_absolute_offset(parent) + slave->mtd.size; +++ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; ++ remainder = do_div(tmp, wr_alignment); ++ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { ++ slave->mtd.flags &= ~MTD_WRITEABLE; +diff --git a/target/linux/generic/backport-4.19/464-v5.6-mtd-spi-nor-Add-4B_OPCODES-flag-to-w25q256.patch b/target/linux/generic/backport-4.19/464-v5.6-mtd-spi-nor-Add-4B_OPCODES-flag-to-w25q256.patch +new file mode 100644 +index 0000000000..db9f379c81 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/464-v5.6-mtd-spi-nor-Add-4B_OPCODES-flag-to-w25q256.patch +@@ -0,0 +1,27 @@ ++From 10050a02f7d508fa88f70fcfceefbacd13488ca7 Mon Sep 17 00:00:00 2001 ++From: Robert Marko ++Date: Mon, 23 Dec 2019 17:05:49 +0200 ++Subject: [PATCH] mtd: spi-nor: Add 4B_OPCODES flag to w25q256 ++ ++The w25q256 supports 4-byte opcodes so lets add the flag. ++Tested on OpenWrt under 4.19.82 kernel on 8devices Habanero. ++ ++Signed-off-by: Robert Marko ++Signed-off-by: Tudor Ambarus ++--- ++ drivers/mtd/spi-nor/spi-nor.c | 4 +++- ++ 1 file changed, 3 insertions(+), 1 deletion(-) ++ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1244,7 +1244,9 @@ static const struct flash_info spi_nor_i ++ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, ++ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, ++ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, ++- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, +++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | +++ SPI_NOR_4B_OPCODES) }, ++ { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, ++ +diff --git a/target/linux/generic/backport-4.19/499-v4.22-iio-add-IIO_MASSCONCENTRATION-channel-type.patch b/target/linux/generic/backport-4.19/499-v4.22-iio-add-IIO_MASSCONCENTRATION-channel-type.patch +new file mode 100644 +index 0000000000..bceb735146 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/499-v4.22-iio-add-IIO_MASSCONCENTRATION-channel-type.patch +@@ -0,0 +1,136 @@ ++From 17abc9ec68b73ddeb262a507a62421016b9c54d5 Mon Sep 17 00:00:00 2001 ++From: Tomasz Duszynski ++Date: Fri, 14 Dec 2018 19:28:01 +0100 ++Subject: [PATCH] iio: add IIO_MASSCONCENTRATION channel type ++ ++Measuring particulate matter in ug / m3 (micro-grams per cubic meter) ++is de facto standard. Existing air quality sensors usually follow ++this convention and are capable of returning measurements using ++this unit. ++ ++IIO currently does not offer suitable channel type for this ++type of measurements hence this patch adds this. ++ ++In addition, extra modifiers are introduced used for distinguishing ++between fine pm1, pm2p5 and coarse pm4, pm10 particle measurements, i.e ++IIO_MOD_PM1, IIO_MOD_PM25 and IIO_MOD_PM4, IIO_MOD_PM10. ++ ++pmX consists of particles with aerodynamic diameter less or equal to ++X micrometers. ++ ++Signed-off-by: Tomasz Duszynski ++Acked-by: Matt Ranostay ++Signed-off-by: Jonathan Cameron ++--- ++ Documentation/ABI/testing/sysfs-bus-iio | 17 ++++++++++++++++- ++ drivers/iio/industrialio-core.c | 5 +++++ ++ include/uapi/linux/iio/types.h | 5 +++++ ++ tools/iio/iio_event_monitor.c | 10 ++++++++++ ++ 4 files changed, 36 insertions(+), 1 deletion(-) ++ ++--- a/Documentation/ABI/testing/sysfs-bus-iio +++++ b/Documentation/ABI/testing/sysfs-bus-iio ++@@ -1684,4 +1684,19 @@ KernelVersion: 4.18 ++ Contact: linux-iio@vger.kernel.org ++ Description: ++ Raw (unscaled) phase difference reading from channel Y ++- that can be processed to radians. ++\ No newline at end of file +++ that can be processed to radians. +++ +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm1_input +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm1_input +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm2p5_input +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm2p5_input +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm4_input +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm4_input +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm10_input +++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm10_input +++KernelVersion: 4.22 +++Contact: linux-iio@vger.kernel.org +++Description: +++ Mass concentration reading of particulate matter in ug / m3. +++ pmX consists of particles with aerodynamic diameter less or +++ equal to X micrometers. ++--- a/drivers/iio/industrialio-core.c +++++ b/drivers/iio/industrialio-core.c ++@@ -87,6 +87,7 @@ static const char * const iio_chan_type_ ++ [IIO_GRAVITY] = "gravity", ++ [IIO_POSITIONRELATIVE] = "positionrelative", ++ [IIO_PHASE] = "phase", +++ [IIO_MASSCONCENTRATION] = "massconcentration", ++ }; ++ ++ static const char * const iio_modifier_names[] = { ++@@ -127,6 +128,10 @@ static const char * const iio_modifier_n ++ [IIO_MOD_Q] = "q", ++ [IIO_MOD_CO2] = "co2", ++ [IIO_MOD_VOC] = "voc", +++ [IIO_MOD_PM1] = "pm1", +++ [IIO_MOD_PM2P5] = "pm2p5", +++ [IIO_MOD_PM4] = "pm4", +++ [IIO_MOD_PM10] = "pm10", ++ }; ++ ++ /* relies on pairs of these shared then separate */ ++--- a/include/uapi/linux/iio/types.h +++++ b/include/uapi/linux/iio/types.h ++@@ -46,6 +46,7 @@ enum iio_chan_type { ++ IIO_GRAVITY, ++ IIO_POSITIONRELATIVE, ++ IIO_PHASE, +++ IIO_MASSCONCENTRATION, ++ }; ++ ++ enum iio_modifier { ++@@ -87,6 +88,10 @@ enum iio_modifier { ++ IIO_MOD_VOC, ++ IIO_MOD_LIGHT_UV, ++ IIO_MOD_LIGHT_DUV, +++ IIO_MOD_PM1, +++ IIO_MOD_PM2P5, +++ IIO_MOD_PM4, +++ IIO_MOD_PM10, ++ }; ++ ++ enum iio_event_type { ++--- a/tools/iio/iio_event_monitor.c +++++ b/tools/iio/iio_event_monitor.c ++@@ -60,6 +60,7 @@ static const char * const iio_chan_type_ ++ [IIO_GRAVITY] = "gravity", ++ [IIO_POSITIONRELATIVE] = "positionrelative", ++ [IIO_PHASE] = "phase", +++ [IIO_MASSCONCENTRATION] = "massconcentration", ++ }; ++ ++ static const char * const iio_ev_type_text[] = { ++@@ -115,6 +116,10 @@ static const char * const iio_modifier_n ++ [IIO_MOD_Q] = "q", ++ [IIO_MOD_CO2] = "co2", ++ [IIO_MOD_VOC] = "voc", +++ [IIO_MOD_PM1] = "pm1", +++ [IIO_MOD_PM2P5] = "pm2p5", +++ [IIO_MOD_PM4] = "pm4", +++ [IIO_MOD_PM10] = "pm10", ++ }; ++ ++ static bool event_is_known(struct iio_event_data *event) ++@@ -156,6 +161,7 @@ static bool event_is_known(struct iio_ev ++ case IIO_GRAVITY: ++ case IIO_POSITIONRELATIVE: ++ case IIO_PHASE: +++ case IIO_MASSCONCENTRATION: ++ break; ++ default: ++ return false; ++@@ -200,6 +206,10 @@ static bool event_is_known(struct iio_ev ++ case IIO_MOD_Q: ++ case IIO_MOD_CO2: ++ case IIO_MOD_VOC: +++ case IIO_MOD_PM1: +++ case IIO_MOD_PM2P5: +++ case IIO_MOD_PM4: +++ case IIO_MOD_PM10: ++ break; ++ default: ++ return false; +diff --git a/target/linux/generic/backport-4.19/500-v5.1-iio-chemical-add-support-for-Sensirion-SPS30-sensor.patch b/target/linux/generic/backport-4.19/500-v5.1-iio-chemical-add-support-for-Sensirion-SPS30-sensor.patch +new file mode 100644 +index 0000000000..d30c7c3cc1 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/500-v5.1-iio-chemical-add-support-for-Sensirion-SPS30-sensor.patch +@@ -0,0 +1,454 @@ ++From 232e0f6ddeaee104d64675fe7d0cc142cf955f35 Mon Sep 17 00:00:00 2001 ++From: Tomasz Duszynski ++Date: Fri, 14 Dec 2018 19:28:02 +0100 ++Subject: [PATCH] iio: chemical: add support for Sensirion SPS30 sensor ++ ++Add support for Sensirion SPS30 particulate matter sensor. ++ ++Signed-off-by: Tomasz Duszynski ++Signed-off-by: Jonathan Cameron ++--- ++ drivers/iio/chemical/Kconfig | 11 + ++ drivers/iio/chemical/Makefile | 1 + ++ drivers/iio/chemical/sps30.c | 407 ++++++++++++++++++++++++++++++++++ ++ 3 files changed, 419 insertions(+) ++ create mode 100644 drivers/iio/chemical/sps30.c ++ ++--- a/drivers/iio/chemical/Kconfig +++++ b/drivers/iio/chemical/Kconfig ++@@ -61,6 +61,17 @@ config IAQCORE ++ iAQ-Core Continuous/Pulsed VOC (Volatile Organic Compounds) ++ sensors ++ +++config SPS30 +++ tristate "SPS30 particulate matter sensor" +++ depends on I2C +++ select CRC8 +++ help +++ Say Y here to build support for the Sensirion SPS30 particulate +++ matter sensor. +++ +++ To compile this driver as a module, choose M here: the module will +++ be called sps30. +++ ++ config VZ89X ++ tristate "SGX Sensortech MiCS VZ89X VOC sensor" ++ depends on I2C ++--- a/drivers/iio/chemical/Makefile +++++ b/drivers/iio/chemical/Makefile ++@@ -9,4 +9,5 @@ obj-$(CONFIG_BME680_I2C) += bme680_i2c.o ++ obj-$(CONFIG_BME680_SPI) += bme680_spi.o ++ obj-$(CONFIG_CCS811) += ccs811.o ++ obj-$(CONFIG_IAQCORE) += ams-iaq-core.o +++obj-$(CONFIG_SPS30) += sps30.o ++ obj-$(CONFIG_VZ89X) += vz89x.o ++--- /dev/null +++++ b/drivers/iio/chemical/sps30.c ++@@ -0,0 +1,407 @@ +++// SPDX-License-Identifier: GPL-2.0 +++/* +++ * Sensirion SPS30 particulate matter sensor driver +++ * +++ * Copyright (c) Tomasz Duszynski +++ * +++ * I2C slave address: 0x69 +++ * +++ * TODO: +++ * - support for turning on fan cleaning +++ * - support for reading/setting auto cleaning interval +++ */ +++ +++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +++ +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++#include +++ +++#define SPS30_CRC8_POLYNOMIAL 0x31 +++/* max number of bytes needed to store PM measurements or serial string */ +++#define SPS30_MAX_READ_SIZE 48 +++/* sensor measures reliably up to 3000 ug / m3 */ +++#define SPS30_MAX_PM 3000 +++ +++/* SPS30 commands */ +++#define SPS30_START_MEAS 0x0010 +++#define SPS30_STOP_MEAS 0x0104 +++#define SPS30_RESET 0xd304 +++#define SPS30_READ_DATA_READY_FLAG 0x0202 +++#define SPS30_READ_DATA 0x0300 +++#define SPS30_READ_SERIAL 0xd033 +++ +++enum { +++ PM1, +++ PM2P5, +++ PM4, +++ PM10, +++}; +++ +++struct sps30_state { +++ struct i2c_client *client; +++ /* +++ * Guards against concurrent access to sensor registers. +++ * Must be held whenever sequence of commands is to be executed. +++ */ +++ struct mutex lock; +++}; +++ +++DECLARE_CRC8_TABLE(sps30_crc8_table); +++ +++static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf, +++ int txsize, u8 *rxbuf, int rxsize) +++{ +++ int ret; +++ +++ /* +++ * Sensor does not support repeated start so instead of +++ * sending two i2c messages in a row we just send one by one. +++ */ +++ ret = i2c_master_send(state->client, txbuf, txsize); +++ if (ret != txsize) +++ return ret < 0 ? ret : -EIO; +++ +++ if (!rxbuf) +++ return 0; +++ +++ ret = i2c_master_recv(state->client, rxbuf, rxsize); +++ if (ret != rxsize) +++ return ret < 0 ? ret : -EIO; +++ +++ return 0; +++} +++ +++static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) +++{ +++ /* +++ * Internally sensor stores measurements in a following manner: +++ * +++ * PM1: upper two bytes, crc8, lower two bytes, crc8 +++ * PM2P5: upper two bytes, crc8, lower two bytes, crc8 +++ * PM4: upper two bytes, crc8, lower two bytes, crc8 +++ * PM10: upper two bytes, crc8, lower two bytes, crc8 +++ * +++ * What follows next are number concentration measurements and +++ * typical particle size measurement which we omit. +++ */ +++ u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd }; +++ int i, ret = 0; +++ +++ switch (cmd) { +++ case SPS30_START_MEAS: +++ buf[2] = 0x03; +++ buf[3] = 0x00; +++ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); +++ ret = sps30_write_then_read(state, buf, 5, NULL, 0); +++ break; +++ case SPS30_STOP_MEAS: +++ case SPS30_RESET: +++ ret = sps30_write_then_read(state, buf, 2, NULL, 0); +++ break; +++ case SPS30_READ_DATA_READY_FLAG: +++ case SPS30_READ_DATA: +++ case SPS30_READ_SERIAL: +++ /* every two data bytes are checksummed */ +++ size += size / 2; +++ ret = sps30_write_then_read(state, buf, 2, buf, size); +++ break; +++ } +++ +++ if (ret) +++ return ret; +++ +++ /* validate received data and strip off crc bytes */ +++ for (i = 0; i < size; i += 3) { +++ u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE); +++ +++ if (crc != buf[i + 2]) { +++ dev_err(&state->client->dev, +++ "data integrity check failed\n"); +++ return -EIO; +++ } +++ +++ *data++ = buf[i]; +++ *data++ = buf[i + 1]; +++ } +++ +++ return 0; +++} +++ +++static s32 sps30_float_to_int_clamped(const u8 *fp) +++{ +++ int val = get_unaligned_be32(fp); +++ int mantissa = val & GENMASK(22, 0); +++ /* this is fine since passed float is always non-negative */ +++ int exp = val >> 23; +++ int fraction, shift; +++ +++ /* special case 0 */ +++ if (!exp && !mantissa) +++ return 0; +++ +++ exp -= 127; +++ if (exp < 0) { +++ /* return values ranging from 1 to 99 */ +++ return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp); +++ } +++ +++ /* return values ranging from 100 to 300000 */ +++ shift = 23 - exp; +++ val = (1 << exp) + (mantissa >> shift); +++ if (val >= SPS30_MAX_PM) +++ return SPS30_MAX_PM * 100; +++ +++ fraction = mantissa & GENMASK(shift - 1, 0); +++ +++ return val * 100 + ((fraction * 100) >> shift); +++} +++ +++static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) +++{ +++ int i, ret, tries = 5; +++ u8 tmp[16]; +++ +++ while (tries--) { +++ ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); +++ if (ret) +++ return -EIO; +++ +++ /* new measurements ready to be read */ +++ if (tmp[1] == 1) +++ break; +++ +++ msleep_interruptible(300); +++ } +++ +++ if (!tries) +++ return -ETIMEDOUT; +++ +++ ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); +++ if (ret) +++ return ret; +++ +++ for (i = 0; i < size; i++) +++ data[i] = sps30_float_to_int_clamped(&tmp[4 * i]); +++ +++ return 0; +++} +++ +++static irqreturn_t sps30_trigger_handler(int irq, void *p) +++{ +++ struct iio_poll_func *pf = p; +++ struct iio_dev *indio_dev = pf->indio_dev; +++ struct sps30_state *state = iio_priv(indio_dev); +++ int ret; +++ s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */ +++ +++ mutex_lock(&state->lock); +++ ret = sps30_do_meas(state, data, 4); +++ mutex_unlock(&state->lock); +++ if (ret) +++ goto err; +++ +++ iio_push_to_buffers_with_timestamp(indio_dev, data, +++ iio_get_time_ns(indio_dev)); +++err: +++ iio_trigger_notify_done(indio_dev->trig); +++ +++ return IRQ_HANDLED; +++} +++ +++static int sps30_read_raw(struct iio_dev *indio_dev, +++ struct iio_chan_spec const *chan, +++ int *val, int *val2, long mask) +++{ +++ struct sps30_state *state = iio_priv(indio_dev); +++ int data[4], ret = -EINVAL; +++ +++ switch (mask) { +++ case IIO_CHAN_INFO_PROCESSED: +++ switch (chan->type) { +++ case IIO_MASSCONCENTRATION: +++ mutex_lock(&state->lock); +++ /* read up to the number of bytes actually needed */ +++ switch (chan->channel2) { +++ case IIO_MOD_PM1: +++ ret = sps30_do_meas(state, data, 1); +++ break; +++ case IIO_MOD_PM2P5: +++ ret = sps30_do_meas(state, data, 2); +++ break; +++ case IIO_MOD_PM4: +++ ret = sps30_do_meas(state, data, 3); +++ break; +++ case IIO_MOD_PM10: +++ ret = sps30_do_meas(state, data, 4); +++ break; +++ } +++ mutex_unlock(&state->lock); +++ if (ret) +++ return ret; +++ +++ *val = data[chan->address] / 100; +++ *val2 = (data[chan->address] % 100) * 10000; +++ +++ return IIO_VAL_INT_PLUS_MICRO; +++ default: +++ return -EINVAL; +++ } +++ case IIO_CHAN_INFO_SCALE: +++ switch (chan->type) { +++ case IIO_MASSCONCENTRATION: +++ switch (chan->channel2) { +++ case IIO_MOD_PM1: +++ case IIO_MOD_PM2P5: +++ case IIO_MOD_PM4: +++ case IIO_MOD_PM10: +++ *val = 0; +++ *val2 = 10000; +++ +++ return IIO_VAL_INT_PLUS_MICRO; +++ } +++ default: +++ return -EINVAL; +++ } +++ } +++ +++ return -EINVAL; +++} +++ +++static const struct iio_info sps30_info = { +++ .read_raw = sps30_read_raw, +++}; +++ +++#define SPS30_CHAN(_index, _mod) { \ +++ .type = IIO_MASSCONCENTRATION, \ +++ .modified = 1, \ +++ .channel2 = IIO_MOD_ ## _mod, \ +++ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ +++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +++ .address = _mod, \ +++ .scan_index = _index, \ +++ .scan_type = { \ +++ .sign = 'u', \ +++ .realbits = 19, \ +++ .storagebits = 32, \ +++ .endianness = IIO_CPU, \ +++ }, \ +++} +++ +++static const struct iio_chan_spec sps30_channels[] = { +++ SPS30_CHAN(0, PM1), +++ SPS30_CHAN(1, PM2P5), +++ SPS30_CHAN(2, PM4), +++ SPS30_CHAN(3, PM10), +++ IIO_CHAN_SOFT_TIMESTAMP(4), +++}; +++ +++static void sps30_stop_meas(void *data) +++{ +++ struct sps30_state *state = data; +++ +++ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); +++} +++ +++static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; +++ +++static int sps30_probe(struct i2c_client *client) +++{ +++ struct iio_dev *indio_dev; +++ struct sps30_state *state; +++ u8 buf[32]; +++ int ret; +++ +++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) +++ return -EOPNOTSUPP; +++ +++ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state)); +++ if (!indio_dev) +++ return -ENOMEM; +++ +++ state = iio_priv(indio_dev); +++ i2c_set_clientdata(client, indio_dev); +++ state->client = client; +++ indio_dev->dev.parent = &client->dev; +++ indio_dev->info = &sps30_info; +++ indio_dev->name = client->name; +++ indio_dev->channels = sps30_channels; +++ indio_dev->num_channels = ARRAY_SIZE(sps30_channels); +++ indio_dev->modes = INDIO_DIRECT_MODE; +++ indio_dev->available_scan_masks = sps30_scan_masks; +++ +++ mutex_init(&state->lock); +++ crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); +++ +++ ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); +++ if (ret) { +++ dev_err(&client->dev, "failed to reset device\n"); +++ return ret; +++ } +++ msleep(300); +++ /* +++ * Power-on-reset causes sensor to produce some glitch on i2c bus and +++ * some controllers end up in error state. Recover simply by placing +++ * some data on the bus, for example STOP_MEAS command, which +++ * is NOP in this case. +++ */ +++ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); +++ +++ ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); +++ if (ret) { +++ dev_err(&client->dev, "failed to read serial number\n"); +++ return ret; +++ } +++ /* returned serial number is already NUL terminated */ +++ dev_info(&client->dev, "serial number: %s\n", buf); +++ +++ ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); +++ if (ret) { +++ dev_err(&client->dev, "failed to start measurement\n"); +++ return ret; +++ } +++ +++ ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); +++ if (ret) +++ return ret; +++ +++ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, +++ sps30_trigger_handler, NULL); +++ if (ret) +++ return ret; +++ +++ return devm_iio_device_register(&client->dev, indio_dev); +++} +++ +++static const struct i2c_device_id sps30_id[] = { +++ { "sps30" }, +++ { } +++}; +++MODULE_DEVICE_TABLE(i2c, sps30_id); +++ +++static const struct of_device_id sps30_of_match[] = { +++ { .compatible = "sensirion,sps30" }, +++ { } +++}; +++MODULE_DEVICE_TABLE(of, sps30_of_match); +++ +++static struct i2c_driver sps30_driver = { +++ .driver = { +++ .name = "sps30", +++ .of_match_table = sps30_of_match, +++ }, +++ .id_table = sps30_id, +++ .probe_new = sps30_probe, +++}; +++module_i2c_driver(sps30_driver); +++ +++MODULE_AUTHOR("Tomasz Duszynski "); +++MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); +++MODULE_LICENSE("GPL v2"); +diff --git a/target/linux/generic/backport-4.19/501-v5.1-iio-chemical-sps30-add-support-for-self-cleaning.patch b/target/linux/generic/backport-4.19/501-v5.1-iio-chemical-sps30-add-support-for-self-cleaning.patch +new file mode 100644 +index 0000000000..7054fb0313 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/501-v5.1-iio-chemical-sps30-add-support-for-self-cleaning.patch +@@ -0,0 +1,100 @@ ++From c546d49656143855093c7b7fde60866e6e23a69d Mon Sep 17 00:00:00 2001 ++From: Tomasz Duszynski ++Date: Tue, 18 Dec 2018 21:28:09 +0100 ++Subject: [PATCH] iio: chemical: sps30: add support for self cleaning ++ ++Self cleaning is especially useful in cases where sensor undergoes ++frequent power on/off cycles. In such scenarios it is recommended to ++turn self cleaning at least once per week in order to maintain reliable ++measurements. ++ ++Self cleaning is activated by writing 1 to a dedicated attribute. ++Internal fan accelerates to its maximum speed and keeps spinning ++for about 10 seconds blowing out accumulated dust. ++ ++Signed-off-by: Tomasz Duszynski ++Tested-by: Andreas Brauchli ++Signed-off-by: Jonathan Cameron ++--- ++ Documentation/ABI/testing/sysfs-bus-iio-sps30 | 8 +++++ ++ drivers/iio/chemical/sps30.c | 35 ++++++++++++++++++- ++ 2 files changed, 42 insertions(+), 1 deletion(-) ++ create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-sps30 ++ ++--- /dev/null +++++ b/Documentation/ABI/testing/sysfs-bus-iio-sps30 ++@@ -0,0 +1,8 @@ +++What: /sys/bus/iio/devices/iio:deviceX/start_cleaning +++Date: December 2018 +++KernelVersion: 4.22 +++Contact: linux-iio@vger.kernel.org +++Description: +++ Writing 1 starts sensor self cleaning. Internal fan accelerates +++ to its maximum speed and keeps spinning for about 10 seconds in +++ order to blow out accumulated dust. ++--- a/drivers/iio/chemical/sps30.c +++++ b/drivers/iio/chemical/sps30.c ++@@ -7,7 +7,6 @@ ++ * I2C slave address: 0x69 ++ * ++ * TODO: ++- * - support for turning on fan cleaning ++ * - support for reading/setting auto cleaning interval ++ */ ++ ++@@ -37,6 +36,7 @@ ++ #define SPS30_READ_DATA_READY_FLAG 0x0202 ++ #define SPS30_READ_DATA 0x0300 ++ #define SPS30_READ_SERIAL 0xd033 +++#define SPS30_START_FAN_CLEANING 0x5607 ++ ++ enum { ++ PM1, ++@@ -104,6 +104,7 @@ static int sps30_do_cmd(struct sps30_sta ++ break; ++ case SPS30_STOP_MEAS: ++ case SPS30_RESET: +++ case SPS30_START_FAN_CLEANING: ++ ret = sps30_write_then_read(state, buf, 2, NULL, 0); ++ break; ++ case SPS30_READ_DATA_READY_FLAG: ++@@ -275,7 +276,39 @@ static int sps30_read_raw(struct iio_dev ++ return -EINVAL; ++ } ++ +++static ssize_t start_cleaning_store(struct device *dev, +++ struct device_attribute *attr, +++ const char *buf, size_t len) +++{ +++ struct iio_dev *indio_dev = dev_to_iio_dev(dev); +++ struct sps30_state *state = iio_priv(indio_dev); +++ int val, ret; +++ +++ if (kstrtoint(buf, 0, &val) || val != 1) +++ return -EINVAL; +++ +++ mutex_lock(&state->lock); +++ ret = sps30_do_cmd(state, SPS30_START_FAN_CLEANING, NULL, 0); +++ mutex_unlock(&state->lock); +++ if (ret) +++ return ret; +++ +++ return len; +++} +++ +++static IIO_DEVICE_ATTR_WO(start_cleaning, 0); +++ +++static struct attribute *sps30_attrs[] = { +++ &iio_dev_attr_start_cleaning.dev_attr.attr, +++ NULL +++}; +++ +++static const struct attribute_group sps30_attr_group = { +++ .attrs = sps30_attrs, +++}; +++ ++ static const struct iio_info sps30_info = { +++ .attrs = &sps30_attr_group, ++ .read_raw = sps30_read_raw, ++ }; ++ +diff --git a/target/linux/generic/backport-4.19/502-v5.1-iio-chemical-sps30-allow-changing-self-cleaning-peri.patch b/target/linux/generic/backport-4.19/502-v5.1-iio-chemical-sps30-allow-changing-self-cleaning-peri.patch +new file mode 100644 +index 0000000000..3a1335ba44 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/502-v5.1-iio-chemical-sps30-allow-changing-self-cleaning-peri.patch +@@ -0,0 +1,293 @@ ++From 62129a0849d27cc94ced832bcf9dcde283dcbe08 Mon Sep 17 00:00:00 2001 ++From: Tomasz Duszynski ++Date: Tue, 15 Jan 2019 20:00:06 +0100 ++Subject: [PATCH] iio: chemical: sps30: allow changing self cleaning period ++ ++Sensor can periodically trigger self cleaning. Period can be changed by ++writing a new value to a dedicated attribute. Upon attribute read ++current period gets returned. ++ ++Signed-off-by: Tomasz Duszynski ++Signed-off-by: Jonathan Cameron ++--- ++ Documentation/ABI/testing/sysfs-bus-iio-sps30 | 20 +++ ++ drivers/iio/chemical/sps30.c | 143 +++++++++++++++--- ++ 2 files changed, 145 insertions(+), 18 deletions(-) ++ ++--- a/Documentation/ABI/testing/sysfs-bus-iio-sps30 +++++ b/Documentation/ABI/testing/sysfs-bus-iio-sps30 ++@@ -6,3 +6,23 @@ Description: ++ Writing 1 starts sensor self cleaning. Internal fan accelerates ++ to its maximum speed and keeps spinning for about 10 seconds in ++ order to blow out accumulated dust. +++ +++What: /sys/bus/iio/devices/iio:deviceX/cleaning_period +++Date: January 2019 +++KernelVersion: 5.1 +++Contact: linux-iio@vger.kernel.org +++Description: +++ Sensor is capable of triggering self cleaning periodically. +++ Period can be changed by writing a new value here. Upon reading +++ the current one is returned. Units are seconds. +++ +++ Writing 0 disables periodical self cleaning entirely. +++ +++What: /sys/bus/iio/devices/iio:deviceX/cleaning_period_available +++Date: January 2019 +++KernelVersion: 5.1 +++Contact: linux-iio@vger.kernel.org +++Description: +++ The range of available values in seconds represented as the +++ minimum value, the step and the maximum value, all enclosed in +++ square brackets. ++--- a/drivers/iio/chemical/sps30.c +++++ b/drivers/iio/chemical/sps30.c ++@@ -5,9 +5,6 @@ ++ * Copyright (c) Tomasz Duszynski ++ * ++ * I2C slave address: 0x69 ++- * ++- * TODO: ++- * - support for reading/setting auto cleaning interval ++ */ ++ ++ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++@@ -21,6 +18,7 @@ ++ #include ++ #include ++ #include +++#include ++ #include ++ ++ #define SPS30_CRC8_POLYNOMIAL 0x31 ++@@ -28,6 +26,9 @@ ++ #define SPS30_MAX_READ_SIZE 48 ++ /* sensor measures reliably up to 3000 ug / m3 */ ++ #define SPS30_MAX_PM 3000 +++/* minimum and maximum self cleaning periods in seconds */ +++#define SPS30_AUTO_CLEANING_PERIOD_MIN 0 +++#define SPS30_AUTO_CLEANING_PERIOD_MAX 604800 ++ ++ /* SPS30 commands */ ++ #define SPS30_START_MEAS 0x0010 ++@@ -37,6 +38,9 @@ ++ #define SPS30_READ_DATA 0x0300 ++ #define SPS30_READ_SERIAL 0xd033 ++ #define SPS30_START_FAN_CLEANING 0x5607 +++#define SPS30_AUTO_CLEANING_PERIOD 0x8004 +++/* not a sensor command per se, used only to distinguish write from read */ +++#define SPS30_READ_AUTO_CLEANING_PERIOD 0x8005 ++ ++ enum { ++ PM1, ++@@ -45,6 +49,11 @@ enum { ++ PM10, ++ }; ++ +++enum { +++ RESET, +++ MEASURING, +++}; +++ ++ struct sps30_state { ++ struct i2c_client *client; ++ /* ++@@ -52,6 +61,7 @@ struct sps30_state { ++ * Must be held whenever sequence of commands is to be executed. ++ */ ++ struct mutex lock; +++ int state; ++ }; ++ ++ DECLARE_CRC8_TABLE(sps30_crc8_table); ++@@ -107,6 +117,9 @@ static int sps30_do_cmd(struct sps30_sta ++ case SPS30_START_FAN_CLEANING: ++ ret = sps30_write_then_read(state, buf, 2, NULL, 0); ++ break; +++ case SPS30_READ_AUTO_CLEANING_PERIOD: +++ buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; +++ buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD; ++ case SPS30_READ_DATA_READY_FLAG: ++ case SPS30_READ_DATA: ++ case SPS30_READ_SERIAL: ++@@ -114,6 +127,15 @@ static int sps30_do_cmd(struct sps30_sta ++ size += size / 2; ++ ret = sps30_write_then_read(state, buf, 2, buf, size); ++ break; +++ case SPS30_AUTO_CLEANING_PERIOD: +++ buf[2] = data[0]; +++ buf[3] = data[1]; +++ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); +++ buf[5] = data[2]; +++ buf[6] = data[3]; +++ buf[7] = crc8(sps30_crc8_table, &buf[5], 2, CRC8_INIT_VALUE); +++ ret = sps30_write_then_read(state, buf, 8, NULL, 0); +++ break; ++ } ++ ++ if (ret) ++@@ -170,6 +192,14 @@ static int sps30_do_meas(struct sps30_st ++ int i, ret, tries = 5; ++ u8 tmp[16]; ++ +++ if (state->state == RESET) { +++ ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); +++ if (ret) +++ return ret; +++ +++ state->state = MEASURING; +++ } +++ ++ while (tries--) { ++ ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); ++ if (ret) ++@@ -276,6 +306,24 @@ static int sps30_read_raw(struct iio_dev ++ return -EINVAL; ++ } ++ +++static int sps30_do_cmd_reset(struct sps30_state *state) +++{ +++ int ret; +++ +++ ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); +++ msleep(300); +++ /* +++ * Power-on-reset causes sensor to produce some glitch on i2c bus and +++ * some controllers end up in error state. Recover simply by placing +++ * some data on the bus, for example STOP_MEAS command, which +++ * is NOP in this case. +++ */ +++ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); +++ state->state = RESET; +++ +++ return ret; +++} +++ ++ static ssize_t start_cleaning_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++@@ -296,10 +344,82 @@ static ssize_t start_cleaning_store(stru ++ return len; ++ } ++ +++static ssize_t cleaning_period_show(struct device *dev, +++ struct device_attribute *attr, +++ char *buf) +++{ +++ struct iio_dev *indio_dev = dev_to_iio_dev(dev); +++ struct sps30_state *state = iio_priv(indio_dev); +++ u8 tmp[4]; +++ int ret; +++ +++ mutex_lock(&state->lock); +++ ret = sps30_do_cmd(state, SPS30_READ_AUTO_CLEANING_PERIOD, tmp, 4); +++ mutex_unlock(&state->lock); +++ if (ret) +++ return ret; +++ +++ return sprintf(buf, "%d\n", get_unaligned_be32(tmp)); +++} +++ +++static ssize_t cleaning_period_store(struct device *dev, +++ struct device_attribute *attr, +++ const char *buf, size_t len) +++{ +++ struct iio_dev *indio_dev = dev_to_iio_dev(dev); +++ struct sps30_state *state = iio_priv(indio_dev); +++ int val, ret; +++ u8 tmp[4]; +++ +++ if (kstrtoint(buf, 0, &val)) +++ return -EINVAL; +++ +++ if ((val < SPS30_AUTO_CLEANING_PERIOD_MIN) || +++ (val > SPS30_AUTO_CLEANING_PERIOD_MAX)) +++ return -EINVAL; +++ +++ put_unaligned_be32(val, tmp); +++ +++ mutex_lock(&state->lock); +++ ret = sps30_do_cmd(state, SPS30_AUTO_CLEANING_PERIOD, tmp, 0); +++ if (ret) { +++ mutex_unlock(&state->lock); +++ return ret; +++ } +++ +++ msleep(20); +++ +++ /* +++ * sensor requires reset in order to return up to date self cleaning +++ * period +++ */ +++ ret = sps30_do_cmd_reset(state); +++ if (ret) +++ dev_warn(dev, +++ "period changed but reads will return the old value\n"); +++ +++ mutex_unlock(&state->lock); +++ +++ return len; +++} +++ +++static ssize_t cleaning_period_available_show(struct device *dev, +++ struct device_attribute *attr, +++ char *buf) +++{ +++ return snprintf(buf, PAGE_SIZE, "[%d %d %d]\n", +++ SPS30_AUTO_CLEANING_PERIOD_MIN, 1, +++ SPS30_AUTO_CLEANING_PERIOD_MAX); +++} +++ ++ static IIO_DEVICE_ATTR_WO(start_cleaning, 0); +++static IIO_DEVICE_ATTR_RW(cleaning_period, 0); +++static IIO_DEVICE_ATTR_RO(cleaning_period_available, 0); ++ ++ static struct attribute *sps30_attrs[] = { ++ &iio_dev_attr_start_cleaning.dev_attr.attr, +++ &iio_dev_attr_cleaning_period.dev_attr.attr, +++ &iio_dev_attr_cleaning_period_available.dev_attr.attr, ++ NULL ++ }; ++ ++@@ -362,6 +482,7 @@ static int sps30_probe(struct i2c_client ++ state = iio_priv(indio_dev); ++ i2c_set_clientdata(client, indio_dev); ++ state->client = client; +++ state->state = RESET; ++ indio_dev->dev.parent = &client->dev; ++ indio_dev->info = &sps30_info; ++ indio_dev->name = client->name; ++@@ -373,19 +494,11 @@ static int sps30_probe(struct i2c_client ++ mutex_init(&state->lock); ++ crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); ++ ++- ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); +++ ret = sps30_do_cmd_reset(state); ++ if (ret) { ++ dev_err(&client->dev, "failed to reset device\n"); ++ return ret; ++ } ++- msleep(300); ++- /* ++- * Power-on-reset causes sensor to produce some glitch on i2c bus and ++- * some controllers end up in error state. Recover simply by placing ++- * some data on the bus, for example STOP_MEAS command, which ++- * is NOP in this case. ++- */ ++- sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); ++ ++ ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); ++ if (ret) { ++@@ -395,12 +508,6 @@ static int sps30_probe(struct i2c_client ++ /* returned serial number is already NUL terminated */ ++ dev_info(&client->dev, "serial number: %s\n", buf); ++ ++- ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); ++- if (ret) { ++- dev_err(&client->dev, "failed to start measurement\n"); ++- return ret; ++- } ++- ++ ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); ++ if (ret) ++ return ret; +diff --git a/target/linux/generic/backport-4.19/503-v5.1-iio-chemical-sps30-remove-printk-format-specifier.patch b/target/linux/generic/backport-4.19/503-v5.1-iio-chemical-sps30-remove-printk-format-specifier.patch +new file mode 100644 +index 0000000000..b0fe5ac2e6 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/503-v5.1-iio-chemical-sps30-remove-printk-format-specifier.patch +@@ -0,0 +1,25 @@ ++From 3fa30bf7004bb8069826ef85487f4753666a73da Mon Sep 17 00:00:00 2001 ++From: Tomasz Duszynski ++Date: Sat, 2 Feb 2019 10:00:03 +0100 ++Subject: [PATCH] iio: chemical: sps30: remove printk format specifier ++ ++pr_fmt is used by printk wrappers. There are not any in the driver ++code so remove the format specifier. ++ ++Signed-off-by: Tomasz Duszynski ++Signed-off-by: Jonathan Cameron ++--- ++ drivers/iio/chemical/sps30.c | 2 -- ++ 1 file changed, 2 deletions(-) ++ ++--- a/drivers/iio/chemical/sps30.c +++++ b/drivers/iio/chemical/sps30.c ++@@ -7,8 +7,6 @@ ++ * I2C slave address: 0x69 ++ */ ++ ++-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++- ++ #include ++ #include ++ #include +diff --git a/target/linux/generic/backport-4.19/504-v5.1-iio-chemical-sps30-fix-a-loop-timeout-test.patch b/target/linux/generic/backport-4.19/504-v5.1-iio-chemical-sps30-fix-a-loop-timeout-test.patch +new file mode 100644 +index 0000000000..c0aae35549 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/504-v5.1-iio-chemical-sps30-fix-a-loop-timeout-test.patch +@@ -0,0 +1,26 @@ ++From 905889b4a34c753a538015f0b2cdaa0c9e3a4fd5 Mon Sep 17 00:00:00 2001 ++From: Dan Carpenter ++Date: Sat, 9 Feb 2019 12:03:52 +0300 ++Subject: [PATCH] iio: chemical: sps30: fix a loop timeout test ++ ++The "while (tries--) {" loop is a postop so it exits with "tries" set ++to -1. ++ ++Fixes: 232e0f6ddeae ("iio: chemical: add support for Sensirion SPS30 sensor") ++Signed-off-by: Dan Carpenter ++Signed-off-by: Jonathan Cameron ++--- ++ drivers/iio/chemical/sps30.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/drivers/iio/chemical/sps30.c +++++ b/drivers/iio/chemical/sps30.c ++@@ -210,7 +210,7 @@ static int sps30_do_meas(struct sps30_st ++ msleep_interruptible(300); ++ } ++ ++- if (!tries) +++ if (tries == -1) ++ return -ETIMEDOUT; ++ ++ ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); +diff --git a/target/linux/generic/backport-4.19/505-v5.1-iio-chemical-sps30-Supress-some-switch-fallthrough-w.patch b/target/linux/generic/backport-4.19/505-v5.1-iio-chemical-sps30-Supress-some-switch-fallthrough-w.patch +new file mode 100644 +index 0000000000..08cc34ff40 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/505-v5.1-iio-chemical-sps30-Supress-some-switch-fallthrough-w.patch +@@ -0,0 +1,34 @@ ++From 59b9bb0abca9efe47207301dbaf0d1beee2bd0f7 Mon Sep 17 00:00:00 2001 ++From: Jonathan Cameron ++Date: Sat, 9 Feb 2019 19:32:58 +0000 ++Subject: [PATCH] iio:chemical:sps30 Supress some switch fallthrough warnings. ++ ++Fixes warnings reported on linux-next but marking one path ++and adding an explicit return in the other. ++ ++Signed-off-by: Jonathan Cameron ++Cc: Andreas Brauchli ++Acked-by: Tomasz Duszynski ++--- ++ drivers/iio/chemical/sps30.c | 3 +++ ++ 1 file changed, 3 insertions(+) ++ ++--- a/drivers/iio/chemical/sps30.c +++++ b/drivers/iio/chemical/sps30.c ++@@ -118,6 +118,7 @@ static int sps30_do_cmd(struct sps30_sta ++ case SPS30_READ_AUTO_CLEANING_PERIOD: ++ buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; ++ buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD; +++ /* fall through */ ++ case SPS30_READ_DATA_READY_FLAG: ++ case SPS30_READ_DATA: ++ case SPS30_READ_SERIAL: ++@@ -295,6 +296,8 @@ static int sps30_read_raw(struct iio_dev ++ *val2 = 10000; ++ ++ return IIO_VAL_INT_PLUS_MICRO; +++ default: +++ return -EINVAL; ++ } ++ default: ++ return -EINVAL; +diff --git a/target/linux/generic/backport-4.19/506-v5.1-iio-chemical-sps30-Explicity-truncate-constant-by-ma.patch b/target/linux/generic/backport-4.19/506-v5.1-iio-chemical-sps30-Explicity-truncate-constant-by-ma.patch +new file mode 100644 +index 0000000000..e1f4a3b635 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/506-v5.1-iio-chemical-sps30-Explicity-truncate-constant-by-ma.patch +@@ -0,0 +1,31 @@ ++From 78b75ab3f8c9dfac563b81105a1b838ec37a940e Mon Sep 17 00:00:00 2001 ++From: Jonathan Cameron ++Date: Sun, 13 Oct 2019 10:55:15 +0100 ++Subject: [PATCH] iio: chemical: sps30: Explicity truncate constant by masking ++ ++When breaking up a constant to write to two 8 bit registers ++it isn't obvious to sparse that it was intentional. ++ ++CHECK drivers/iio/chemical/sps30.c ++drivers/iio/chemical/sps30.c:120:30: warning: cast truncates bits from constant value (8004 becomes 4) ++ ++So in the interests of minimising noisy warnings, let us add ++a mask. ++ ++Signed-off-by: Jonathan Cameron ++Acked-by: Tomasz Duszynski ++--- ++ drivers/iio/chemical/sps30.c | 2 +- ++ 1 file changed, 1 insertion(+), 1 deletion(-) ++ ++--- a/drivers/iio/chemical/sps30.c +++++ b/drivers/iio/chemical/sps30.c ++@@ -117,7 +117,7 @@ static int sps30_do_cmd(struct sps30_sta ++ break; ++ case SPS30_READ_AUTO_CLEANING_PERIOD: ++ buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; ++- buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD; +++ buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff); ++ /* fall through */ ++ case SPS30_READ_DATA_READY_FLAG: ++ case SPS30_READ_DATA: +diff --git a/target/linux/generic/backport-4.19/507-v5.6-iio-chemical-sps30-fix-missing-triggered-buffer-depe.patch b/target/linux/generic/backport-4.19/507-v5.6-iio-chemical-sps30-fix-missing-triggered-buffer-depe.patch +new file mode 100644 +index 0000000000..c2b999b1cb +--- /dev/null ++++ b/target/linux/generic/backport-4.19/507-v5.6-iio-chemical-sps30-fix-missing-triggered-buffer-depe.patch +@@ -0,0 +1,30 @@ ++From 61338e27e2eef3bfcd3df5c39cec5b9dc10ba25c Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Petr=20=C5=A0tetiar?= ++Date: Sun, 23 Feb 2020 22:08:25 +0100 ++Subject: [PATCH] iio: chemical: sps30: fix missing triggered buffer dependency ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++SPS30 uses triggered buffer, but the dependency is not specified in the ++Kconfig file. Fix this by selecting IIO_BUFFER and IIO_TRIGGERED_BUFFER ++config symbols. ++ ++Cc: stable@vger.kernel.org ++Fixes: 232e0f6ddeae ("iio: chemical: add support for Sensirion SPS30 sensor") ++Signed-off-by: Petr Štetiar ++--- ++ drivers/iio/chemical/Kconfig | 2 ++ ++ 1 file changed, 2 insertions(+) ++ ++--- a/drivers/iio/chemical/Kconfig +++++ b/drivers/iio/chemical/Kconfig ++@@ -65,6 +65,8 @@ config SPS30 ++ tristate "SPS30 particulate matter sensor" ++ depends on I2C ++ select CRC8 +++ select IIO_BUFFER +++ select IIO_TRIGGERED_BUFFER ++ help ++ Say Y here to build support for the Sensirion SPS30 particulate ++ matter sensor. +diff --git a/target/linux/generic/backport-4.19/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch b/target/linux/generic/backport-4.19/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch +new file mode 100644 +index 0000000000..d2d86f3df1 +--- /dev/null ++++ b/target/linux/generic/backport-4.19/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch +@@ -0,0 +1,71 @@ ++From 82afdcd4ec3c8ca6551cbf7c43c09e2fd240487a Mon Sep 17 00:00:00 2001 ++From: Hangbin Liu ++Date: Tue, 10 Mar 2020 15:27:37 +0800 ++Subject: [PATCH] ipv6/addrconf: call ipv6_mc_up() for non-Ethernet interface ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Rafał found an issue that for non-Ethernet interface, if we down and up ++frequently, the memory will be consumed slowly. ++ ++The reason is we add allnodes/allrouters addressed in multicast list in ++ipv6_add_dev(). When link down, we call ipv6_mc_down(), store all multicast ++addresses via mld_add_delrec(). But when link up, we don't call ipv6_mc_up() ++for non-Ethernet interface to remove the addresses. This makes idev->mc_tomb ++getting bigger and bigger. The call stack looks like: ++ ++addrconf_notify(NETDEV_REGISTER) ++ ipv6_add_dev ++ ipv6_dev_mc_inc(ff01::1) ++ ipv6_dev_mc_inc(ff02::1) ++ ipv6_dev_mc_inc(ff02::2) ++ ++addrconf_notify(NETDEV_UP) ++ addrconf_dev_config ++ /* Alas, we support only Ethernet autoconfiguration. */ ++ return; ++ ++addrconf_notify(NETDEV_DOWN) ++ addrconf_ifdown ++ ipv6_mc_down ++ igmp6_group_dropped(ff02::2) ++ mld_add_delrec(ff02::2) ++ igmp6_group_dropped(ff02::1) ++ igmp6_group_dropped(ff01::1) ++ ++After investigating, I can't found a rule to disable multicast on ++non-Ethernet interface. In RFC2460, the link could be Ethernet, PPP, ATM, ++tunnels, etc. In IPv4, it doesn't check the dev type when calls ip_mc_up() ++in inetdev_event(). Even for IPv6, we don't check the dev type and call ++ipv6_add_dev(), ipv6_dev_mc_inc() after register device. ++ ++So I think it's OK to fix this memory consumer by calling ipv6_mc_up() for ++non-Ethernet interface. ++ ++v2: Also check IFF_MULTICAST flag to make sure the interface supports ++ multicast ++ ++Reported-by: Rafał Miłecki ++Tested-by: Rafał Miłecki ++Fixes: 74235a25c673 ("[IPV6] addrconf: Fix IPv6 on tuntap tunnels") ++Fixes: 1666d49e1d41 ("mld: do not remove mld souce list info when set link down") ++Signed-off-by: Hangbin Liu ++Signed-off-by: David S. Miller ++--- ++ net/ipv6/addrconf.c | 4 ++++ ++ 1 file changed, 4 insertions(+) ++ ++--- a/net/ipv6/addrconf.c +++++ b/net/ipv6/addrconf.c ++@@ -3291,6 +3291,10 @@ static void addrconf_dev_config(struct n ++ (dev->type != ARPHRD_NONE) && ++ (dev->type != ARPHRD_RAWIP)) { ++ /* Alas, we support only Ethernet autoconfiguration. */ +++ idev = __in6_dev_get(dev); +++ if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP && +++ dev->flags & IFF_MULTICAST) +++ ipv6_mc_up(idev); ++ return; ++ } ++ +diff --git a/target/linux/generic/hack-4.19/550-loop-Report-EOPNOTSUPP-properly.patch b/target/linux/generic/hack-4.19/550-loop-Report-EOPNOTSUPP-properly.patch +index a3046cd8d1..023de0078d 100644 +--- a/target/linux/generic/hack-4.19/550-loop-Report-EOPNOTSUPP-properly.patch ++++ b/target/linux/generic/hack-4.19/550-loop-Report-EOPNOTSUPP-properly.patch +@@ -26,7 +26,7 @@ Reviewed-by: Bart Van Assche + + ret = errno_to_blk_status(cmd->ret); + goto end_io; + } +- ++ + @@ -1904,7 +1904,10 @@ static void loop_handle_cmd(struct loop_ + failed: + /* complete non-aio request */ +diff --git a/target/linux/generic/hack-4.19/551-loop-Better-discard-support-for-block-devices.patch b/target/linux/generic/hack-4.19/551-loop-Better-discard-support-for-block-devices.patch +index 271389a4da..ac393e5f13 100644 +--- a/target/linux/generic/hack-4.19/551-loop-Better-discard-support-for-block-devices.patch ++++ b/target/linux/generic/hack-4.19/551-loop-Better-discard-support-for-block-devices.patch +@@ -34,9 +34,9 @@ Reviewed-by: Chaitanya Kulkarni + struct file *file = lo->lo_backing_file; + + struct request_queue *q = lo->lo_queue; + int ret; +- ++ + mode |= FALLOC_FL_KEEP_SIZE; +- ++ + - if ((!file->f_op->fallocate) || lo->lo_encrypt_key_size) { + + if (!blk_queue_discard(q)) { + ret = -EOPNOTSUPP; +@@ -61,7 +61,7 @@ Reviewed-by: Chaitanya Kulkarni + + + + blk_queue_max_write_zeroes_sectors(q, + + backingq->limits.max_write_zeroes_sectors); +- ++ + /* + * We use punch hole to reclaim the free space used by the + @@ -870,22 +886,24 @@ static void loop_config_discard(struct l +@@ -78,13 +78,13 @@ Reviewed-by: Chaitanya Kulkarni + - blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q); + - return; + - } +- ++ + - q->limits.discard_granularity = inode->i_sb->s_blocksize; + - q->limits.discard_alignment = 0; + + } else { + + q->limits.discard_granularity = inode->i_sb->s_blocksize; + + q->limits.discard_alignment = 0; +- ++ + - blk_queue_max_discard_sectors(q, UINT_MAX >> 9); + - blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9); + - blk_queue_flag_set(QUEUE_FLAG_DISCARD, q); +@@ -97,5 +97,5 @@ Reviewed-by: Chaitanya Kulkarni + + else + + blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q); + } +- ++ + static void loop_unprepare_queue(struct loop_device *lo) +diff --git a/target/linux/generic/hack-4.19/645-netfilter-connmark-introduce-savedscp.patch b/target/linux/generic/hack-4.19/645-netfilter-connmark-introduce-savedscp.patch +deleted file mode 100644 +index 0c4ef92c00..0000000000 +--- a/target/linux/generic/hack-4.19/645-netfilter-connmark-introduce-savedscp.patch ++++ /dev/null +@@ -1,135 +0,0 @@ +-From f171924dcf1d0b31fb7bd1cff113d7a1f7f05ec2 Mon Sep 17 00:00:00 2001 +-From: Kevin Darbyshire-Bryant +-Date: Sat, 23 Mar 2019 09:29:49 +0000 +-Subject: [PATCH] netfilter: connmark: introduce savedscp +- +-savedscp is a method of storing the DSCP of an ip packet into conntrack +-mark. In combination with a suitable tc filter action (act_ctinfo) DSCP +-values are able to be stored in the mark on egress and restored on +-ingress across links that otherwise alter or bleach DSCP. +- +-This is useful for qdiscs such as CAKE which are able to shape according +-to policies based on DSCP. +- +-Ingress classification is traditionally a challenging task since +-iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT +-lookups, hence are unable to see internal IPv4 addresses as used on the +-typical home masquerading gateway. +- +-x_tables CONNMARK savedscp action solves the problem of storing the DSCP +-to the conntrack mark in a way suitable for the new act_ctinfo tc action +-to restore. +- +-The savedsp option accepts 2 parameters, a 32bit 'dscpmask' and a 32bit +-'statemask'. The dscp mask must be a minimum of 6 contiguous bits and +-represents the area where the DSCP will be stored in the connmark. The +-state mask is a minimum 1 bit length mask that must not overlap with the +-dscpmask. It represents a flag which is set when the DSCP has been +-stored in the conntrack mark. This is useful to implement a 'one shot' +-iptables based classification where the 'complicated' iptables rules are +-only run once to classify the connection on initial (egress) packet and +-subsequent packets are all marked/restored with the same DSCP. A state +-mask of zero disables the setting of a status bit/s. +- +-example syntax with a suitably modified iptables user space application: +- +-iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --savedscp-mark 0xfc000000/0x01000000 +- +-Would store the DSCP in the top 6 bits of the 32bit mark field, and use +-the LSB of the top byte as the 'DSCP has been stored' marker. +- +-|----0xFC----conntrack mark----000000---| +-| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +-| DSCP | unused | flag |unused | +-|-----------------------0x01---000000---| +- ^ ^ +- | | +- ---| Conditional flag +- | set this when dscp +-|-ip diffserv-| stored in mark +-| 6 bits | +-|-------------| +- +-an identically configured tc action to restore looks like: +- +-tc filter show dev eth0 ingress +-filter parent ffff: protocol all pref 10 u32 chain 0 +-filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1 +-filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw +- match 00000000/00000000 at 0 +- action order 1: ctinfo zone 0 pipe +- index 2 ref 1 bind 1 dscp 0xfc000000/0x1000000 +- +- action order 2: mirred (Egress Redirect to device ifb4eth0) stolen +- index 1 ref 1 bind 1 +- +-|----0xFC----conntrack mark----000000---| +-| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| +-| DSCP | unused | flag |unused | +-|-----------------------0x01---000000---| +- | | +- | | +- ---| Conditional flag +- v only restore if set +-|-ip diffserv-| +-| 6 bits | +-|-------------| +- +-Signed-off-by: Kevin Darbyshire-Bryant +---- +- include/uapi/linux/netfilter/xt_connmark.h | 3 ++- +- net/netfilter/xt_connmark.c | 17 +++++++++++++++++ +- 2 files changed, 19 insertions(+), 1 deletion(-) +- +---- a/include/uapi/linux/netfilter/xt_connmark.h +-+++ b/include/uapi/linux/netfilter/xt_connmark.h +-@@ -16,7 +16,8 @@ +- enum { +- XT_CONNMARK_SET = 0, +- XT_CONNMARK_SAVE, +-- XT_CONNMARK_RESTORE +-+ XT_CONNMARK_RESTORE, +-+ XT_CONNMARK_SAVEDSCP +- }; +- +- enum { +---- a/net/netfilter/xt_connmark.c +-+++ b/net/netfilter/xt_connmark.c +-@@ -42,6 +42,7 @@ connmark_tg_shift(struct sk_buff *skb, c +- u_int32_t new_targetmark; +- struct nf_conn *ct; +- u_int32_t newmark; +-+ u_int8_t dscp; +- +- ct = nf_ct_get(skb, &ctinfo); +- if (ct == NULL) +-@@ -74,6 +75,21 @@ connmark_tg_shift(struct sk_buff *skb, c +- nf_conntrack_event_cache(IPCT_MARK, ct); +- } +- break; +-+ case XT_CONNMARK_SAVEDSCP: +-+ if (skb->protocol == htons(ETH_P_IP)) +-+ dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2; +-+ else if (skb->protocol == htons(ETH_P_IPV6)) +-+ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2; +-+ else /* protocol doesn't have diffserv */ +-+ break; +-+ +-+ newmark = (ct->mark & ~info->ctmark) | +-+ (info->ctmask | (dscp << info->shift_bits)); +-+ if (ct->mark != newmark) { +-+ ct->mark = newmark; +-+ nf_conntrack_event_cache(IPCT_MARK, ct); +-+ } +-+ break; +- case XT_CONNMARK_RESTORE: +- new_targetmark = (ct->mark & info->ctmask); +- if (info->shift_dir == D_SHIFT_RIGHT) +-@@ -86,6 +102,7 @@ connmark_tg_shift(struct sk_buff *skb, c +- skb->mark = newmark; +- break; +- } +-+out: +- return XT_CONTINUE; +- } +- +diff --git a/target/linux/generic/hack-4.19/645-netfilter-connmark-introduce-set-dscpmark.patch b/target/linux/generic/hack-4.19/645-netfilter-connmark-introduce-set-dscpmark.patch +new file mode 100644 +index 0000000000..ca98187059 +--- /dev/null ++++ b/target/linux/generic/hack-4.19/645-netfilter-connmark-introduce-set-dscpmark.patch +@@ -0,0 +1,212 @@ ++From eda40b8c8c82e0f2789d6bc8bf63846dce2e8f32 Mon Sep 17 00:00:00 2001 ++From: Kevin Darbyshire-Bryant ++Date: Sat, 23 Mar 2019 09:29:49 +0000 ++Subject: [PATCH] netfilter: connmark: introduce set-dscpmark ++ ++set-dscpmark is a method of storing the DSCP of an ip packet into ++conntrack mark. In combination with a suitable tc filter action ++(act_ctinfo) DSCP values are able to be stored in the mark on egress and ++restored on ingress across links that otherwise alter or bleach DSCP. ++ ++This is useful for qdiscs such as CAKE which are able to shape according ++to policies based on DSCP. ++ ++Ingress classification is traditionally a challenging task since ++iptables rules haven't yet run and tc filter/eBPF programs are pre-NAT ++lookups, hence are unable to see internal IPv4 addresses as used on the ++typical home masquerading gateway. ++ ++x_tables CONNMARK set-dscpmark target solves the problem of storing the ++DSCP to the conntrack mark in a way suitable for the new act_ctinfo tc ++action to restore. ++ ++The set-dscpmark option accepts 2 parameters, a 32bit 'dscpmask' and a ++32bit 'statemask'. The dscp mask must be 6 contiguous bits and ++represents the area where the DSCP will be stored in the connmark. The ++state mask is a minimum 1 bit length mask that must not overlap with the ++dscpmask. It represents a flag which is set when the DSCP has been ++stored in the conntrack mark. This is useful to implement a 'one shot' ++iptables based classification where the 'complicated' iptables rules are ++only run once to classify the connection on initial (egress) packet and ++subsequent packets are all marked/restored with the same DSCP. A state ++mask of zero disables the setting of a status bit/s. ++ ++example syntax with a suitably modified iptables user space application: ++ ++iptables -A QOS_MARK_eth0 -t mangle -j CONNMARK --set-dscpmark 0xfc000000/0x01000000 ++ ++Would store the DSCP in the top 6 bits of the 32bit mark field, and use ++the LSB of the top byte as the 'DSCP has been stored' marker. ++ ++|----0xFC----conntrack mark----000000---| ++| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| ++| DSCP | unused | flag |unused | ++|-----------------------0x01---000000---| ++ ^ ^ ++ | | ++ ---| Conditional flag ++ | set this when dscp ++|-ip diffserv-| stored in mark ++| 6 bits | ++|-------------| ++ ++an identically configured tc action to restore looks like: ++ ++tc filter show dev eth0 ingress ++filter parent ffff: protocol all pref 10 u32 chain 0 ++filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1 ++filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1: not_in_hw ++ match 00000000/00000000 at 0 ++ action order 1: ctinfo zone 0 pipe ++ index 2 ref 1 bind 1 dscp 0xfc000000/0x1000000 ++ ++ action order 2: mirred (Egress Redirect to device ifb4eth0) stolen ++ index 1 ref 1 bind 1 ++ ++|----0xFC----conntrack mark----000000---| ++| Bits 31-26 | bit 25 | bit24 |~~~ Bit 0| ++| DSCP | unused | flag |unused | ++|-----------------------0x01---000000---| ++ | | ++ | | ++ ---| Conditional flag ++ v only restore if set ++|-ip diffserv-| ++| 6 bits | ++|-------------| ++ ++Signed-off-by: Kevin Darbyshire-Bryant ++--- ++ include/uapi/linux/netfilter/xt_connmark.h | 10 ++++ ++ net/netfilter/xt_connmark.c | 55 ++++++++++++++++++---- ++ 2 files changed, 57 insertions(+), 8 deletions(-) ++ ++--- a/include/uapi/linux/netfilter/xt_connmark.h +++++ b/include/uapi/linux/netfilter/xt_connmark.h ++@@ -20,6 +20,11 @@ enum { ++ }; ++ ++ enum { +++ XT_CONNMARK_VALUE = (1 << 0), +++ XT_CONNMARK_DSCP = (1 << 1) +++}; +++ +++enum { ++ D_SHIFT_LEFT = 0, ++ D_SHIFT_RIGHT, ++ }; ++@@ -34,6 +39,11 @@ struct xt_connmark_tginfo2 { ++ __u8 shift_dir, shift_bits, mode; ++ }; ++ +++struct xt_connmark_tginfo3 { +++ __u32 ctmark, ctmask, nfmask; +++ __u8 shift_dir, shift_bits, mode, func; +++}; +++ ++ struct xt_connmark_mtinfo1 { ++ __u32 mark, mask; ++ __u8 invert; ++--- a/net/netfilter/xt_connmark.c +++++ b/net/netfilter/xt_connmark.c ++@@ -36,12 +36,13 @@ MODULE_ALIAS("ipt_connmark"); ++ MODULE_ALIAS("ip6t_connmark"); ++ ++ static unsigned int ++-connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info) +++connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo3 *info) ++ { ++ enum ip_conntrack_info ctinfo; ++ u_int32_t new_targetmark; ++ struct nf_conn *ct; ++ u_int32_t newmark; +++ u_int8_t dscp; ++ ++ ct = nf_ct_get(skb, &ctinfo); ++ if (ct == NULL) ++@@ -49,12 +50,24 @@ connmark_tg_shift(struct sk_buff *skb, c ++ ++ switch (info->mode) { ++ case XT_CONNMARK_SET: ++- newmark = (ct->mark & ~info->ctmask) ^ info->ctmark; ++- if (info->shift_dir == D_SHIFT_RIGHT) ++- newmark >>= info->shift_bits; ++- else ++- newmark <<= info->shift_bits; +++ newmark = ct->mark; +++ if (info->func & XT_CONNMARK_VALUE) { +++ newmark = (newmark & ~info->ctmask) ^ info->ctmark; +++ if (info->shift_dir == D_SHIFT_RIGHT) +++ newmark >>= info->shift_bits; +++ else +++ newmark <<= info->shift_bits; +++ } else if (info->func & XT_CONNMARK_DSCP) { +++ if (skb->protocol == htons(ETH_P_IP)) +++ dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2; +++ else if (skb->protocol == htons(ETH_P_IPV6)) +++ dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2; +++ else /* protocol doesn't have diffserv */ +++ break; ++ +++ newmark = (newmark & ~info->ctmark) | +++ (info->ctmask | (dscp << info->shift_bits)); +++ } ++ if (ct->mark != newmark) { ++ ct->mark = newmark; ++ nf_conntrack_event_cache(IPCT_MARK, ct); ++@@ -93,20 +106,36 @@ static unsigned int ++ connmark_tg(struct sk_buff *skb, const struct xt_action_param *par) ++ { ++ const struct xt_connmark_tginfo1 *info = par->targinfo; ++- const struct xt_connmark_tginfo2 info2 = { +++ const struct xt_connmark_tginfo3 info3 = { ++ .ctmark = info->ctmark, ++ .ctmask = info->ctmask, ++ .nfmask = info->nfmask, ++ .mode = info->mode, +++ .func = XT_CONNMARK_VALUE ++ }; ++ ++- return connmark_tg_shift(skb, &info2); +++ return connmark_tg_shift(skb, &info3); ++ } ++ ++ static unsigned int ++ connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par) ++ { ++ const struct xt_connmark_tginfo2 *info = par->targinfo; +++ const struct xt_connmark_tginfo3 info3 = { +++ .ctmark = info->ctmark, +++ .ctmask = info->ctmask, +++ .nfmask = info->nfmask, +++ .mode = info->mode, +++ .func = XT_CONNMARK_VALUE +++ }; +++ +++ return connmark_tg_shift(skb, &info3); +++} +++ +++static unsigned int +++connmark_tg_v3(struct sk_buff *skb, const struct xt_action_param *par) +++{ +++ const struct xt_connmark_tginfo3 *info = par->targinfo; ++ ++ return connmark_tg_shift(skb, info); ++ } ++@@ -177,6 +206,16 @@ static struct xt_target connmark_tg_reg[ ++ .targetsize = sizeof(struct xt_connmark_tginfo2), ++ .destroy = connmark_tg_destroy, ++ .me = THIS_MODULE, +++ }, +++ { +++ .name = "CONNMARK", +++ .revision = 3, +++ .family = NFPROTO_UNSPEC, +++ .checkentry = connmark_tg_check, +++ .target = connmark_tg_v3, +++ .targetsize = sizeof(struct xt_connmark_tginfo3), +++ .destroy = connmark_tg_destroy, +++ .me = THIS_MODULE, ++ } ++ }; ++ +diff --git a/target/linux/generic/hack-4.19/702-phy_add_aneg_done_function.patch b/target/linux/generic/hack-4.19/702-phy_add_aneg_done_function.patch +index fe295906ee..a0e6484be8 100644 +--- a/target/linux/generic/hack-4.19/702-phy_add_aneg_done_function.patch ++++ b/target/linux/generic/hack-4.19/702-phy_add_aneg_done_function.patch +@@ -1,6 +1,6 @@ + --- a/include/linux/phy.h + +++ b/include/linux/phy.h +-@@ -548,6 +548,12 @@ struct phy_driver { ++@@ -555,6 +555,12 @@ struct phy_driver { + /* Determines the negotiated speed and duplex */ + int (*read_status)(struct phy_device *phydev); + +diff --git a/target/linux/generic/hack-4.19/902-debloat_proc.patch b/target/linux/generic/hack-4.19/902-debloat_proc.patch +index 1442cee8bb..0f4f445624 100644 +--- a/target/linux/generic/hack-4.19/902-debloat_proc.patch ++++ b/target/linux/generic/hack-4.19/902-debloat_proc.patch +@@ -189,7 +189,7 @@ Signed-off-by: Felix Fietkau + } + --- a/kernel/irq/proc.c + +++ b/kernel/irq/proc.c +-@@ -333,6 +333,9 @@ void register_irq_proc(unsigned int irq, ++@@ -355,6 +355,9 @@ void register_irq_proc(unsigned int irq, + void __maybe_unused *irqp = (void *)(unsigned long) irq; + char name [MAX_NAMELEN]; + +@@ -199,7 +199,7 @@ Signed-off-by: Felix Fietkau + if (!root_irq_dir || (desc->irq_data.chip == &no_irq_chip)) + return; + +-@@ -386,6 +389,9 @@ void unregister_irq_proc(unsigned int ir ++@@ -408,6 +411,9 @@ void unregister_irq_proc(unsigned int ir + { + char name [MAX_NAMELEN]; + +@@ -209,7 +209,7 @@ Signed-off-by: Felix Fietkau + if (!root_irq_dir || !desc->dir) + return; + #ifdef CONFIG_SMP +-@@ -424,6 +430,9 @@ void init_irq_proc(void) ++@@ -446,6 +452,9 @@ void init_irq_proc(void) + unsigned int irq; + struct irq_desc *desc; + +diff --git a/target/linux/generic/pending-4.14/647-netfilter-nf_flow_table_hw-fix-incorrect-ethernet-ds.patch b/target/linux/generic/pending-4.14/647-netfilter-nf_flow_table_hw-fix-incorrect-ethernet-ds.patch +new file mode 100644 +index 0000000000..a81445bb95 +--- /dev/null ++++ b/target/linux/generic/pending-4.14/647-netfilter-nf_flow_table_hw-fix-incorrect-ethernet-ds.patch +@@ -0,0 +1,87 @@ ++From: Konstantin Vasin ++Date: Mon, 9 Mar 2020 18:38:54 +0300 ++Subject: [PATCH] netfilter: nf_flow_table_hw: fix incorrect ethernet dst ++ address ++ ++Ethernet destination for original traffic takes the source ethernet ++address in the reply direction. For reply traffic, this takes ++the source ethernet address of the original destination. ++ ++This fix is based on the upstream commit 1b67e506: ++("netfilter: nf_flow_table_offload: fix incorrect ethernet dst address") ++from wenxu ++ ++Signed-off-by: Konstantin Vasin ++--- ++ ++--- a/net/netfilter/nf_flow_table_hw.c +++++ b/net/netfilter/nf_flow_table_hw.c ++@@ -24,17 +24,23 @@ struct flow_offload_hw { ++ struct flow_offload_hw_path dest; ++ }; ++ ++-static void flow_offload_check_ethernet(struct flow_offload_tuple *tuple, +++static void flow_offload_check_ethernet(struct flow_offload *flow, +++ enum flow_offload_tuple_dir dir, ++ struct flow_offload_hw_path *path) ++ { ++ struct net_device *dev = path->dev; ++ struct neighbour *n; +++ const void *daddr; +++ const struct dst_entry *dst_cache; ++ ++ if (dev->type != ARPHRD_ETHER) ++ return; ++ ++ memcpy(path->eth_src, path->dev->dev_addr, ETH_ALEN); ++- n = dst_neigh_lookup(tuple->dst_cache, &tuple->src_v4); +++ +++ daddr = &flow->tuplehash[dir].tuple.src_v4; +++ dst_cache = flow->tuplehash[!dir].tuple.dst_cache; +++ n = dst_neigh_lookup(dst_cache, daddr); ++ if (!n) ++ return; ++ ++@@ -44,17 +50,18 @@ static void flow_offload_check_ethernet(struct flow_offload_tuple *tuple, ++ } ++ ++ static int flow_offload_check_path(struct net *net, ++- struct flow_offload_tuple *tuple, +++ struct flow_offload *flow, +++ enum flow_offload_tuple_dir dir, ++ struct flow_offload_hw_path *path) ++ { ++ struct net_device *dev; ++ ++- dev = dev_get_by_index_rcu(net, tuple->iifidx); +++ dev = dev_get_by_index_rcu(net, flow->tuplehash[dir].tuple.iifidx); ++ if (!dev) ++ return -ENOENT; ++ ++ path->dev = dev; ++- flow_offload_check_ethernet(tuple, path); +++ flow_offload_check_ethernet(flow, dir, path); ++ ++ if (dev->netdev_ops->ndo_flow_offload_check) ++ return dev->netdev_ops->ndo_flow_offload_check(path); ++@@ -133,17 +140,14 @@ flow_offload_hw_prepare(struct net *net, struct flow_offload *flow) ++ { ++ struct flow_offload_hw_path src = {}; ++ struct flow_offload_hw_path dest = {}; ++- struct flow_offload_tuple *tuple; ++ struct flow_offload_hw *offload = NULL; ++ ++ rcu_read_lock_bh(); ++ ++- tuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple; ++- if (flow_offload_check_path(net, tuple, &src)) +++ if (flow_offload_check_path(net, flow, FLOW_OFFLOAD_DIR_ORIGINAL, &src)) ++ goto out; ++ ++- tuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple; ++- if (flow_offload_check_path(net, tuple, &dest)) +++ if (flow_offload_check_path(net, flow, FLOW_OFFLOAD_DIR_REPLY, &dest)) ++ goto out; ++ ++ if (!src.dev->netdev_ops->ndo_flow_offload) ++ +diff --git a/target/linux/generic/pending-4.14/648-netfilter-nf_flow_table_hw-check-the-status-of-dst_n.patch b/target/linux/generic/pending-4.14/648-netfilter-nf_flow_table_hw-check-the-status-of-dst_n.patch +new file mode 100644 +index 0000000000..ed4a1e3a3e +--- /dev/null ++++ b/target/linux/generic/pending-4.14/648-netfilter-nf_flow_table_hw-check-the-status-of-dst_n.patch +@@ -0,0 +1,32 @@ ++From: Konstantin Vasin ++Date: Mon, 9 Mar 2020 17:41:22 +0300 ++Subject: [PATCH] netfilter: nf_flow_table_hw: check the status of ++ dst_neigh ++ ++It's better to check the nud_state is VALID. ++If there is not neigh previos, the lookup will ++create a non NUD_VALID with 00:00:00:00:00:00 mac. ++ ++This fix is based on the upstream commit f31ad71c44 ++("netfilter: nf_flow_table_offload: check the status of dst_neigh") ++from wenxu ++ ++Signed-off-by: Konstantin Vasin ++--- ++ ++index e831c8830e91..1238d675a316 100644 ++--- a/net/netfilter/nf_flow_table_hw.c +++++ b/net/netfilter/nf_flow_table_hw.c ++@@ -44,8 +44,10 @@ static void flow_offload_check_ethernet(struct flow_offload *flow, ++ if (!n) ++ return; ++ ++- memcpy(path->eth_dest, n->ha, ETH_ALEN); ++- path->flags |= FLOW_OFFLOAD_PATH_ETHERNET; +++ if (n->nud_state & NUD_VALID) { +++ memcpy(path->eth_dest, n->ha, ETH_ALEN); +++ path->flags |= FLOW_OFFLOAD_PATH_ETHERNET; +++ } ++ neigh_release(n); ++ } ++ +diff --git a/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch +index bf9822fda8..f3a314ae02 100644 +--- a/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch ++++ b/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch +@@ -114,8 +114,7 @@ Signed-off-by: Felix Fietkau + + slave->mtd.erasesize = slave->mtd.size; + } + +-- tmp = part_absolute_offset(parent) + slave->mtd.size; +-+ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; ++ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; + remainder = do_div(tmp, wr_alignment); + if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { + - slave->mtd.flags &= ~MTD_WRITEABLE; +diff --git a/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch b/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch +index 6981c6d943..4d64fca90b 100644 +--- a/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch ++++ b/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch +@@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau + + --- a/drivers/mtd/spi-nor/spi-nor.c + +++ b/drivers/mtd/spi-nor/spi-nor.c +-@@ -1457,7 +1457,7 @@ static int spi_nor_write(struct mtd_info ++@@ -1459,7 +1459,7 @@ static int spi_nor_write(struct mtd_info + + write_enable(nor); + ret = nor->write(nor, addr, page_remain, buf + i); +@@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau + goto write_err; + written = ret; + +-@@ -1466,13 +1466,6 @@ static int spi_nor_write(struct mtd_info ++@@ -1468,13 +1468,6 @@ static int spi_nor_write(struct mtd_info + goto write_err; + *retlen += written; + i += written; +diff --git a/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch +index 0c5d6cfa63..3172c223f2 100644 +--- a/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch ++++ b/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch +@@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau + + --- a/drivers/mtd/spi-nor/spi-nor.c + +++ b/drivers/mtd/spi-nor/spi-nor.c +-@@ -2735,6 +2735,7 @@ static int spi_nor_init(struct spi_nor * ++@@ -2737,6 +2737,7 @@ static int spi_nor_init(struct spi_nor * + */ + if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL || + JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || +diff --git a/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch b/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +index fb6ae7df7b..f6a98af6ac 100644 +--- a/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch ++++ b/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +@@ -17,7 +17,7 @@ Signed-off-by: Matthias Schiffer + + --- a/drivers/mtd/spi-nor/spi-nor.c + +++ b/drivers/mtd/spi-nor/spi-nor.c +-@@ -2737,6 +2737,7 @@ static int spi_nor_init(struct spi_nor * ++@@ -2739,6 +2739,7 @@ static int spi_nor_init(struct spi_nor * + JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || + JEDEC_MFR(nor->info) == SNOR_MFR_MACRONIX || + JEDEC_MFR(nor->info) == SNOR_MFR_SST || +@@ -25,7 +25,7 @@ Signed-off-by: Matthias Schiffer + nor->info->flags & SPI_NOR_HAS_LOCK) { + write_enable(nor); + write_sr(nor, 0); +-@@ -2873,7 +2874,8 @@ int spi_nor_scan(struct spi_nor *nor, co ++@@ -2875,7 +2876,8 @@ int spi_nor_scan(struct spi_nor *nor, co + + /* NOR protection support for STmicro/Micron chips and similar */ + if (JEDEC_MFR(info) == SNOR_MFR_MICRON || +diff --git a/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +index 12d785856a..695c38cf0f 100644 +--- a/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch ++++ b/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +@@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau + depends on ARCH_AT91 || (ARM && COMPILE_TEST && !ARCH_EBSA110) + --- a/drivers/mtd/spi-nor/spi-nor.c + +++ b/drivers/mtd/spi-nor/spi-nor.c +-@@ -2649,10 +2649,12 @@ static int spi_nor_select_erase(struct s ++@@ -2651,10 +2651,12 @@ static int spi_nor_select_erase(struct s + + #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS + /* prefer "small sector" erase if possible */ +diff --git a/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch +index 664837928b..da60939bb3 100644 +--- a/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch ++++ b/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch +@@ -30,7 +30,7 @@ Signed-off-by: Daniel Golle + + --- a/drivers/mtd/spi-nor/spi-nor.c + +++ b/drivers/mtd/spi-nor/spi-nor.c +-@@ -1273,6 +1273,9 @@ static const struct flash_info spi_nor_i ++@@ -1275,6 +1275,9 @@ static const struct flash_info spi_nor_i + /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ + { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +diff --git a/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +index c35aca8a18..cfdfe10836 100644 +--- a/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch ++++ b/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +@@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski + cfg->fc_flags |= RTF_REJECT; + + if (rtm->rtm_type == RTN_LOCAL) +-@@ -5084,6 +5115,8 @@ static int ip6_route_dev_notify(struct n ++@@ -5085,6 +5116,8 @@ static int ip6_route_dev_notify(struct n + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + net->ipv6.ip6_prohibit_entry->dst.dev = dev; + net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); +@@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski + net->ipv6.ip6_blk_hole_entry->dst.dev = dev; + net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); + #endif +-@@ -5095,6 +5128,7 @@ static int ip6_route_dev_notify(struct n ++@@ -5096,6 +5129,7 @@ static int ip6_route_dev_notify(struct n + in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); +@@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski + in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); + #endif + } +-@@ -5289,6 +5323,15 @@ static int __net_init ip6_route_net_init ++@@ -5290,6 +5324,15 @@ static int __net_init ip6_route_net_init + net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; + dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, + ip6_template_metrics, true); +@@ -218,7 +218,7 @@ Signed-off-by: Jonas Gorski + #endif + + net->ipv6.sysctl.flush_delay = 0; +-@@ -5307,6 +5350,8 @@ out: ++@@ -5308,6 +5351,8 @@ out: + return ret; + + #ifdef CONFIG_IPV6_MULTIPLE_TABLES +@@ -227,7 +227,7 @@ Signed-off-by: Jonas Gorski + out_ip6_prohibit_entry: + kfree(net->ipv6.ip6_prohibit_entry); + out_ip6_null_entry: +-@@ -5327,6 +5372,7 @@ static void __net_exit ip6_route_net_exi ++@@ -5328,6 +5373,7 @@ static void __net_exit ip6_route_net_exi + #ifdef CONFIG_IPV6_MULTIPLE_TABLES + kfree(net->ipv6.ip6_prohibit_entry); + kfree(net->ipv6.ip6_blk_hole_entry); +@@ -235,7 +235,7 @@ Signed-off-by: Jonas Gorski + #endif + dst_entries_destroy(&net->ipv6.ip6_dst_ops); + } +-@@ -5403,6 +5449,9 @@ void __init ip6_route_init_special_entri ++@@ -5404,6 +5450,9 @@ void __init ip6_route_init_special_entri + init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); + init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; + init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); +diff --git a/target/linux/generic/pending-4.9/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/target/linux/generic/pending-4.9/931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch +similarity index 100% +rename from target/linux/generic/pending-4.9/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch +rename to target/linux/generic/pending-4.9/931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch +diff --git a/target/linux/ipq40xx/config-4.19 b/target/linux/ipq40xx/config-4.19 +index 0de3001c8a..d01ae3cebc 100644 +--- a/target/linux/ipq40xx/config-4.19 ++++ b/target/linux/ipq40xx/config-4.19 +@@ -47,6 +47,7 @@ CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y + CONFIG_ARM_CPUIDLE=y + CONFIG_ARM_CPU_SUSPEND=y + # CONFIG_ARM_CPU_TOPOLOGY is not set ++CONFIG_ARM_CRYPTO=y + CONFIG_ARM_GIC=y + CONFIG_ARM_HAS_SG_CHAIN=y + CONFIG_ARM_L1_CACHE_SHIFT=6 +@@ -115,34 +116,26 @@ CONFIG_CRC32_SLICEBY8=y + CONFIG_CRYPTO_ACOMP2=y + CONFIG_CRYPTO_AEAD=y + CONFIG_CRYPTO_AEAD2=y +-CONFIG_CRYPTO_CBC=y +-CONFIG_CRYPTO_CTR=y ++CONFIG_CRYPTO_AES_ARM=y ++CONFIG_CRYPTO_AES_ARM_BS=y + CONFIG_CRYPTO_DEFLATE=y +-CONFIG_CRYPTO_DES=y +-CONFIG_CRYPTO_DEV_QCE=y + CONFIG_CRYPTO_DEV_QCOM_RNG=y +-CONFIG_CRYPTO_DRBG=y +-CONFIG_CRYPTO_DRBG_HMAC=y +-CONFIG_CRYPTO_DRBG_MENU=y +-CONFIG_CRYPTO_ECB=y +-CONFIG_CRYPTO_GF128MUL=y ++# CONFIG_CRYPTO_GHASH_ARM_CE is not set + CONFIG_CRYPTO_HASH=y + CONFIG_CRYPTO_HASH2=y +-CONFIG_CRYPTO_HMAC=y + CONFIG_CRYPTO_HW=y +-CONFIG_CRYPTO_JITTERENTROPY=y + CONFIG_CRYPTO_LZO=y + CONFIG_CRYPTO_MANAGER=y + CONFIG_CRYPTO_MANAGER2=y +-CONFIG_CRYPTO_NULL=y + CONFIG_CRYPTO_NULL2=y + CONFIG_CRYPTO_RNG=y + CONFIG_CRYPTO_RNG2=y +-CONFIG_CRYPTO_RNG_DEFAULT=y +-CONFIG_CRYPTO_SEQIV=y ++# CONFIG_CRYPTO_SHA1_ARM_CE is not set ++# CONFIG_CRYPTO_SHA1_ARM_NEON is not set + CONFIG_CRYPTO_SHA256=y ++CONFIG_CRYPTO_SHA256_ARM=y ++CONFIG_CRYPTO_SIMD=y + CONFIG_CRYPTO_WORKQUEUE=y +-CONFIG_CRYPTO_XTS=y + CONFIG_DCACHE_WORD_ACCESS=y + CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" + # CONFIG_DEBUG_USER is not set +diff --git a/target/linux/ipq40xx/patches-4.19/181-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch b/target/linux/ipq40xx/patches-4.19/039-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch +similarity index 100% +rename from target/linux/ipq40xx/patches-4.19/181-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch +rename to target/linux/ipq40xx/patches-4.19/039-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch +diff --git a/target/linux/ipq40xx/patches-4.19/040-crypto-qce-switch-to-skcipher-API.patch b/target/linux/ipq40xx/patches-4.19/040-crypto-qce-switch-to-skcipher-API.patch +new file mode 100644 +index 0000000000..2adfe622e3 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/040-crypto-qce-switch-to-skcipher-API.patch +@@ -0,0 +1,463 @@ ++From f441873642eebf20566c18d2966a8cd4b433ec1c Mon Sep 17 00:00:00 2001 ++From: Ard Biesheuvel ++Date: Tue, 5 Nov 2019 14:28:17 +0100 ++Subject: [PATCH] crypto: qce - switch to skcipher API ++ ++Commit 7a7ffe65c8c5 ("crypto: skcipher - Add top-level skcipher interface") ++dated 20 august 2015 introduced the new skcipher API which is supposed to ++replace both blkcipher and ablkcipher. While all consumers of the API have ++been converted long ago, some producers of the ablkcipher remain, forcing ++us to keep the ablkcipher support routines alive, along with the matching ++code to expose [a]blkciphers via the skcipher API. ++ ++So switch this driver to the skcipher API, allowing us to finally drop the ++blkcipher code in the near future. ++ ++Reviewed-by: Stanimir Varbanov ++Signed-off-by: Ard Biesheuvel ++Backported-to-4.19-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile ++index 19a7f899acff..8caa04e1ec43 100644 ++--- a/drivers/crypto/qce/Makefile +++++ b/drivers/crypto/qce/Makefile ++@@ -4,4 +4,4 @@ qcrypto-objs := core.o \ ++ common.o \ ++ dma.o \ ++ sha.o \ ++- ablkcipher.o +++ skcipher.o ++diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h ++index 2b0278bb6e92..f93fab1dd1ff 100644 ++--- a/drivers/crypto/qce/cipher.h +++++ b/drivers/crypto/qce/cipher.h ++@@ -53,12 +53,12 @@ struct qce_cipher_reqctx { ++ unsigned int cryptlen; ++ }; ++ ++-static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm) +++static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm) ++ { ++- struct crypto_alg *alg = tfm->__crt_alg; ++- return container_of(alg, struct qce_alg_template, alg.crypto); +++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); +++ return container_of(alg, struct qce_alg_template, alg.skcipher); ++ } ++ ++-extern const struct qce_algo_ops ablkcipher_ops; +++extern const struct qce_algo_ops skcipher_ops; ++ ++ #endif /* _CIPHER_H_ */ ++diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c ++index 1fb5fde7fc03..e0202755682b 100644 ++--- a/drivers/crypto/qce/common.c +++++ b/drivers/crypto/qce/common.c ++@@ -312,13 +312,13 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req, ++ return 0; ++ } ++ ++-static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req, +++static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, ++ u32 totallen, u32 offset) ++ { ++- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); ++- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +++ struct skcipher_request *req = skcipher_request_cast(async_req); +++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm); ++- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); +++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; ++ __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0}; ++ __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0}; ++@@ -397,8 +397,8 @@ int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen, ++ u32 offset) ++ { ++ switch (type) { ++- case CRYPTO_ALG_TYPE_ABLKCIPHER: ++- return qce_setup_regs_ablkcipher(async_req, totallen, offset); +++ case CRYPTO_ALG_TYPE_SKCIPHER: +++ return qce_setup_regs_skcipher(async_req, totallen, offset); ++ case CRYPTO_ALG_TYPE_AHASH: ++ return qce_setup_regs_ahash(async_req, totallen, offset); ++ default: ++diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h ++index a4addd4f7d6c..3252efa41e7a 100644 ++--- a/drivers/crypto/qce/common.h +++++ b/drivers/crypto/qce/common.h ++@@ -18,6 +18,7 @@ ++ #include ++ #include ++ #include +++#include ++ ++ /* key size in bytes */ ++ #define QCE_SHA_HMAC_KEY_SIZE 64 ++@@ -87,7 +88,7 @@ struct qce_alg_template { ++ unsigned long alg_flags; ++ const u32 *std_iv; ++ union { ++- struct crypto_alg crypto; +++ struct skcipher_alg skcipher; ++ struct ahash_alg ahash; ++ } alg; ++ struct qce_device *qce; ++diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c ++index 1c3b36b75467..bf409edc23ab 100644 ++--- a/drivers/crypto/qce/core.c +++++ b/drivers/crypto/qce/core.c ++@@ -30,7 +30,7 @@ ++ #define QCE_QUEUE_LENGTH 1 ++ ++ static const struct qce_algo_ops *qce_ops[] = { ++- &ablkcipher_ops, +++ &skcipher_ops, ++ &ahash_ops, ++ }; ++ ++diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/skcipher.c ++similarity index 62% ++rename from drivers/crypto/qce/ablkcipher.c ++rename to drivers/crypto/qce/skcipher.c ++index 3658c46ef9c7..0376bb969834 100644 ++--- a/drivers/crypto/qce/ablkcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -20,14 +20,14 @@ ++ ++ #include "cipher.h" ++ ++-static LIST_HEAD(ablkcipher_algs); +++static LIST_HEAD(skcipher_algs); ++ ++-static void qce_ablkcipher_done(void *data) +++static void qce_skcipher_done(void *data) ++ { ++ struct crypto_async_request *async_req = data; ++- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); ++- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); ++- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); +++ struct skcipher_request *req = skcipher_request_cast(async_req); +++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); +++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; ++ enum dma_data_direction dir_src, dir_dst; ++ u32 status; ++@@ -40,7 +40,7 @@ static void qce_ablkcipher_done(void *data) ++ ++ error = qce_dma_terminate_all(&qce->dma); ++ if (error) ++- dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n", +++ dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", ++ error); ++ ++ if (diff_dst) ++@@ -51,18 +51,18 @@ static void qce_ablkcipher_done(void *data) ++ ++ error = qce_check_status(qce, &status); ++ if (error < 0) ++- dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status); +++ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); ++ ++ qce->async_req_done(tmpl->qce, error); ++ } ++ ++ static int ++-qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) +++qce_skcipher_async_req_handle(struct crypto_async_request *async_req) ++ { ++- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); ++- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); ++- struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); ++- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); +++ struct skcipher_request *req = skcipher_request_cast(async_req); +++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); +++ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); +++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; ++ enum dma_data_direction dir_src, dir_dst; ++ struct scatterlist *sg; ++@@ -70,17 +70,17 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) ++ gfp_t gfp; ++ int ret; ++ ++- rctx->iv = req->info; ++- rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher); ++- rctx->cryptlen = req->nbytes; +++ rctx->iv = req->iv; +++ rctx->ivsize = crypto_skcipher_ivsize(skcipher); +++ rctx->cryptlen = req->cryptlen; ++ ++ diff_dst = (req->src != req->dst) ? true : false; ++ dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; ++ dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; ++ ++- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes); +++ rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); ++ if (diff_dst) ++- rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes); +++ rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); ++ else ++ rctx->dst_nents = rctx->src_nents; ++ if (rctx->src_nents < 0) { ++@@ -133,13 +133,13 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) ++ ++ ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, ++ rctx->dst_sg, rctx->dst_nents, ++- qce_ablkcipher_done, async_req); +++ qce_skcipher_done, async_req); ++ if (ret) ++ goto error_unmap_src; ++ ++ qce_dma_issue_pending(&qce->dma); ++ ++- ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0); +++ ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); ++ if (ret) ++ goto error_terminate; ++ ++@@ -157,12 +157,11 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) ++ return ret; ++ } ++ ++-static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, +++static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ unsigned int keylen) ++ { ++- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk); ++- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++- unsigned long flags = to_cipher_tmpl(tfm)->alg_flags; +++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); +++ unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; ++ int ret; ++ ++ if (!key || !keylen) ++@@ -180,7 +179,7 @@ static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, ++ u32 tmp[DES_EXPKEY_WORDS]; ++ ++ ret = des_ekey(tmp, key); ++- if (!ret && crypto_ablkcipher_get_flags(ablk) & +++ if (!ret && crypto_skcipher_get_flags(ablk) & ++ CRYPTO_TFM_REQ_WEAK_KEY) ++ goto weakkey; ++ } ++@@ -194,16 +193,15 @@ static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, ++ ctx->enc_keylen = keylen; ++ return ret; ++ weakkey: ++- crypto_ablkcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY); +++ crypto_skcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY); ++ return -EINVAL; ++ } ++ ++-static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) +++static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) ++ { ++- struct crypto_tfm *tfm = ++- crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); ++- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); ++ int ret; ++ ++@@ -218,7 +216,7 @@ static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) ++ skcipher_request_set_callback(subreq, req->base.flags, ++ NULL, NULL); ++ skcipher_request_set_crypt(subreq, req->src, req->dst, ++- req->nbytes, req->info); +++ req->cryptlen, req->iv); ++ ret = encrypt ? crypto_skcipher_encrypt(subreq) : ++ crypto_skcipher_decrypt(subreq); ++ skcipher_request_zero(subreq); ++@@ -228,37 +226,37 @@ static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) ++ return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); ++ } ++ ++-static int qce_ablkcipher_encrypt(struct ablkcipher_request *req) +++static int qce_skcipher_encrypt(struct skcipher_request *req) ++ { ++- return qce_ablkcipher_crypt(req, 1); +++ return qce_skcipher_crypt(req, 1); ++ } ++ ++-static int qce_ablkcipher_decrypt(struct ablkcipher_request *req) +++static int qce_skcipher_decrypt(struct skcipher_request *req) ++ { ++- return qce_ablkcipher_crypt(req, 0); +++ return qce_skcipher_crypt(req, 0); ++ } ++ ++-static int qce_ablkcipher_init(struct crypto_tfm *tfm) +++static int qce_skcipher_init(struct crypto_skcipher *tfm) ++ { ++- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ ++ memset(ctx, 0, sizeof(*ctx)); ++- tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx); +++ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); ++ ++- ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(tfm), 0, ++- CRYPTO_ALG_ASYNC | ++- CRYPTO_ALG_NEED_FALLBACK); +++ ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(&tfm->base), +++ 0, CRYPTO_ALG_ASYNC | +++ CRYPTO_ALG_NEED_FALLBACK); ++ return PTR_ERR_OR_ZERO(ctx->fallback); ++ } ++ ++-static void qce_ablkcipher_exit(struct crypto_tfm *tfm) +++static void qce_skcipher_exit(struct crypto_skcipher *tfm) ++ { ++- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ ++ crypto_free_skcipher(ctx->fallback); ++ } ++ ++-struct qce_ablkcipher_def { +++struct qce_skcipher_def { ++ unsigned long flags; ++ const char *name; ++ const char *drv_name; ++@@ -268,7 +266,7 @@ struct qce_ablkcipher_def { ++ unsigned int max_keysize; ++ }; ++ ++-static const struct qce_ablkcipher_def ablkcipher_def[] = { +++static const struct qce_skcipher_def skcipher_def[] = { ++ { ++ .flags = QCE_ALG_AES | QCE_MODE_ECB, ++ .name = "ecb(aes)", ++@@ -343,89 +341,89 @@ static const struct qce_ablkcipher_def ablkcipher_def[] = { ++ }, ++ }; ++ ++-static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def, +++static int qce_skcipher_register_one(const struct qce_skcipher_def *def, ++ struct qce_device *qce) ++ { ++ struct qce_alg_template *tmpl; ++- struct crypto_alg *alg; +++ struct skcipher_alg *alg; ++ int ret; ++ ++ tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); ++ if (!tmpl) ++ return -ENOMEM; ++ ++- alg = &tmpl->alg.crypto; +++ alg = &tmpl->alg.skcipher; ++ ++- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); ++- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", +++ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); +++ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", ++ def->drv_name); ++ ++- alg->cra_blocksize = def->blocksize; ++- alg->cra_ablkcipher.ivsize = def->ivsize; ++- alg->cra_ablkcipher.min_keysize = def->min_keysize; ++- alg->cra_ablkcipher.max_keysize = def->max_keysize; ++- alg->cra_ablkcipher.setkey = qce_ablkcipher_setkey; ++- alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt; ++- alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt; ++- ++- alg->cra_priority = 300; ++- alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | ++- CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; ++- alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); ++- alg->cra_alignmask = 0; ++- alg->cra_type = &crypto_ablkcipher_type; ++- alg->cra_module = THIS_MODULE; ++- alg->cra_init = qce_ablkcipher_init; ++- alg->cra_exit = qce_ablkcipher_exit; ++- INIT_LIST_HEAD(&alg->cra_list); +++ alg->base.cra_blocksize = def->blocksize; +++ alg->ivsize = def->ivsize; +++ alg->min_keysize = def->min_keysize; +++ alg->max_keysize = def->max_keysize; +++ alg->setkey = qce_skcipher_setkey; +++ alg->encrypt = qce_skcipher_encrypt; +++ alg->decrypt = qce_skcipher_decrypt; +++ +++ alg->base.cra_priority = 300; +++ alg->base.cra_flags = CRYPTO_ALG_ASYNC | +++ CRYPTO_ALG_NEED_FALLBACK | +++ CRYPTO_ALG_KERN_DRIVER_ONLY; +++ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); +++ alg->base.cra_alignmask = 0; +++ alg->base.cra_module = THIS_MODULE; +++ +++ alg->init = qce_skcipher_init; +++ alg->exit = qce_skcipher_exit; ++ ++ INIT_LIST_HEAD(&tmpl->entry); ++- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER; +++ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; ++ tmpl->alg_flags = def->flags; ++ tmpl->qce = qce; ++ ++- ret = crypto_register_alg(alg); +++ ret = crypto_register_skcipher(alg); ++ if (ret) { ++ kfree(tmpl); ++- dev_err(qce->dev, "%s registration failed\n", alg->cra_name); +++ dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); ++ return ret; ++ } ++ ++- list_add_tail(&tmpl->entry, &ablkcipher_algs); ++- dev_dbg(qce->dev, "%s is registered\n", alg->cra_name); +++ list_add_tail(&tmpl->entry, &skcipher_algs); +++ dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); ++ return 0; ++ } ++ ++-static void qce_ablkcipher_unregister(struct qce_device *qce) +++static void qce_skcipher_unregister(struct qce_device *qce) ++ { ++ struct qce_alg_template *tmpl, *n; ++ ++- list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) { ++- crypto_unregister_alg(&tmpl->alg.crypto); +++ list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { +++ crypto_unregister_skcipher(&tmpl->alg.skcipher); ++ list_del(&tmpl->entry); ++ kfree(tmpl); ++ } ++ } ++ ++-static int qce_ablkcipher_register(struct qce_device *qce) +++static int qce_skcipher_register(struct qce_device *qce) ++ { ++ int ret, i; ++ ++- for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) { ++- ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce); +++ for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { +++ ret = qce_skcipher_register_one(&skcipher_def[i], qce); ++ if (ret) ++ goto err; ++ } ++ ++ return 0; ++ err: ++- qce_ablkcipher_unregister(qce); +++ qce_skcipher_unregister(qce); ++ return ret; ++ } ++ ++-const struct qce_algo_ops ablkcipher_ops = { ++- .type = CRYPTO_ALG_TYPE_ABLKCIPHER, ++- .register_algs = qce_ablkcipher_register, ++- .unregister_algs = qce_ablkcipher_unregister, ++- .async_req_handle = qce_ablkcipher_async_req_handle, +++const struct qce_algo_ops skcipher_ops = { +++ .type = CRYPTO_ALG_TYPE_SKCIPHER, +++ .register_algs = qce_skcipher_register, +++ .unregister_algs = qce_skcipher_unregister, +++ .async_req_handle = qce_skcipher_async_req_handle, ++ }; +diff --git a/target/linux/ipq40xx/patches-4.19/041-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch b/target/linux/ipq40xx/patches-4.19/041-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch +new file mode 100644 +index 0000000000..7d822c59d6 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/041-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch +@@ -0,0 +1,41 @@ ++From 3f5598286445f695bb63a22239dd3603c69a6eaf Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Mon, 28 Oct 2019 09:03:07 -0300 ++Subject: [PATCH] crypto: qce - fix ctr-aes-qce block, chunk sizes ++ ++Set blocksize of ctr-aes-qce to 1, so it can operate as a stream cipher, ++adding the definition for chucksize instead, where the underlying block ++size belongs. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 0376bb969834..0776286cfc9e 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -261,6 +261,7 @@ struct qce_skcipher_def { ++ const char *name; ++ const char *drv_name; ++ unsigned int blocksize; +++ unsigned int chunksize; ++ unsigned int ivsize; ++ unsigned int min_keysize; ++ unsigned int max_keysize; ++@@ -289,7 +290,8 @@ static const struct qce_skcipher_def skcipher_def[] = { ++ .flags = QCE_ALG_AES | QCE_MODE_CTR, ++ .name = "ctr(aes)", ++ .drv_name = "ctr-aes-qce", ++- .blocksize = AES_BLOCK_SIZE, +++ .blocksize = 1, +++ .chunksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++@@ -359,6 +361,7 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, ++ def->drv_name); ++ ++ alg->base.cra_blocksize = def->blocksize; +++ alg->chunksize = def->chunksize; ++ alg->ivsize = def->ivsize; ++ alg->min_keysize = def->min_keysize; ++ alg->max_keysize = def->max_keysize; +diff --git a/target/linux/ipq40xx/patches-4.19/042-crypto-qce-fix-xts-aes-qce-key-sizes.patch b/target/linux/ipq40xx/patches-4.19/042-crypto-qce-fix-xts-aes-qce-key-sizes.patch +new file mode 100644 +index 0000000000..dd58dcd801 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/042-crypto-qce-fix-xts-aes-qce-key-sizes.patch +@@ -0,0 +1,52 @@ ++From 0138c3c13809250338d7cfba6f4ca3b2da02b2c8 Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Thu, 21 Nov 2019 14:28:23 -0300 ++Subject: [PATCH] crypto: qce - fix xts-aes-qce key sizes ++ ++XTS-mode uses two keys, so the keysizes should be doubled in ++skcipher_def, and halved when checking if it is AES-128/192/256. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 0776286cfc9e..9b1bb32515b4 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -168,7 +168,7 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ return -EINVAL; ++ ++ if (IS_AES(flags)) { ++- switch (keylen) { +++ switch (IS_XTS(flags) ? keylen >> 1 : keylen) { ++ case AES_KEYSIZE_128: ++ case AES_KEYSIZE_256: ++ break; ++@@ -203,13 +203,15 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); +++ int keylen; ++ int ret; ++ ++ rctx->flags = tmpl->alg_flags; ++ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; +++ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; ++ ++- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && ++- ctx->enc_keylen != AES_KEYSIZE_256) { +++ if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && +++ keylen != AES_KEYSIZE_256) { ++ SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); ++ ++ skcipher_request_set_tfm(subreq, ctx->fallback); ++@@ -302,8 +304,8 @@ static const struct qce_skcipher_def skcipher_def[] = { ++ .drv_name = "xts-aes-qce", ++ .blocksize = AES_BLOCK_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++- .min_keysize = AES_MIN_KEY_SIZE, ++- .max_keysize = AES_MAX_KEY_SIZE, +++ .min_keysize = AES_MIN_KEY_SIZE * 2, +++ .max_keysize = AES_MAX_KEY_SIZE * 2, ++ }, ++ { ++ .flags = QCE_ALG_DES | QCE_MODE_ECB, +diff --git a/target/linux/ipq40xx/patches-4.19/043-crypto-qce-save-a-sg-table-slot-for-result-buf.patch b/target/linux/ipq40xx/patches-4.19/043-crypto-qce-save-a-sg-table-slot-for-result-buf.patch +new file mode 100644 +index 0000000000..9f107db035 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/043-crypto-qce-save-a-sg-table-slot-for-result-buf.patch +@@ -0,0 +1,85 @@ ++From 31f796293b6c38126a466414c565827b9cfdbe39 Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Wed, 20 Nov 2019 21:39:11 -0300 ++Subject: [PATCH] crypto: qce - save a sg table slot for result buf ++ ++When ctr-aes-qce is used for gcm-mode, an extra sg entry for the ++authentication tag is present, causing trouble when the qce driver ++prepares the dst-results eg table for dma. ++ ++It computes the number of entries needed with sg_nents_for_len, leaving ++out the tag entry. Then it creates a sg table with that number plus ++one, used to store a "result" sg. ++ ++When copying the sg table, it does not limit the number of entries ++copied, so tha extra slot is filled with the authentication tag sg. ++When the driver tries to add the result sg, the list is full, and it ++returns EINVAL. ++ ++By limiting the number of sg entries copied to the dest table, the slot ++for the result buffer is guaranteed to be unused. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c ++index 4797e795c9b9..db560c3d3e4f 100644 ++--- a/drivers/crypto/qce/dma.c +++++ b/drivers/crypto/qce/dma.c ++@@ -55,7 +55,8 @@ void qce_dma_release(struct qce_dma_data *dma) ++ } ++ ++ struct scatterlist * ++-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) +++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, +++ int max_ents) ++ { ++ struct scatterlist *sg = sgt->sgl, *sg_last = NULL; ++ ++@@ -68,12 +69,13 @@ qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) ++ if (!sg) ++ return ERR_PTR(-EINVAL); ++ ++- while (new_sgl && sg) { +++ while (new_sgl && sg && max_ents) { ++ sg_set_page(sg, sg_page(new_sgl), new_sgl->length, ++ new_sgl->offset); ++ sg_last = sg; ++ sg = sg_next(sg); ++ new_sgl = sg_next(new_sgl); +++ max_ents--; ++ } ++ ++ return sg_last; ++diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h ++index 130235d17bb4..0be71f7f7a58 100644 ++--- a/drivers/crypto/qce/dma.h +++++ b/drivers/crypto/qce/dma.h ++@@ -50,6 +50,7 @@ int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in, ++ void qce_dma_issue_pending(struct qce_dma_data *dma); ++ int qce_dma_terminate_all(struct qce_dma_data *dma); ++ struct scatterlist * ++-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add); +++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, +++ int max_ents); ++ ++ #endif /* _DMA_H_ */ ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 12f882032544..33d998f5cf5f 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -103,13 +103,13 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) ++ ++ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); ++ ++- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); +++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; ++ } ++ ++- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); +++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; +diff --git a/target/linux/ipq40xx/patches-4.19/044-crypto-qce-update-the-skcipher-IV.patch b/target/linux/ipq40xx/patches-4.19/044-crypto-qce-update-the-skcipher-IV.patch +new file mode 100644 +index 0000000000..de7829e767 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/044-crypto-qce-update-the-skcipher-IV.patch +@@ -0,0 +1,29 @@ ++From 502ca0b7c1d856a46dbd78e67690c12c47775b97 Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Fri, 22 Nov 2019 09:00:02 -0300 ++Subject: [PATCH] crypto: qce - update the skcipher IV ++ ++Update the IV after the completion of each cipher operation. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 33d998f5cf5f..51377395ed53 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -29,6 +29,7 @@ static void qce_skcipher_done(void *data) ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); ++ struct qce_device *qce = tmpl->qce; +++ struct qce_result_dump *result_buf = qce->dma.result_buf; ++ enum dma_data_direction dir_src, dir_dst; ++ u32 status; ++ int error; ++@@ -53,6 +54,7 @@ static void qce_skcipher_done(void *data) ++ if (error < 0) ++ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); ++ +++ memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); ++ qce->async_req_done(tmpl->qce, error); ++ } ++ +diff --git a/target/linux/ipq40xx/patches-4.19/046-crypto-qce-initialize-fallback-only-for-AES.patch b/target/linux/ipq40xx/patches-4.19/046-crypto-qce-initialize-fallback-only-for-AES.patch +new file mode 100644 +index 0000000000..b673884ba2 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/046-crypto-qce-initialize-fallback-only-for-AES.patch +@@ -0,0 +1,56 @@ ++From f2a33ce18232919d3831d1c61a06b6067209282d Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Fri, 22 Nov 2019 09:34:29 -0300 ++Subject: [PATCH] crypto: qce - initialize fallback only for AES ++ ++Adjust cra_flags to add CRYPTO_NEED_FALLBACK only for AES ciphers, where ++AES-192 is not handled by the qce hardware, and don't allocate & free ++the fallback skcipher for anything other than AES. ++ ++The rest of the code is unchanged, as the use of the fallback is already ++restricted to AES. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 51377395ed53..5a4863091f2a 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -246,7 +246,15 @@ static int qce_skcipher_init(struct crypto_skcipher *tfm) ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); +++ return 0; +++} +++ +++static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) +++{ +++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +++ int ret; ++ +++ qce_skcipher_init(tfm); ++ ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(&tfm->base), ++ 0, CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK); ++@@ -375,14 +383,18 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, ++ ++ alg->base.cra_priority = 300; ++ alg->base.cra_flags = CRYPTO_ALG_ASYNC | ++- CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY; ++ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); ++ alg->base.cra_alignmask = 0; ++ alg->base.cra_module = THIS_MODULE; ++ ++- alg->init = qce_skcipher_init; ++- alg->exit = qce_skcipher_exit; +++ if (IS_AES(def->flags)) { +++ alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; +++ alg->init = qce_skcipher_init_fallback; +++ alg->exit = qce_skcipher_exit; +++ } else { +++ alg->init = qce_skcipher_init; +++ } ++ ++ INIT_LIST_HEAD(&tmpl->entry); ++ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; +diff --git a/target/linux/ipq40xx/patches-4.19/047-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch b/target/linux/ipq40xx/patches-4.19/047-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch +new file mode 100644 +index 0000000000..8003f7502a +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/047-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch +@@ -0,0 +1,89 @@ ++From 686aa4db696270dadc5e8b2971769e1676251ff1 Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Fri, 31 Jan 2020 17:43:16 -0300 ++Subject: [PATCH] crypto: qce - use cryptlen when adding extra sgl ++ ++The qce crypto driver appends an extra entry to the dst sgl, to maintain ++private state information. ++ ++When the gcm driver sends requests to the ctr skcipher, it passes the ++authentication tag after the actual crypto payload, but it must not be ++touched. ++ ++Commit 1336c2221bee ("crypto: qce - save a sg table slot for result ++buf") limited the destination sgl to avoid overwriting the ++authentication tag but it assumed the tag would be in a separate sgl ++entry. ++ ++This is not always the case, so it is better to limit the length of the ++destination buffer to req->cryptlen before appending the result buf. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c ++index db560c3d3e4f..0ae9d28afa69 100644 ++--- a/drivers/crypto/qce/dma.c +++++ b/drivers/crypto/qce/dma.c ++@@ -56,9 +56,10 @@ void qce_dma_release(struct qce_dma_data *dma) ++ ++ struct scatterlist * ++ qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, ++- int max_ents) +++ unsigned int max_len) ++ { ++ struct scatterlist *sg = sgt->sgl, *sg_last = NULL; +++ unsigned int new_len; ++ ++ while (sg) { ++ if (!sg_page(sg)) ++@@ -69,13 +70,13 @@ qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, ++ if (!sg) ++ return ERR_PTR(-EINVAL); ++ ++- while (new_sgl && sg && max_ents) { ++- sg_set_page(sg, sg_page(new_sgl), new_sgl->length, ++- new_sgl->offset); +++ while (new_sgl && sg && max_len) { +++ new_len = new_sgl->length > max_len ? max_len : new_sgl->length; +++ sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset); ++ sg_last = sg; ++ sg = sg_next(sg); ++ new_sgl = sg_next(new_sgl); ++- max_ents--; +++ max_len -= new_len; ++ } ++ ++ return sg_last; ++diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h ++index 0be71f7f7a58..710d5e370293 100644 ++--- a/drivers/crypto/qce/dma.h +++++ b/drivers/crypto/qce/dma.h ++@@ -51,6 +51,6 @@ void qce_dma_issue_pending(struct qce_dma_data *dma); ++ int qce_dma_terminate_all(struct qce_dma_data *dma); ++ struct scatterlist * ++ qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, ++- int max_ents); +++ unsigned int max_len); ++ ++ #endif /* _DMA_H_ */ ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 5af74f2431ca..188eb234ba2c 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -105,13 +105,14 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) ++ ++ sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); ++ ++- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); +++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; ++ } ++ ++- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); +++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, +++ QCE_RESULT_BUF_SZ); ++ if (IS_ERR(sg)) { ++ ret = PTR_ERR(sg); ++ goto error_free; +diff --git a/target/linux/ipq40xx/patches-4.19/048-crypto-qce-use-AES-fallback-for-small-requests.patch b/target/linux/ipq40xx/patches-4.19/048-crypto-qce-use-AES-fallback-for-small-requests.patch +new file mode 100644 +index 0000000000..60ebe95c36 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/048-crypto-qce-use-AES-fallback-for-small-requests.patch +@@ -0,0 +1,126 @@ ++From 2d3b6fae7d1a2ad821769440daa91d7eec5c8250 Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Fri, 20 Dec 2019 09:41:44 -0300 ++Subject: [PATCH] crypto: qce - use AES fallback for small requests ++ ++Process small blocks using the fallback cipher, as a workaround for an ++observed failure (DMA-related, apparently) when computing the GCM ghash ++key. This brings a speed gain as well, since it avoids the latency of ++using the hardware engine to process small blocks. ++ ++Using software for all 16-byte requests would be enough to make GCM ++work, but to increase performance, a larger threshold would be better. ++Measuring the performance of supported ciphers with openssl speed, ++software matches hardware at around 768-1024 bytes. ++ ++Considering the 256-bit ciphers, software is 2-3 times faster than qce ++at 256-bytes, 30% faster at 512, and about even at 768-bytes. With ++128-bit keys, the break-even point would be around 1024-bytes. ++ ++This adds the 'aes_sw_max_len' parameter, to set the largest request ++length processed by the software fallback. Its default is being set to ++512 bytes, a little lower than the break-even point, to balance the cost ++in CPU usage. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig ++index c1595750864e..a0c4d85de4c3 100644 ++--- a/drivers/crypto/Kconfig +++++ b/drivers/crypto/Kconfig ++@@ -640,6 +640,29 @@ choice ++ ++ endchoice ++ +++config CRYPTO_DEV_QCE_SW_MAX_LEN +++ int "Default maximum request size to use software for AES" +++ depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER +++ default 512 +++ help +++ This sets the default maximum request size to perform AES requests +++ using software instead of the crypto engine. It can be changed by +++ setting the aes_sw_max_len parameter. +++ +++ Small blocks are processed faster in software than hardware. +++ Considering the 256-bit ciphers, software is 2-3 times faster than +++ qce at 256-bytes, 30% faster at 512, and about even at 768-bytes. +++ With 128-bit keys, the break-even point would be around 1024-bytes. +++ +++ The default is set a little lower, to 512 bytes, to balance the +++ cost in CPU usage. The minimum recommended setting is 16-bytes +++ (1 AES block), since AES-GCM will fail if you set it lower. +++ Setting this to zero will send all requests to the hardware. +++ +++ Note that 192-bit keys are not supported by the hardware and are +++ always processed by the software fallback, and all DES requests +++ are done by the hardware. +++ ++ config CRYPTO_DEV_QCOM_RNG ++ tristate "Qualcomm Random Number Generator Driver" ++ depends on ARCH_QCOM || COMPILE_TEST ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 188eb234ba2c..9b72fec2ab2e 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -13,6 +13,7 @@ ++ ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -20,6 +21,13 @@ ++ ++ #include "cipher.h" ++ +++static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; +++module_param(aes_sw_max_len, uint, 0644); +++MODULE_PARM_DESC(aes_sw_max_len, +++ "Only use hardware for AES requests larger than this " +++ "[0=always use hardware; anything <16 breaks AES-GCM; default=" +++ __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]"); +++ ++ static LIST_HEAD(skcipher_algs); ++ ++ static void qce_skcipher_done(void *data) ++@@ -170,15 +178,7 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ if (!key || !keylen) ++ return -EINVAL; ++ ++- if (IS_AES(flags)) { ++- switch (IS_XTS(flags) ? keylen >> 1 : keylen) { ++- case AES_KEYSIZE_128: ++- case AES_KEYSIZE_256: ++- break; ++- default: ++- goto fallback; ++- } ++- } else if (IS_DES(flags)) { +++ if (IS_DES(flags)) { ++ u32 tmp[DES_EXPKEY_WORDS]; ++ ++ ret = des_ekey(tmp, key); ++@@ -189,8 +189,8 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, ++ ++ ctx->enc_keylen = keylen; ++ memcpy(ctx->enc_key, key, keylen); ++- return 0; ++-fallback: +++ if (!IS_AES(flags)) +++ return 0; ++ ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); ++ if (!ret) ++ ctx->enc_keylen = keylen; ++@@ -213,8 +213,9 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) ++ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; ++ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; ++ ++- if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && ++- keylen != AES_KEYSIZE_256) { +++ if (IS_AES(rctx->flags) && +++ ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || +++ req->cryptlen <= aes_sw_max_len)) { ++ SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); ++ ++ skcipher_request_set_tfm(subreq, ctx->fallback); +diff --git a/target/linux/ipq40xx/patches-4.19/049-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch b/target/linux/ipq40xx/patches-4.19/049-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch +new file mode 100644 +index 0000000000..eee2241d19 +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/049-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch +@@ -0,0 +1,59 @@ ++From bbf2b1cf22dc98f3df33b6666df046dfb9564d91 Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Wed, 5 Feb 2020 13:42:25 -0300 ++Subject: [PATCH] crypto: qce - handle AES-XTS cases that qce fails ++ ++QCE hangs when presented with an AES-XTS request whose length is larger ++than QCE_SECTOR_SIZE (512-bytes), and is not a multiple of it. Let the ++fallback cipher handle them. ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c ++index 3849d7bcaeb0..3e0fcd7613f1 100644 ++--- a/drivers/crypto/qce/common.c +++++ b/drivers/crypto/qce/common.c ++@@ -23,8 +23,6 @@ ++ #include "regs-v5.h" ++ #include "sha.h" ++ ++-#define QCE_SECTOR_SIZE 512 ++- ++ static inline u32 qce_read(struct qce_device *qce, u32 offset) ++ { ++ return readl(qce->base + offset); ++diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h ++index 3252efa41e7a..5f9d3c4e3ead 100644 ++--- a/drivers/crypto/qce/common.h +++++ b/drivers/crypto/qce/common.h ++@@ -20,6 +20,9 @@ ++ #include ++ #include ++ +++/* xts du size */ +++#define QCE_SECTOR_SIZE 512 +++ ++ /* key size in bytes */ ++ #define QCE_SHA_HMAC_KEY_SIZE 64 ++ #define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256 ++diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c ++index 9b72fec2ab2e..e46cb8269640 100644 ++--- a/drivers/crypto/qce/skcipher.c +++++ b/drivers/crypto/qce/skcipher.c ++@@ -213,9 +213,14 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) ++ rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; ++ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; ++ +++ /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and +++ * is not a multiple of it; pass such requests to the fallback +++ */ ++ if (IS_AES(rctx->flags) && ++- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || ++- req->cryptlen <= aes_sw_max_len)) { +++ (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || +++ req->cryptlen <= aes_sw_max_len) || +++ (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE && +++ req->cryptlen % QCE_SECTOR_SIZE))) { ++ SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); ++ ++ skcipher_request_set_tfm(subreq, ctx->fallback); +diff --git a/target/linux/ipq40xx/patches-4.19/051-crypto-qce-allow-building-only-hashes-ciphers.patch b/target/linux/ipq40xx/patches-4.19/051-crypto-qce-allow-building-only-hashes-ciphers.patch +new file mode 100644 +index 0000000000..3d4214929c +--- /dev/null ++++ b/target/linux/ipq40xx/patches-4.19/051-crypto-qce-allow-building-only-hashes-ciphers.patch +@@ -0,0 +1,415 @@ ++From 62134842498927a0fcc19798a615340a7a6a9e62 Mon Sep 17 00:00:00 2001 ++From: Eneas U de Queiroz ++Date: Mon, 28 Oct 2019 15:17:19 -0300 ++Subject: [PATCH] crypto: qce - allow building only hashes/ciphers ++ ++Signed-off-by: Eneas U de Queiroz ++ ++diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig ++index a8c4ce07fc9d..c1595750864e 100644 ++--- a/drivers/crypto/Kconfig +++++ b/drivers/crypto/Kconfig ++@@ -573,6 +573,14 @@ config CRYPTO_DEV_QCE ++ tristate "Qualcomm crypto engine accelerator" ++ depends on ARCH_QCOM || COMPILE_TEST ++ depends on HAS_IOMEM +++ help +++ This driver supports Qualcomm crypto engine accelerator +++ hardware. To compile this driver as a module, choose M here. The +++ module will be called qcrypto. +++ +++config CRYPTO_DEV_QCE_SKCIPHER +++ bool +++ depends on CRYPTO_DEV_QCE ++ select CRYPTO_AES ++ select CRYPTO_DES ++ select CRYPTO_ECB ++@@ -580,10 +588,57 @@ config CRYPTO_DEV_QCE ++ select CRYPTO_XTS ++ select CRYPTO_CTR ++ select CRYPTO_BLKCIPHER ++- help ++- This driver supports Qualcomm crypto engine accelerator ++- hardware. To compile this driver as a module, choose M here. The ++- module will be called qcrypto. +++ +++config CRYPTO_DEV_QCE_SHA +++ bool +++ depends on CRYPTO_DEV_QCE +++ +++choice +++ prompt "Algorithms enabled for QCE acceleration" +++ default CRYPTO_DEV_QCE_ENABLE_ALL +++ depends on CRYPTO_DEV_QCE +++ help +++ This option allows to choose whether to build support for all algorihtms +++ (default), hashes-only, or skciphers-only. +++ +++ The QCE engine does not appear to scale as well as the CPU to handle +++ multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the +++ QCE handles only 2 requests in parallel. +++ +++ Ipsec throughput seems to improve when disabling either family of +++ algorithms, sharing the load with the CPU. Enabling skciphers-only +++ appears to work best. +++ +++ config CRYPTO_DEV_QCE_ENABLE_ALL +++ bool "All supported algorithms" +++ select CRYPTO_DEV_QCE_SKCIPHER +++ select CRYPTO_DEV_QCE_SHA +++ help +++ Enable all supported algorithms: +++ - AES (CBC, CTR, ECB, XTS) +++ - 3DES (CBC, ECB) +++ - DES (CBC, ECB) +++ - SHA1, HMAC-SHA1 +++ - SHA256, HMAC-SHA256 +++ +++ config CRYPTO_DEV_QCE_ENABLE_SKCIPHER +++ bool "Symmetric-key ciphers only" +++ select CRYPTO_DEV_QCE_SKCIPHER +++ help +++ Enable symmetric-key ciphers only: +++ - AES (CBC, CTR, ECB, XTS) +++ - 3DES (ECB, CBC) +++ - DES (ECB, CBC) +++ +++ config CRYPTO_DEV_QCE_ENABLE_SHA +++ bool "Hash/HMAC only" +++ select CRYPTO_DEV_QCE_SHA +++ help +++ Enable hashes/HMAC algorithms only: +++ - SHA1, HMAC-SHA1 +++ - SHA256, HMAC-SHA256 +++ +++endchoice ++ ++ config CRYPTO_DEV_QCOM_RNG ++ tristate "Qualcomm Random Number Generator Driver" ++diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile ++index 8caa04e1ec43..14ade8a7d664 100644 ++--- a/drivers/crypto/qce/Makefile +++++ b/drivers/crypto/qce/Makefile ++@@ -2,6 +2,7 @@ ++ obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o ++ qcrypto-objs := core.o \ ++ common.o \ ++- dma.o \ ++- sha.o \ ++- skcipher.o +++ dma.o +++ +++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o +++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o ++diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c ++index e0202755682b..3849d7bcaeb0 100644 ++--- a/drivers/crypto/qce/common.c +++++ b/drivers/crypto/qce/common.c ++@@ -53,52 +53,56 @@ qce_clear_array(struct qce_device *qce, u32 offset, unsigned int len) ++ qce_write(qce, offset + i * sizeof(u32), 0); ++ } ++ ++-static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) +++static u32 qce_config_reg(struct qce_device *qce, int little) ++ { ++- u32 cfg = 0; +++ u32 beats = (qce->burst_size >> 3) - 1; +++ u32 pipe_pair = qce->pipe_pair_id; +++ u32 config; ++ ++- if (IS_AES(flags)) { ++- if (aes_key_size == AES_KEYSIZE_128) ++- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; ++- else if (aes_key_size == AES_KEYSIZE_256) ++- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; ++- } +++ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; +++ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | +++ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); +++ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; +++ config &= ~HIGH_SPD_EN_N_SHIFT; ++ ++- if (IS_AES(flags)) ++- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; ++- else if (IS_DES(flags) || IS_3DES(flags)) ++- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; +++ if (little) +++ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); ++ ++- if (IS_DES(flags)) ++- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; +++ return config; +++} ++ ++- if (IS_3DES(flags)) ++- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; +++void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) +++{ +++ __be32 *d = dst; +++ const u8 *s = src; +++ unsigned int n; ++ ++- switch (flags & QCE_MODE_MASK) { ++- case QCE_MODE_ECB: ++- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; ++- break; ++- case QCE_MODE_CBC: ++- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; ++- break; ++- case QCE_MODE_CTR: ++- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; ++- break; ++- case QCE_MODE_XTS: ++- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; ++- break; ++- case QCE_MODE_CCM: ++- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; ++- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; ++- break; ++- default: ++- return ~0; +++ n = len / sizeof(u32); +++ for (; n > 0; n--) { +++ *d = cpu_to_be32p((const __u32 *) s); +++ s += sizeof(__u32); +++ d++; ++ } +++} ++ ++- return cfg; +++static void qce_setup_config(struct qce_device *qce) +++{ +++ u32 config; +++ +++ /* get big endianness */ +++ config = qce_config_reg(qce, 0); +++ +++ /* clear status */ +++ qce_write(qce, REG_STATUS, 0); +++ qce_write(qce, REG_CONFIG, config); +++} +++ +++static inline void qce_crypto_go(struct qce_device *qce) +++{ +++ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); ++ } ++ +++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA ++ static u32 qce_auth_cfg(unsigned long flags, u32 key_size) ++ { ++ u32 cfg = 0; ++@@ -145,88 +149,6 @@ static u32 qce_auth_cfg(unsigned long flags, u32 key_size) ++ return cfg; ++ } ++ ++-static u32 qce_config_reg(struct qce_device *qce, int little) ++-{ ++- u32 beats = (qce->burst_size >> 3) - 1; ++- u32 pipe_pair = qce->pipe_pair_id; ++- u32 config; ++- ++- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; ++- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | ++- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); ++- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; ++- config &= ~HIGH_SPD_EN_N_SHIFT; ++- ++- if (little) ++- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); ++- ++- return config; ++-} ++- ++-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) ++-{ ++- __be32 *d = dst; ++- const u8 *s = src; ++- unsigned int n; ++- ++- n = len / sizeof(u32); ++- for (; n > 0; n--) { ++- *d = cpu_to_be32p((const __u32 *) s); ++- s += sizeof(__u32); ++- d++; ++- } ++-} ++- ++-static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) ++-{ ++- u8 swap[QCE_AES_IV_LENGTH]; ++- u32 i, j; ++- ++- if (ivsize > QCE_AES_IV_LENGTH) ++- return; ++- ++- memset(swap, 0, QCE_AES_IV_LENGTH); ++- ++- for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; ++- i < QCE_AES_IV_LENGTH; i++, j--) ++- swap[i] = src[j]; ++- ++- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); ++-} ++- ++-static void qce_xtskey(struct qce_device *qce, const u8 *enckey, ++- unsigned int enckeylen, unsigned int cryptlen) ++-{ ++- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; ++- unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); ++- unsigned int xtsdusize; ++- ++- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, ++- enckeylen / 2); ++- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); ++- ++- /* xts du size 512B */ ++- xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); ++- qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); ++-} ++- ++-static void qce_setup_config(struct qce_device *qce) ++-{ ++- u32 config; ++- ++- /* get big endianness */ ++- config = qce_config_reg(qce, 0); ++- ++- /* clear status */ ++- qce_write(qce, REG_STATUS, 0); ++- qce_write(qce, REG_CONFIG, config); ++-} ++- ++-static inline void qce_crypto_go(struct qce_device *qce) ++-{ ++- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); ++-} ++- ++ static int qce_setup_regs_ahash(struct crypto_async_request *async_req, ++ u32 totallen, u32 offset) ++ { ++@@ -311,6 +233,87 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req, ++ ++ return 0; ++ } +++#endif +++ +++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER +++static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) +++{ +++ u32 cfg = 0; +++ +++ if (IS_AES(flags)) { +++ if (aes_key_size == AES_KEYSIZE_128) +++ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; +++ else if (aes_key_size == AES_KEYSIZE_256) +++ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; +++ } +++ +++ if (IS_AES(flags)) +++ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; +++ else if (IS_DES(flags) || IS_3DES(flags)) +++ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; +++ +++ if (IS_DES(flags)) +++ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; +++ +++ if (IS_3DES(flags)) +++ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; +++ +++ switch (flags & QCE_MODE_MASK) { +++ case QCE_MODE_ECB: +++ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; +++ break; +++ case QCE_MODE_CBC: +++ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; +++ break; +++ case QCE_MODE_CTR: +++ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; +++ break; +++ case QCE_MODE_XTS: +++ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; +++ break; +++ case QCE_MODE_CCM: +++ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; +++ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; +++ break; +++ default: +++ return ~0; +++ } +++ +++ return cfg; +++} +++ +++static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) +++{ +++ u8 swap[QCE_AES_IV_LENGTH]; +++ u32 i, j; +++ +++ if (ivsize > QCE_AES_IV_LENGTH) +++ return; +++ +++ memset(swap, 0, QCE_AES_IV_LENGTH); +++ +++ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; +++ i < QCE_AES_IV_LENGTH; i++, j--) +++ swap[i] = src[j]; +++ +++ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); +++} +++ +++static void qce_xtskey(struct qce_device *qce, const u8 *enckey, +++ unsigned int enckeylen, unsigned int cryptlen) +++{ +++ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; +++ unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); +++ unsigned int xtsdusize; +++ +++ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, +++ enckeylen / 2); +++ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); +++ +++ /* xts du size 512B */ +++ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); +++ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); +++} ++ ++ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, ++ u32 totallen, u32 offset) ++@@ -392,15 +395,20 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, ++ ++ return 0; ++ } +++#endif ++ ++ int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen, ++ u32 offset) ++ { ++ switch (type) { +++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER ++ case CRYPTO_ALG_TYPE_SKCIPHER: ++ return qce_setup_regs_skcipher(async_req, totallen, offset); +++#endif +++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA ++ case CRYPTO_ALG_TYPE_AHASH: ++ return qce_setup_regs_ahash(async_req, totallen, offset); +++#endif ++ default: ++ return -EINVAL; ++ } ++diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c ++index bf409edc23ab..4ad79b67fc51 100644 ++--- a/drivers/crypto/qce/core.c +++++ b/drivers/crypto/qce/core.c ++@@ -30,8 +30,12 @@ ++ #define QCE_QUEUE_LENGTH 1 ++ ++ static const struct qce_algo_ops *qce_ops[] = { +++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER ++ &skcipher_ops, +++#endif +++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA ++ &ahash_ops, +++#endif ++ }; ++ ++ static void qce_unregister_algs(struct qce_device *qce) +diff --git a/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch b/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch +index 6f7a3a693b..4cabfc8f59 100644 +--- a/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch ++++ b/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch +@@ -8,7 +8,7 @@ + { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, + { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, +-@@ -1284,11 +1285,12 @@ static const struct flash_info spi_nor_i ++@@ -1286,11 +1287,12 @@ static const struct flash_info spi_nor_i + { }, + }; + +@@ -23,7 +23,7 @@ + + tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + if (tmp < 0) { +-@@ -1299,10 +1301,16 @@ static const struct flash_info *spi_nor_ ++@@ -1301,10 +1303,16 @@ static const struct flash_info *spi_nor_ + for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { + info = &spi_nor_ids[tmp]; + if (info->id_len) { +@@ -42,7 +42,7 @@ + dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); +-@@ -2836,7 +2844,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++@@ -2838,7 +2846,7 @@ int spi_nor_scan(struct spi_nor *nor, co + info = spi_nor_match_id(name); + /* Try to auto-detect if chip name wasn't specified or not found */ + if (!info) +@@ -51,7 +51,7 @@ + if (IS_ERR_OR_NULL(info)) + return -ENOENT; + +-@@ -2847,7 +2855,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++@@ -2849,7 +2857,7 @@ int spi_nor_scan(struct spi_nor *nor, co + if (name && info->id_len) { + const struct flash_info *jinfo; + diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index dc7eb77986..60267f3c8e 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -110,8 +110,8 @@ define KernelPackage/crypto-crc32 DEPENDS:=+kmod-crypto-hash KCONFIG:=CONFIG_CRYPTO_CRC32 HIDDEN:=1 - FILES:=$(LINUX_DIR)/crypto/crc32_generic.ko@ge4.9 - AUTOLOAD:=$(call AutoLoad,04,crc32_generic@ge4.9,1) + FILES:=$(LINUX_DIR)/crypto/crc32_generic.ko + AUTOLOAD:=$(call AutoLoad,04,crc32_generic,1) $(call AddDepends/crypto) endef @@ -169,7 +169,9 @@ $(eval $(call KernelPackage,crypto-deflate)) define KernelPackage/crypto-des TITLE:=DES/3DES cipher CryptoAPI module KCONFIG:=CONFIG_CRYPTO_DES - FILES:=$(LINUX_DIR)/crypto/des_generic.ko + FILES:= \ + $(LINUX_DIR)/crypto/des_generic.ko \ + $(LINUX_DIR)/lib/crypto/libdes.ko@ge5.4 AUTOLOAD:=$(call AutoLoad,09,des_generic) $(call AddDepends/crypto) endef @@ -194,7 +196,8 @@ define KernelPackage/crypto-ecdh DEPENDS:=+kmod-crypto-kpp KCONFIG:= CONFIG_CRYPTO_ECDH FILES:= \ - $(LINUX_DIR)/crypto/ecdh_generic.ko + $(LINUX_DIR)/crypto/ecdh_generic.ko \ + $(LINUX_DIR)/crypto/ecc.ko@ge5.2 AUTOLOAD:=$(call AutoLoad,10,ecdh_generic) $(call AddDepends/crypto) endef @@ -263,12 +266,23 @@ $(eval $(call KernelPackage,crypto-gf128)) define KernelPackage/crypto-ghash TITLE:=GHASH digest CryptoAPI module DEPENDS:=+kmod-crypto-gf128 +kmod-crypto-hash - KCONFIG:=CONFIG_CRYPTO_GHASH + KCONFIG:= \ + CONFIG_CRYPTO_GHASH \ + CONFIG_CRYPTO_GHASH_ARM_CE FILES:=$(LINUX_DIR)/crypto/ghash-generic.ko AUTOLOAD:=$(call AutoLoad,09,ghash-generic) $(call AddDepends/crypto) endef +define KernelPackage/crypto-ghash/arm-ce + FILES+= $(LINUX_DIR)/arch/arm/crypto/ghash-arm-ce.ko + AUTOLOAD+=$(call AutoLoad,09,ghash-arm-ce) +endef + +KernelPackage/crypto-ghash/imx6=$(KernelPackage/crypto-ghash/arm-ce) +KernelPackage/crypto-ghash/ipq40xx=$(KernelPackage/crypto-ghash/arm-ce) +KernelPackage/crypto-ghash/mvebu=$(KernelPackage/crypto-ghash/arm-ce) + $(eval $(call KernelPackage,crypto-ghash)) @@ -402,7 +416,6 @@ endef $(eval $(call KernelPackage,crypto-hw-talitos)) - define KernelPackage/crypto-iv TITLE:=CryptoAPI initialization vectors DEPENDS:=+kmod-crypto-manager +kmod-crypto-rng +kmod-crypto-wq @@ -417,7 +430,6 @@ endef $(eval $(call KernelPackage,crypto-iv)) - define KernelPackage/crypto-kpp TITLE:=Key-agreement Protocol Primitives KCONFIG:=CONFIG_CRYPTO_KPP @@ -656,11 +668,10 @@ define KernelPackage/crypto-rng CONFIG_CRYPTO_JITTERENTROPY \ CONFIG_CRYPTO_RNG2 FILES:= \ - $(LINUX_DIR)/crypto/drbg.ko@ge4.2 \ - $(LINUX_DIR)/crypto/jitterentropy_rng.ko@ge4.2 \ - $(LINUX_DIR)/crypto/krng.ko@lt4.2 \ + $(LINUX_DIR)/crypto/drbg.ko \ + $(LINUX_DIR)/crypto/jitterentropy_rng.ko \ $(LINUX_DIR)/crypto/rng.ko - AUTOLOAD:=$(call AutoLoad,09,drbg@ge4.2 jitterentropy_rng@ge4.2 krng@lt4.2 rng) + AUTOLOAD:=$(call AutoLoad,09,drbg jitterentropy_rng rng) $(call AddDepends/crypto) endef @@ -684,6 +695,8 @@ define KernelPackage/crypto-sha1 DEPENDS:=+kmod-crypto-hash KCONFIG:= \ CONFIG_CRYPTO_SHA1 \ + CONFIG_CRYPTO_SHA1_ARM \ + CONFIG_CRYPTO_SHA1_ARM_NEON \ CONFIG_CRYPTO_SHA1_OCTEON \ CONFIG_CRYPTO_SHA1_SSSE3 FILES:=$(LINUX_DIR)/crypto/sha1_generic.ko @@ -691,11 +704,28 @@ define KernelPackage/crypto-sha1 $(call AddDepends/crypto) endef +define KernelPackage/crypto-sha1/arm + FILES+=$(LINUX_DIR)/arch/arm/crypto/sha1-arm.ko + AUTOLOAD+=$(call AutoLoad,09,sha1-arm) +endef + +define KernelPackage/crypto-sha1/arm-neon + $(call KernelPackage/crypto-sha1/arm) + FILES+=$(LINUX_DIR)/arch/arm/crypto/sha1-arm-neon.ko + AUTOLOAD+=$(call AutoLoad,09,sha1-arm-neon) +endef + +KernelPackage/crypto-sha1/imx6=$(KernelPackage/crypto-sha1/arm-neon) +KernelPackage/crypto-sha1/ipq40xx=$(KernelPackage/crypto-sha1/arm-neon) +KernelPackage/crypto-sha1/mvebu/cortexa9=$(KernelPackage/crypto-sha1/arm-neon) + define KernelPackage/crypto-sha1/octeon FILES+=$(LINUX_DIR)/arch/mips/cavium-octeon/crypto/octeon-sha1.ko AUTOLOAD+=$(call AutoLoad,09,octeon-sha1) endef +KernelPackage/crypto-sha1/tegra=$(KernelPakcage/crypto-sha1/arm) + define KernelPackage/crypto-sha1/x86/64 FILES+=$(LINUX_DIR)/arch/x86/crypto/sha1-ssse3.ko AUTOLOAD+=$(call AutoLoad,09,sha1-ssse3) @@ -711,7 +741,9 @@ define KernelPackage/crypto-sha256 CONFIG_CRYPTO_SHA256 \ CONFIG_CRYPTO_SHA256_OCTEON \ CONFIG_CRYPTO_SHA256_SSSE3 - FILES:=$(LINUX_DIR)/crypto/sha256_generic.ko + FILES:= \ + $(LINUX_DIR)/crypto/sha256_generic.ko \ + $(LINUX_DIR)/lib/crypto/libsha256.ko@ge5.4 AUTOLOAD:=$(call AutoLoad,09,sha256_generic) $(call AddDepends/crypto) endef @@ -734,6 +766,7 @@ define KernelPackage/crypto-sha512 DEPENDS:=+kmod-crypto-hash KCONFIG:= \ CONFIG_CRYPTO_SHA512 \ + CONFIG_CRYPTO_SHA512_ARM \ CONFIG_CRYPTO_SHA512_OCTEON \ CONFIG_CRYPTO_SHA512_SSSE3 FILES:=$(LINUX_DIR)/crypto/sha512_generic.ko @@ -741,11 +774,22 @@ define KernelPackage/crypto-sha512 $(call AddDepends/crypto) endef +define KernelPackage/crypto-sha512/arm + FILES+=$(LINUX_DIR)/arch/arm/crypto/sha512-arm.ko + AUTOLOAD+=$(call AutoLoad,09,sha512-arm) +endef + +KernelPackage/crypto-sha512/imx6=$(KernelPackage/crypto-sha512/arm) +KernelPackage/crypto-sha512/ipq40xx=$(KernelPackage/crypto-sha512/arm) +KernelPackage/crypto-sha512/mvebu/cortexa9=$(KernelPackage/crypto-sha512/arm) + define KernelPackage/crypto-sha512/octeon FILES+=$(LINUX_DIR)/arch/mips/cavium-octeon/crypto/octeon-sha512.ko AUTOLOAD+=$(call AutoLoad,09,octeon-sha512) endef +KernelPackage/crypto-sha512/tegra=$(KernelPackage/crypto-sha512/arm) + define KernelPackage/crypto-sha512/x86/64 FILES+=$(LINUX_DIR)/arch/x86/crypto/sha512-ssse3.ko AUTOLOAD+=$(call AutoLoad,09,sha512-ssse3) @@ -768,6 +812,7 @@ define KernelPackage/crypto-user TITLE:=CryptoAPI userspace interface DEPENDS:=+kmod-crypto-hash +kmod-crypto-manager KCONFIG:= \ + CONFIG_CRYPTO_USER \ CONFIG_CRYPTO_USER_API \ CONFIG_CRYPTO_USER_API_AEAD \ CONFIG_CRYPTO_USER_API_HASH \ @@ -778,8 +823,9 @@ define KernelPackage/crypto-user $(LINUX_DIR)/crypto/algif_aead.ko \ $(LINUX_DIR)/crypto/algif_hash.ko \ $(LINUX_DIR)/crypto/algif_rng.ko \ - $(LINUX_DIR)/crypto/algif_skcipher.ko - AUTOLOAD:=$(call AutoLoad,09,af_alg algif_aead algif_hash algif_rng algif_skcipher) + $(LINUX_DIR)/crypto/algif_skcipher.ko \ + $(LINUX_DIR)/crypto/crypto_user.ko + AUTOLOAD:=$(call AutoLoad,09,af_alg algif_aead algif_hash algif_rng algif_skcipher crypto_user) $(call AddDepends/crypto) endef diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index d26bcb813e..1782bae0f8 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -1,4 +1,4 @@ -# +# # Copyright (C) 2007-2015 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. diff --git a/package/kernel/mac80211/patches/build/100-backports-pci-Include-linux-pci-aspm.h.patch b/package/kernel/mac80211/patches/build/100-backports-pci-Include-linux-pci-aspm.h.patch new file mode 100644 index 0000000000..5faeb96748 --- /dev/null +++ b/package/kernel/mac80211/patches/build/100-backports-pci-Include-linux-pci-aspm.h.patch @@ -0,0 +1,24 @@ +From: Hauke Mehrtens +Date: Fri, 27 Sep 2019 23:12:08 +0200 +Subject: [PATCH] backports: pci: Include linux/pci-aspm.h + +In upstream commit 7ce2e76a0420 linux/pci-aspm.h was removed and the +content included into pci.h. Add an include to have the functions +defined in linux/pci-aspm.h available when linux/pci.h is included. + +Signed-off-by: Hauke Mehrtens +--- + +--- a/backport-include/linux/pci.h ++++ b/backport-include/linux/pci.h +@@ -3,6 +3,10 @@ + #include_next + #include + ++#if LINUX_VERSION_IS_LESS(5,4,0) ++#include ++#endif ++ + #ifndef module_pci_driver + /** + * module_pci_driver() - Helper macro for registering a PCI driver diff --git a/package/kernel/mac80211/patches/build/101-backport-add-pci_disable_link_state-wrapper-with-ret.patch b/package/kernel/mac80211/patches/build/101-backport-add-pci_disable_link_state-wrapper-with-ret.patch new file mode 100644 index 0000000000..a41879184b --- /dev/null +++ b/package/kernel/mac80211/patches/build/101-backport-add-pci_disable_link_state-wrapper-with-ret.patch @@ -0,0 +1,43 @@ +From: Felix Fietkau +Date: Mon, 28 Oct 2019 15:20:40 +0100 +Subject: [PATCH] backport: add pci_disable_link_state wrapper with return code + +The signature of pci_disable_link_state was changed to indicate if the state +was successfully disabled. Since the old version did not have this, add a +wrapper which checks the pcie register to determine the return code + +Signed-off-by: Felix Fietkau +--- + +--- a/backport-include/linux/pci.h ++++ b/backport-include/linux/pci.h +@@ -236,4 +236,29 @@ static inline struct pci_dev *pcie_find_ + (PCI_IRQ_LEGACY | PCI_IRQ_MSI | PCI_IRQ_MSIX) + #endif + ++#if defined(CONFIG_PCI) && LINUX_VERSION_IS_LESS(5,3,0) ++ ++static inline int ++LINUX_BACKPORT(pci_disable_link_state)(struct pci_dev *pdev, int state) ++{ ++ u16 aspmc; ++ ++ pci_disable_link_state(pdev, state); ++ ++ pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &aspmc); ++ if ((state & PCIE_LINK_STATE_L0S) && ++ (aspmc & PCI_EXP_LNKCTL_ASPM_L0S)) ++ return -EPERM; ++ ++ if ((state & PCIE_LINK_STATE_L1) && ++ (aspmc & PCI_EXP_LNKCTL_ASPM_L1)) ++ return -EPERM; ++ ++ return 0; ++} ++ ++#define pci_disable_link_state LINUX_BACKPORT(pci_disable_link_state) ++ ++#endif ++ + #endif /* _BACKPORT_LINUX_PCI_H */ diff --git a/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch new file mode 100644 index 0000000000..c486b2251b --- /dev/null +++ b/package/kernel/mac80211/patches/rt2x00/612-rt2x00-led-tpt-trigger-support.patch @@ -0,0 +1,44 @@ +From: David Bauer +Date: Mon, 16 Dec 2019 20:47:06 +0100 +Subject: [PATCH] rt2x00: add throughput LED trigger + +This adds a (currently missing) throughput LED trigger for the rt2x00 +driver. Previously, LED triggers had to be assigned to the netdev, which +was limited to a single VAP. + +Signed-off-by: David Bauer +Tested-by: Christoph Krapp + +--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +@@ -1140,6 +1140,19 @@ static void rt2x00lib_remove_hw(struct r + kfree(rt2x00dev->spec.channels_info); + } + ++static const struct ieee80211_tpt_blink rt2x00_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 }, ++}; ++ + static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) + { + struct hw_mode_spec *spec = &rt2x00dev->spec; +@@ -1222,6 +1235,10 @@ static int rt2x00lib_probe_hw(struct rt2 + + #undef RT2X00_TASKLET_INIT + ++ ieee80211_create_tpt_led_trigger(rt2x00dev->hw, ++ IEEE80211_TPT_LEDTRIG_FL_RADIO, rt2x00_tpt_blink, ++ ARRAY_SIZE(rt2x00_tpt_blink)); ++ + /* + * Register HW. + */ diff --git a/package/kernel/mac80211/patches/subsys/368-cfg80211-add-local-BSS-receive-time-to-survey-inform.patch b/package/kernel/mac80211/patches/subsys/368-cfg80211-add-local-BSS-receive-time-to-survey-inform.patch new file mode 100644 index 0000000000..e6d384784e --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/368-cfg80211-add-local-BSS-receive-time-to-survey-inform.patch @@ -0,0 +1,77 @@ +From: Felix Fietkau +Date: Wed, 28 Aug 2019 12:13:55 +0200 +Subject: [PATCH] cfg80211: add local BSS receive time to survey information + +This is useful for checking how much airtime is being used up by other +transmissions on the channel, e.g. by calculating (time_rx - time_bss_rx) +or (time_busy - time_bss_rx - time_tx) + +Signed-off-by: Felix Fietkau +--- + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -668,6 +668,7 @@ ieee80211_chandef_max_power(struct cfg80 + * @SURVEY_INFO_TIME_RX: receive time was filled in + * @SURVEY_INFO_TIME_TX: transmit time was filled in + * @SURVEY_INFO_TIME_SCAN: scan time was filled in ++ * @SURVEY_INFO_TIME_BSS_RX: local BSS receive time was filled in + * + * Used by the driver to indicate which info in &struct survey_info + * it has filled in during the get_survey(). +@@ -681,6 +682,7 @@ enum survey_info_flags { + SURVEY_INFO_TIME_RX = BIT(5), + SURVEY_INFO_TIME_TX = BIT(6), + SURVEY_INFO_TIME_SCAN = BIT(7), ++ SURVEY_INFO_TIME_BSS_RX = BIT(8), + }; + + /** +@@ -697,6 +699,7 @@ enum survey_info_flags { + * @time_rx: amount of time the radio spent receiving data + * @time_tx: amount of time the radio spent transmitting data + * @time_scan: amount of time the radio spent for scanning ++ * @time_bss_rx: amount of time the radio spent receiving data on a local BSS + * + * Used by dump_survey() to report back per-channel survey information. + * +@@ -711,6 +714,7 @@ struct survey_info { + u64 time_rx; + u64 time_tx; + u64 time_scan; ++ u64 time_bss_rx; + u32 filled; + s8 noise; + }; +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -3693,6 +3693,8 @@ enum nl80211_user_reg_hint_type { + * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan + * (on this channel or globally) + * @NL80211_SURVEY_INFO_PAD: attribute used for padding for 64-bit alignment ++ * @NL80211_SURVEY_INFO_TIME_BSS_RX: amount of time the radio spent ++ * receiving local BSS data + * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number + * currently defined + * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use +@@ -3709,6 +3711,7 @@ enum nl80211_survey_info { + NL80211_SURVEY_INFO_TIME_TX, + NL80211_SURVEY_INFO_TIME_SCAN, + NL80211_SURVEY_INFO_PAD, ++ NL80211_SURVEY_INFO_TIME_BSS_RX, + + /* keep last */ + __NL80211_SURVEY_INFO_AFTER_LAST, +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -8367,6 +8367,10 @@ static int nl80211_send_survey(struct sk + nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN, + survey->time_scan, NL80211_SURVEY_INFO_PAD)) + goto nla_put_failure; ++ if ((survey->filled & SURVEY_INFO_TIME_BSS_RX) && ++ nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BSS_RX, ++ survey->time_bss_rx, NL80211_SURVEY_INFO_PAD)) ++ goto nla_put_failure; + + nla_nest_end(msg, infoattr); + diff --git a/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch index 81007b87cc..cf4fdc13e9 100644 --- a/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/subsys/522-mac80211_configure_antenna_gain.patch @@ -1,6 +1,6 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -2968,6 +2968,7 @@ struct cfg80211_external_auth_params { +@@ -2972,6 +2972,7 @@ struct cfg80211_external_auth_params { * (as advertised by the nl80211 feature flag.) * @get_tx_power: store the current TX power into the dbm variable; * return 0 if successful @@ -8,7 +8,7 @@ * * @set_wds_peer: set the WDS peer for a WDS interface * -@@ -3268,6 +3269,7 @@ struct cfg80211_ops { +@@ -3272,6 +3273,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); diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index db0bf04d0a..921c32c56b 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2019-08-22 -PKG_SOURCE_VERSION:=2a0edbb4473b71dfaa4756f7189abf6cb7f7be8b -PKG_MIRROR_HASH:=a37975c179b929716c40d19fdcd5b131386d7f497eb8cd5d848be74e76d50d21 +PKG_SOURCE_DATE:=2020-03-10 +PKG_SOURCE_VERSION:=08054d5ab1350fcb8563feb90e6ab7f8f4a0a1b7 +PKG_MIRROR_HASH:=b41a3cab1485c68befb1dcb4c1e426d41705db1b2a57851dafd6e8f75eeea3d7 PKG_MAINTAINER:=Felix Fietkau PKG_BUILD_PARALLEL:=1 @@ -246,12 +246,12 @@ define KernelPackage/mt7603/install endef define KernelPackage/mt7615e/install - $(INSTALL_DIR) $(1)/lib/firmware + $(INSTALL_DIR) $(1)/lib/firmware/mediatek cp \ $(PKG_BUILD_DIR)/firmware/mt7615_cr4.bin \ $(PKG_BUILD_DIR)/firmware/mt7615_n9.bin \ $(PKG_BUILD_DIR)/firmware/mt7615_rom_patch.bin \ - $(1)/lib/firmware + $(1)/lib/firmware/mediatek endef $(eval $(call KernelPackage,mt76-core)) @@ -266,4 +266,4 @@ $(eval $(call KernelPackage,mt76x2u)) $(eval $(call KernelPackage,mt76x2)) $(eval $(call KernelPackage,mt7603)) $(eval $(call KernelPackage,mt7615e)) -$(eval $(call KernelPackage,mt76)) +$(eval $(call KernelPackage,mt76)) \ No newline at end of file diff --git a/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po b/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po index 86a01d9b55..b462b053e7 100644 --- a/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po +++ b/package/lean/luci-app-adbyby-plus/po/zh-cn/adbyby.po @@ -91,6 +91,9 @@ msgstr "更新失败!" msgid "No new data!" msgstr "你已经是最新数据,无需更新!" +msgid "Total Records:" +msgstr "新的总纪录数:" + msgid "Delete All Subscribe Rules" msgstr "清空所有订阅的规则库" diff --git a/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot b/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot index 934477d415..aba2fce12a 100755 --- a/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot +++ b/package/lean/luci-app-autoreboot/root/etc/init.d/autoreboot @@ -19,10 +19,12 @@ run_reboot() week="*" fi sed -i '/reboot/d' /etc/crontabs/root >/dev/null 2>&1 + /etc/init.d/cron restart echo "$minute $hour * * $week sleep 5 && touch /etc/banner && reboot" >> /etc/crontabs/root echo "Auto REBOOT has started." else sed -i '/reboot/d' /etc/crontabs/root >/dev/null 2>&1 + /etc/init.d/cron restart echo "Auto REBOOT has started." fi } diff --git a/package/lean/luci-app-nps/po/zh-cn/nps.po b/package/lean/luci-app-nps/po/zh-cn/nps.po index 4fb9ad411e..3891bc0c89 100644 --- a/package/lean/luci-app-nps/po/zh-cn/nps.po +++ b/package/lean/luci-app-nps/po/zh-cn/nps.po @@ -26,4 +26,19 @@ msgid "Nps is running." msgstr "Nps 运行中" msgid "Nps is not running." -msgstr "Nps 未运行" \ No newline at end of file +msgstr "Nps 未运行" + +msgid "Basic Setting" +msgstr "基本设置" + +msgid "Protocol Type" +msgstr "协议类型" + +msgid "Server" +msgstr "服务端地址" + +msgid "TCP Protocol" +msgstr "TCP" + +msgid "KCP Protocol" +msgstr "KCP" diff --git a/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm b/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm index 67aad5f534..778de53bf2 100644 --- a/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm +++ b/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm @@ -221,7 +221,7 @@ var others = serverPart[1].split('?'); var port = others[0] var queryParam = {} - if(others.length > 0) { + if(others.length > 1) { var queryParams = others[1] var queryArray = queryParams.split('&') for (i = 0; i < queryArray.length; i++) { diff --git a/package/lean/npc/Makefile b/package/lean/npc/Makefile index e3b3527868..bb97ff1f91 100644 --- a/package/lean/npc/Makefile +++ b/package/lean/npc/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=npc -PKG_VERSION:=0.26.4 +PKG_VERSION:=0.26.5 PKG_RELEASE:=2 ifeq ($(ARCH),mipsel) diff --git a/package/libs/openssl/Config.in b/package/libs/openssl/Config.in index 42d3845081..ecfd2834b6 100644 --- a/package/libs/openssl/Config.in +++ b/package/libs/openssl/Config.in @@ -38,7 +38,7 @@ config OPENSSL_WITH_ASM config OPENSSL_WITH_SSE2 bool - default y if !TARGET_x86_legacy && !TARGET_x86_geode + default y if x86_64 || i386 && !TARGET_x86_legacy prompt "Enable use of x86 SSE2 instructions" depends on OPENSSL_WITH_ASM && x86_64 || i386 help @@ -248,6 +248,7 @@ config OPENSSL_ENGINE config OPENSSL_ENGINE_BUILTIN bool "Build chosen engines into libcrypto" + default y depends on OPENSSL_ENGINE help This builds all chosen engines into libcrypto.so, instead of building @@ -257,6 +258,7 @@ config OPENSSL_ENGINE_BUILTIN config OPENSSL_ENGINE_BUILTIN_AFALG bool + default y prompt "Acceleration support through AF_ALG sockets engine" depends on OPENSSL_ENGINE_BUILTIN && KERNEL_AIO select PACKAGE_libopenssl-conf diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile index 627f2bf62f..5c154a9054 100644 --- a/package/libs/openssl/Makefile +++ b/package/libs/openssl/Makefile @@ -11,7 +11,7 @@ PKG_NAME:=openssl PKG_BASE:=1.1.1 PKG_BUGFIX:=e-dev PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX) -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/openssl/openssl.git diff --git a/target/linux/generic/backport-4.14/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch b/target/linux/generic/backport-4.14/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch new file mode 100644 index 0000000000..ba0d137096 --- /dev/null +++ b/target/linux/generic/backport-4.14/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch @@ -0,0 +1,71 @@ +From 82afdcd4ec3c8ca6551cbf7c43c09e2fd240487a Mon Sep 17 00:00:00 2001 +From: Hangbin Liu +Date: Tue, 10 Mar 2020 15:27:37 +0800 +Subject: [PATCH] ipv6/addrconf: call ipv6_mc_up() for non-Ethernet interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rafał found an issue that for non-Ethernet interface, if we down and up +frequently, the memory will be consumed slowly. + +The reason is we add allnodes/allrouters addressed in multicast list in +ipv6_add_dev(). When link down, we call ipv6_mc_down(), store all multicast +addresses via mld_add_delrec(). But when link up, we don't call ipv6_mc_up() +for non-Ethernet interface to remove the addresses. This makes idev->mc_tomb +getting bigger and bigger. The call stack looks like: + +addrconf_notify(NETDEV_REGISTER) + ipv6_add_dev + ipv6_dev_mc_inc(ff01::1) + ipv6_dev_mc_inc(ff02::1) + ipv6_dev_mc_inc(ff02::2) + +addrconf_notify(NETDEV_UP) + addrconf_dev_config + /* Alas, we support only Ethernet autoconfiguration. */ + return; + +addrconf_notify(NETDEV_DOWN) + addrconf_ifdown + ipv6_mc_down + igmp6_group_dropped(ff02::2) + mld_add_delrec(ff02::2) + igmp6_group_dropped(ff02::1) + igmp6_group_dropped(ff01::1) + +After investigating, I can't found a rule to disable multicast on +non-Ethernet interface. In RFC2460, the link could be Ethernet, PPP, ATM, +tunnels, etc. In IPv4, it doesn't check the dev type when calls ip_mc_up() +in inetdev_event(). Even for IPv6, we don't check the dev type and call +ipv6_add_dev(), ipv6_dev_mc_inc() after register device. + +So I think it's OK to fix this memory consumer by calling ipv6_mc_up() for +non-Ethernet interface. + +v2: Also check IFF_MULTICAST flag to make sure the interface supports + multicast + +Reported-by: Rafał Miłecki +Tested-by: Rafał Miłecki +Fixes: 74235a25c673 ("[IPV6] addrconf: Fix IPv6 on tuntap tunnels") +Fixes: 1666d49e1d41 ("mld: do not remove mld souce list info when set link down") +Signed-off-by: Hangbin Liu +Signed-off-by: David S. Miller +--- + net/ipv6/addrconf.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -3223,6 +3223,10 @@ static void addrconf_dev_config(struct n + (dev->type != ARPHRD_TUNNEL) && + (dev->type != ARPHRD_NONE)) { + /* Alas, we support only Ethernet autoconfiguration. */ ++ idev = __in6_dev_get(dev); ++ if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP && ++ dev->flags & IFF_MULTICAST) ++ ipv6_mc_up(idev); + return; + } + diff --git a/target/linux/generic/backport-4.19/410-mtd-fix-calculating-partition-end-address.patch b/target/linux/generic/backport-4.19/410-mtd-fix-calculating-partition-end-address.patch new file mode 100644 index 0000000000..4027bfd714 --- /dev/null +++ b/target/linux/generic/backport-4.19/410-mtd-fix-calculating-partition-end-address.patch @@ -0,0 +1,28 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 9 Mar 2020 08:30:19 +0100 +Subject: [PATCH] mtd: fix calculating partition end address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes check for partitions that don't start at beginning of their +parents. Missing partition's offset in formula could result in forcing +read-only incorrectly. + +Fixes: 6750f61a13a0 ("mtd: improve calculating partition boundaries when checking for alignment") +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/mtdpart.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -538,7 +538,7 @@ static struct mtd_part *allocate_partiti + part->name); + } + +- tmp = part_absolute_offset(parent) + slave->mtd.size; ++ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; + remainder = do_div(tmp, wr_alignment); + if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { + slave->mtd.flags &= ~MTD_WRITEABLE; diff --git a/target/linux/generic/backport-4.19/464-v5.6-mtd-spi-nor-Add-4B_OPCODES-flag-to-w25q256.patch b/target/linux/generic/backport-4.19/464-v5.6-mtd-spi-nor-Add-4B_OPCODES-flag-to-w25q256.patch new file mode 100644 index 0000000000..db9f379c81 --- /dev/null +++ b/target/linux/generic/backport-4.19/464-v5.6-mtd-spi-nor-Add-4B_OPCODES-flag-to-w25q256.patch @@ -0,0 +1,27 @@ +From 10050a02f7d508fa88f70fcfceefbacd13488ca7 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 23 Dec 2019 17:05:49 +0200 +Subject: [PATCH] mtd: spi-nor: Add 4B_OPCODES flag to w25q256 + +The w25q256 supports 4-byte opcodes so lets add the flag. +Tested on OpenWrt under 4.19.82 kernel on 8devices Habanero. + +Signed-off-by: Robert Marko +Signed-off-by: Tudor Ambarus +--- + drivers/mtd/spi-nor/spi-nor.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1244,7 +1244,9 @@ static const struct flash_info spi_nor_i + { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, +- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_4B_OPCODES) }, + { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, + diff --git a/target/linux/generic/backport-4.19/499-v4.22-iio-add-IIO_MASSCONCENTRATION-channel-type.patch b/target/linux/generic/backport-4.19/499-v4.22-iio-add-IIO_MASSCONCENTRATION-channel-type.patch new file mode 100644 index 0000000000..bceb735146 --- /dev/null +++ b/target/linux/generic/backport-4.19/499-v4.22-iio-add-IIO_MASSCONCENTRATION-channel-type.patch @@ -0,0 +1,136 @@ +From 17abc9ec68b73ddeb262a507a62421016b9c54d5 Mon Sep 17 00:00:00 2001 +From: Tomasz Duszynski +Date: Fri, 14 Dec 2018 19:28:01 +0100 +Subject: [PATCH] iio: add IIO_MASSCONCENTRATION channel type + +Measuring particulate matter in ug / m3 (micro-grams per cubic meter) +is de facto standard. Existing air quality sensors usually follow +this convention and are capable of returning measurements using +this unit. + +IIO currently does not offer suitable channel type for this +type of measurements hence this patch adds this. + +In addition, extra modifiers are introduced used for distinguishing +between fine pm1, pm2p5 and coarse pm4, pm10 particle measurements, i.e +IIO_MOD_PM1, IIO_MOD_PM25 and IIO_MOD_PM4, IIO_MOD_PM10. + +pmX consists of particles with aerodynamic diameter less or equal to +X micrometers. + +Signed-off-by: Tomasz Duszynski +Acked-by: Matt Ranostay +Signed-off-by: Jonathan Cameron +--- + Documentation/ABI/testing/sysfs-bus-iio | 17 ++++++++++++++++- + drivers/iio/industrialio-core.c | 5 +++++ + include/uapi/linux/iio/types.h | 5 +++++ + tools/iio/iio_event_monitor.c | 10 ++++++++++ + 4 files changed, 36 insertions(+), 1 deletion(-) + +--- a/Documentation/ABI/testing/sysfs-bus-iio ++++ b/Documentation/ABI/testing/sysfs-bus-iio +@@ -1684,4 +1684,19 @@ KernelVersion: 4.18 + Contact: linux-iio@vger.kernel.org + Description: + Raw (unscaled) phase difference reading from channel Y +- that can be processed to radians. +\ No newline at end of file ++ that can be processed to radians. ++ ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm1_input ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm1_input ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm2p5_input ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm2p5_input ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm4_input ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm4_input ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentration_pm10_input ++What: /sys/bus/iio/devices/iio:deviceX/in_massconcentrationY_pm10_input ++KernelVersion: 4.22 ++Contact: linux-iio@vger.kernel.org ++Description: ++ Mass concentration reading of particulate matter in ug / m3. ++ pmX consists of particles with aerodynamic diameter less or ++ equal to X micrometers. +--- a/drivers/iio/industrialio-core.c ++++ b/drivers/iio/industrialio-core.c +@@ -87,6 +87,7 @@ static const char * const iio_chan_type_ + [IIO_GRAVITY] = "gravity", + [IIO_POSITIONRELATIVE] = "positionrelative", + [IIO_PHASE] = "phase", ++ [IIO_MASSCONCENTRATION] = "massconcentration", + }; + + static const char * const iio_modifier_names[] = { +@@ -127,6 +128,10 @@ static const char * const iio_modifier_n + [IIO_MOD_Q] = "q", + [IIO_MOD_CO2] = "co2", + [IIO_MOD_VOC] = "voc", ++ [IIO_MOD_PM1] = "pm1", ++ [IIO_MOD_PM2P5] = "pm2p5", ++ [IIO_MOD_PM4] = "pm4", ++ [IIO_MOD_PM10] = "pm10", + }; + + /* relies on pairs of these shared then separate */ +--- a/include/uapi/linux/iio/types.h ++++ b/include/uapi/linux/iio/types.h +@@ -46,6 +46,7 @@ enum iio_chan_type { + IIO_GRAVITY, + IIO_POSITIONRELATIVE, + IIO_PHASE, ++ IIO_MASSCONCENTRATION, + }; + + enum iio_modifier { +@@ -87,6 +88,10 @@ enum iio_modifier { + IIO_MOD_VOC, + IIO_MOD_LIGHT_UV, + IIO_MOD_LIGHT_DUV, ++ IIO_MOD_PM1, ++ IIO_MOD_PM2P5, ++ IIO_MOD_PM4, ++ IIO_MOD_PM10, + }; + + enum iio_event_type { +--- a/tools/iio/iio_event_monitor.c ++++ b/tools/iio/iio_event_monitor.c +@@ -60,6 +60,7 @@ static const char * const iio_chan_type_ + [IIO_GRAVITY] = "gravity", + [IIO_POSITIONRELATIVE] = "positionrelative", + [IIO_PHASE] = "phase", ++ [IIO_MASSCONCENTRATION] = "massconcentration", + }; + + static const char * const iio_ev_type_text[] = { +@@ -115,6 +116,10 @@ static const char * const iio_modifier_n + [IIO_MOD_Q] = "q", + [IIO_MOD_CO2] = "co2", + [IIO_MOD_VOC] = "voc", ++ [IIO_MOD_PM1] = "pm1", ++ [IIO_MOD_PM2P5] = "pm2p5", ++ [IIO_MOD_PM4] = "pm4", ++ [IIO_MOD_PM10] = "pm10", + }; + + static bool event_is_known(struct iio_event_data *event) +@@ -156,6 +161,7 @@ static bool event_is_known(struct iio_ev + case IIO_GRAVITY: + case IIO_POSITIONRELATIVE: + case IIO_PHASE: ++ case IIO_MASSCONCENTRATION: + break; + default: + return false; +@@ -200,6 +206,10 @@ static bool event_is_known(struct iio_ev + case IIO_MOD_Q: + case IIO_MOD_CO2: + case IIO_MOD_VOC: ++ case IIO_MOD_PM1: ++ case IIO_MOD_PM2P5: ++ case IIO_MOD_PM4: ++ case IIO_MOD_PM10: + break; + default: + return false; diff --git a/target/linux/generic/backport-4.19/500-v5.1-iio-chemical-add-support-for-Sensirion-SPS30-sensor.patch b/target/linux/generic/backport-4.19/500-v5.1-iio-chemical-add-support-for-Sensirion-SPS30-sensor.patch new file mode 100644 index 0000000000..d30c7c3cc1 --- /dev/null +++ b/target/linux/generic/backport-4.19/500-v5.1-iio-chemical-add-support-for-Sensirion-SPS30-sensor.patch @@ -0,0 +1,454 @@ +From 232e0f6ddeaee104d64675fe7d0cc142cf955f35 Mon Sep 17 00:00:00 2001 +From: Tomasz Duszynski +Date: Fri, 14 Dec 2018 19:28:02 +0100 +Subject: [PATCH] iio: chemical: add support for Sensirion SPS30 sensor + +Add support for Sensirion SPS30 particulate matter sensor. + +Signed-off-by: Tomasz Duszynski +Signed-off-by: Jonathan Cameron +--- + drivers/iio/chemical/Kconfig | 11 + + drivers/iio/chemical/Makefile | 1 + + drivers/iio/chemical/sps30.c | 407 ++++++++++++++++++++++++++++++++++ + 3 files changed, 419 insertions(+) + create mode 100644 drivers/iio/chemical/sps30.c + +--- a/drivers/iio/chemical/Kconfig ++++ b/drivers/iio/chemical/Kconfig +@@ -61,6 +61,17 @@ config IAQCORE + iAQ-Core Continuous/Pulsed VOC (Volatile Organic Compounds) + sensors + ++config SPS30 ++ tristate "SPS30 particulate matter sensor" ++ depends on I2C ++ select CRC8 ++ help ++ Say Y here to build support for the Sensirion SPS30 particulate ++ matter sensor. ++ ++ To compile this driver as a module, choose M here: the module will ++ be called sps30. ++ + config VZ89X + tristate "SGX Sensortech MiCS VZ89X VOC sensor" + depends on I2C +--- a/drivers/iio/chemical/Makefile ++++ b/drivers/iio/chemical/Makefile +@@ -9,4 +9,5 @@ obj-$(CONFIG_BME680_I2C) += bme680_i2c.o + obj-$(CONFIG_BME680_SPI) += bme680_spi.o + obj-$(CONFIG_CCS811) += ccs811.o + obj-$(CONFIG_IAQCORE) += ams-iaq-core.o ++obj-$(CONFIG_SPS30) += sps30.o + obj-$(CONFIG_VZ89X) += vz89x.o +--- /dev/null ++++ b/drivers/iio/chemical/sps30.c +@@ -0,0 +1,407 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Sensirion SPS30 particulate matter sensor driver ++ * ++ * Copyright (c) Tomasz Duszynski ++ * ++ * I2C slave address: 0x69 ++ * ++ * TODO: ++ * - support for turning on fan cleaning ++ * - support for reading/setting auto cleaning interval ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SPS30_CRC8_POLYNOMIAL 0x31 ++/* max number of bytes needed to store PM measurements or serial string */ ++#define SPS30_MAX_READ_SIZE 48 ++/* sensor measures reliably up to 3000 ug / m3 */ ++#define SPS30_MAX_PM 3000 ++ ++/* SPS30 commands */ ++#define SPS30_START_MEAS 0x0010 ++#define SPS30_STOP_MEAS 0x0104 ++#define SPS30_RESET 0xd304 ++#define SPS30_READ_DATA_READY_FLAG 0x0202 ++#define SPS30_READ_DATA 0x0300 ++#define SPS30_READ_SERIAL 0xd033 ++ ++enum { ++ PM1, ++ PM2P5, ++ PM4, ++ PM10, ++}; ++ ++struct sps30_state { ++ struct i2c_client *client; ++ /* ++ * Guards against concurrent access to sensor registers. ++ * Must be held whenever sequence of commands is to be executed. ++ */ ++ struct mutex lock; ++}; ++ ++DECLARE_CRC8_TABLE(sps30_crc8_table); ++ ++static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf, ++ int txsize, u8 *rxbuf, int rxsize) ++{ ++ int ret; ++ ++ /* ++ * Sensor does not support repeated start so instead of ++ * sending two i2c messages in a row we just send one by one. ++ */ ++ ret = i2c_master_send(state->client, txbuf, txsize); ++ if (ret != txsize) ++ return ret < 0 ? ret : -EIO; ++ ++ if (!rxbuf) ++ return 0; ++ ++ ret = i2c_master_recv(state->client, rxbuf, rxsize); ++ if (ret != rxsize) ++ return ret < 0 ? ret : -EIO; ++ ++ return 0; ++} ++ ++static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) ++{ ++ /* ++ * Internally sensor stores measurements in a following manner: ++ * ++ * PM1: upper two bytes, crc8, lower two bytes, crc8 ++ * PM2P5: upper two bytes, crc8, lower two bytes, crc8 ++ * PM4: upper two bytes, crc8, lower two bytes, crc8 ++ * PM10: upper two bytes, crc8, lower two bytes, crc8 ++ * ++ * What follows next are number concentration measurements and ++ * typical particle size measurement which we omit. ++ */ ++ u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd }; ++ int i, ret = 0; ++ ++ switch (cmd) { ++ case SPS30_START_MEAS: ++ buf[2] = 0x03; ++ buf[3] = 0x00; ++ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); ++ ret = sps30_write_then_read(state, buf, 5, NULL, 0); ++ break; ++ case SPS30_STOP_MEAS: ++ case SPS30_RESET: ++ ret = sps30_write_then_read(state, buf, 2, NULL, 0); ++ break; ++ case SPS30_READ_DATA_READY_FLAG: ++ case SPS30_READ_DATA: ++ case SPS30_READ_SERIAL: ++ /* every two data bytes are checksummed */ ++ size += size / 2; ++ ret = sps30_write_then_read(state, buf, 2, buf, size); ++ break; ++ } ++ ++ if (ret) ++ return ret; ++ ++ /* validate received data and strip off crc bytes */ ++ for (i = 0; i < size; i += 3) { ++ u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE); ++ ++ if (crc != buf[i + 2]) { ++ dev_err(&state->client->dev, ++ "data integrity check failed\n"); ++ return -EIO; ++ } ++ ++ *data++ = buf[i]; ++ *data++ = buf[i + 1]; ++ } ++ ++ return 0; ++} ++ ++static s32 sps30_float_to_int_clamped(const u8 *fp) ++{ ++ int val = get_unaligned_be32(fp); ++ int mantissa = val & GENMASK(22, 0); ++ /* this is fine since passed float is always non-negative */ ++ int exp = val >> 23; ++ int fraction, shift; ++ ++ /* special case 0 */ ++ if (!exp && !mantissa) ++ return 0; ++ ++ exp -= 127; ++ if (exp < 0) { ++ /* return values ranging from 1 to 99 */ ++ return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp); ++ } ++ ++ /* return values ranging from 100 to 300000 */ ++ shift = 23 - exp; ++ val = (1 << exp) + (mantissa >> shift); ++ if (val >= SPS30_MAX_PM) ++ return SPS30_MAX_PM * 100; ++ ++ fraction = mantissa & GENMASK(shift - 1, 0); ++ ++ return val * 100 + ((fraction * 100) >> shift); ++} ++ ++static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) ++{ ++ int i, ret, tries = 5; ++ u8 tmp[16]; ++ ++ while (tries--) { ++ ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); ++ if (ret) ++ return -EIO; ++ ++ /* new measurements ready to be read */ ++ if (tmp[1] == 1) ++ break; ++ ++ msleep_interruptible(300); ++ } ++ ++ if (!tries) ++ return -ETIMEDOUT; ++ ++ ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < size; i++) ++ data[i] = sps30_float_to_int_clamped(&tmp[4 * i]); ++ ++ return 0; ++} ++ ++static irqreturn_t sps30_trigger_handler(int irq, void *p) ++{ ++ struct iio_poll_func *pf = p; ++ struct iio_dev *indio_dev = pf->indio_dev; ++ struct sps30_state *state = iio_priv(indio_dev); ++ int ret; ++ s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */ ++ ++ mutex_lock(&state->lock); ++ ret = sps30_do_meas(state, data, 4); ++ mutex_unlock(&state->lock); ++ if (ret) ++ goto err; ++ ++ iio_push_to_buffers_with_timestamp(indio_dev, data, ++ iio_get_time_ns(indio_dev)); ++err: ++ iio_trigger_notify_done(indio_dev->trig); ++ ++ return IRQ_HANDLED; ++} ++ ++static int sps30_read_raw(struct iio_dev *indio_dev, ++ struct iio_chan_spec const *chan, ++ int *val, int *val2, long mask) ++{ ++ struct sps30_state *state = iio_priv(indio_dev); ++ int data[4], ret = -EINVAL; ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_PROCESSED: ++ switch (chan->type) { ++ case IIO_MASSCONCENTRATION: ++ mutex_lock(&state->lock); ++ /* read up to the number of bytes actually needed */ ++ switch (chan->channel2) { ++ case IIO_MOD_PM1: ++ ret = sps30_do_meas(state, data, 1); ++ break; ++ case IIO_MOD_PM2P5: ++ ret = sps30_do_meas(state, data, 2); ++ break; ++ case IIO_MOD_PM4: ++ ret = sps30_do_meas(state, data, 3); ++ break; ++ case IIO_MOD_PM10: ++ ret = sps30_do_meas(state, data, 4); ++ break; ++ } ++ mutex_unlock(&state->lock); ++ if (ret) ++ return ret; ++ ++ *val = data[chan->address] / 100; ++ *val2 = (data[chan->address] % 100) * 10000; ++ ++ return IIO_VAL_INT_PLUS_MICRO; ++ default: ++ return -EINVAL; ++ } ++ case IIO_CHAN_INFO_SCALE: ++ switch (chan->type) { ++ case IIO_MASSCONCENTRATION: ++ switch (chan->channel2) { ++ case IIO_MOD_PM1: ++ case IIO_MOD_PM2P5: ++ case IIO_MOD_PM4: ++ case IIO_MOD_PM10: ++ *val = 0; ++ *val2 = 10000; ++ ++ return IIO_VAL_INT_PLUS_MICRO; ++ } ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct iio_info sps30_info = { ++ .read_raw = sps30_read_raw, ++}; ++ ++#define SPS30_CHAN(_index, _mod) { \ ++ .type = IIO_MASSCONCENTRATION, \ ++ .modified = 1, \ ++ .channel2 = IIO_MOD_ ## _mod, \ ++ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ ++ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ ++ .address = _mod, \ ++ .scan_index = _index, \ ++ .scan_type = { \ ++ .sign = 'u', \ ++ .realbits = 19, \ ++ .storagebits = 32, \ ++ .endianness = IIO_CPU, \ ++ }, \ ++} ++ ++static const struct iio_chan_spec sps30_channels[] = { ++ SPS30_CHAN(0, PM1), ++ SPS30_CHAN(1, PM2P5), ++ SPS30_CHAN(2, PM4), ++ SPS30_CHAN(3, PM10), ++ IIO_CHAN_SOFT_TIMESTAMP(4), ++}; ++ ++static void sps30_stop_meas(void *data) ++{ ++ struct sps30_state *state = data; ++ ++ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); ++} ++ ++static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; ++ ++static int sps30_probe(struct i2c_client *client) ++{ ++ struct iio_dev *indio_dev; ++ struct sps30_state *state; ++ u8 buf[32]; ++ int ret; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) ++ return -EOPNOTSUPP; ++ ++ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state)); ++ if (!indio_dev) ++ return -ENOMEM; ++ ++ state = iio_priv(indio_dev); ++ i2c_set_clientdata(client, indio_dev); ++ state->client = client; ++ indio_dev->dev.parent = &client->dev; ++ indio_dev->info = &sps30_info; ++ indio_dev->name = client->name; ++ indio_dev->channels = sps30_channels; ++ indio_dev->num_channels = ARRAY_SIZE(sps30_channels); ++ indio_dev->modes = INDIO_DIRECT_MODE; ++ indio_dev->available_scan_masks = sps30_scan_masks; ++ ++ mutex_init(&state->lock); ++ crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); ++ ++ ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); ++ if (ret) { ++ dev_err(&client->dev, "failed to reset device\n"); ++ return ret; ++ } ++ msleep(300); ++ /* ++ * Power-on-reset causes sensor to produce some glitch on i2c bus and ++ * some controllers end up in error state. Recover simply by placing ++ * some data on the bus, for example STOP_MEAS command, which ++ * is NOP in this case. ++ */ ++ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); ++ ++ ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); ++ if (ret) { ++ dev_err(&client->dev, "failed to read serial number\n"); ++ return ret; ++ } ++ /* returned serial number is already NUL terminated */ ++ dev_info(&client->dev, "serial number: %s\n", buf); ++ ++ ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); ++ if (ret) { ++ dev_err(&client->dev, "failed to start measurement\n"); ++ return ret; ++ } ++ ++ ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); ++ if (ret) ++ return ret; ++ ++ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, ++ sps30_trigger_handler, NULL); ++ if (ret) ++ return ret; ++ ++ return devm_iio_device_register(&client->dev, indio_dev); ++} ++ ++static const struct i2c_device_id sps30_id[] = { ++ { "sps30" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, sps30_id); ++ ++static const struct of_device_id sps30_of_match[] = { ++ { .compatible = "sensirion,sps30" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sps30_of_match); ++ ++static struct i2c_driver sps30_driver = { ++ .driver = { ++ .name = "sps30", ++ .of_match_table = sps30_of_match, ++ }, ++ .id_table = sps30_id, ++ .probe_new = sps30_probe, ++}; ++module_i2c_driver(sps30_driver); ++ ++MODULE_AUTHOR("Tomasz Duszynski "); ++MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/generic/backport-4.19/501-v5.1-iio-chemical-sps30-add-support-for-self-cleaning.patch b/target/linux/generic/backport-4.19/501-v5.1-iio-chemical-sps30-add-support-for-self-cleaning.patch new file mode 100644 index 0000000000..7054fb0313 --- /dev/null +++ b/target/linux/generic/backport-4.19/501-v5.1-iio-chemical-sps30-add-support-for-self-cleaning.patch @@ -0,0 +1,100 @@ +From c546d49656143855093c7b7fde60866e6e23a69d Mon Sep 17 00:00:00 2001 +From: Tomasz Duszynski +Date: Tue, 18 Dec 2018 21:28:09 +0100 +Subject: [PATCH] iio: chemical: sps30: add support for self cleaning + +Self cleaning is especially useful in cases where sensor undergoes +frequent power on/off cycles. In such scenarios it is recommended to +turn self cleaning at least once per week in order to maintain reliable +measurements. + +Self cleaning is activated by writing 1 to a dedicated attribute. +Internal fan accelerates to its maximum speed and keeps spinning +for about 10 seconds blowing out accumulated dust. + +Signed-off-by: Tomasz Duszynski +Tested-by: Andreas Brauchli +Signed-off-by: Jonathan Cameron +--- + Documentation/ABI/testing/sysfs-bus-iio-sps30 | 8 +++++ + drivers/iio/chemical/sps30.c | 35 ++++++++++++++++++- + 2 files changed, 42 insertions(+), 1 deletion(-) + create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-sps30 + +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-bus-iio-sps30 +@@ -0,0 +1,8 @@ ++What: /sys/bus/iio/devices/iio:deviceX/start_cleaning ++Date: December 2018 ++KernelVersion: 4.22 ++Contact: linux-iio@vger.kernel.org ++Description: ++ Writing 1 starts sensor self cleaning. Internal fan accelerates ++ to its maximum speed and keeps spinning for about 10 seconds in ++ order to blow out accumulated dust. +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -7,7 +7,6 @@ + * I2C slave address: 0x69 + * + * TODO: +- * - support for turning on fan cleaning + * - support for reading/setting auto cleaning interval + */ + +@@ -37,6 +36,7 @@ + #define SPS30_READ_DATA_READY_FLAG 0x0202 + #define SPS30_READ_DATA 0x0300 + #define SPS30_READ_SERIAL 0xd033 ++#define SPS30_START_FAN_CLEANING 0x5607 + + enum { + PM1, +@@ -104,6 +104,7 @@ static int sps30_do_cmd(struct sps30_sta + break; + case SPS30_STOP_MEAS: + case SPS30_RESET: ++ case SPS30_START_FAN_CLEANING: + ret = sps30_write_then_read(state, buf, 2, NULL, 0); + break; + case SPS30_READ_DATA_READY_FLAG: +@@ -275,7 +276,39 @@ static int sps30_read_raw(struct iio_dev + return -EINVAL; + } + ++static ssize_t start_cleaning_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct sps30_state *state = iio_priv(indio_dev); ++ int val, ret; ++ ++ if (kstrtoint(buf, 0, &val) || val != 1) ++ return -EINVAL; ++ ++ mutex_lock(&state->lock); ++ ret = sps30_do_cmd(state, SPS30_START_FAN_CLEANING, NULL, 0); ++ mutex_unlock(&state->lock); ++ if (ret) ++ return ret; ++ ++ return len; ++} ++ ++static IIO_DEVICE_ATTR_WO(start_cleaning, 0); ++ ++static struct attribute *sps30_attrs[] = { ++ &iio_dev_attr_start_cleaning.dev_attr.attr, ++ NULL ++}; ++ ++static const struct attribute_group sps30_attr_group = { ++ .attrs = sps30_attrs, ++}; ++ + static const struct iio_info sps30_info = { ++ .attrs = &sps30_attr_group, + .read_raw = sps30_read_raw, + }; + diff --git a/target/linux/generic/backport-4.19/502-v5.1-iio-chemical-sps30-allow-changing-self-cleaning-peri.patch b/target/linux/generic/backport-4.19/502-v5.1-iio-chemical-sps30-allow-changing-self-cleaning-peri.patch new file mode 100644 index 0000000000..3a1335ba44 --- /dev/null +++ b/target/linux/generic/backport-4.19/502-v5.1-iio-chemical-sps30-allow-changing-self-cleaning-peri.patch @@ -0,0 +1,293 @@ +From 62129a0849d27cc94ced832bcf9dcde283dcbe08 Mon Sep 17 00:00:00 2001 +From: Tomasz Duszynski +Date: Tue, 15 Jan 2019 20:00:06 +0100 +Subject: [PATCH] iio: chemical: sps30: allow changing self cleaning period + +Sensor can periodically trigger self cleaning. Period can be changed by +writing a new value to a dedicated attribute. Upon attribute read +current period gets returned. + +Signed-off-by: Tomasz Duszynski +Signed-off-by: Jonathan Cameron +--- + Documentation/ABI/testing/sysfs-bus-iio-sps30 | 20 +++ + drivers/iio/chemical/sps30.c | 143 +++++++++++++++--- + 2 files changed, 145 insertions(+), 18 deletions(-) + +--- a/Documentation/ABI/testing/sysfs-bus-iio-sps30 ++++ b/Documentation/ABI/testing/sysfs-bus-iio-sps30 +@@ -6,3 +6,23 @@ Description: + Writing 1 starts sensor self cleaning. Internal fan accelerates + to its maximum speed and keeps spinning for about 10 seconds in + order to blow out accumulated dust. ++ ++What: /sys/bus/iio/devices/iio:deviceX/cleaning_period ++Date: January 2019 ++KernelVersion: 5.1 ++Contact: linux-iio@vger.kernel.org ++Description: ++ Sensor is capable of triggering self cleaning periodically. ++ Period can be changed by writing a new value here. Upon reading ++ the current one is returned. Units are seconds. ++ ++ Writing 0 disables periodical self cleaning entirely. ++ ++What: /sys/bus/iio/devices/iio:deviceX/cleaning_period_available ++Date: January 2019 ++KernelVersion: 5.1 ++Contact: linux-iio@vger.kernel.org ++Description: ++ The range of available values in seconds represented as the ++ minimum value, the step and the maximum value, all enclosed in ++ square brackets. +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -5,9 +5,6 @@ + * Copyright (c) Tomasz Duszynski + * + * I2C slave address: 0x69 +- * +- * TODO: +- * - support for reading/setting auto cleaning interval + */ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +@@ -21,6 +18,7 @@ + #include + #include + #include ++#include + #include + + #define SPS30_CRC8_POLYNOMIAL 0x31 +@@ -28,6 +26,9 @@ + #define SPS30_MAX_READ_SIZE 48 + /* sensor measures reliably up to 3000 ug / m3 */ + #define SPS30_MAX_PM 3000 ++/* minimum and maximum self cleaning periods in seconds */ ++#define SPS30_AUTO_CLEANING_PERIOD_MIN 0 ++#define SPS30_AUTO_CLEANING_PERIOD_MAX 604800 + + /* SPS30 commands */ + #define SPS30_START_MEAS 0x0010 +@@ -37,6 +38,9 @@ + #define SPS30_READ_DATA 0x0300 + #define SPS30_READ_SERIAL 0xd033 + #define SPS30_START_FAN_CLEANING 0x5607 ++#define SPS30_AUTO_CLEANING_PERIOD 0x8004 ++/* not a sensor command per se, used only to distinguish write from read */ ++#define SPS30_READ_AUTO_CLEANING_PERIOD 0x8005 + + enum { + PM1, +@@ -45,6 +49,11 @@ enum { + PM10, + }; + ++enum { ++ RESET, ++ MEASURING, ++}; ++ + struct sps30_state { + struct i2c_client *client; + /* +@@ -52,6 +61,7 @@ struct sps30_state { + * Must be held whenever sequence of commands is to be executed. + */ + struct mutex lock; ++ int state; + }; + + DECLARE_CRC8_TABLE(sps30_crc8_table); +@@ -107,6 +117,9 @@ static int sps30_do_cmd(struct sps30_sta + case SPS30_START_FAN_CLEANING: + ret = sps30_write_then_read(state, buf, 2, NULL, 0); + break; ++ case SPS30_READ_AUTO_CLEANING_PERIOD: ++ buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; ++ buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD; + case SPS30_READ_DATA_READY_FLAG: + case SPS30_READ_DATA: + case SPS30_READ_SERIAL: +@@ -114,6 +127,15 @@ static int sps30_do_cmd(struct sps30_sta + size += size / 2; + ret = sps30_write_then_read(state, buf, 2, buf, size); + break; ++ case SPS30_AUTO_CLEANING_PERIOD: ++ buf[2] = data[0]; ++ buf[3] = data[1]; ++ buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); ++ buf[5] = data[2]; ++ buf[6] = data[3]; ++ buf[7] = crc8(sps30_crc8_table, &buf[5], 2, CRC8_INIT_VALUE); ++ ret = sps30_write_then_read(state, buf, 8, NULL, 0); ++ break; + } + + if (ret) +@@ -170,6 +192,14 @@ static int sps30_do_meas(struct sps30_st + int i, ret, tries = 5; + u8 tmp[16]; + ++ if (state->state == RESET) { ++ ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); ++ if (ret) ++ return ret; ++ ++ state->state = MEASURING; ++ } ++ + while (tries--) { + ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); + if (ret) +@@ -276,6 +306,24 @@ static int sps30_read_raw(struct iio_dev + return -EINVAL; + } + ++static int sps30_do_cmd_reset(struct sps30_state *state) ++{ ++ int ret; ++ ++ ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); ++ msleep(300); ++ /* ++ * Power-on-reset causes sensor to produce some glitch on i2c bus and ++ * some controllers end up in error state. Recover simply by placing ++ * some data on the bus, for example STOP_MEAS command, which ++ * is NOP in this case. ++ */ ++ sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); ++ state->state = RESET; ++ ++ return ret; ++} ++ + static ssize_t start_cleaning_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +@@ -296,10 +344,82 @@ static ssize_t start_cleaning_store(stru + return len; + } + ++static ssize_t cleaning_period_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct sps30_state *state = iio_priv(indio_dev); ++ u8 tmp[4]; ++ int ret; ++ ++ mutex_lock(&state->lock); ++ ret = sps30_do_cmd(state, SPS30_READ_AUTO_CLEANING_PERIOD, tmp, 4); ++ mutex_unlock(&state->lock); ++ if (ret) ++ return ret; ++ ++ return sprintf(buf, "%d\n", get_unaligned_be32(tmp)); ++} ++ ++static ssize_t cleaning_period_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ struct iio_dev *indio_dev = dev_to_iio_dev(dev); ++ struct sps30_state *state = iio_priv(indio_dev); ++ int val, ret; ++ u8 tmp[4]; ++ ++ if (kstrtoint(buf, 0, &val)) ++ return -EINVAL; ++ ++ if ((val < SPS30_AUTO_CLEANING_PERIOD_MIN) || ++ (val > SPS30_AUTO_CLEANING_PERIOD_MAX)) ++ return -EINVAL; ++ ++ put_unaligned_be32(val, tmp); ++ ++ mutex_lock(&state->lock); ++ ret = sps30_do_cmd(state, SPS30_AUTO_CLEANING_PERIOD, tmp, 0); ++ if (ret) { ++ mutex_unlock(&state->lock); ++ return ret; ++ } ++ ++ msleep(20); ++ ++ /* ++ * sensor requires reset in order to return up to date self cleaning ++ * period ++ */ ++ ret = sps30_do_cmd_reset(state); ++ if (ret) ++ dev_warn(dev, ++ "period changed but reads will return the old value\n"); ++ ++ mutex_unlock(&state->lock); ++ ++ return len; ++} ++ ++static ssize_t cleaning_period_available_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "[%d %d %d]\n", ++ SPS30_AUTO_CLEANING_PERIOD_MIN, 1, ++ SPS30_AUTO_CLEANING_PERIOD_MAX); ++} ++ + static IIO_DEVICE_ATTR_WO(start_cleaning, 0); ++static IIO_DEVICE_ATTR_RW(cleaning_period, 0); ++static IIO_DEVICE_ATTR_RO(cleaning_period_available, 0); + + static struct attribute *sps30_attrs[] = { + &iio_dev_attr_start_cleaning.dev_attr.attr, ++ &iio_dev_attr_cleaning_period.dev_attr.attr, ++ &iio_dev_attr_cleaning_period_available.dev_attr.attr, + NULL + }; + +@@ -362,6 +482,7 @@ static int sps30_probe(struct i2c_client + state = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + state->client = client; ++ state->state = RESET; + indio_dev->dev.parent = &client->dev; + indio_dev->info = &sps30_info; + indio_dev->name = client->name; +@@ -373,19 +494,11 @@ static int sps30_probe(struct i2c_client + mutex_init(&state->lock); + crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); + +- ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); ++ ret = sps30_do_cmd_reset(state); + if (ret) { + dev_err(&client->dev, "failed to reset device\n"); + return ret; + } +- msleep(300); +- /* +- * Power-on-reset causes sensor to produce some glitch on i2c bus and +- * some controllers end up in error state. Recover simply by placing +- * some data on the bus, for example STOP_MEAS command, which +- * is NOP in this case. +- */ +- sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); + + ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); + if (ret) { +@@ -395,12 +508,6 @@ static int sps30_probe(struct i2c_client + /* returned serial number is already NUL terminated */ + dev_info(&client->dev, "serial number: %s\n", buf); + +- ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); +- if (ret) { +- dev_err(&client->dev, "failed to start measurement\n"); +- return ret; +- } +- + ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); + if (ret) + return ret; diff --git a/target/linux/generic/backport-4.19/503-v5.1-iio-chemical-sps30-remove-printk-format-specifier.patch b/target/linux/generic/backport-4.19/503-v5.1-iio-chemical-sps30-remove-printk-format-specifier.patch new file mode 100644 index 0000000000..b0fe5ac2e6 --- /dev/null +++ b/target/linux/generic/backport-4.19/503-v5.1-iio-chemical-sps30-remove-printk-format-specifier.patch @@ -0,0 +1,25 @@ +From 3fa30bf7004bb8069826ef85487f4753666a73da Mon Sep 17 00:00:00 2001 +From: Tomasz Duszynski +Date: Sat, 2 Feb 2019 10:00:03 +0100 +Subject: [PATCH] iio: chemical: sps30: remove printk format specifier + +pr_fmt is used by printk wrappers. There are not any in the driver +code so remove the format specifier. + +Signed-off-by: Tomasz Duszynski +Signed-off-by: Jonathan Cameron +--- + drivers/iio/chemical/sps30.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -7,8 +7,6 @@ + * I2C slave address: 0x69 + */ + +-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +- + #include + #include + #include diff --git a/target/linux/generic/backport-4.19/504-v5.1-iio-chemical-sps30-fix-a-loop-timeout-test.patch b/target/linux/generic/backport-4.19/504-v5.1-iio-chemical-sps30-fix-a-loop-timeout-test.patch new file mode 100644 index 0000000000..c0aae35549 --- /dev/null +++ b/target/linux/generic/backport-4.19/504-v5.1-iio-chemical-sps30-fix-a-loop-timeout-test.patch @@ -0,0 +1,26 @@ +From 905889b4a34c753a538015f0b2cdaa0c9e3a4fd5 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Sat, 9 Feb 2019 12:03:52 +0300 +Subject: [PATCH] iio: chemical: sps30: fix a loop timeout test + +The "while (tries--) {" loop is a postop so it exits with "tries" set +to -1. + +Fixes: 232e0f6ddeae ("iio: chemical: add support for Sensirion SPS30 sensor") +Signed-off-by: Dan Carpenter +Signed-off-by: Jonathan Cameron +--- + drivers/iio/chemical/sps30.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -210,7 +210,7 @@ static int sps30_do_meas(struct sps30_st + msleep_interruptible(300); + } + +- if (!tries) ++ if (tries == -1) + return -ETIMEDOUT; + + ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); diff --git a/target/linux/generic/backport-4.19/505-v5.1-iio-chemical-sps30-Supress-some-switch-fallthrough-w.patch b/target/linux/generic/backport-4.19/505-v5.1-iio-chemical-sps30-Supress-some-switch-fallthrough-w.patch new file mode 100644 index 0000000000..08cc34ff40 --- /dev/null +++ b/target/linux/generic/backport-4.19/505-v5.1-iio-chemical-sps30-Supress-some-switch-fallthrough-w.patch @@ -0,0 +1,34 @@ +From 59b9bb0abca9efe47207301dbaf0d1beee2bd0f7 Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Sat, 9 Feb 2019 19:32:58 +0000 +Subject: [PATCH] iio:chemical:sps30 Supress some switch fallthrough warnings. + +Fixes warnings reported on linux-next but marking one path +and adding an explicit return in the other. + +Signed-off-by: Jonathan Cameron +Cc: Andreas Brauchli +Acked-by: Tomasz Duszynski +--- + drivers/iio/chemical/sps30.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -118,6 +118,7 @@ static int sps30_do_cmd(struct sps30_sta + case SPS30_READ_AUTO_CLEANING_PERIOD: + buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; + buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD; ++ /* fall through */ + case SPS30_READ_DATA_READY_FLAG: + case SPS30_READ_DATA: + case SPS30_READ_SERIAL: +@@ -295,6 +296,8 @@ static int sps30_read_raw(struct iio_dev + *val2 = 10000; + + return IIO_VAL_INT_PLUS_MICRO; ++ default: ++ return -EINVAL; + } + default: + return -EINVAL; diff --git a/target/linux/generic/backport-4.19/506-v5.1-iio-chemical-sps30-Explicity-truncate-constant-by-ma.patch b/target/linux/generic/backport-4.19/506-v5.1-iio-chemical-sps30-Explicity-truncate-constant-by-ma.patch new file mode 100644 index 0000000000..e1f4a3b635 --- /dev/null +++ b/target/linux/generic/backport-4.19/506-v5.1-iio-chemical-sps30-Explicity-truncate-constant-by-ma.patch @@ -0,0 +1,31 @@ +From 78b75ab3f8c9dfac563b81105a1b838ec37a940e Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Sun, 13 Oct 2019 10:55:15 +0100 +Subject: [PATCH] iio: chemical: sps30: Explicity truncate constant by masking + +When breaking up a constant to write to two 8 bit registers +it isn't obvious to sparse that it was intentional. + +CHECK drivers/iio/chemical/sps30.c +drivers/iio/chemical/sps30.c:120:30: warning: cast truncates bits from constant value (8004 becomes 4) + +So in the interests of minimising noisy warnings, let us add +a mask. + +Signed-off-by: Jonathan Cameron +Acked-by: Tomasz Duszynski +--- + drivers/iio/chemical/sps30.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/chemical/sps30.c ++++ b/drivers/iio/chemical/sps30.c +@@ -117,7 +117,7 @@ static int sps30_do_cmd(struct sps30_sta + break; + case SPS30_READ_AUTO_CLEANING_PERIOD: + buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; +- buf[1] = (u8)SPS30_AUTO_CLEANING_PERIOD; ++ buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff); + /* fall through */ + case SPS30_READ_DATA_READY_FLAG: + case SPS30_READ_DATA: diff --git a/target/linux/generic/backport-4.19/507-v5.6-iio-chemical-sps30-fix-missing-triggered-buffer-depe.patch b/target/linux/generic/backport-4.19/507-v5.6-iio-chemical-sps30-fix-missing-triggered-buffer-depe.patch new file mode 100644 index 0000000000..c2b999b1cb --- /dev/null +++ b/target/linux/generic/backport-4.19/507-v5.6-iio-chemical-sps30-fix-missing-triggered-buffer-depe.patch @@ -0,0 +1,30 @@ +From 61338e27e2eef3bfcd3df5c39cec5b9dc10ba25c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20=C5=A0tetiar?= +Date: Sun, 23 Feb 2020 22:08:25 +0100 +Subject: [PATCH] iio: chemical: sps30: fix missing triggered buffer dependency +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +SPS30 uses triggered buffer, but the dependency is not specified in the +Kconfig file. Fix this by selecting IIO_BUFFER and IIO_TRIGGERED_BUFFER +config symbols. + +Cc: stable@vger.kernel.org +Fixes: 232e0f6ddeae ("iio: chemical: add support for Sensirion SPS30 sensor") +Signed-off-by: Petr Štetiar +--- + drivers/iio/chemical/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/iio/chemical/Kconfig ++++ b/drivers/iio/chemical/Kconfig +@@ -65,6 +65,8 @@ config SPS30 + tristate "SPS30 particulate matter sensor" + depends on I2C + select CRC8 ++ select IIO_BUFFER ++ select IIO_TRIGGERED_BUFFER + help + Say Y here to build support for the Sensirion SPS30 particulate + matter sensor. diff --git a/target/linux/generic/backport-4.19/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch b/target/linux/generic/backport-4.19/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch new file mode 100644 index 0000000000..d2d86f3df1 --- /dev/null +++ b/target/linux/generic/backport-4.19/600-ipv6-addrconf-call-ipv6_mc_up-for-non-Ethernet-inter.patch @@ -0,0 +1,71 @@ +From 82afdcd4ec3c8ca6551cbf7c43c09e2fd240487a Mon Sep 17 00:00:00 2001 +From: Hangbin Liu +Date: Tue, 10 Mar 2020 15:27:37 +0800 +Subject: [PATCH] ipv6/addrconf: call ipv6_mc_up() for non-Ethernet interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Rafał found an issue that for non-Ethernet interface, if we down and up +frequently, the memory will be consumed slowly. + +The reason is we add allnodes/allrouters addressed in multicast list in +ipv6_add_dev(). When link down, we call ipv6_mc_down(), store all multicast +addresses via mld_add_delrec(). But when link up, we don't call ipv6_mc_up() +for non-Ethernet interface to remove the addresses. This makes idev->mc_tomb +getting bigger and bigger. The call stack looks like: + +addrconf_notify(NETDEV_REGISTER) + ipv6_add_dev + ipv6_dev_mc_inc(ff01::1) + ipv6_dev_mc_inc(ff02::1) + ipv6_dev_mc_inc(ff02::2) + +addrconf_notify(NETDEV_UP) + addrconf_dev_config + /* Alas, we support only Ethernet autoconfiguration. */ + return; + +addrconf_notify(NETDEV_DOWN) + addrconf_ifdown + ipv6_mc_down + igmp6_group_dropped(ff02::2) + mld_add_delrec(ff02::2) + igmp6_group_dropped(ff02::1) + igmp6_group_dropped(ff01::1) + +After investigating, I can't found a rule to disable multicast on +non-Ethernet interface. In RFC2460, the link could be Ethernet, PPP, ATM, +tunnels, etc. In IPv4, it doesn't check the dev type when calls ip_mc_up() +in inetdev_event(). Even for IPv6, we don't check the dev type and call +ipv6_add_dev(), ipv6_dev_mc_inc() after register device. + +So I think it's OK to fix this memory consumer by calling ipv6_mc_up() for +non-Ethernet interface. + +v2: Also check IFF_MULTICAST flag to make sure the interface supports + multicast + +Reported-by: Rafał Miłecki +Tested-by: Rafał Miłecki +Fixes: 74235a25c673 ("[IPV6] addrconf: Fix IPv6 on tuntap tunnels") +Fixes: 1666d49e1d41 ("mld: do not remove mld souce list info when set link down") +Signed-off-by: Hangbin Liu +Signed-off-by: David S. Miller +--- + net/ipv6/addrconf.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -3291,6 +3291,10 @@ static void addrconf_dev_config(struct n + (dev->type != ARPHRD_NONE) && + (dev->type != ARPHRD_RAWIP)) { + /* Alas, we support only Ethernet autoconfiguration. */ ++ idev = __in6_dev_get(dev); ++ if (!IS_ERR_OR_NULL(idev) && dev->flags & IFF_UP && ++ dev->flags & IFF_MULTICAST) ++ ipv6_mc_up(idev); + return; + } + diff --git a/target/linux/generic/pending-4.14/647-netfilter-nf_flow_table_hw-fix-incorrect-ethernet-ds.patch b/target/linux/generic/pending-4.14/647-netfilter-nf_flow_table_hw-fix-incorrect-ethernet-ds.patch new file mode 100644 index 0000000000..a81445bb95 --- /dev/null +++ b/target/linux/generic/pending-4.14/647-netfilter-nf_flow_table_hw-fix-incorrect-ethernet-ds.patch @@ -0,0 +1,87 @@ +From: Konstantin Vasin +Date: Mon, 9 Mar 2020 18:38:54 +0300 +Subject: [PATCH] netfilter: nf_flow_table_hw: fix incorrect ethernet dst + address + +Ethernet destination for original traffic takes the source ethernet +address in the reply direction. For reply traffic, this takes +the source ethernet address of the original destination. + +This fix is based on the upstream commit 1b67e506: +("netfilter: nf_flow_table_offload: fix incorrect ethernet dst address") +from wenxu + +Signed-off-by: Konstantin Vasin +--- + +--- a/net/netfilter/nf_flow_table_hw.c ++++ b/net/netfilter/nf_flow_table_hw.c +@@ -24,17 +24,23 @@ struct flow_offload_hw { + struct flow_offload_hw_path dest; + }; + +-static void flow_offload_check_ethernet(struct flow_offload_tuple *tuple, ++static void flow_offload_check_ethernet(struct flow_offload *flow, ++ enum flow_offload_tuple_dir dir, + struct flow_offload_hw_path *path) + { + struct net_device *dev = path->dev; + struct neighbour *n; ++ const void *daddr; ++ const struct dst_entry *dst_cache; + + if (dev->type != ARPHRD_ETHER) + return; + + memcpy(path->eth_src, path->dev->dev_addr, ETH_ALEN); +- n = dst_neigh_lookup(tuple->dst_cache, &tuple->src_v4); ++ ++ daddr = &flow->tuplehash[dir].tuple.src_v4; ++ dst_cache = flow->tuplehash[!dir].tuple.dst_cache; ++ n = dst_neigh_lookup(dst_cache, daddr); + if (!n) + return; + +@@ -44,17 +50,18 @@ static void flow_offload_check_ethernet(struct flow_offload_tuple *tuple, + } + + static int flow_offload_check_path(struct net *net, +- struct flow_offload_tuple *tuple, ++ struct flow_offload *flow, ++ enum flow_offload_tuple_dir dir, + struct flow_offload_hw_path *path) + { + struct net_device *dev; + +- dev = dev_get_by_index_rcu(net, tuple->iifidx); ++ dev = dev_get_by_index_rcu(net, flow->tuplehash[dir].tuple.iifidx); + if (!dev) + return -ENOENT; + + path->dev = dev; +- flow_offload_check_ethernet(tuple, path); ++ flow_offload_check_ethernet(flow, dir, path); + + if (dev->netdev_ops->ndo_flow_offload_check) + return dev->netdev_ops->ndo_flow_offload_check(path); +@@ -133,17 +140,14 @@ flow_offload_hw_prepare(struct net *net, struct flow_offload *flow) + { + struct flow_offload_hw_path src = {}; + struct flow_offload_hw_path dest = {}; +- struct flow_offload_tuple *tuple; + struct flow_offload_hw *offload = NULL; + + rcu_read_lock_bh(); + +- tuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple; +- if (flow_offload_check_path(net, tuple, &src)) ++ if (flow_offload_check_path(net, flow, FLOW_OFFLOAD_DIR_ORIGINAL, &src)) + goto out; + +- tuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple; +- if (flow_offload_check_path(net, tuple, &dest)) ++ if (flow_offload_check_path(net, flow, FLOW_OFFLOAD_DIR_REPLY, &dest)) + goto out; + + if (!src.dev->netdev_ops->ndo_flow_offload) + diff --git a/target/linux/generic/pending-4.14/648-netfilter-nf_flow_table_hw-check-the-status-of-dst_n.patch b/target/linux/generic/pending-4.14/648-netfilter-nf_flow_table_hw-check-the-status-of-dst_n.patch new file mode 100644 index 0000000000..ed4a1e3a3e --- /dev/null +++ b/target/linux/generic/pending-4.14/648-netfilter-nf_flow_table_hw-check-the-status-of-dst_n.patch @@ -0,0 +1,32 @@ +From: Konstantin Vasin +Date: Mon, 9 Mar 2020 17:41:22 +0300 +Subject: [PATCH] netfilter: nf_flow_table_hw: check the status of + dst_neigh + +It's better to check the nud_state is VALID. +If there is not neigh previos, the lookup will +create a non NUD_VALID with 00:00:00:00:00:00 mac. + +This fix is based on the upstream commit f31ad71c44 +("netfilter: nf_flow_table_offload: check the status of dst_neigh") +from wenxu + +Signed-off-by: Konstantin Vasin +--- + +index e831c8830e91..1238d675a316 100644 +--- a/net/netfilter/nf_flow_table_hw.c ++++ b/net/netfilter/nf_flow_table_hw.c +@@ -44,8 +44,10 @@ static void flow_offload_check_ethernet(struct flow_offload *flow, + if (!n) + return; + +- memcpy(path->eth_dest, n->ha, ETH_ALEN); +- path->flags |= FLOW_OFFLOAD_PATH_ETHERNET; ++ if (n->nud_state & NUD_VALID) { ++ memcpy(path->eth_dest, n->ha, ETH_ALEN); ++ path->flags |= FLOW_OFFLOAD_PATH_ETHERNET; ++ } + neigh_release(n); + } + diff --git a/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch b/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch index bf9822fda8..f3a314ae02 100644 --- a/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch +++ b/target/linux/generic/pending-4.19/411-mtd-partial_eraseblock_write.patch @@ -114,8 +114,7 @@ Signed-off-by: Felix Fietkau + slave->mtd.erasesize = slave->mtd.size; } -- tmp = part_absolute_offset(parent) + slave->mtd.size; -+ tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; + tmp = part_absolute_offset(parent) + slave->offset + slave->mtd.size; remainder = do_div(tmp, wr_alignment); if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) { - slave->mtd.flags &= ~MTD_WRITEABLE; diff --git a/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch b/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch index 6981c6d943..4d64fca90b 100644 --- a/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch +++ b/target/linux/generic/pending-4.19/450-mtd-spi-nor-allow-NOR-driver-to-write-fewer-bytes-th.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -1457,7 +1457,7 @@ static int spi_nor_write(struct mtd_info +@@ -1459,7 +1459,7 @@ static int spi_nor_write(struct mtd_info write_enable(nor); ret = nor->write(nor, addr, page_remain, buf + i); @@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau goto write_err; written = ret; -@@ -1466,13 +1466,6 @@ static int spi_nor_write(struct mtd_info +@@ -1468,13 +1468,6 @@ static int spi_nor_write(struct mtd_info goto write_err; *retlen += written; i += written; diff --git a/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch b/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch index 0c5d6cfa63..3172c223f2 100644 --- a/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch +++ b/target/linux/generic/pending-4.19/465-m25p80-mx-disable-software-protection.patch @@ -8,7 +8,7 @@ Signed-off-by: Felix Fietkau --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2735,6 +2735,7 @@ static int spi_nor_init(struct spi_nor * +@@ -2737,6 +2737,7 @@ static int spi_nor_init(struct spi_nor * */ if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL || JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || diff --git a/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch b/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch index fb6ae7df7b..f6a98af6ac 100644 --- a/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +++ b/target/linux/generic/pending-4.19/466-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch @@ -17,7 +17,7 @@ Signed-off-by: Matthias Schiffer --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2737,6 +2737,7 @@ static int spi_nor_init(struct spi_nor * +@@ -2739,6 +2739,7 @@ static int spi_nor_init(struct spi_nor * JEDEC_MFR(nor->info) == SNOR_MFR_INTEL || JEDEC_MFR(nor->info) == SNOR_MFR_MACRONIX || JEDEC_MFR(nor->info) == SNOR_MFR_SST || @@ -25,7 +25,7 @@ Signed-off-by: Matthias Schiffer nor->info->flags & SPI_NOR_HAS_LOCK) { write_enable(nor); write_sr(nor, 0); -@@ -2873,7 +2874,8 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -2875,7 +2876,8 @@ int spi_nor_scan(struct spi_nor *nor, co /* NOR protection support for STmicro/Micron chips and similar */ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || diff --git a/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch b/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch index 12d785856a..695c38cf0f 100644 --- a/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch +++ b/target/linux/generic/pending-4.19/470-mtd-spi-nor-support-limiting-4K-sectors-support-base.patch @@ -39,7 +39,7 @@ Signed-off-by: Felix Fietkau depends on ARCH_AT91 || (ARM && COMPILE_TEST && !ARCH_EBSA110) --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -2649,10 +2649,12 @@ static int spi_nor_select_erase(struct s +@@ -2651,10 +2651,12 @@ static int spi_nor_select_erase(struct s #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ diff --git a/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch b/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch index 664837928b..da60939bb3 100644 --- a/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch +++ b/target/linux/generic/pending-4.19/479-mtd-spi-nor-add-xtx-xt25f128b.patch @@ -30,7 +30,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -1273,6 +1273,9 @@ static const struct flash_info spi_nor_i +@@ -1275,6 +1275,9 @@ static const struct flash_info spi_nor_i /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, diff --git a/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch b/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch index c35aca8a18..cfdfe10836 100644 --- a/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch +++ b/target/linux/generic/pending-4.19/670-ipv6-allow-rejecting-with-source-address-failed-policy.patch @@ -185,7 +185,7 @@ Signed-off-by: Jonas Gorski cfg->fc_flags |= RTF_REJECT; if (rtm->rtm_type == RTN_LOCAL) -@@ -5084,6 +5115,8 @@ static int ip6_route_dev_notify(struct n +@@ -5085,6 +5116,8 @@ static int ip6_route_dev_notify(struct n #ifdef CONFIG_IPV6_MULTIPLE_TABLES net->ipv6.ip6_prohibit_entry->dst.dev = dev; net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev); @@ -194,7 +194,7 @@ Signed-off-by: Jonas Gorski net->ipv6.ip6_blk_hole_entry->dst.dev = dev; net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev); #endif -@@ -5095,6 +5128,7 @@ static int ip6_route_dev_notify(struct n +@@ -5096,6 +5129,7 @@ static int ip6_route_dev_notify(struct n in6_dev_put_clear(&net->ipv6.ip6_null_entry->rt6i_idev); #ifdef CONFIG_IPV6_MULTIPLE_TABLES in6_dev_put_clear(&net->ipv6.ip6_prohibit_entry->rt6i_idev); @@ -202,7 +202,7 @@ Signed-off-by: Jonas Gorski in6_dev_put_clear(&net->ipv6.ip6_blk_hole_entry->rt6i_idev); #endif } -@@ -5289,6 +5323,15 @@ static int __net_init ip6_route_net_init +@@ -5290,6 +5324,15 @@ static int __net_init ip6_route_net_init net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst, ip6_template_metrics, true); @@ -218,7 +218,7 @@ Signed-off-by: Jonas Gorski #endif net->ipv6.sysctl.flush_delay = 0; -@@ -5307,6 +5350,8 @@ out: +@@ -5308,6 +5351,8 @@ out: return ret; #ifdef CONFIG_IPV6_MULTIPLE_TABLES @@ -227,7 +227,7 @@ Signed-off-by: Jonas Gorski out_ip6_prohibit_entry: kfree(net->ipv6.ip6_prohibit_entry); out_ip6_null_entry: -@@ -5327,6 +5372,7 @@ static void __net_exit ip6_route_net_exi +@@ -5328,6 +5373,7 @@ static void __net_exit ip6_route_net_exi #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); kfree(net->ipv6.ip6_blk_hole_entry); @@ -235,7 +235,7 @@ Signed-off-by: Jonas Gorski #endif dst_entries_destroy(&net->ipv6.ip6_dst_ops); } -@@ -5403,6 +5449,9 @@ void __init ip6_route_init_special_entri +@@ -5404,6 +5450,9 @@ void __init ip6_route_init_special_entri init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); diff --git a/target/linux/generic/pending-4.9/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch b/target/linux/generic/pending-4.9/931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch similarity index 100% rename from target/linux/generic/pending-4.9/0931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch rename to target/linux/generic/pending-4.9/931-w1-gpio-fix-problem-with-platfom-data-in-w1-gpio.patch diff --git a/target/linux/ipq40xx/config-4.19 b/target/linux/ipq40xx/config-4.19 index 0de3001c8a..d01ae3cebc 100644 --- a/target/linux/ipq40xx/config-4.19 +++ b/target/linux/ipq40xx/config-4.19 @@ -47,6 +47,7 @@ CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y CONFIG_ARM_CPUIDLE=y CONFIG_ARM_CPU_SUSPEND=y # CONFIG_ARM_CPU_TOPOLOGY is not set +CONFIG_ARM_CRYPTO=y CONFIG_ARM_GIC=y CONFIG_ARM_HAS_SG_CHAIN=y CONFIG_ARM_L1_CACHE_SHIFT=6 @@ -115,34 +116,26 @@ CONFIG_CRC32_SLICEBY8=y CONFIG_CRYPTO_ACOMP2=y CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_CBC=y -CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y CONFIG_CRYPTO_DEFLATE=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_DEV_QCE=y CONFIG_CRYPTO_DEV_QCOM_RNG=y -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_DRBG_HMAC=y -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_GF128MUL=y +# CONFIG_CRYPTO_GHASH_ARM_CE is not set CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_JITTERENTROPY=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_SEQIV=y +# CONFIG_CRYPTO_SHA1_ARM_CE is not set +# CONFIG_CRYPTO_SHA1_ARM_NEON is not set CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_SIMD=y CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_CRYPTO_XTS=y CONFIG_DCACHE_WORD_ACCESS=y CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" # CONFIG_DEBUG_USER is not set diff --git a/target/linux/ipq40xx/patches-4.19/181-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch b/target/linux/ipq40xx/patches-4.19/039-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch similarity index 100% rename from target/linux/ipq40xx/patches-4.19/181-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch rename to target/linux/ipq40xx/patches-4.19/039-crypto-qce-add-CRYPTO_ALG_KERN_DRIVER_ONLY-flag.patch diff --git a/target/linux/ipq40xx/patches-4.19/040-crypto-qce-switch-to-skcipher-API.patch b/target/linux/ipq40xx/patches-4.19/040-crypto-qce-switch-to-skcipher-API.patch new file mode 100644 index 0000000000..2adfe622e3 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/040-crypto-qce-switch-to-skcipher-API.patch @@ -0,0 +1,463 @@ +From f441873642eebf20566c18d2966a8cd4b433ec1c Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Tue, 5 Nov 2019 14:28:17 +0100 +Subject: [PATCH] crypto: qce - switch to skcipher API + +Commit 7a7ffe65c8c5 ("crypto: skcipher - Add top-level skcipher interface") +dated 20 august 2015 introduced the new skcipher API which is supposed to +replace both blkcipher and ablkcipher. While all consumers of the API have +been converted long ago, some producers of the ablkcipher remain, forcing +us to keep the ablkcipher support routines alive, along with the matching +code to expose [a]blkciphers via the skcipher API. + +So switch this driver to the skcipher API, allowing us to finally drop the +blkcipher code in the near future. + +Reviewed-by: Stanimir Varbanov +Signed-off-by: Ard Biesheuvel +Backported-to-4.19-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile +index 19a7f899acff..8caa04e1ec43 100644 +--- a/drivers/crypto/qce/Makefile ++++ b/drivers/crypto/qce/Makefile +@@ -4,4 +4,4 @@ qcrypto-objs := core.o \ + common.o \ + dma.o \ + sha.o \ +- ablkcipher.o ++ skcipher.o +diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h +index 2b0278bb6e92..f93fab1dd1ff 100644 +--- a/drivers/crypto/qce/cipher.h ++++ b/drivers/crypto/qce/cipher.h +@@ -53,12 +53,12 @@ struct qce_cipher_reqctx { + unsigned int cryptlen; + }; + +-static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm) ++static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm) + { +- struct crypto_alg *alg = tfm->__crt_alg; +- return container_of(alg, struct qce_alg_template, alg.crypto); ++ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ return container_of(alg, struct qce_alg_template, alg.skcipher); + } + +-extern const struct qce_algo_ops ablkcipher_ops; ++extern const struct qce_algo_ops skcipher_ops; + + #endif /* _CIPHER_H_ */ +diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c +index 1fb5fde7fc03..e0202755682b 100644 +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -312,13 +312,13 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req, + return 0; + } + +-static int qce_setup_regs_ablkcipher(struct crypto_async_request *async_req, ++static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, + u32 totallen, u32 offset) + { +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; + __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0}; + __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0}; +@@ -397,8 +397,8 @@ int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen, + u32 offset) + { + switch (type) { +- case CRYPTO_ALG_TYPE_ABLKCIPHER: +- return qce_setup_regs_ablkcipher(async_req, totallen, offset); ++ case CRYPTO_ALG_TYPE_SKCIPHER: ++ return qce_setup_regs_skcipher(async_req, totallen, offset); + case CRYPTO_ALG_TYPE_AHASH: + return qce_setup_regs_ahash(async_req, totallen, offset); + default: +diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h +index a4addd4f7d6c..3252efa41e7a 100644 +--- a/drivers/crypto/qce/common.h ++++ b/drivers/crypto/qce/common.h +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + /* key size in bytes */ + #define QCE_SHA_HMAC_KEY_SIZE 64 +@@ -87,7 +88,7 @@ struct qce_alg_template { + unsigned long alg_flags; + const u32 *std_iv; + union { +- struct crypto_alg crypto; ++ struct skcipher_alg skcipher; + struct ahash_alg ahash; + } alg; + struct qce_device *qce; +diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c +index 1c3b36b75467..bf409edc23ab 100644 +--- a/drivers/crypto/qce/core.c ++++ b/drivers/crypto/qce/core.c +@@ -30,7 +30,7 @@ + #define QCE_QUEUE_LENGTH 1 + + static const struct qce_algo_ops *qce_ops[] = { +- &ablkcipher_ops, ++ &skcipher_ops, + &ahash_ops, + }; + +diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/skcipher.c +similarity index 62% +rename from drivers/crypto/qce/ablkcipher.c +rename to drivers/crypto/qce/skcipher.c +index 3658c46ef9c7..0376bb969834 100644 +--- a/drivers/crypto/qce/ablkcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -20,14 +20,14 @@ + + #include "cipher.h" + +-static LIST_HEAD(ablkcipher_algs); ++static LIST_HEAD(skcipher_algs); + +-static void qce_ablkcipher_done(void *data) ++static void qce_skcipher_done(void *data) + { + struct crypto_async_request *async_req = data; +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; + enum dma_data_direction dir_src, dir_dst; + u32 status; +@@ -40,7 +40,7 @@ static void qce_ablkcipher_done(void *data) + + error = qce_dma_terminate_all(&qce->dma); + if (error) +- dev_dbg(qce->dev, "ablkcipher dma termination error (%d)\n", ++ dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", + error); + + if (diff_dst) +@@ -51,18 +51,18 @@ static void qce_ablkcipher_done(void *data) + + error = qce_check_status(qce, &status); + if (error < 0) +- dev_dbg(qce->dev, "ablkcipher operation error (%x)\n", status); ++ dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); + + qce->async_req_done(tmpl->qce, error); + } + + static int +-qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) ++qce_skcipher_async_req_handle(struct crypto_async_request *async_req) + { +- struct ablkcipher_request *req = ablkcipher_request_cast(async_req); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); +- struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); +- struct qce_alg_template *tmpl = to_cipher_tmpl(async_req->tfm); ++ struct skcipher_request *req = skcipher_request_cast(async_req); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); ++ struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; + enum dma_data_direction dir_src, dir_dst; + struct scatterlist *sg; +@@ -70,17 +70,17 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) + gfp_t gfp; + int ret; + +- rctx->iv = req->info; +- rctx->ivsize = crypto_ablkcipher_ivsize(ablkcipher); +- rctx->cryptlen = req->nbytes; ++ rctx->iv = req->iv; ++ rctx->ivsize = crypto_skcipher_ivsize(skcipher); ++ rctx->cryptlen = req->cryptlen; + + diff_dst = (req->src != req->dst) ? true : false; + dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; + dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; + +- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes); ++ rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); + if (diff_dst) +- rctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes); ++ rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); + else + rctx->dst_nents = rctx->src_nents; + if (rctx->src_nents < 0) { +@@ -133,13 +133,13 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) + + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, + rctx->dst_sg, rctx->dst_nents, +- qce_ablkcipher_done, async_req); ++ qce_skcipher_done, async_req); + if (ret) + goto error_unmap_src; + + qce_dma_issue_pending(&qce->dma); + +- ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0); ++ ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); + if (ret) + goto error_terminate; + +@@ -157,12 +157,11 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req) + return ret; + } + +-static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, ++static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, + unsigned int keylen) + { +- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablk); +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- unsigned long flags = to_cipher_tmpl(tfm)->alg_flags; ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); ++ unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; + int ret; + + if (!key || !keylen) +@@ -180,7 +179,7 @@ static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, + u32 tmp[DES_EXPKEY_WORDS]; + + ret = des_ekey(tmp, key); +- if (!ret && crypto_ablkcipher_get_flags(ablk) & ++ if (!ret && crypto_skcipher_get_flags(ablk) & + CRYPTO_TFM_REQ_WEAK_KEY) + goto weakkey; + } +@@ -194,16 +193,15 @@ static int qce_ablkcipher_setkey(struct crypto_ablkcipher *ablk, const u8 *key, + ctx->enc_keylen = keylen; + return ret; + weakkey: +- crypto_ablkcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY); ++ crypto_skcipher_set_flags(ablk, CRYPTO_TFM_RES_WEAK_KEY); + return -EINVAL; + } + +-static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) ++static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) + { +- struct crypto_tfm *tfm = +- crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req)); +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); +- struct qce_cipher_reqctx *rctx = ablkcipher_request_ctx(req); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); + int ret; + +@@ -218,7 +216,7 @@ static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) + skcipher_request_set_callback(subreq, req->base.flags, + NULL, NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, +- req->nbytes, req->info); ++ req->cryptlen, req->iv); + ret = encrypt ? crypto_skcipher_encrypt(subreq) : + crypto_skcipher_decrypt(subreq); + skcipher_request_zero(subreq); +@@ -228,37 +226,37 @@ static int qce_ablkcipher_crypt(struct ablkcipher_request *req, int encrypt) + return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); + } + +-static int qce_ablkcipher_encrypt(struct ablkcipher_request *req) ++static int qce_skcipher_encrypt(struct skcipher_request *req) + { +- return qce_ablkcipher_crypt(req, 1); ++ return qce_skcipher_crypt(req, 1); + } + +-static int qce_ablkcipher_decrypt(struct ablkcipher_request *req) ++static int qce_skcipher_decrypt(struct skcipher_request *req) + { +- return qce_ablkcipher_crypt(req, 0); ++ return qce_skcipher_crypt(req, 0); + } + +-static int qce_ablkcipher_init(struct crypto_tfm *tfm) ++static int qce_skcipher_init(struct crypto_skcipher *tfm) + { +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + + memset(ctx, 0, sizeof(*ctx)); +- tfm->crt_ablkcipher.reqsize = sizeof(struct qce_cipher_reqctx); ++ crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); + +- ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(tfm), 0, +- CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK); ++ ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(&tfm->base), ++ 0, CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK); + return PTR_ERR_OR_ZERO(ctx->fallback); + } + +-static void qce_ablkcipher_exit(struct crypto_tfm *tfm) ++static void qce_skcipher_exit(struct crypto_skcipher *tfm) + { +- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + + crypto_free_skcipher(ctx->fallback); + } + +-struct qce_ablkcipher_def { ++struct qce_skcipher_def { + unsigned long flags; + const char *name; + const char *drv_name; +@@ -268,7 +266,7 @@ struct qce_ablkcipher_def { + unsigned int max_keysize; + }; + +-static const struct qce_ablkcipher_def ablkcipher_def[] = { ++static const struct qce_skcipher_def skcipher_def[] = { + { + .flags = QCE_ALG_AES | QCE_MODE_ECB, + .name = "ecb(aes)", +@@ -343,89 +341,89 @@ static const struct qce_ablkcipher_def ablkcipher_def[] = { + }, + }; + +-static int qce_ablkcipher_register_one(const struct qce_ablkcipher_def *def, ++static int qce_skcipher_register_one(const struct qce_skcipher_def *def, + struct qce_device *qce) + { + struct qce_alg_template *tmpl; +- struct crypto_alg *alg; ++ struct skcipher_alg *alg; + int ret; + + tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); + if (!tmpl) + return -ENOMEM; + +- alg = &tmpl->alg.crypto; ++ alg = &tmpl->alg.skcipher; + +- snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); +- snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", ++ snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); ++ snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", + def->drv_name); + +- alg->cra_blocksize = def->blocksize; +- alg->cra_ablkcipher.ivsize = def->ivsize; +- alg->cra_ablkcipher.min_keysize = def->min_keysize; +- alg->cra_ablkcipher.max_keysize = def->max_keysize; +- alg->cra_ablkcipher.setkey = qce_ablkcipher_setkey; +- alg->cra_ablkcipher.encrypt = qce_ablkcipher_encrypt; +- alg->cra_ablkcipher.decrypt = qce_ablkcipher_decrypt; +- +- alg->cra_priority = 300; +- alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_KERN_DRIVER_ONLY; +- alg->cra_ctxsize = sizeof(struct qce_cipher_ctx); +- alg->cra_alignmask = 0; +- alg->cra_type = &crypto_ablkcipher_type; +- alg->cra_module = THIS_MODULE; +- alg->cra_init = qce_ablkcipher_init; +- alg->cra_exit = qce_ablkcipher_exit; +- INIT_LIST_HEAD(&alg->cra_list); ++ alg->base.cra_blocksize = def->blocksize; ++ alg->ivsize = def->ivsize; ++ alg->min_keysize = def->min_keysize; ++ alg->max_keysize = def->max_keysize; ++ alg->setkey = qce_skcipher_setkey; ++ alg->encrypt = qce_skcipher_encrypt; ++ alg->decrypt = qce_skcipher_decrypt; ++ ++ alg->base.cra_priority = 300; ++ alg->base.cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY; ++ alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); ++ alg->base.cra_alignmask = 0; ++ alg->base.cra_module = THIS_MODULE; ++ ++ alg->init = qce_skcipher_init; ++ alg->exit = qce_skcipher_exit; + + INIT_LIST_HEAD(&tmpl->entry); +- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_ABLKCIPHER; ++ tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; + tmpl->alg_flags = def->flags; + tmpl->qce = qce; + +- ret = crypto_register_alg(alg); ++ ret = crypto_register_skcipher(alg); + if (ret) { + kfree(tmpl); +- dev_err(qce->dev, "%s registration failed\n", alg->cra_name); ++ dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); + return ret; + } + +- list_add_tail(&tmpl->entry, &ablkcipher_algs); +- dev_dbg(qce->dev, "%s is registered\n", alg->cra_name); ++ list_add_tail(&tmpl->entry, &skcipher_algs); ++ dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); + return 0; + } + +-static void qce_ablkcipher_unregister(struct qce_device *qce) ++static void qce_skcipher_unregister(struct qce_device *qce) + { + struct qce_alg_template *tmpl, *n; + +- list_for_each_entry_safe(tmpl, n, &ablkcipher_algs, entry) { +- crypto_unregister_alg(&tmpl->alg.crypto); ++ list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { ++ crypto_unregister_skcipher(&tmpl->alg.skcipher); + list_del(&tmpl->entry); + kfree(tmpl); + } + } + +-static int qce_ablkcipher_register(struct qce_device *qce) ++static int qce_skcipher_register(struct qce_device *qce) + { + int ret, i; + +- for (i = 0; i < ARRAY_SIZE(ablkcipher_def); i++) { +- ret = qce_ablkcipher_register_one(&ablkcipher_def[i], qce); ++ for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { ++ ret = qce_skcipher_register_one(&skcipher_def[i], qce); + if (ret) + goto err; + } + + return 0; + err: +- qce_ablkcipher_unregister(qce); ++ qce_skcipher_unregister(qce); + return ret; + } + +-const struct qce_algo_ops ablkcipher_ops = { +- .type = CRYPTO_ALG_TYPE_ABLKCIPHER, +- .register_algs = qce_ablkcipher_register, +- .unregister_algs = qce_ablkcipher_unregister, +- .async_req_handle = qce_ablkcipher_async_req_handle, ++const struct qce_algo_ops skcipher_ops = { ++ .type = CRYPTO_ALG_TYPE_SKCIPHER, ++ .register_algs = qce_skcipher_register, ++ .unregister_algs = qce_skcipher_unregister, ++ .async_req_handle = qce_skcipher_async_req_handle, + }; diff --git a/target/linux/ipq40xx/patches-4.19/041-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch b/target/linux/ipq40xx/patches-4.19/041-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch new file mode 100644 index 0000000000..7d822c59d6 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/041-crypto-qce-fix-ctr-aes-qce-block-chunk-sizes.patch @@ -0,0 +1,41 @@ +From 3f5598286445f695bb63a22239dd3603c69a6eaf Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Mon, 28 Oct 2019 09:03:07 -0300 +Subject: [PATCH] crypto: qce - fix ctr-aes-qce block, chunk sizes + +Set blocksize of ctr-aes-qce to 1, so it can operate as a stream cipher, +adding the definition for chucksize instead, where the underlying block +size belongs. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 0376bb969834..0776286cfc9e 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -261,6 +261,7 @@ struct qce_skcipher_def { + const char *name; + const char *drv_name; + unsigned int blocksize; ++ unsigned int chunksize; + unsigned int ivsize; + unsigned int min_keysize; + unsigned int max_keysize; +@@ -289,7 +290,8 @@ static const struct qce_skcipher_def skcipher_def[] = { + .flags = QCE_ALG_AES | QCE_MODE_CTR, + .name = "ctr(aes)", + .drv_name = "ctr-aes-qce", +- .blocksize = AES_BLOCK_SIZE, ++ .blocksize = 1, ++ .chunksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, +@@ -359,6 +361,7 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, + def->drv_name); + + alg->base.cra_blocksize = def->blocksize; ++ alg->chunksize = def->chunksize; + alg->ivsize = def->ivsize; + alg->min_keysize = def->min_keysize; + alg->max_keysize = def->max_keysize; diff --git a/target/linux/ipq40xx/patches-4.19/042-crypto-qce-fix-xts-aes-qce-key-sizes.patch b/target/linux/ipq40xx/patches-4.19/042-crypto-qce-fix-xts-aes-qce-key-sizes.patch new file mode 100644 index 0000000000..dd58dcd801 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/042-crypto-qce-fix-xts-aes-qce-key-sizes.patch @@ -0,0 +1,52 @@ +From 0138c3c13809250338d7cfba6f4ca3b2da02b2c8 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Thu, 21 Nov 2019 14:28:23 -0300 +Subject: [PATCH] crypto: qce - fix xts-aes-qce key sizes + +XTS-mode uses two keys, so the keysizes should be doubled in +skcipher_def, and halved when checking if it is AES-128/192/256. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 0776286cfc9e..9b1bb32515b4 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -168,7 +168,7 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, + return -EINVAL; + + if (IS_AES(flags)) { +- switch (keylen) { ++ switch (IS_XTS(flags) ? keylen >> 1 : keylen) { + case AES_KEYSIZE_128: + case AES_KEYSIZE_256: + break; +@@ -203,13 +203,15 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) + struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); ++ int keylen; + int ret; + + rctx->flags = tmpl->alg_flags; + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; ++ keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + +- if (IS_AES(rctx->flags) && ctx->enc_keylen != AES_KEYSIZE_128 && +- ctx->enc_keylen != AES_KEYSIZE_256) { ++ if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && ++ keylen != AES_KEYSIZE_256) { + SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_tfm(subreq, ctx->fallback); +@@ -302,8 +304,8 @@ static const struct qce_skcipher_def skcipher_def[] = { + .drv_name = "xts-aes-qce", + .blocksize = AES_BLOCK_SIZE, + .ivsize = AES_BLOCK_SIZE, +- .min_keysize = AES_MIN_KEY_SIZE, +- .max_keysize = AES_MAX_KEY_SIZE, ++ .min_keysize = AES_MIN_KEY_SIZE * 2, ++ .max_keysize = AES_MAX_KEY_SIZE * 2, + }, + { + .flags = QCE_ALG_DES | QCE_MODE_ECB, diff --git a/target/linux/ipq40xx/patches-4.19/043-crypto-qce-save-a-sg-table-slot-for-result-buf.patch b/target/linux/ipq40xx/patches-4.19/043-crypto-qce-save-a-sg-table-slot-for-result-buf.patch new file mode 100644 index 0000000000..9f107db035 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/043-crypto-qce-save-a-sg-table-slot-for-result-buf.patch @@ -0,0 +1,85 @@ +From 31f796293b6c38126a466414c565827b9cfdbe39 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Wed, 20 Nov 2019 21:39:11 -0300 +Subject: [PATCH] crypto: qce - save a sg table slot for result buf + +When ctr-aes-qce is used for gcm-mode, an extra sg entry for the +authentication tag is present, causing trouble when the qce driver +prepares the dst-results eg table for dma. + +It computes the number of entries needed with sg_nents_for_len, leaving +out the tag entry. Then it creates a sg table with that number plus +one, used to store a "result" sg. + +When copying the sg table, it does not limit the number of entries +copied, so tha extra slot is filled with the authentication tag sg. +When the driver tries to add the result sg, the list is full, and it +returns EINVAL. + +By limiting the number of sg entries copied to the dest table, the slot +for the result buffer is guaranteed to be unused. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c +index 4797e795c9b9..db560c3d3e4f 100644 +--- a/drivers/crypto/qce/dma.c ++++ b/drivers/crypto/qce/dma.c +@@ -55,7 +55,8 @@ void qce_dma_release(struct qce_dma_data *dma) + } + + struct scatterlist * +-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) ++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, ++ int max_ents) + { + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; + +@@ -68,12 +69,13 @@ qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl) + if (!sg) + return ERR_PTR(-EINVAL); + +- while (new_sgl && sg) { ++ while (new_sgl && sg && max_ents) { + sg_set_page(sg, sg_page(new_sgl), new_sgl->length, + new_sgl->offset); + sg_last = sg; + sg = sg_next(sg); + new_sgl = sg_next(new_sgl); ++ max_ents--; + } + + return sg_last; +diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h +index 130235d17bb4..0be71f7f7a58 100644 +--- a/drivers/crypto/qce/dma.h ++++ b/drivers/crypto/qce/dma.h +@@ -50,6 +50,7 @@ int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in, + void qce_dma_issue_pending(struct qce_dma_data *dma); + int qce_dma_terminate_all(struct qce_dma_data *dma); + struct scatterlist * +-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add); ++qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, ++ int max_ents); + + #endif /* _DMA_H_ */ +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 12f882032544..33d998f5cf5f 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -103,13 +103,13 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) + + sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); + +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst); ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; + } + +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg); ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; diff --git a/target/linux/ipq40xx/patches-4.19/044-crypto-qce-update-the-skcipher-IV.patch b/target/linux/ipq40xx/patches-4.19/044-crypto-qce-update-the-skcipher-IV.patch new file mode 100644 index 0000000000..de7829e767 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/044-crypto-qce-update-the-skcipher-IV.patch @@ -0,0 +1,29 @@ +From 502ca0b7c1d856a46dbd78e67690c12c47775b97 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 22 Nov 2019 09:00:02 -0300 +Subject: [PATCH] crypto: qce - update the skcipher IV + +Update the IV after the completion of each cipher operation. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 33d998f5cf5f..51377395ed53 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -29,6 +29,7 @@ static void qce_skcipher_done(void *data) + struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); + struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); + struct qce_device *qce = tmpl->qce; ++ struct qce_result_dump *result_buf = qce->dma.result_buf; + enum dma_data_direction dir_src, dir_dst; + u32 status; + int error; +@@ -53,6 +54,7 @@ static void qce_skcipher_done(void *data) + if (error < 0) + dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); + ++ memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); + qce->async_req_done(tmpl->qce, error); + } + diff --git a/target/linux/ipq40xx/patches-4.19/046-crypto-qce-initialize-fallback-only-for-AES.patch b/target/linux/ipq40xx/patches-4.19/046-crypto-qce-initialize-fallback-only-for-AES.patch new file mode 100644 index 0000000000..b673884ba2 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/046-crypto-qce-initialize-fallback-only-for-AES.patch @@ -0,0 +1,56 @@ +From f2a33ce18232919d3831d1c61a06b6067209282d Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 22 Nov 2019 09:34:29 -0300 +Subject: [PATCH] crypto: qce - initialize fallback only for AES + +Adjust cra_flags to add CRYPTO_NEED_FALLBACK only for AES ciphers, where +AES-192 is not handled by the qce hardware, and don't allocate & free +the fallback skcipher for anything other than AES. + +The rest of the code is unchanged, as the use of the fallback is already +restricted to AES. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 51377395ed53..5a4863091f2a 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -246,7 +246,15 @@ static int qce_skcipher_init(struct crypto_skcipher *tfm) + + memset(ctx, 0, sizeof(*ctx)); + crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx)); ++ return 0; ++} ++ ++static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) ++{ ++ struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ int ret; + ++ qce_skcipher_init(tfm); + ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(&tfm->base), + 0, CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK); +@@ -375,14 +383,18 @@ static int qce_skcipher_register_one(const struct qce_skcipher_def *def, + + alg->base.cra_priority = 300; + alg->base.cra_flags = CRYPTO_ALG_ASYNC | +- CRYPTO_ALG_NEED_FALLBACK | + CRYPTO_ALG_KERN_DRIVER_ONLY; + alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); + alg->base.cra_alignmask = 0; + alg->base.cra_module = THIS_MODULE; + +- alg->init = qce_skcipher_init; +- alg->exit = qce_skcipher_exit; ++ if (IS_AES(def->flags)) { ++ alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; ++ alg->init = qce_skcipher_init_fallback; ++ alg->exit = qce_skcipher_exit; ++ } else { ++ alg->init = qce_skcipher_init; ++ } + + INIT_LIST_HEAD(&tmpl->entry); + tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; diff --git a/target/linux/ipq40xx/patches-4.19/047-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch b/target/linux/ipq40xx/patches-4.19/047-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch new file mode 100644 index 0000000000..8003f7502a --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/047-crypto-qce-use-cryptlen-when-adding-extra-sgl.patch @@ -0,0 +1,89 @@ +From 686aa4db696270dadc5e8b2971769e1676251ff1 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 31 Jan 2020 17:43:16 -0300 +Subject: [PATCH] crypto: qce - use cryptlen when adding extra sgl + +The qce crypto driver appends an extra entry to the dst sgl, to maintain +private state information. + +When the gcm driver sends requests to the ctr skcipher, it passes the +authentication tag after the actual crypto payload, but it must not be +touched. + +Commit 1336c2221bee ("crypto: qce - save a sg table slot for result +buf") limited the destination sgl to avoid overwriting the +authentication tag but it assumed the tag would be in a separate sgl +entry. + +This is not always the case, so it is better to limit the length of the +destination buffer to req->cryptlen before appending the result buf. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c +index db560c3d3e4f..0ae9d28afa69 100644 +--- a/drivers/crypto/qce/dma.c ++++ b/drivers/crypto/qce/dma.c +@@ -56,9 +56,10 @@ void qce_dma_release(struct qce_dma_data *dma) + + struct scatterlist * + qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, +- int max_ents) ++ unsigned int max_len) + { + struct scatterlist *sg = sgt->sgl, *sg_last = NULL; ++ unsigned int new_len; + + while (sg) { + if (!sg_page(sg)) +@@ -69,13 +70,13 @@ qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl, + if (!sg) + return ERR_PTR(-EINVAL); + +- while (new_sgl && sg && max_ents) { +- sg_set_page(sg, sg_page(new_sgl), new_sgl->length, +- new_sgl->offset); ++ while (new_sgl && sg && max_len) { ++ new_len = new_sgl->length > max_len ? max_len : new_sgl->length; ++ sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset); + sg_last = sg; + sg = sg_next(sg); + new_sgl = sg_next(new_sgl); +- max_ents--; ++ max_len -= new_len; + } + + return sg_last; +diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h +index 0be71f7f7a58..710d5e370293 100644 +--- a/drivers/crypto/qce/dma.h ++++ b/drivers/crypto/qce/dma.h +@@ -51,6 +51,6 @@ void qce_dma_issue_pending(struct qce_dma_data *dma); + int qce_dma_terminate_all(struct qce_dma_data *dma); + struct scatterlist * + qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add, +- int max_ents); ++ unsigned int max_len); + + #endif /* _DMA_H_ */ +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 5af74f2431ca..188eb234ba2c 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -105,13 +105,14 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) + + sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); + +- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, rctx->dst_nents - 1); ++ sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; + } + +- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 1); ++ sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, ++ QCE_RESULT_BUF_SZ); + if (IS_ERR(sg)) { + ret = PTR_ERR(sg); + goto error_free; diff --git a/target/linux/ipq40xx/patches-4.19/048-crypto-qce-use-AES-fallback-for-small-requests.patch b/target/linux/ipq40xx/patches-4.19/048-crypto-qce-use-AES-fallback-for-small-requests.patch new file mode 100644 index 0000000000..60ebe95c36 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/048-crypto-qce-use-AES-fallback-for-small-requests.patch @@ -0,0 +1,126 @@ +From 2d3b6fae7d1a2ad821769440daa91d7eec5c8250 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Fri, 20 Dec 2019 09:41:44 -0300 +Subject: [PATCH] crypto: qce - use AES fallback for small requests + +Process small blocks using the fallback cipher, as a workaround for an +observed failure (DMA-related, apparently) when computing the GCM ghash +key. This brings a speed gain as well, since it avoids the latency of +using the hardware engine to process small blocks. + +Using software for all 16-byte requests would be enough to make GCM +work, but to increase performance, a larger threshold would be better. +Measuring the performance of supported ciphers with openssl speed, +software matches hardware at around 768-1024 bytes. + +Considering the 256-bit ciphers, software is 2-3 times faster than qce +at 256-bytes, 30% faster at 512, and about even at 768-bytes. With +128-bit keys, the break-even point would be around 1024-bytes. + +This adds the 'aes_sw_max_len' parameter, to set the largest request +length processed by the software fallback. Its default is being set to +512 bytes, a little lower than the break-even point, to balance the cost +in CPU usage. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index c1595750864e..a0c4d85de4c3 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -640,6 +640,29 @@ choice + + endchoice + ++config CRYPTO_DEV_QCE_SW_MAX_LEN ++ int "Default maximum request size to use software for AES" ++ depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER ++ default 512 ++ help ++ This sets the default maximum request size to perform AES requests ++ using software instead of the crypto engine. It can be changed by ++ setting the aes_sw_max_len parameter. ++ ++ Small blocks are processed faster in software than hardware. ++ Considering the 256-bit ciphers, software is 2-3 times faster than ++ qce at 256-bytes, 30% faster at 512, and about even at 768-bytes. ++ With 128-bit keys, the break-even point would be around 1024-bytes. ++ ++ The default is set a little lower, to 512 bytes, to balance the ++ cost in CPU usage. The minimum recommended setting is 16-bytes ++ (1 AES block), since AES-GCM will fail if you set it lower. ++ Setting this to zero will send all requests to the hardware. ++ ++ Note that 192-bit keys are not supported by the hardware and are ++ always processed by the software fallback, and all DES requests ++ are done by the hardware. ++ + config CRYPTO_DEV_QCOM_RNG + tristate "Qualcomm Random Number Generator Driver" + depends on ARCH_QCOM || COMPILE_TEST +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 188eb234ba2c..9b72fec2ab2e 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -13,6 +13,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -20,6 +21,13 @@ + + #include "cipher.h" + ++static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; ++module_param(aes_sw_max_len, uint, 0644); ++MODULE_PARM_DESC(aes_sw_max_len, ++ "Only use hardware for AES requests larger than this " ++ "[0=always use hardware; anything <16 breaks AES-GCM; default=" ++ __stringify(CONFIG_CRYPTO_DEV_QCE_SOFT_THRESHOLD)"]"); ++ + static LIST_HEAD(skcipher_algs); + + static void qce_skcipher_done(void *data) +@@ -170,15 +178,7 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, + if (!key || !keylen) + return -EINVAL; + +- if (IS_AES(flags)) { +- switch (IS_XTS(flags) ? keylen >> 1 : keylen) { +- case AES_KEYSIZE_128: +- case AES_KEYSIZE_256: +- break; +- default: +- goto fallback; +- } +- } else if (IS_DES(flags)) { ++ if (IS_DES(flags)) { + u32 tmp[DES_EXPKEY_WORDS]; + + ret = des_ekey(tmp, key); +@@ -189,8 +189,8 @@ static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, + + ctx->enc_keylen = keylen; + memcpy(ctx->enc_key, key, keylen); +- return 0; +-fallback: ++ if (!IS_AES(flags)) ++ return 0; + ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); + if (!ret) + ctx->enc_keylen = keylen; +@@ -213,8 +213,9 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; + keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + +- if (IS_AES(rctx->flags) && keylen != AES_KEYSIZE_128 && +- keylen != AES_KEYSIZE_256) { ++ if (IS_AES(rctx->flags) && ++ ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || ++ req->cryptlen <= aes_sw_max_len)) { + SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_tfm(subreq, ctx->fallback); diff --git a/target/linux/ipq40xx/patches-4.19/049-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch b/target/linux/ipq40xx/patches-4.19/049-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch new file mode 100644 index 0000000000..eee2241d19 --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/049-crypto-qce-handle-AES-XTS-cases-that-qce-fails.patch @@ -0,0 +1,59 @@ +From bbf2b1cf22dc98f3df33b6666df046dfb9564d91 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Wed, 5 Feb 2020 13:42:25 -0300 +Subject: [PATCH] crypto: qce - handle AES-XTS cases that qce fails + +QCE hangs when presented with an AES-XTS request whose length is larger +than QCE_SECTOR_SIZE (512-bytes), and is not a multiple of it. Let the +fallback cipher handle them. + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c +index 3849d7bcaeb0..3e0fcd7613f1 100644 +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -23,8 +23,6 @@ + #include "regs-v5.h" + #include "sha.h" + +-#define QCE_SECTOR_SIZE 512 +- + static inline u32 qce_read(struct qce_device *qce, u32 offset) + { + return readl(qce->base + offset); +diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h +index 3252efa41e7a..5f9d3c4e3ead 100644 +--- a/drivers/crypto/qce/common.h ++++ b/drivers/crypto/qce/common.h +@@ -20,6 +20,9 @@ + #include + #include + ++/* xts du size */ ++#define QCE_SECTOR_SIZE 512 ++ + /* key size in bytes */ + #define QCE_SHA_HMAC_KEY_SIZE 64 + #define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256 +diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c +index 9b72fec2ab2e..e46cb8269640 100644 +--- a/drivers/crypto/qce/skcipher.c ++++ b/drivers/crypto/qce/skcipher.c +@@ -213,9 +213,14 @@ static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) + rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; + keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; + ++ /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and ++ * is not a multiple of it; pass such requests to the fallback ++ */ + if (IS_AES(rctx->flags) && +- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || +- req->cryptlen <= aes_sw_max_len)) { ++ (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || ++ req->cryptlen <= aes_sw_max_len) || ++ (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE && ++ req->cryptlen % QCE_SECTOR_SIZE))) { + SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + + skcipher_request_set_tfm(subreq, ctx->fallback); diff --git a/target/linux/ipq40xx/patches-4.19/051-crypto-qce-allow-building-only-hashes-ciphers.patch b/target/linux/ipq40xx/patches-4.19/051-crypto-qce-allow-building-only-hashes-ciphers.patch new file mode 100644 index 0000000000..3d4214929c --- /dev/null +++ b/target/linux/ipq40xx/patches-4.19/051-crypto-qce-allow-building-only-hashes-ciphers.patch @@ -0,0 +1,415 @@ +From 62134842498927a0fcc19798a615340a7a6a9e62 Mon Sep 17 00:00:00 2001 +From: Eneas U de Queiroz +Date: Mon, 28 Oct 2019 15:17:19 -0300 +Subject: [PATCH] crypto: qce - allow building only hashes/ciphers + +Signed-off-by: Eneas U de Queiroz + +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index a8c4ce07fc9d..c1595750864e 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -573,6 +573,14 @@ config CRYPTO_DEV_QCE + tristate "Qualcomm crypto engine accelerator" + depends on ARCH_QCOM || COMPILE_TEST + depends on HAS_IOMEM ++ help ++ This driver supports Qualcomm crypto engine accelerator ++ hardware. To compile this driver as a module, choose M here. The ++ module will be called qcrypto. ++ ++config CRYPTO_DEV_QCE_SKCIPHER ++ bool ++ depends on CRYPTO_DEV_QCE + select CRYPTO_AES + select CRYPTO_DES + select CRYPTO_ECB +@@ -580,10 +588,57 @@ config CRYPTO_DEV_QCE + select CRYPTO_XTS + select CRYPTO_CTR + select CRYPTO_BLKCIPHER +- help +- This driver supports Qualcomm crypto engine accelerator +- hardware. To compile this driver as a module, choose M here. The +- module will be called qcrypto. ++ ++config CRYPTO_DEV_QCE_SHA ++ bool ++ depends on CRYPTO_DEV_QCE ++ ++choice ++ prompt "Algorithms enabled for QCE acceleration" ++ default CRYPTO_DEV_QCE_ENABLE_ALL ++ depends on CRYPTO_DEV_QCE ++ help ++ This option allows to choose whether to build support for all algorihtms ++ (default), hashes-only, or skciphers-only. ++ ++ The QCE engine does not appear to scale as well as the CPU to handle ++ multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the ++ QCE handles only 2 requests in parallel. ++ ++ Ipsec throughput seems to improve when disabling either family of ++ algorithms, sharing the load with the CPU. Enabling skciphers-only ++ appears to work best. ++ ++ config CRYPTO_DEV_QCE_ENABLE_ALL ++ bool "All supported algorithms" ++ select CRYPTO_DEV_QCE_SKCIPHER ++ select CRYPTO_DEV_QCE_SHA ++ help ++ Enable all supported algorithms: ++ - AES (CBC, CTR, ECB, XTS) ++ - 3DES (CBC, ECB) ++ - DES (CBC, ECB) ++ - SHA1, HMAC-SHA1 ++ - SHA256, HMAC-SHA256 ++ ++ config CRYPTO_DEV_QCE_ENABLE_SKCIPHER ++ bool "Symmetric-key ciphers only" ++ select CRYPTO_DEV_QCE_SKCIPHER ++ help ++ Enable symmetric-key ciphers only: ++ - AES (CBC, CTR, ECB, XTS) ++ - 3DES (ECB, CBC) ++ - DES (ECB, CBC) ++ ++ config CRYPTO_DEV_QCE_ENABLE_SHA ++ bool "Hash/HMAC only" ++ select CRYPTO_DEV_QCE_SHA ++ help ++ Enable hashes/HMAC algorithms only: ++ - SHA1, HMAC-SHA1 ++ - SHA256, HMAC-SHA256 ++ ++endchoice + + config CRYPTO_DEV_QCOM_RNG + tristate "Qualcomm Random Number Generator Driver" +diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile +index 8caa04e1ec43..14ade8a7d664 100644 +--- a/drivers/crypto/qce/Makefile ++++ b/drivers/crypto/qce/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o + qcrypto-objs := core.o \ + common.o \ +- dma.o \ +- sha.o \ +- skcipher.o ++ dma.o ++ ++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o ++qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o +diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c +index e0202755682b..3849d7bcaeb0 100644 +--- a/drivers/crypto/qce/common.c ++++ b/drivers/crypto/qce/common.c +@@ -53,52 +53,56 @@ qce_clear_array(struct qce_device *qce, u32 offset, unsigned int len) + qce_write(qce, offset + i * sizeof(u32), 0); + } + +-static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) ++static u32 qce_config_reg(struct qce_device *qce, int little) + { +- u32 cfg = 0; ++ u32 beats = (qce->burst_size >> 3) - 1; ++ u32 pipe_pair = qce->pipe_pair_id; ++ u32 config; + +- if (IS_AES(flags)) { +- if (aes_key_size == AES_KEYSIZE_128) +- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; +- else if (aes_key_size == AES_KEYSIZE_256) +- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; +- } ++ config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; ++ config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | ++ BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); ++ config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; ++ config &= ~HIGH_SPD_EN_N_SHIFT; + +- if (IS_AES(flags)) +- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; +- else if (IS_DES(flags) || IS_3DES(flags)) +- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; ++ if (little) ++ config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); + +- if (IS_DES(flags)) +- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; ++ return config; ++} + +- if (IS_3DES(flags)) +- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; ++void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) ++{ ++ __be32 *d = dst; ++ const u8 *s = src; ++ unsigned int n; + +- switch (flags & QCE_MODE_MASK) { +- case QCE_MODE_ECB: +- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CBC: +- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CTR: +- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_XTS: +- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; +- break; +- case QCE_MODE_CCM: +- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; +- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; +- break; +- default: +- return ~0; ++ n = len / sizeof(u32); ++ for (; n > 0; n--) { ++ *d = cpu_to_be32p((const __u32 *) s); ++ s += sizeof(__u32); ++ d++; + } ++} + +- return cfg; ++static void qce_setup_config(struct qce_device *qce) ++{ ++ u32 config; ++ ++ /* get big endianness */ ++ config = qce_config_reg(qce, 0); ++ ++ /* clear status */ ++ qce_write(qce, REG_STATUS, 0); ++ qce_write(qce, REG_CONFIG, config); ++} ++ ++static inline void qce_crypto_go(struct qce_device *qce) ++{ ++ qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); + } + ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + static u32 qce_auth_cfg(unsigned long flags, u32 key_size) + { + u32 cfg = 0; +@@ -145,88 +149,6 @@ static u32 qce_auth_cfg(unsigned long flags, u32 key_size) + return cfg; + } + +-static u32 qce_config_reg(struct qce_device *qce, int little) +-{ +- u32 beats = (qce->burst_size >> 3) - 1; +- u32 pipe_pair = qce->pipe_pair_id; +- u32 config; +- +- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK; +- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) | +- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT); +- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK; +- config &= ~HIGH_SPD_EN_N_SHIFT; +- +- if (little) +- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT); +- +- return config; +-} +- +-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len) +-{ +- __be32 *d = dst; +- const u8 *s = src; +- unsigned int n; +- +- n = len / sizeof(u32); +- for (; n > 0; n--) { +- *d = cpu_to_be32p((const __u32 *) s); +- s += sizeof(__u32); +- d++; +- } +-} +- +-static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) +-{ +- u8 swap[QCE_AES_IV_LENGTH]; +- u32 i, j; +- +- if (ivsize > QCE_AES_IV_LENGTH) +- return; +- +- memset(swap, 0, QCE_AES_IV_LENGTH); +- +- for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; +- i < QCE_AES_IV_LENGTH; i++, j--) +- swap[i] = src[j]; +- +- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); +-} +- +-static void qce_xtskey(struct qce_device *qce, const u8 *enckey, +- unsigned int enckeylen, unsigned int cryptlen) +-{ +- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; +- unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); +- unsigned int xtsdusize; +- +- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, +- enckeylen / 2); +- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); +- +- /* xts du size 512B */ +- xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); +- qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); +-} +- +-static void qce_setup_config(struct qce_device *qce) +-{ +- u32 config; +- +- /* get big endianness */ +- config = qce_config_reg(qce, 0); +- +- /* clear status */ +- qce_write(qce, REG_STATUS, 0); +- qce_write(qce, REG_CONFIG, config); +-} +- +-static inline void qce_crypto_go(struct qce_device *qce) +-{ +- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT)); +-} +- + static int qce_setup_regs_ahash(struct crypto_async_request *async_req, + u32 totallen, u32 offset) + { +@@ -311,6 +233,87 @@ static int qce_setup_regs_ahash(struct crypto_async_request *async_req, + + return 0; + } ++#endif ++ ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER ++static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size) ++{ ++ u32 cfg = 0; ++ ++ if (IS_AES(flags)) { ++ if (aes_key_size == AES_KEYSIZE_128) ++ cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT; ++ else if (aes_key_size == AES_KEYSIZE_256) ++ cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT; ++ } ++ ++ if (IS_AES(flags)) ++ cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT; ++ else if (IS_DES(flags) || IS_3DES(flags)) ++ cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT; ++ ++ if (IS_DES(flags)) ++ cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT; ++ ++ if (IS_3DES(flags)) ++ cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT; ++ ++ switch (flags & QCE_MODE_MASK) { ++ case QCE_MODE_ECB: ++ cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CBC: ++ cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CTR: ++ cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_XTS: ++ cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT; ++ break; ++ case QCE_MODE_CCM: ++ cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT; ++ cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT; ++ break; ++ default: ++ return ~0; ++ } ++ ++ return cfg; ++} ++ ++static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize) ++{ ++ u8 swap[QCE_AES_IV_LENGTH]; ++ u32 i, j; ++ ++ if (ivsize > QCE_AES_IV_LENGTH) ++ return; ++ ++ memset(swap, 0, QCE_AES_IV_LENGTH); ++ ++ for (i = (QCE_AES_IV_LENGTH - ivsize), j = ivsize - 1; ++ i < QCE_AES_IV_LENGTH; i++, j--) ++ swap[i] = src[j]; ++ ++ qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH); ++} ++ ++static void qce_xtskey(struct qce_device *qce, const u8 *enckey, ++ unsigned int enckeylen, unsigned int cryptlen) ++{ ++ u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0}; ++ unsigned int xtsklen = enckeylen / (2 * sizeof(u32)); ++ unsigned int xtsdusize; ++ ++ qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2, ++ enckeylen / 2); ++ qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen); ++ ++ /* xts du size 512B */ ++ xtsdusize = min_t(u32, QCE_SECTOR_SIZE, cryptlen); ++ qce_write(qce, REG_ENCR_XTS_DU_SIZE, xtsdusize); ++} + + static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, + u32 totallen, u32 offset) +@@ -392,15 +395,20 @@ static int qce_setup_regs_skcipher(struct crypto_async_request *async_req, + + return 0; + } ++#endif + + int qce_start(struct crypto_async_request *async_req, u32 type, u32 totallen, + u32 offset) + { + switch (type) { ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER + case CRYPTO_ALG_TYPE_SKCIPHER: + return qce_setup_regs_skcipher(async_req, totallen, offset); ++#endif ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + case CRYPTO_ALG_TYPE_AHASH: + return qce_setup_regs_ahash(async_req, totallen, offset); ++#endif + default: + return -EINVAL; + } +diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c +index bf409edc23ab..4ad79b67fc51 100644 +--- a/drivers/crypto/qce/core.c ++++ b/drivers/crypto/qce/core.c +@@ -30,8 +30,12 @@ + #define QCE_QUEUE_LENGTH 1 + + static const struct qce_algo_ops *qce_ops[] = { ++#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER + &skcipher_ops, ++#endif ++#ifdef CONFIG_CRYPTO_DEV_QCE_SHA + &ahash_ops, ++#endif + }; + + static void qce_unregister_algs(struct qce_device *qce) diff --git a/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch b/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch index 6f7a3a693b..4cabfc8f59 100644 --- a/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch +++ b/target/linux/ipq40xx/patches-4.19/303-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch @@ -8,7 +8,7 @@ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, -@@ -1284,11 +1285,12 @@ static const struct flash_info spi_nor_i +@@ -1286,11 +1287,12 @@ static const struct flash_info spi_nor_i { }, }; @@ -23,7 +23,7 @@ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); if (tmp < 0) { -@@ -1299,10 +1301,16 @@ static const struct flash_info *spi_nor_ +@@ -1301,10 +1303,16 @@ static const struct flash_info *spi_nor_ for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { info = &spi_nor_ids[tmp]; if (info->id_len) { @@ -42,7 +42,7 @@ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", id[0], id[1], id[2]); return ERR_PTR(-ENODEV); -@@ -2836,7 +2844,7 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -2838,7 +2846,7 @@ int spi_nor_scan(struct spi_nor *nor, co info = spi_nor_match_id(name); /* Try to auto-detect if chip name wasn't specified or not found */ if (!info) @@ -51,7 +51,7 @@ if (IS_ERR_OR_NULL(info)) return -ENOENT; -@@ -2847,7 +2855,7 @@ int spi_nor_scan(struct spi_nor *nor, co +@@ -2849,7 +2857,7 @@ int spi_nor_scan(struct spi_nor *nor, co if (name && info->id_len) { const struct flash_info *jinfo;