소스 검색

releaseversion

Reinhard Russinger 5 년 전
부모
커밋
cfc8dfc42f
56개의 변경된 파일4350개의 추가작업 그리고 41개의 파일을 삭제
  1. 1 0
      Config.in
  2. 2 2
      board/PSG/iot2000/linux-4.4-patches/0001-stmmac-pci-Make-stmmac_pci_info-structure-constant.patch
  3. 2 2
      board/PSG/iot2000/linux-4.4-patches/0002-stmmac-pci-Use-stmmac_pci_info-for-all-devices.patch
  4. 2 2
      board/PSG/iot2000/linux-4.4-patches/0003-stmmac-pci-Make-stmmac_pci_find_phy_addr-truly-gener.patch
  5. 2 2
      board/PSG/iot2000/linux-4.4-patches/0004-stmmac-pci-Select-quark_pci_dmi_data-from-quark_defa.patch
  6. 2 2
      board/PSG/iot2000/linux-4.4-patches/0005-stmmac-pci-Use-dmi_system_id-table-for-retrieving-PH.patch
  7. 2 2
      board/PSG/iot2000/linux-4.4-patches/0006-stmmac-pci-Adjust-IOT2000-matching.patch
  8. 2 2
      board/PSG/iot2000/linux-4.4-patches/0007-serial-8250_exar-Adjust-IOT2000-matching.patch
  9. 2 2
      board/PSG/iot2000/linux-4.4-patches/0008-mfd-intel_quark_i2c_gpio-Adjust-IOT2000-matching.patch
  10. 2 2
      board/PSG/iot2000/linux-4.4-patches/0009-gpio-sch-use-gpiochip-data-pointer.patch
  11. 2 2
      board/PSG/iot2000/linux-4.4-patches/0010-gpio-sch-Use-devm_gpiochip_add_data-for-gpio-registr.patch
  12. 2 2
      board/PSG/iot2000/linux-4.4-patches/0011-gpio-sch-Fix-Oops-on-module-load-on-Asus-Eee-PC-1201.patch
  13. 2 2
      board/PSG/iot2000/linux-4.4-patches/0012-gpio-sch-Implement-.get_direction.patch
  14. 2 2
      board/PSG/iot2000/linux-4.4-patches/0013-gpio-sch-Add-interrupt-support.patch
  15. 2 2
      board/PSG/iot2000/linux-4.4-patches/0014-iot2000-hack-Work-around-DSDT-mistake.patch
  16. 2 2
      board/PSG/iot2000/linux-4.4-patches/0015-iot2000-hack-Adjust-pca9685-gpio-base-for-legacy-com.patch
  17. 2 2
      board/PSG/iot2000/linux-4.4-patches/0016-iot2000-hack-gpio-pca953x-provide-GPIO-base-based-on.patch
  18. 6 6
      board/PSG/iot2000/linux-4.4-patches/0017-iot2000-hack-gpio-pca953x-add-drive-property.patch
  19. 2 2
      board/PSG/iot2000/linux-4.4-patches/0018-iot2000-hack-pwm-pca-9685-Provide-chip-level-pwm_per.patch
  20. 801 0
      board/PSG/iot2000/linux-4.4-patches/0019-random-replace-non-blocking-pool-with-a-Chacha20-bas.patch
  21. 143 0
      board/PSG/iot2000/linux-4.4-patches/0020-random-make-dev-urandom-scalable-for-silly-userspace.patch
  22. 109 0
      board/PSG/iot2000/linux-4.4-patches/0021-random-add-backtracking-protection-to-the-CRNG.patch
  23. 35 0
      board/PSG/iot2000/linux-4.4-patches/0022-random-remove-stale-maybe_reseed_primary_crng.patch
  24. 180 0
      board/PSG/iot2000/linux-4.4-patches/0023-random-use-chacha20-for-get_random_int-long.patch
  25. 147 0
      board/PSG/iot2000/linux-4.4-patches/0024-random-convert-get_random_int-long-into-get_random_u.patch
  26. 148 0
      board/PSG/iot2000/linux-4.4-patches/0025-random-invalidate-batched-entropy-after-crng-init.patch
  27. 87 0
      board/PSG/iot2000/linux-4.4-patches/0026-random-silence-compiler-warnings-and-fix-race.patch
  28. 118 0
      board/PSG/iot2000/linux-4.4-patches/0027-random-add-wait_for_random_bytes-API.patch
  29. 77 0
      board/PSG/iot2000/linux-4.4-patches/0028-random-fix-crng_ready-test.patch
  30. 110 0
      board/PSG/iot2000/linux-4.4-patches/0029-random-use-a-different-mixing-algorithm-for-add_devi.patch
  31. 163 0
      board/PSG/iot2000/linux-4.4-patches/0030-random-only-read-from-dev-random-after-its-pool-has-.patch
  32. 58 0
      board/PSG/iot2000/linux-4.4-patches/0031-random-fix-soft-lockup-when-trying-to-read-from-an-u.patch
  33. 145 0
      board/PSG/iot2000/linux-4.4-patches/0032-random-try-to-actively-add-entropy-rather-than-passi.patch
  34. 90 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0001-stmmac-pci-Make-stmmac_pci_info-structure-constant.patch
  35. 95 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0002-stmmac-pci-Use-stmmac_pci_info-for-all-devices.patch
  36. 61 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0003-stmmac-pci-Make-stmmac_pci_find_phy_addr-truly-gener.patch
  37. 165 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0004-stmmac-pci-Select-quark_pci_dmi_data-from-quark_defa.patch
  38. 167 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0005-stmmac-pci-Use-dmi_system_id-table-for-retrieving-PH.patch
  39. 47 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0006-stmmac-pci-Adjust-IOT2000-matching.patch
  40. 44 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0007-serial-8250_exar-Adjust-IOT2000-matching.patch
  41. 45 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0008-mfd-intel_quark_i2c_gpio-Adjust-IOT2000-matching.patch
  42. 86 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0009-gpio-sch-use-gpiochip-data-pointer.patch
  43. 46 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0010-gpio-sch-Use-devm_gpiochip_add_data-for-gpio-registr.patch
  44. 114 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0011-gpio-sch-Fix-Oops-on-module-load-on-Asus-Eee-PC-1201.patch
  45. 45 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0012-gpio-sch-Implement-.get_direction.patch
  46. 230 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0013-gpio-sch-Add-interrupt-support.patch
  47. 44 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0014-iot2000-hack-Work-around-DSDT-mistake.patch
  48. 42 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0015-iot2000-hack-Adjust-pca9685-gpio-base-for-legacy-com.patch
  49. 99 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0016-iot2000-hack-gpio-pca953x-provide-GPIO-base-based-on.patch
  50. 334 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0017-iot2000-hack-gpio-pca953x-add-drive-property.patch
  51. 105 0
      board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0018-iot2000-hack-pwm-pca-9685-Provide-chip-level-pwm_per.patch
  52. BIN
      board/PSG/iot2000/rootfs_overlay/lib/libsnap7.so
  53. 1 1
      configs/iot2000_defconfig
  54. 6 0
      package/Snap7/Config.in
  55. 24 0
      package/Snap7/Snap7.mk
  56. 98 0
      patches/007-modifications-CrossCompile-Toolchain.patch

+ 1 - 0
Config.in

@@ -6,3 +6,4 @@ source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/galileogen2-fake/Config.in"
 source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/adc1x8s102/Config.in"
 source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/adc1x8s102/Config.in"
 source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/icinga2/Config.in"
 source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/icinga2/Config.in"
 source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/python-ufw/Config.in"
 source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/python-ufw/Config.in"
+source "$BR2_EXTERNAL_PSG_IOT2000_PATH/package/Snap7/Config.in"

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0001-stmmac-pci-Make-stmmac_pci_info-structure-constant.patch

@@ -1,7 +1,7 @@
-From 2ca48f47b659edbd5cf4c4e55c420ef40712ce9b Mon Sep 17 00:00:00 2001
+From 9d215622c3277114820de51365109896e0337ab8 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Thu, 22 Jun 2017 08:17:57 +0200
 Date: Thu, 22 Jun 2017 08:17:57 +0200
-Subject: [PATCH 01/18] stmmac: pci: Make stmmac_pci_info structure constant
+Subject: [PATCH 01/32] stmmac: pci: Make stmmac_pci_info structure constant
 
 
 Commit c5d5287ef0f763e836bf94659b3a6080358373f1 upstream.
 Commit c5d5287ef0f763e836bf94659b3a6080358373f1 upstream.
 
 

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0002-stmmac-pci-Use-stmmac_pci_info-for-all-devices.patch

@@ -1,7 +1,7 @@
-From 5222a576c02eed33b0499a7e632a56680742a885 Mon Sep 17 00:00:00 2001
+From 94eff655c67ea28f35715f8864f3412faa2d827e Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Thu, 22 Jun 2017 08:17:58 +0200
 Date: Thu, 22 Jun 2017 08:17:58 +0200
-Subject: [PATCH 02/18] stmmac: pci: Use stmmac_pci_info for all devices
+Subject: [PATCH 02/32] stmmac: pci: Use stmmac_pci_info for all devices
 
 
 Commit b6a4c8f013ea2dd1ead7ee14b44712189a7bc6c6 upstream.
 Commit b6a4c8f013ea2dd1ead7ee14b44712189a7bc6c6 upstream.
 
 

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0003-stmmac-pci-Make-stmmac_pci_find_phy_addr-truly-gener.patch

@@ -1,7 +1,7 @@
-From d9478f26f2c620cf284f5022d3d852c47227e8da Mon Sep 17 00:00:00 2001
+From 553355e45eac94312df999431b4491bb0dc43122 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Thu, 22 Jun 2017 08:17:59 +0200
 Date: Thu, 22 Jun 2017 08:17:59 +0200
-Subject: [PATCH 03/18] stmmac: pci: Make stmmac_pci_find_phy_addr truly
+Subject: [PATCH 03/32] stmmac: pci: Make stmmac_pci_find_phy_addr truly
  generic
  generic
 
 
 Commit c5f657e49c878756f21349f9e4b0f1c9631d5352 upstream.
 Commit c5f657e49c878756f21349f9e4b0f1c9631d5352 upstream.

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0004-stmmac-pci-Select-quark_pci_dmi_data-from-quark_defa.patch

@@ -1,7 +1,7 @@
-From 0747f34d4be27952be866461c97d386c29000817 Mon Sep 17 00:00:00 2001
+From 95e91552d7a7d0fd28afc42191d8be1c3096d6c2 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Thu, 22 Jun 2017 08:18:00 +0200
 Date: Thu, 22 Jun 2017 08:18:00 +0200
-Subject: [PATCH 04/18] stmmac: pci: Select quark_pci_dmi_data from
+Subject: [PATCH 04/32] stmmac: pci: Select quark_pci_dmi_data from
  quark_default_data
  quark_default_data
 
 
 Commit 7bc519b3ea04026877242328d2fe73cc8e6102bd upsteam.
 Commit 7bc519b3ea04026877242328d2fe73cc8e6102bd upsteam.

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0005-stmmac-pci-Use-dmi_system_id-table-for-retrieving-PH.patch

@@ -1,7 +1,7 @@
-From 1b2894107ad2d9de45402ecc4ffe14f075a08bbc Mon Sep 17 00:00:00 2001
+From d771759e71dfab46de09fc2efcd1282926a775b8 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Thu, 22 Jun 2017 08:18:01 +0200
 Date: Thu, 22 Jun 2017 08:18:01 +0200
-Subject: [PATCH 05/18] stmmac: pci: Use dmi_system_id table for retrieving PHY
+Subject: [PATCH 05/32] stmmac: pci: Use dmi_system_id table for retrieving PHY
  addresses
  addresses
 
 
 Commit 8d78b69091845386b6096f3adae98f28b9bf96ed upstream.
 Commit 8d78b69091845386b6096f3adae98f28b9bf96ed upstream.

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0006-stmmac-pci-Adjust-IOT2000-matching.patch

@@ -1,7 +1,7 @@
-From e3ba8c4f83c6c206a20e4645a37612b1e10580c6 Mon Sep 17 00:00:00 2001
+From 81aabe391560f74d9dafc5b139b3b3c2e6de08df Mon Sep 17 00:00:00 2001
 From: Su Bao Cheng <baocheng.su@siemens.com>
 From: Su Bao Cheng <baocheng.su@siemens.com>
 Date: Fri, 12 Oct 2018 15:08:11 +0200
 Date: Fri, 12 Oct 2018 15:08:11 +0200
-Subject: [PATCH 06/18] stmmac: pci: Adjust IOT2000 matching
+Subject: [PATCH 06/32] stmmac: pci: Adjust IOT2000 matching
 
 
 Since there are more IOT2040 variants with identical hardware but
 Since there are more IOT2040 variants with identical hardware but
 different asset tags, the asset tag matching should be adjusted to
 different asset tags, the asset tag matching should be adjusted to

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0007-serial-8250_exar-Adjust-IOT2000-matching.patch

@@ -1,7 +1,7 @@
-From df74e188ffc38176d4caba969e104d2ab2e4e609 Mon Sep 17 00:00:00 2001
+From 186847dd575416b337ae370b46744a163fcf31fc Mon Sep 17 00:00:00 2001
 From: Su Bao Cheng <baocheng.su@siemens.com>
 From: Su Bao Cheng <baocheng.su@siemens.com>
 Date: Fri, 12 Oct 2018 15:12:37 +0200
 Date: Fri, 12 Oct 2018 15:12:37 +0200
-Subject: [PATCH 07/18] serial: 8250_exar: Adjust IOT2000 matching
+Subject: [PATCH 07/32] serial: 8250_exar: Adjust IOT2000 matching
 
 
 Since there are more IOT2040 variants with identical hardware but
 Since there are more IOT2040 variants with identical hardware but
 different asset tags, the asset tag matching should be adjusted to
 different asset tags, the asset tag matching should be adjusted to

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0008-mfd-intel_quark_i2c_gpio-Adjust-IOT2000-matching.patch

@@ -1,7 +1,7 @@
-From 6e378b789ebcfcdc4ae957b25f1ac6eb2ef64edc Mon Sep 17 00:00:00 2001
+From f95eb6b146bc6107b082c8d600ac5ae51c05054e Mon Sep 17 00:00:00 2001
 From: Su Bao Cheng <baocheng.su@siemens.com>
 From: Su Bao Cheng <baocheng.su@siemens.com>
 Date: Fri, 12 Oct 2018 15:05:07 +0200
 Date: Fri, 12 Oct 2018 15:05:07 +0200
-Subject: [PATCH 08/18] mfd: intel_quark_i2c_gpio: Adjust IOT2000 matching
+Subject: [PATCH 08/32] mfd: intel_quark_i2c_gpio: Adjust IOT2000 matching
 
 
 Since there are more IOT2040 variants with identical hardware but
 Since there are more IOT2040 variants with identical hardware but
 different asset tags, the asset tag matching should be adjusted to
 different asset tags, the asset tag matching should be adjusted to

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0009-gpio-sch-use-gpiochip-data-pointer.patch

@@ -1,7 +1,7 @@
-From cf3d1330c71d47c4cdb9268f68d2ee5931890d93 Mon Sep 17 00:00:00 2001
+From 31273219d4787459eea40094ac811a24cf20eaf6 Mon Sep 17 00:00:00 2001
 From: Linus Walleij <linus.walleij@linaro.org>
 From: Linus Walleij <linus.walleij@linaro.org>
 Date: Mon, 7 Dec 2015 14:21:49 +0100
 Date: Mon, 7 Dec 2015 14:21:49 +0100
-Subject: [PATCH 09/18] gpio: sch: use gpiochip data pointer
+Subject: [PATCH 09/32] gpio: sch: use gpiochip data pointer
 
 
 This makes the driver use the data pointer added to the gpio_chip
 This makes the driver use the data pointer added to the gpio_chip
 to store a pointer to the state container instead of relying on
 to store a pointer to the state container instead of relying on

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0010-gpio-sch-Use-devm_gpiochip_add_data-for-gpio-registr.patch

@@ -1,7 +1,7 @@
-From 6a930e4d040061edcaf0c3e3e43a10acdc20f09c Mon Sep 17 00:00:00 2001
+From 01837820d1cc75845d0c771f24eea5fe3d4ae109 Mon Sep 17 00:00:00 2001
 From: Laxman Dewangan <ldewangan@nvidia.com>
 From: Laxman Dewangan <ldewangan@nvidia.com>
 Date: Mon, 22 Feb 2016 17:43:28 +0530
 Date: Mon, 22 Feb 2016 17:43:28 +0530
-Subject: [PATCH 10/18] gpio: sch: Use devm_gpiochip_add_data() for gpio
+Subject: [PATCH 10/32] gpio: sch: Use devm_gpiochip_add_data() for gpio
  registration
  registration
 
 
 Use devm_gpiochip_add_data() for GPIO registration and remove the
 Use devm_gpiochip_add_data() for GPIO registration and remove the

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0011-gpio-sch-Fix-Oops-on-module-load-on-Asus-Eee-PC-1201.patch

@@ -1,7 +1,7 @@
-From 9fd1991d762b6092f462f3cc551b2d7df3009b52 Mon Sep 17 00:00:00 2001
+From 3ecc35879dfd4a4df2ae418892743446fe05f3a0 Mon Sep 17 00:00:00 2001
 From: Colin Pitrat <colin.pitrat@gmail.com>
 From: Colin Pitrat <colin.pitrat@gmail.com>
 Date: Sat, 18 Jun 2016 19:05:04 +0100
 Date: Sat, 18 Jun 2016 19:05:04 +0100
-Subject: [PATCH 11/18] gpio: sch: Fix Oops on module load on Asus Eee PC 1201
+Subject: [PATCH 11/32] gpio: sch: Fix Oops on module load on Asus Eee PC 1201
 
 
 This fixes the issue descirbe in bug 117531
 This fixes the issue descirbe in bug 117531
 (https://bugzilla.kernel.org/show_bug.cgi?id=117531).
 (https://bugzilla.kernel.org/show_bug.cgi?id=117531).

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0012-gpio-sch-Implement-.get_direction.patch

@@ -1,7 +1,7 @@
-From 8fec046f568e2b946abd55a82d5417717a115b21 Mon Sep 17 00:00:00 2001
+From 8c5cc2a98dcbcbd4208c62e5709d3669405072f7 Mon Sep 17 00:00:00 2001
 From: Linus Walleij <linus.walleij@linaro.org>
 From: Linus Walleij <linus.walleij@linaro.org>
 Date: Wed, 27 Jun 2018 10:39:31 +0200
 Date: Wed, 27 Jun 2018 10:39:31 +0200
-Subject: [PATCH 12/18] gpio: sch: Implement .get_direction()
+Subject: [PATCH 12/32] gpio: sch: Implement .get_direction()
 
 
 It's pretty simple to implement the .get_direction() for this
 It's pretty simple to implement the .get_direction() for this
 chip, so let's just do it.
 chip, so let's just do it.

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0013-gpio-sch-Add-interrupt-support.patch

@@ -1,7 +1,7 @@
-From 53c90b014f54743b5a2180f90b90b1f198535583 Mon Sep 17 00:00:00 2001
+From d046375f1bc2a63d945bad8c4026ce1a6eabd838 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Wed, 17 Apr 2019 22:26:22 +0200
 Date: Wed, 17 Apr 2019 22:26:22 +0200
-Subject: [PATCH 13/18] gpio: sch: Add interrupt support
+Subject: [PATCH 13/32] gpio: sch: Add interrupt support
 
 
 Validated on the Quark platform, this adds interrupt support on rising
 Validated on the Quark platform, this adds interrupt support on rising
 and/or falling edges.
 and/or falling edges.

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0014-iot2000-hack-Work-around-DSDT-mistake.patch

@@ -1,7 +1,7 @@
-From f43a54ec8a8b5f070d4b1b59f3d47dc03f74ad32 Mon Sep 17 00:00:00 2001
+From 63e4ba1816a80a258e4c7a846b3bd389b9a04e32 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Thu, 25 May 2017 11:09:42 +0200
 Date: Thu, 25 May 2017 11:09:42 +0200
-Subject: [PATCH 14/18] iot2000-hack: Work around DSDT mistake
+Subject: [PATCH 14/32] iot2000-hack: Work around DSDT mistake
 
 
 Until we have a new firmware revision, fix up the incorrect GPIO
 Until we have a new firmware revision, fix up the incorrect GPIO
 interrupt pin in software.
 interrupt pin in software.

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0015-iot2000-hack-Adjust-pca9685-gpio-base-for-legacy-com.patch

@@ -1,7 +1,7 @@
-From 88f2d0ccdee1f1890af0d049c60fe24f6c6eb048 Mon Sep 17 00:00:00 2001
+From e679338fe980d8722246366906bf71971fa2f538 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Thu, 25 May 2017 13:05:12 +0200
 Date: Thu, 25 May 2017 13:05:12 +0200
-Subject: [PATCH 15/18] iot2000-hack: Adjust pca9685-gpio base for legacy
+Subject: [PATCH 15/32] iot2000-hack: Adjust pca9685-gpio base for legacy
  compatibility
  compatibility
 
 
 mraa and the Arduino runtime expect this.
 mraa and the Arduino runtime expect this.

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0016-iot2000-hack-gpio-pca953x-provide-GPIO-base-based-on.patch

@@ -1,7 +1,7 @@
-From 5c102aea3f4ffea811eec719edd638fc7888e9c3 Mon Sep 17 00:00:00 2001
+From b4513d4a15616321e240c93436e8ffd58aa931ed Mon Sep 17 00:00:00 2001
 From: Yong Li <sdliyong@gmail.com>
 From: Yong Li <sdliyong@gmail.com>
 Date: Thu, 31 Mar 2016 15:33:08 +0800
 Date: Thu, 31 Mar 2016 15:33:08 +0800
-Subject: [PATCH 16/18] iot2000-hack: gpio: pca953x: provide GPIO base based on
+Subject: [PATCH 16/32] iot2000-hack: gpio: pca953x: provide GPIO base based on
  _UID
  _UID
 
 
 Custom kernel for Intel Galileo Gen2 provides and moreover libmraa relies on
 Custom kernel for Intel Galileo Gen2 provides and moreover libmraa relies on

+ 6 - 6
board/PSG/iot2000/linux-4.4-patches/0017-iot2000-hack-gpio-pca953x-add-drive-property.patch

@@ -1,7 +1,7 @@
-From a66a980a3520859c1a01fc65f76c4f2abd2a2eed Mon Sep 17 00:00:00 2001
+From 7190fa3b9d76d0d554dab7c0a220a2be3e866560 Mon Sep 17 00:00:00 2001
 From: Yong Li <sdliyong@gmail.com>
 From: Yong Li <sdliyong@gmail.com>
 Date: Thu, 31 Mar 2016 15:33:09 +0800
 Date: Thu, 31 Mar 2016 15:33:09 +0800
-Subject: [PATCH 17/18] iot2000-hack: gpio-pca953x: add "drive" property
+Subject: [PATCH 17/32] iot2000-hack: gpio-pca953x: add "drive" property
 
 
 Galileo gen 2 has support for setting GPIO modes. Expose these
 Galileo gen 2 has support for setting GPIO modes. Expose these
 properties through the GPIO sysfs interface. This approach is bit hacky,
 properties through the GPIO sysfs interface. This approach is bit hacky,
@@ -201,10 +201,10 @@ index b57ed8e55ab5..72a8647146fa 100644
  };
  };
  
  
 diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
 diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
-index 827510dbba30..d19928b9a311 100644
+index d72218fcaeeb..66d4e4a59035 100644
 --- a/drivers/gpio/gpiolib.c
 --- a/drivers/gpio/gpiolib.c
 +++ b/drivers/gpio/gpiolib.c
 +++ b/drivers/gpio/gpiolib.c
-@@ -1315,6 +1315,23 @@ int gpiod_is_active_low(const struct gpio_desc *desc)
+@@ -1376,6 +1376,23 @@ int gpiod_is_active_low(const struct gpio_desc *desc)
  }
  }
  EXPORT_SYMBOL_GPL(gpiod_is_active_low);
  EXPORT_SYMBOL_GPL(gpiod_is_active_low);
  
  
@@ -260,7 +260,7 @@ index 40ec1433f05d..519e8d458878 100644
  {
  {
  	return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio));
  	return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio));
 diff --git a/include/linux/gpio.h b/include/linux/gpio.h
 diff --git a/include/linux/gpio.h b/include/linux/gpio.h
-index d12b5d566e4b..344e62d27700 100644
+index 11555bd821b7..1e8ab82f2787 100644
 --- a/include/linux/gpio.h
 --- a/include/linux/gpio.h
 +++ b/include/linux/gpio.h
 +++ b/include/linux/gpio.h
 @@ -30,6 +30,11 @@
 @@ -30,6 +30,11 @@
@@ -317,7 +317,7 @@ index fb0fde686cb1..17f5f187699b 100644
  {
  {
  	/* GPIO can never have been requested */
  	/* GPIO can never have been requested */
 diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
 diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
-index de502c7e4171..d59080ba9fec 100644
+index c0fc8effdba9..b73af28ac7d8 100644
 --- a/include/linux/gpio/driver.h
 --- a/include/linux/gpio/driver.h
 +++ b/include/linux/gpio/driver.h
 +++ b/include/linux/gpio/driver.h
 @@ -116,6 +116,8 @@ struct gpio_chip {
 @@ -116,6 +116,8 @@ struct gpio_chip {

+ 2 - 2
board/PSG/iot2000/linux-4.4-patches/0018-iot2000-hack-pwm-pca-9685-Provide-chip-level-pwm_per.patch

@@ -1,7 +1,7 @@
-From c25a8e605bcbb0ed2adde384587ffcfcf5783eef Mon Sep 17 00:00:00 2001
+From 0bdd0c91036a0c6a1cb74eebc3a95e08faf9e7b8 Mon Sep 17 00:00:00 2001
 From: Jan Kiszka <jan.kiszka@siemens.com>
 From: Jan Kiszka <jan.kiszka@siemens.com>
 Date: Fri, 17 Nov 2017 20:25:54 +0100
 Date: Fri, 17 Nov 2017 20:25:54 +0100
-Subject: [PATCH 18/18] iot2000-hack: pwm: pca-9685: Provide chip-level
+Subject: [PATCH 18/32] iot2000-hack: pwm: pca-9685: Provide chip-level
  pwm_period attribute
  pwm_period attribute
 
 
 Arduino runtime relies on this path to program the PWM period, rather
 Arduino runtime relies on this path to program the PWM period, rather

+ 801 - 0
board/PSG/iot2000/linux-4.4-patches/0019-random-replace-non-blocking-pool-with-a-Chacha20-bas.patch

@@ -0,0 +1,801 @@
+From af72f4e73aa5a951d998e88260154082c5ffd340 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sun, 12 Jun 2016 18:13:36 -0400
+Subject: [PATCH 19/32] random: replace non-blocking pool with a Chacha20-based
+ CRNG
+
+The CRNG is faster, and we don't pretend to track entropy usage in the
+CRNG any more.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ crypto/chacha20_generic.c |  61 --------
+ drivers/char/random.c     | 378 +++++++++++++++++++++++++++++++++-------------
+ include/crypto/chacha20.h |   1 +
+ lib/Makefile              |   2 +-
+ lib/chacha20.c            |  79 ++++++++++
+ 5 files changed, 357 insertions(+), 164 deletions(-)
+ create mode 100644 lib/chacha20.c
+
+diff --git a/crypto/chacha20_generic.c b/crypto/chacha20_generic.c
+index da9c89968223..1cab83146e33 100644
+--- a/crypto/chacha20_generic.c
++++ b/crypto/chacha20_generic.c
+@@ -15,72 +15,11 @@
+ #include <linux/module.h>
+ #include <crypto/chacha20.h>
+ 
+-static inline u32 rotl32(u32 v, u8 n)
+-{
+-	return (v << n) | (v >> (sizeof(v) * 8 - n));
+-}
+-
+ static inline u32 le32_to_cpuvp(const void *p)
+ {
+ 	return le32_to_cpup(p);
+ }
+ 
+-static void chacha20_block(u32 *state, void *stream)
+-{
+-	u32 x[16], *out = stream;
+-	int i;
+-
+-	for (i = 0; i < ARRAY_SIZE(x); i++)
+-		x[i] = state[i];
+-
+-	for (i = 0; i < 20; i += 2) {
+-		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],  16);
+-		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],  16);
+-		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],  16);
+-		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],  16);
+-
+-		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],  12);
+-		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],  12);
+-		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10], 12);
+-		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11], 12);
+-
+-		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],   8);
+-		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],   8);
+-		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],   8);
+-		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],   8);
+-
+-		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],   7);
+-		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],   7);
+-		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10],  7);
+-		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11],  7);
+-
+-		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],  16);
+-		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],  16);
+-		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],  16);
+-		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],  16);
+-
+-		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10], 12);
+-		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11], 12);
+-		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],  12);
+-		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],  12);
+-
+-		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],   8);
+-		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],   8);
+-		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],   8);
+-		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],   8);
+-
+-		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10],  7);
+-		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11],  7);
+-		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],   7);
+-		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],   7);
+-	}
+-
+-	for (i = 0; i < ARRAY_SIZE(x); i++)
+-		out[i] = cpu_to_le32(x[i] + state[i]);
+-
+-	state[12]++;
+-}
+-
+ static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src,
+ 			     unsigned int bytes)
+ {
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 2916d08ee30e..6d2abeae9434 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -260,6 +260,7 @@
+ #include <linux/irq.h>
+ #include <linux/syscalls.h>
+ #include <linux/completion.h>
++#include <crypto/chacha20.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/uaccess.h>
+@@ -412,6 +413,31 @@ static struct fasync_struct *fasync;
+ static DEFINE_SPINLOCK(random_ready_list_lock);
+ static LIST_HEAD(random_ready_list);
+ 
++struct crng_state {
++	__u32		state[16];
++	unsigned long	init_time;
++	spinlock_t	lock;
++};
++
++struct crng_state primary_crng = {
++	.lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock),
++};
++
++/*
++ * crng_init =  0 --> Uninitialized
++ *		1 --> Initialized
++ *		2 --> Initialized from input_pool
++ *
++ * crng_init is protected by primary_crng->lock, and only increases
++ * its value (from 0->1->2).
++ */
++static int crng_init = 0;
++#define crng_ready() (likely(crng_init > 0))
++static int crng_init_cnt = 0;
++#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
++static void process_random_ready_list(void);
++
+ /**********************************************************************
+  *
+  * OS independent entropy store.   Here are the functions which handle
+@@ -441,10 +467,15 @@ struct entropy_store {
+ 	__u8 last_data[EXTRACT_SIZE];
+ };
+ 
++static ssize_t extract_entropy(struct entropy_store *r, void *buf,
++			       size_t nbytes, int min, int rsvd);
++static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
++				size_t nbytes, int fips);
++
++static void crng_reseed(struct crng_state *crng, struct entropy_store *r);
+ static void push_to_pool(struct work_struct *work);
+ static __u32 input_pool_data[INPUT_POOL_WORDS];
+ static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
+-static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
+ 
+ static struct entropy_store input_pool = {
+ 	.poolinfo = &poolinfo_table[0],
+@@ -465,16 +496,6 @@ static struct entropy_store blocking_pool = {
+ 					push_to_pool),
+ };
+ 
+-static struct entropy_store nonblocking_pool = {
+-	.poolinfo = &poolinfo_table[1],
+-	.name = "nonblocking",
+-	.pull = &input_pool,
+-	.lock = __SPIN_LOCK_UNLOCKED(nonblocking_pool.lock),
+-	.pool = nonblocking_pool_data,
+-	.push_work = __WORK_INITIALIZER(nonblocking_pool.push_work,
+-					push_to_pool),
+-};
+-
+ static __u32 const twist_table[8] = {
+ 	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+ 	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+@@ -677,12 +698,6 @@ retry:
+ 	if (!r->initialized && r->entropy_total > 128) {
+ 		r->initialized = 1;
+ 		r->entropy_total = 0;
+-		if (r == &nonblocking_pool) {
+-			prandom_reseed_late();
+-			process_random_ready_list();
+-			wake_up_all(&urandom_init_wait);
+-			pr_notice("random: %s pool is initialized\n", r->name);
+-		}
+ 	}
+ 
+ 	trace_credit_entropy_bits(r->name, nbits,
+@@ -692,30 +707,27 @@ retry:
+ 	if (r == &input_pool) {
+ 		int entropy_bits = entropy_count >> ENTROPY_SHIFT;
+ 
++		if (crng_init < 2 && entropy_bits >= 128) {
++			crng_reseed(&primary_crng, r);
++			entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
++		}
++
+ 		/* should we wake readers? */
+ 		if (entropy_bits >= random_read_wakeup_bits) {
+ 			wake_up_interruptible(&random_read_wait);
+ 			kill_fasync(&fasync, SIGIO, POLL_IN);
+ 		}
+ 		/* If the input pool is getting full, send some
+-		 * entropy to the two output pools, flipping back and
+-		 * forth between them, until the output pools are 75%
+-		 * full.
++		 * entropy to the blocking pool until it is 75% full.
+ 		 */
+ 		if (entropy_bits > random_write_wakeup_bits &&
+ 		    r->initialized &&
+ 		    r->entropy_total >= 2*random_read_wakeup_bits) {
+-			static struct entropy_store *last = &blocking_pool;
+ 			struct entropy_store *other = &blocking_pool;
+ 
+-			if (last == &blocking_pool)
+-				other = &nonblocking_pool;
+ 			if (other->entropy_count <=
+-			    3 * other->poolinfo->poolfracbits / 4)
+-				last = other;
+-			if (last->entropy_count <=
+-			    3 * last->poolinfo->poolfracbits / 4) {
+-				schedule_work(&last->push_work);
++			    3 * other->poolinfo->poolfracbits / 4) {
++				schedule_work(&other->push_work);
+ 				r->entropy_total = 0;
+ 			}
+ 		}
+@@ -736,6 +748,152 @@ static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+ 	return 0;
+ }
+ 
++/*********************************************************************
++ *
++ * CRNG using CHACHA20
++ *
++ *********************************************************************/
++
++#define CRNG_RESEED_INTERVAL (300*HZ)
++
++static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
++
++static void crng_initialize(struct crng_state *crng)
++{
++	int		i;
++	unsigned long	rv;
++
++	memcpy(&crng->state[0], "expand 32-byte k", 16);
++	if (crng == &primary_crng)
++		_extract_entropy(&input_pool, &crng->state[4],
++				 sizeof(__u32) * 12, 0);
++	else
++		get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
++	for (i = 4; i < 16; i++) {
++		if (!arch_get_random_seed_long(&rv) &&
++		    !arch_get_random_long(&rv))
++			rv = random_get_entropy();
++		crng->state[i] ^= rv;
++	}
++	crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
++}
++
++static int crng_fast_load(const char *cp, size_t len)
++{
++	unsigned long flags;
++	char *p;
++
++	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
++		return 0;
++	if (crng_ready()) {
++		spin_unlock_irqrestore(&primary_crng.lock, flags);
++		return 0;
++	}
++	p = (unsigned char *) &primary_crng.state[4];
++	while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
++		p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp;
++		cp++; crng_init_cnt++; len--;
++	}
++	if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
++		crng_init = 1;
++		wake_up_interruptible(&crng_init_wait);
++		pr_notice("random: fast init done\n");
++	}
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
++	return 1;
++}
++
++static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
++{
++	unsigned long	flags;
++	int		i, num;
++	union {
++		__u8	block[CHACHA20_BLOCK_SIZE];
++		__u32	key[8];
++	} buf;
++
++	if (r) {
++		num = extract_entropy(r, &buf, 32, 16, 0);
++		if (num == 0)
++			return;
++	} else
++		extract_crng(buf.block);
++	spin_lock_irqsave(&primary_crng.lock, flags);
++	for (i = 0; i < 8; i++) {
++		unsigned long	rv;
++		if (!arch_get_random_seed_long(&rv) &&
++		    !arch_get_random_long(&rv))
++			rv = random_get_entropy();
++		crng->state[i+4] ^= buf.key[i] ^ rv;
++	}
++	memzero_explicit(&buf, sizeof(buf));
++	crng->init_time = jiffies;
++	if (crng == &primary_crng && crng_init < 2) {
++		crng_init = 2;
++		process_random_ready_list();
++		wake_up_interruptible(&crng_init_wait);
++		pr_notice("random: crng init done\n");
++	}
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
++}
++
++static inline void crng_wait_ready(void)
++{
++	wait_event_interruptible(crng_init_wait, crng_ready());
++}
++
++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
++{
++	unsigned long v, flags;
++	struct crng_state *crng = &primary_crng;
++
++	if (crng_init > 1 &&
++	    time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
++		crng_reseed(crng, &input_pool);
++	spin_lock_irqsave(&crng->lock, flags);
++	if (arch_get_random_long(&v))
++		crng->state[14] ^= v;
++	chacha20_block(&crng->state[0], out);
++	if (crng->state[12] == 0)
++		crng->state[13]++;
++	spin_unlock_irqrestore(&crng->lock, flags);
++}
++
++static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
++{
++	ssize_t ret = 0, i;
++	__u8 tmp[CHACHA20_BLOCK_SIZE];
++	int large_request = (nbytes > 256);
++
++	while (nbytes) {
++		if (large_request && need_resched()) {
++			if (signal_pending(current)) {
++				if (ret == 0)
++					ret = -ERESTARTSYS;
++				break;
++			}
++			schedule();
++		}
++
++		extract_crng(tmp);
++		i = min_t(int, nbytes, CHACHA20_BLOCK_SIZE);
++		if (copy_to_user(buf, tmp, i)) {
++			ret = -EFAULT;
++			break;
++		}
++
++		nbytes -= i;
++		buf += i;
++		ret += i;
++	}
++
++	/* Wipe data just written to memory */
++	memzero_explicit(tmp, sizeof(tmp));
++
++	return ret;
++}
++
++
+ /*********************************************************************
+  *
+  * Entropy input management
+@@ -752,12 +910,12 @@ struct timer_rand_state {
+ #define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
+ 
+ /*
+- * Add device- or boot-specific data to the input and nonblocking
+- * pools to help initialize them to unique values.
++ * Add device- or boot-specific data to the input pool to help
++ * initialize it.
+  *
+- * None of this adds any entropy, it is meant to avoid the
+- * problem of the nonblocking pool having similar initial state
+- * across largely identical devices.
++ * None of this adds any entropy; it is meant to avoid the problem of
++ * the entropy pool having similar initial state across largely
++ * identical devices.
+  */
+ void add_device_randomness(const void *buf, unsigned int size)
+ {
+@@ -769,11 +927,6 @@ void add_device_randomness(const void *buf, unsigned int size)
+ 	_mix_pool_bytes(&input_pool, buf, size);
+ 	_mix_pool_bytes(&input_pool, &time, sizeof(time));
+ 	spin_unlock_irqrestore(&input_pool.lock, flags);
+-
+-	spin_lock_irqsave(&nonblocking_pool.lock, flags);
+-	_mix_pool_bytes(&nonblocking_pool, buf, size);
+-	_mix_pool_bytes(&nonblocking_pool, &time, sizeof(time));
+-	spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
+ }
+ EXPORT_SYMBOL(add_device_randomness);
+ 
+@@ -804,7 +957,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+ 	sample.jiffies = jiffies;
+ 	sample.cycles = random_get_entropy();
+ 	sample.num = num;
+-	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	r = &input_pool;
+ 	mix_pool_bytes(r, &sample, sizeof(sample));
+ 
+ 	/*
+@@ -924,11 +1077,21 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	fast_mix(fast_pool);
+ 	add_interrupt_bench(cycles);
+ 
++	if (!crng_ready()) {
++		if ((fast_pool->count >= 64) &&
++		    crng_fast_load((char *) fast_pool->pool,
++				   sizeof(fast_pool->pool))) {
++			fast_pool->count = 0;
++			fast_pool->last = now;
++		}
++		return;
++	}
++
+ 	if ((fast_pool->count < 64) &&
+ 	    !time_after(now, fast_pool->last + HZ))
+ 		return;
+ 
+-	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
++	r = &input_pool;
+ 	if (!spin_trylock(&r->lock))
+ 		return;
+ 
+@@ -972,9 +1135,6 @@ EXPORT_SYMBOL_GPL(add_disk_randomness);
+  *
+  *********************************************************************/
+ 
+-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+-			       size_t nbytes, int min, int rsvd);
+-
+ /*
+  * This utility inline function is responsible for transferring entropy
+  * from the primary pool to the secondary extraction pool. We make
+@@ -1149,6 +1309,36 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ 	memzero_explicit(&hash, sizeof(hash));
+ }
+ 
++static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
++				size_t nbytes, int fips)
++{
++	ssize_t ret = 0, i;
++	__u8 tmp[EXTRACT_SIZE];
++	unsigned long flags;
++
++	while (nbytes) {
++		extract_buf(r, tmp);
++
++		if (fips) {
++			spin_lock_irqsave(&r->lock, flags);
++			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
++				panic("Hardware RNG duplicated output!\n");
++			memcpy(r->last_data, tmp, EXTRACT_SIZE);
++			spin_unlock_irqrestore(&r->lock, flags);
++		}
++		i = min_t(int, nbytes, EXTRACT_SIZE);
++		memcpy(buf, tmp, i);
++		nbytes -= i;
++		buf += i;
++		ret += i;
++	}
++
++	/* Wipe data just returned from memory */
++	memzero_explicit(tmp, sizeof(tmp));
++
++	return ret;
++}
++
+ /*
+  * This function extracts randomness from the "entropy pool", and
+  * returns it in a buffer.
+@@ -1161,7 +1351,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
+ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ 				 size_t nbytes, int min, int reserved)
+ {
+-	ssize_t ret = 0, i;
+ 	__u8 tmp[EXTRACT_SIZE];
+ 	unsigned long flags;
+ 
+@@ -1185,27 +1374,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, min, reserved);
+ 
+-	while (nbytes) {
+-		extract_buf(r, tmp);
+-
+-		if (fips_enabled) {
+-			spin_lock_irqsave(&r->lock, flags);
+-			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
+-				panic("Hardware RNG duplicated output!\n");
+-			memcpy(r->last_data, tmp, EXTRACT_SIZE);
+-			spin_unlock_irqrestore(&r->lock, flags);
+-		}
+-		i = min_t(int, nbytes, EXTRACT_SIZE);
+-		memcpy(buf, tmp, i);
+-		nbytes -= i;
+-		buf += i;
+-		ret += i;
+-	}
+-
+-	/* Wipe data just returned from memory */
+-	memzero_explicit(tmp, sizeof(tmp));
+-
+-	return ret;
++	return _extract_entropy(r, buf, nbytes, fips_enabled);
+ }
+ 
+ /*
+@@ -1260,15 +1429,26 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+  */
+ void get_random_bytes(void *buf, int nbytes)
+ {
++	__u8 tmp[CHACHA20_BLOCK_SIZE];
++
+ #if DEBUG_RANDOM_BOOT > 0
+-	if (unlikely(nonblocking_pool.initialized == 0))
++	if (!crng_ready())
+ 		printk(KERN_NOTICE "random: %pF get_random_bytes called "
+-		       "with %d bits of entropy available\n",
+-		       (void *) _RET_IP_,
+-		       nonblocking_pool.entropy_total);
++		       "with crng_init = %d\n", (void *) _RET_IP_, crng_init);
+ #endif
+ 	trace_get_random_bytes(nbytes, _RET_IP_);
+-	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
++
++	while (nbytes >= CHACHA20_BLOCK_SIZE) {
++		extract_crng(buf);
++		buf += CHACHA20_BLOCK_SIZE;
++		nbytes -= CHACHA20_BLOCK_SIZE;
++	}
++
++	if (nbytes > 0) {
++		extract_crng(tmp);
++		memcpy(buf, tmp, nbytes);
++		memzero_explicit(tmp, nbytes);
++	}
+ }
+ EXPORT_SYMBOL(get_random_bytes);
+ 
+@@ -1286,7 +1466,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy)
+ 	unsigned long flags;
+ 	int err = -EALREADY;
+ 
+-	if (likely(nonblocking_pool.initialized))
++	if (crng_ready())
+ 		return err;
+ 
+ 	owner = rdy->owner;
+@@ -1294,7 +1474,7 @@ int add_random_ready_callback(struct random_ready_callback *rdy)
+ 		return -ENOENT;
+ 
+ 	spin_lock_irqsave(&random_ready_list_lock, flags);
+-	if (nonblocking_pool.initialized)
++	if (crng_ready())
+ 		goto out;
+ 
+ 	owner = NULL;
+@@ -1358,7 +1538,7 @@ void get_random_bytes_arch(void *buf, int nbytes)
+ 	}
+ 
+ 	if (nbytes)
+-		extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
++		get_random_bytes(p, nbytes);
+ }
+ EXPORT_SYMBOL(get_random_bytes_arch);
+ 
+@@ -1403,7 +1583,7 @@ static int rand_initialize(void)
+ {
+ 	init_std_data(&input_pool);
+ 	init_std_data(&blocking_pool);
+-	init_std_data(&nonblocking_pool);
++	crng_initialize(&primary_crng);
+ 	return 0;
+ }
+ early_initcall(rand_initialize);
+@@ -1465,22 +1645,22 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ static ssize_t
+ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
+ {
++	unsigned long flags;
+ 	static int maxwarn = 10;
+ 	int ret;
+ 
+-	if (unlikely(nonblocking_pool.initialized == 0) &&
+-	    maxwarn > 0) {
++	if (!crng_ready() && maxwarn > 0) {
+ 		maxwarn--;
+ 		printk(KERN_NOTICE "random: %s: uninitialized urandom read "
+-		       "(%zd bytes read, %d bits of entropy available)\n",
+-		       current->comm, nbytes, nonblocking_pool.entropy_total);
++		       "(%zd bytes read)\n",
++		       current->comm, nbytes);
++		spin_lock_irqsave(&primary_crng.lock, flags);
++		crng_init_cnt = 0;
++		spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 	}
+-
+ 	nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
+-	ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
+-
+-	trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),
+-			   ENTROPY_BITS(&input_pool));
++	ret = extract_crng_user(buf, nbytes);
++	trace_urandom_read(8 * nbytes, 0, ENTROPY_BITS(&input_pool));
+ 	return ret;
+ }
+ 
+@@ -1534,10 +1714,7 @@ static ssize_t random_write(struct file *file, const char __user *buffer,
+ {
+ 	size_t ret;
+ 
+-	ret = write_pool(&blocking_pool, buffer, count);
+-	if (ret)
+-		return ret;
+-	ret = write_pool(&nonblocking_pool, buffer, count);
++	ret = write_pool(&input_pool, buffer, count);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -1586,7 +1763,6 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+ 		if (!capable(CAP_SYS_ADMIN))
+ 			return -EPERM;
+ 		input_pool.entropy_count = 0;
+-		nonblocking_pool.entropy_count = 0;
+ 		blocking_pool.entropy_count = 0;
+ 		return 0;
+ 	default:
+@@ -1628,11 +1804,10 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+ 	if (flags & GRND_RANDOM)
+ 		return _random_read(flags & GRND_NONBLOCK, buf, count);
+ 
+-	if (unlikely(nonblocking_pool.initialized == 0)) {
++	if (!crng_ready()) {
+ 		if (flags & GRND_NONBLOCK)
+ 			return -EAGAIN;
+-		wait_event_interruptible(urandom_init_wait,
+-					 nonblocking_pool.initialized);
++		crng_wait_ready();
+ 		if (signal_pending(current))
+ 			return -ERESTARTSYS;
+ 	}
+@@ -1888,18 +2063,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
+ {
+ 	struct entropy_store *poolp = &input_pool;
+ 
+-	if (unlikely(nonblocking_pool.initialized == 0))
+-		poolp = &nonblocking_pool;
+-	else {
+-		/* Suspend writing if we're above the trickle
+-		 * threshold.  We'll be woken up again once below
+-		 * random_write_wakeup_thresh, or when the calling
+-		 * thread is about to terminate.
+-		 */
+-		wait_event_interruptible(random_write_wait,
+-					 kthread_should_stop() ||
+-			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
++	if (!crng_ready()) {
++		crng_fast_load(buffer, count);
++		return;
+ 	}
++
++	/* Suspend writing if we're above the trickle threshold.
++	 * We'll be woken up again once below random_write_wakeup_thresh,
++	 * or when the calling thread is about to terminate.
++	 */
++	wait_event_interruptible(random_write_wait, kthread_should_stop() ||
++			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
+ 	mix_pool_bytes(poolp, buffer, count);
+ 	credit_entropy_bits(poolp, entropy);
+ }
+diff --git a/include/crypto/chacha20.h b/include/crypto/chacha20.h
+index 274bbaeeed0f..20d20f681a72 100644
+--- a/include/crypto/chacha20.h
++++ b/include/crypto/chacha20.h
+@@ -16,6 +16,7 @@ struct chacha20_ctx {
+ 	u32 key[8];
+ };
+ 
++void chacha20_block(u32 *state, void *stream);
+ void crypto_chacha20_init(u32 *state, struct chacha20_ctx *ctx, u8 *iv);
+ int crypto_chacha20_setkey(struct crypto_tfm *tfm, const u8 *key,
+ 			   unsigned int keysize);
+diff --git a/lib/Makefile b/lib/Makefile
+index 34a7460c7005..c9ab674107ef 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -10,7 +10,7 @@ endif
+ lib-y := ctype.o string.o vsprintf.o cmdline.o \
+ 	 rbtree.o radix-tree.o dump_stack.o timerqueue.o\
+ 	 idr.o int_sqrt.o extable.o \
+-	 sha1.o md5.o irq_regs.o argv_split.o \
++	 sha1.o chacha20.o md5.o irq_regs.o argv_split.o \
+ 	 proportions.o flex_proportions.o ratelimit.o show_mem.o \
+ 	 is_single_threaded.o plist.o decompress.o kobject_uevent.o \
+ 	 earlycpio.o seq_buf.o siphash.o nmi_backtrace.o
+diff --git a/lib/chacha20.c b/lib/chacha20.c
+new file mode 100644
+index 000000000000..250ceed9ec9a
+--- /dev/null
++++ b/lib/chacha20.c
+@@ -0,0 +1,79 @@
++/*
++ * ChaCha20 256-bit cipher algorithm, RFC7539
++ *
++ * Copyright (C) 2015 Martin Willi
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#include <linux/kernel.h>
++#include <linux/export.h>
++#include <linux/bitops.h>
++#include <linux/cryptohash.h>
++#include <asm/unaligned.h>
++#include <crypto/chacha20.h>
++
++static inline u32 rotl32(u32 v, u8 n)
++{
++	return (v << n) | (v >> (sizeof(v) * 8 - n));
++}
++
++extern void chacha20_block(u32 *state, void *stream)
++{
++	u32 x[16], *out = stream;
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(x); i++)
++		x[i] = state[i];
++
++	for (i = 0; i < 20; i += 2) {
++		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],  16);
++		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],  16);
++		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],  16);
++		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],  16);
++
++		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],  12);
++		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],  12);
++		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10], 12);
++		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11], 12);
++
++		x[0]  += x[4];    x[12] = rotl32(x[12] ^ x[0],   8);
++		x[1]  += x[5];    x[13] = rotl32(x[13] ^ x[1],   8);
++		x[2]  += x[6];    x[14] = rotl32(x[14] ^ x[2],   8);
++		x[3]  += x[7];    x[15] = rotl32(x[15] ^ x[3],   8);
++
++		x[8]  += x[12];   x[4]  = rotl32(x[4]  ^ x[8],   7);
++		x[9]  += x[13];   x[5]  = rotl32(x[5]  ^ x[9],   7);
++		x[10] += x[14];   x[6]  = rotl32(x[6]  ^ x[10],  7);
++		x[11] += x[15];   x[7]  = rotl32(x[7]  ^ x[11],  7);
++
++		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],  16);
++		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],  16);
++		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],  16);
++		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],  16);
++
++		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10], 12);
++		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11], 12);
++		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],  12);
++		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],  12);
++
++		x[0]  += x[5];    x[15] = rotl32(x[15] ^ x[0],   8);
++		x[1]  += x[6];    x[12] = rotl32(x[12] ^ x[1],   8);
++		x[2]  += x[7];    x[13] = rotl32(x[13] ^ x[2],   8);
++		x[3]  += x[4];    x[14] = rotl32(x[14] ^ x[3],   8);
++
++		x[10] += x[15];   x[5]  = rotl32(x[5]  ^ x[10],  7);
++		x[11] += x[12];   x[6]  = rotl32(x[6]  ^ x[11],  7);
++		x[8]  += x[13];   x[7]  = rotl32(x[7]  ^ x[8],   7);
++		x[9]  += x[14];   x[4]  = rotl32(x[4]  ^ x[9],   7);
++	}
++
++	for (i = 0; i < ARRAY_SIZE(x); i++)
++		out[i] = cpu_to_le32(x[i] + state[i]);
++
++	state[12]++;
++}
++EXPORT_SYMBOL(chacha20_block);
+-- 
+2.16.4
+

+ 143 - 0
board/PSG/iot2000/linux-4.4-patches/0020-random-make-dev-urandom-scalable-for-silly-userspace.patch

@@ -0,0 +1,143 @@
+From 90e62ff12f7205a70151ab1f45c437674a4fb81b Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Mon, 2 May 2016 02:04:41 -0400
+Subject: [PATCH 20/32] random: make /dev/urandom scalable for silly userspace
+ programs
+
+On a system with a 4 socket (NUMA) system where a large number of
+application threads were all trying to read from /dev/urandom, this
+can result in the system spending 80% of its time contending on the
+global urandom spinlock.  The application should have used its own
+PRNG, but let's try to help it from running, lemming-like, straight
+over the locking cliff.
+
+Reported-by: Andi Kleen <ak@linux.intel.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 58 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 6d2abeae9434..79b049e644f3 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -435,6 +435,8 @@ static int crng_init = 0;
+ #define crng_ready() (likely(crng_init > 0))
+ static int crng_init_cnt = 0;
+ #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
++static void _extract_crng(struct crng_state *crng,
++			  __u8 out[CHACHA20_BLOCK_SIZE]);
+ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
+ static void process_random_ready_list(void);
+ 
+@@ -758,6 +760,16 @@ static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+ 
+ static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
+ 
++#ifdef CONFIG_NUMA
++/*
++ * Hack to deal with crazy userspace progams when they are all trying
++ * to access /dev/urandom in parallel.  The programs are almost
++ * certainly doing something terribly wrong, but we'll work around
++ * their brain damage.
++ */
++static struct crng_state **crng_node_pool __read_mostly;
++#endif
++
+ static void crng_initialize(struct crng_state *crng)
+ {
+ 	int		i;
+@@ -817,7 +829,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 		if (num == 0)
+ 			return;
+ 	} else
+-		extract_crng(buf.block);
++		_extract_crng(&primary_crng, buf.block);
+ 	spin_lock_irqsave(&primary_crng.lock, flags);
+ 	for (i = 0; i < 8; i++) {
+ 		unsigned long	rv;
+@@ -837,19 +849,26 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ }
+ 
++static inline void maybe_reseed_primary_crng(void)
++{
++	if (crng_init > 2 &&
++	    time_after(jiffies, primary_crng.init_time + CRNG_RESEED_INTERVAL))
++		crng_reseed(&primary_crng, &input_pool);
++}
++
+ static inline void crng_wait_ready(void)
+ {
+ 	wait_event_interruptible(crng_init_wait, crng_ready());
+ }
+ 
+-static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
++static void _extract_crng(struct crng_state *crng,
++			  __u8 out[CHACHA20_BLOCK_SIZE])
+ {
+ 	unsigned long v, flags;
+-	struct crng_state *crng = &primary_crng;
+ 
+ 	if (crng_init > 1 &&
+ 	    time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
+-		crng_reseed(crng, &input_pool);
++		crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
+ 	spin_lock_irqsave(&crng->lock, flags);
+ 	if (arch_get_random_long(&v))
+ 		crng->state[14] ^= v;
+@@ -859,6 +878,19 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
+ 	spin_unlock_irqrestore(&crng->lock, flags);
+ }
+ 
++static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
++{
++	struct crng_state *crng = NULL;
++
++#ifdef CONFIG_NUMA
++	if (crng_node_pool)
++		crng = crng_node_pool[numa_node_id()];
++	if (crng == NULL)
++#endif
++		crng = &primary_crng;
++	_extract_crng(crng, out);
++}
++
+ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+ {
+ 	ssize_t ret = 0, i;
+@@ -1581,9 +1613,31 @@ static void init_std_data(struct entropy_store *r)
+  */
+ static int rand_initialize(void)
+ {
++#ifdef CONFIG_NUMA
++	int i;
++	int num_nodes = num_possible_nodes();
++	struct crng_state *crng;
++	struct crng_state **pool;
++#endif
++
+ 	init_std_data(&input_pool);
+ 	init_std_data(&blocking_pool);
+ 	crng_initialize(&primary_crng);
++
++#ifdef CONFIG_NUMA
++	pool = kmalloc(num_nodes * sizeof(void *),
++		       GFP_KERNEL|__GFP_NOFAIL|__GFP_ZERO);
++	for (i=0; i < num_nodes; i++) {
++		crng = kmalloc_node(sizeof(struct crng_state),
++				    GFP_KERNEL | __GFP_NOFAIL, i);
++		spin_lock_init(&crng->lock);
++		crng_initialize(crng);
++		pool[i] = crng;
++
++	}
++	mb();
++	crng_node_pool = pool;
++#endif
+ 	return 0;
+ }
+ early_initcall(rand_initialize);
+-- 
+2.16.4
+

+ 109 - 0
board/PSG/iot2000/linux-4.4-patches/0021-random-add-backtracking-protection-to-the-CRNG.patch

@@ -0,0 +1,109 @@
+From a6d1adf3fed33218b5059d41128ab2b8b429d08c Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 4 May 2016 13:29:18 -0400
+Subject: [PATCH 21/32] random: add backtracking protection to the CRNG
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 49 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 79b049e644f3..a1214c0fbaf3 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -437,7 +437,8 @@ static int crng_init_cnt = 0;
+ #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
+ static void _extract_crng(struct crng_state *crng,
+ 			  __u8 out[CHACHA20_BLOCK_SIZE]);
+-static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
++static void _crng_backtrack_protect(struct crng_state *crng,
++				    __u8 tmp[CHACHA20_BLOCK_SIZE], int used);
+ static void process_random_ready_list(void);
+ 
+ /**********************************************************************
+@@ -828,8 +829,11 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 		num = extract_entropy(r, &buf, 32, 16, 0);
+ 		if (num == 0)
+ 			return;
+-	} else
++	} else {
+ 		_extract_crng(&primary_crng, buf.block);
++		_crng_backtrack_protect(&primary_crng, buf.block,
++					CHACHA20_KEY_SIZE);
++	}
+ 	spin_lock_irqsave(&primary_crng.lock, flags);
+ 	for (i = 0; i < 8; i++) {
+ 		unsigned long	rv;
+@@ -891,9 +895,46 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
+ 	_extract_crng(crng, out);
+ }
+ 
++/*
++ * Use the leftover bytes from the CRNG block output (if there is
++ * enough) to mutate the CRNG key to provide backtracking protection.
++ */
++static void _crng_backtrack_protect(struct crng_state *crng,
++				    __u8 tmp[CHACHA20_BLOCK_SIZE], int used)
++{
++	unsigned long	flags;
++	__u32		*s, *d;
++	int		i;
++
++	used = round_up(used, sizeof(__u32));
++	if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) {
++		extract_crng(tmp);
++		used = 0;
++	}
++	spin_lock_irqsave(&crng->lock, flags);
++	s = (__u32 *) &tmp[used];
++	d = &crng->state[4];
++	for (i=0; i < 8; i++)
++		*d++ ^= *s++;
++	spin_unlock_irqrestore(&crng->lock, flags);
++}
++
++static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used)
++{
++	struct crng_state *crng = NULL;
++
++#ifdef CONFIG_NUMA
++	if (crng_node_pool)
++		crng = crng_node_pool[numa_node_id()];
++	if (crng == NULL)
++#endif
++		crng = &primary_crng;
++	_crng_backtrack_protect(crng, tmp, used);
++}
++
+ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+ {
+-	ssize_t ret = 0, i;
++	ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE;
+ 	__u8 tmp[CHACHA20_BLOCK_SIZE];
+ 	int large_request = (nbytes > 256);
+ 
+@@ -918,6 +959,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+ 		buf += i;
+ 		ret += i;
+ 	}
++	crng_backtrack_protect(tmp, i);
+ 
+ 	/* Wipe data just written to memory */
+ 	memzero_explicit(tmp, sizeof(tmp));
+@@ -1479,8 +1521,10 @@ void get_random_bytes(void *buf, int nbytes)
+ 	if (nbytes > 0) {
+ 		extract_crng(tmp);
+ 		memcpy(buf, tmp, nbytes);
+-		memzero_explicit(tmp, nbytes);
+-	}
++		crng_backtrack_protect(tmp, nbytes);
++	} else
++		crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE);
++	memzero_explicit(tmp, sizeof(tmp));
+ }
+ EXPORT_SYMBOL(get_random_bytes);
+ 
+-- 
+2.16.4
+

+ 35 - 0
board/PSG/iot2000/linux-4.4-patches/0022-random-remove-stale-maybe_reseed_primary_crng.patch

@@ -0,0 +1,35 @@
+From 1eadc614c3546b2cef698c337c95034253c99771 Mon Sep 17 00:00:00 2001
+From: Stephan Mueller <stephan.mueller@atsec.com>
+Date: Thu, 15 Dec 2016 12:42:33 +0100
+Subject: [PATCH 22/32] random: remove stale maybe_reseed_primary_crng
+
+The function maybe_reseed_primary_crng is not used anywhere and thus can
+be removed.
+
+Signed-off-by: Stephan Mueller <smueller@chronox.de>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a1214c0fbaf3..a6a6a357ddae 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -853,13 +853,6 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ }
+ 
+-static inline void maybe_reseed_primary_crng(void)
+-{
+-	if (crng_init > 2 &&
+-	    time_after(jiffies, primary_crng.init_time + CRNG_RESEED_INTERVAL))
+-		crng_reseed(&primary_crng, &input_pool);
+-}
+-
+ static inline void crng_wait_ready(void)
+ {
+ 	wait_event_interruptible(crng_init_wait, crng_ready());
+-- 
+2.16.4
+

+ 180 - 0
board/PSG/iot2000/linux-4.4-patches/0023-random-use-chacha20-for-get_random_int-long.patch

@@ -0,0 +1,180 @@
+From b2a4ee8c97a7102789f81e428ce13d14a2ac1954 Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Fri, 6 Jan 2017 19:32:01 +0100
+Subject: [PATCH 23/32] random: use chacha20 for get_random_int/long
+
+Now that our crng uses chacha20, we can rely on its speedy
+characteristics for replacing MD5, while simultaneously achieving a
+higher security guarantee. Before the idea was to use these functions if
+you wanted random integers that aren't stupidly insecure but aren't
+necessarily secure either, a vague gray zone, that hopefully was "good
+enough" for its users. With chacha20, we can strengthen this claim,
+since either we're using an rdrand-like instruction, or we're using the
+same crng as /dev/urandom. And it's faster than what was before.
+
+We could have chosen to replace this with a SipHash-derived function,
+which might be slightly faster, but at the cost of having yet another
+RNG construction in the kernel. By moving to chacha20, we have a single
+RNG to analyze and verify, and we also already get good performance
+improvements on all platforms.
+
+Implementation-wise, rather than use a generic buffer for both
+get_random_int/long and memcpy based on the size needs, we use a
+specific buffer for 32-bit reads and for 64-bit reads. This way, we're
+guaranteed to always have aligned accesses on all platforms. While
+slightly more verbose in C, the assembly this generates is a lot
+simpler than otherwise.
+
+Finally, on 32-bit platforms where longs and ints are the same size,
+we simply alias get_random_int to get_random_long.
+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Suggested-by: Theodore Ts'o <tytso@mit.edu>
+Cc: Theodore Ts'o <tytso@mit.edu>
+Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Cc: Andy Lutomirski <luto@amacapital.net>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c  | 84 ++++++++++++++++++++++++++------------------------
+ include/linux/random.h |  1 -
+ init/main.c            |  1 -
+ 3 files changed, 43 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a6a6a357ddae..a10ff9c50cea 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -2068,63 +2068,65 @@ struct ctl_table random_table[] = {
+ };
+ #endif 	/* CONFIG_SYSCTL */
+ 
+-static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
+-
+-int random_int_secret_init(void)
+-{
+-	get_random_bytes(random_int_secret, sizeof(random_int_secret));
+-	return 0;
+-}
+-
+-static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash)
+-		__aligned(sizeof(unsigned long));
++struct batched_entropy {
++	union {
++		unsigned long entropy_long[CHACHA20_BLOCK_SIZE / sizeof(unsigned long)];
++		unsigned int entropy_int[CHACHA20_BLOCK_SIZE / sizeof(unsigned int)];
++	};
++	unsigned int position;
++};
+ 
+ /*
+- * Get a random word for internal kernel use only. Similar to urandom but
+- * with the goal of minimal entropy pool depletion. As a result, the random
+- * value is not cryptographically secure but for several uses the cost of
+- * depleting entropy is too high
++ * Get a random word for internal kernel use only. The quality of the random
++ * number is either as good as RDRAND or as good as /dev/urandom, with the
++ * goal of being quite fast and not depleting entropy.
+  */
+-unsigned int get_random_int(void)
++static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_long);
++unsigned long get_random_long(void)
+ {
+-	__u32 *hash;
+-	unsigned int ret;
++	unsigned long ret;
++	struct batched_entropy *batch;
+ 
+-	if (arch_get_random_int(&ret))
++	if (arch_get_random_long(&ret))
+ 		return ret;
+ 
+-	hash = get_cpu_var(get_random_int_hash);
+-
+-	hash[0] += current->pid + jiffies + random_get_entropy();
+-	md5_transform(hash, random_int_secret);
+-	ret = hash[0];
+-	put_cpu_var(get_random_int_hash);
+-
++	batch = &get_cpu_var(batched_entropy_long);
++	if (batch->position % ARRAY_SIZE(batch->entropy_long) == 0) {
++		extract_crng((u8 *)batch->entropy_long);
++		batch->position = 0;
++	}
++	ret = batch->entropy_long[batch->position++];
++	put_cpu_var(batched_entropy_long);
+ 	return ret;
+ }
+-EXPORT_SYMBOL(get_random_int);
++EXPORT_SYMBOL(get_random_long);
+ 
+-/*
+- * Same as get_random_int(), but returns unsigned long.
+- */
+-unsigned long get_random_long(void)
++#if BITS_PER_LONG == 32
++unsigned int get_random_int(void)
+ {
+-	__u32 *hash;
+-	unsigned long ret;
++	return get_random_long();
++}
++#else
++static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_int);
++unsigned int get_random_int(void)
++{
++	unsigned int ret;
++	struct batched_entropy *batch;
+ 
+-	if (arch_get_random_long(&ret))
++	if (arch_get_random_int(&ret))
+ 		return ret;
+ 
+-	hash = get_cpu_var(get_random_int_hash);
+-
+-	hash[0] += current->pid + jiffies + random_get_entropy();
+-	md5_transform(hash, random_int_secret);
+-	ret = *(unsigned long *)hash;
+-	put_cpu_var(get_random_int_hash);
+-
++	batch = &get_cpu_var(batched_entropy_int);
++	if (batch->position % ARRAY_SIZE(batch->entropy_int) == 0) {
++		extract_crng((u8 *)batch->entropy_int);
++		batch->position = 0;
++	}
++	ret = batch->entropy_int[batch->position++];
++	put_cpu_var(batched_entropy_int);
+ 	return ret;
+ }
+-EXPORT_SYMBOL(get_random_long);
++#endif
++EXPORT_SYMBOL(get_random_int);
+ 
+ /*
+  * randomize_range() returns a start address such that
+diff --git a/include/linux/random.h b/include/linux/random.h
+index 9c29122037f9..3e874bcdf8b8 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -27,7 +27,6 @@ extern int add_random_ready_callback(struct random_ready_callback *rdy);
+ extern void del_random_ready_callback(struct random_ready_callback *rdy);
+ extern void get_random_bytes_arch(void *buf, int nbytes);
+ void generate_random_uuid(unsigned char uuid_out[16]);
+-extern int random_int_secret_init(void);
+ 
+ #ifndef MODULE
+ extern const struct file_operations random_fops, urandom_fops;
+diff --git a/init/main.c b/init/main.c
+index e88c8cdef6a7..406cddf01de8 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -885,7 +885,6 @@ static void __init do_basic_setup(void)
+ 	do_ctors();
+ 	usermodehelper_enable();
+ 	do_initcalls();
+-	random_int_secret_init();
+ }
+ 
+ static void __init do_pre_smp_initcalls(void)
+-- 
+2.16.4
+

+ 147 - 0
board/PSG/iot2000/linux-4.4-patches/0024-random-convert-get_random_int-long-into-get_random_u.patch

@@ -0,0 +1,147 @@
+From 74f881a90ad219b51f59cc3ea700b3dd9decc2a3 Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Sun, 22 Jan 2017 16:34:08 +0100
+Subject: [PATCH 24/32] random: convert get_random_int/long into
+ get_random_u32/u64
+
+Many times, when a user wants a random number, he wants a random number
+of a guaranteed size. So, thinking of get_random_int and get_random_long
+in terms of get_random_u32 and get_random_u64 makes it much easier to
+achieve this. It also makes the code simpler.
+
+On 32-bit platforms, get_random_int and get_random_long are both aliased
+to get_random_u32. On 64-bit platforms, int->u32 and long->u64.
+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c  | 55 +++++++++++++++++++++++++-------------------------
+ include/linux/random.h | 17 ++++++++++++++--
+ 2 files changed, 42 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index a10ff9c50cea..d79a631a2b5e 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -2070,8 +2070,8 @@ struct ctl_table random_table[] = {
+ 
+ struct batched_entropy {
+ 	union {
+-		unsigned long entropy_long[CHACHA20_BLOCK_SIZE / sizeof(unsigned long)];
+-		unsigned int entropy_int[CHACHA20_BLOCK_SIZE / sizeof(unsigned int)];
++		u64 entropy_u64[CHACHA20_BLOCK_SIZE / sizeof(u64)];
++		u32 entropy_u32[CHACHA20_BLOCK_SIZE / sizeof(u32)];
+ 	};
+ 	unsigned int position;
+ };
+@@ -2081,52 +2081,51 @@ struct batched_entropy {
+  * number is either as good as RDRAND or as good as /dev/urandom, with the
+  * goal of being quite fast and not depleting entropy.
+  */
+-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_long);
+-unsigned long get_random_long(void)
++static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
++u64 get_random_u64(void)
+ {
+-	unsigned long ret;
++	u64 ret;
+ 	struct batched_entropy *batch;
+ 
+-	if (arch_get_random_long(&ret))
++#if BITS_PER_LONG == 64
++	if (arch_get_random_long((unsigned long *)&ret))
+ 		return ret;
++#else
++	if (arch_get_random_long((unsigned long *)&ret) &&
++	    arch_get_random_long((unsigned long *)&ret + 1))
++	    return ret;
++#endif
+ 
+-	batch = &get_cpu_var(batched_entropy_long);
+-	if (batch->position % ARRAY_SIZE(batch->entropy_long) == 0) {
+-		extract_crng((u8 *)batch->entropy_long);
++	batch = &get_cpu_var(batched_entropy_u64);
++	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
++		extract_crng((u8 *)batch->entropy_u64);
+ 		batch->position = 0;
+ 	}
+-	ret = batch->entropy_long[batch->position++];
+-	put_cpu_var(batched_entropy_long);
++	ret = batch->entropy_u64[batch->position++];
++	put_cpu_var(batched_entropy_u64);
+ 	return ret;
+ }
+-EXPORT_SYMBOL(get_random_long);
++EXPORT_SYMBOL(get_random_u64);
+ 
+-#if BITS_PER_LONG == 32
+-unsigned int get_random_int(void)
+-{
+-	return get_random_long();
+-}
+-#else
+-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_int);
+-unsigned int get_random_int(void)
++static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
++u32 get_random_u32(void)
+ {
+-	unsigned int ret;
++	u32 ret;
+ 	struct batched_entropy *batch;
+ 
+ 	if (arch_get_random_int(&ret))
+ 		return ret;
+ 
+-	batch = &get_cpu_var(batched_entropy_int);
+-	if (batch->position % ARRAY_SIZE(batch->entropy_int) == 0) {
+-		extract_crng((u8 *)batch->entropy_int);
++	batch = &get_cpu_var(batched_entropy_u32);
++	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
++		extract_crng((u8 *)batch->entropy_u32);
+ 		batch->position = 0;
+ 	}
+-	ret = batch->entropy_int[batch->position++];
+-	put_cpu_var(batched_entropy_int);
++	ret = batch->entropy_u32[batch->position++];
++	put_cpu_var(batched_entropy_u32);
+ 	return ret;
+ }
+-#endif
+-EXPORT_SYMBOL(get_random_int);
++EXPORT_SYMBOL(get_random_u32);
+ 
+ /*
+  * randomize_range() returns a start address such that
+diff --git a/include/linux/random.h b/include/linux/random.h
+index 3e874bcdf8b8..39f125ba80bb 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -32,8 +32,21 @@ void generate_random_uuid(unsigned char uuid_out[16]);
+ extern const struct file_operations random_fops, urandom_fops;
+ #endif
+ 
+-unsigned int get_random_int(void);
+-unsigned long get_random_long(void);
++u32 get_random_u32(void);
++u64 get_random_u64(void);
++static inline unsigned int get_random_int(void)
++{
++	return get_random_u32();
++}
++static inline unsigned long get_random_long(void)
++{
++#if BITS_PER_LONG == 64
++	return get_random_u64();
++#else
++	return get_random_u32();
++#endif
++}
++
+ unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
+ 
+ u32 prandom_u32(void);
+-- 
+2.16.4
+

+ 148 - 0
board/PSG/iot2000/linux-4.4-patches/0025-random-invalidate-batched-entropy-after-crng-init.patch

@@ -0,0 +1,148 @@
+From a4829bebf0be947a5ec2880b15ec77d5178d6a17 Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Wed, 7 Jun 2017 19:45:31 -0400
+Subject: [PATCH 25/32] random: invalidate batched entropy after crng init
+
+It's possible that get_random_{u32,u64} is used before the crng has
+initialized, in which case, its output might not be cryptographically
+secure. For this problem, directly, this patch set is introducing the
+*_wait variety of functions, but even with that, there's a subtle issue:
+what happens to our batched entropy that was generated before
+initialization. Prior to this commit, it'd stick around, supplying bad
+numbers. After this commit, we force the entropy to be re-extracted
+after each phase of the crng has initialized.
+
+In order to avoid a race condition with the position counter, we
+introduce a simple rwlock for this invalidation. Since it's only during
+this awkward transition period, after things are all set up, we stop
+using it, so that it doesn't have an impact on performance.
+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@vger.kernel.org  # v4.11+
+---
+ drivers/char/random.c | 37 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 37 insertions(+)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index d79a631a2b5e..6c571ee0d6c4 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1,6 +1,9 @@
+ /*
+  * random.c -- A strong random number generator
+  *
++ * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
++ * Rights Reserved.
++ *
+  * Copyright Matt Mackall <mpm@selenic.com>, 2003, 2004, 2005
+  *
+  * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.  All
+@@ -771,6 +774,8 @@ static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
+ static struct crng_state **crng_node_pool __read_mostly;
+ #endif
+ 
++static void invalidate_batched_entropy(void);
++
+ static void crng_initialize(struct crng_state *crng)
+ {
+ 	int		i;
+@@ -808,6 +813,7 @@ static int crng_fast_load(const char *cp, size_t len)
+ 		cp++; crng_init_cnt++; len--;
+ 	}
+ 	if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
++		invalidate_batched_entropy();
+ 		crng_init = 1;
+ 		wake_up_interruptible(&crng_init_wait);
+ 		pr_notice("random: fast init done\n");
+@@ -845,6 +851,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	memzero_explicit(&buf, sizeof(buf));
+ 	crng->init_time = jiffies;
+ 	if (crng == &primary_crng && crng_init < 2) {
++		invalidate_batched_entropy();
+ 		crng_init = 2;
+ 		process_random_ready_list();
+ 		wake_up_interruptible(&crng_init_wait);
+@@ -2075,6 +2082,7 @@ struct batched_entropy {
+ 	};
+ 	unsigned int position;
+ };
++static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_reset_lock);
+ 
+ /*
+  * Get a random word for internal kernel use only. The quality of the random
+@@ -2085,6 +2093,8 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
+ u64 get_random_u64(void)
+ {
+ 	u64 ret;
++	bool use_lock = crng_init < 2;
++	unsigned long flags;
+ 	struct batched_entropy *batch;
+ 
+ #if BITS_PER_LONG == 64
+@@ -2097,11 +2107,15 @@ u64 get_random_u64(void)
+ #endif
+ 
+ 	batch = &get_cpu_var(batched_entropy_u64);
++	if (use_lock)
++		read_lock_irqsave(&batched_entropy_reset_lock, flags);
+ 	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
+ 		extract_crng((u8 *)batch->entropy_u64);
+ 		batch->position = 0;
+ 	}
+ 	ret = batch->entropy_u64[batch->position++];
++	if (use_lock)
++		read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
+ 	put_cpu_var(batched_entropy_u64);
+ 	return ret;
+ }
+@@ -2111,22 +2125,45 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
+ u32 get_random_u32(void)
+ {
+ 	u32 ret;
++	bool use_lock = crng_init < 2;
++	unsigned long flags;
+ 	struct batched_entropy *batch;
+ 
+ 	if (arch_get_random_int(&ret))
+ 		return ret;
+ 
+ 	batch = &get_cpu_var(batched_entropy_u32);
++	if (use_lock)
++		read_lock_irqsave(&batched_entropy_reset_lock, flags);
+ 	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
+ 		extract_crng((u8 *)batch->entropy_u32);
+ 		batch->position = 0;
+ 	}
+ 	ret = batch->entropy_u32[batch->position++];
++	if (use_lock)
++		read_unlock_irqrestore(&batched_entropy_reset_lock, flags);
+ 	put_cpu_var(batched_entropy_u32);
+ 	return ret;
+ }
+ EXPORT_SYMBOL(get_random_u32);
+ 
++/* It's important to invalidate all potential batched entropy that might
++ * be stored before the crng is initialized, which we can do lazily by
++ * simply resetting the counter to zero so that it's re-extracted on the
++ * next usage. */
++static void invalidate_batched_entropy(void)
++{
++	int cpu;
++	unsigned long flags;
++
++	write_lock_irqsave(&batched_entropy_reset_lock, flags);
++	for_each_possible_cpu (cpu) {
++		per_cpu_ptr(&batched_entropy_u32, cpu)->position = 0;
++		per_cpu_ptr(&batched_entropy_u64, cpu)->position = 0;
++	}
++	write_unlock_irqrestore(&batched_entropy_reset_lock, flags);
++}
++
+ /*
+  * randomize_range() returns a start address such that
+  *
+-- 
+2.16.4
+

+ 87 - 0
board/PSG/iot2000/linux-4.4-patches/0026-random-silence-compiler-warnings-and-fix-race.patch

@@ -0,0 +1,87 @@
+From 45cf6623ee8462c12e9a971620ea01fdae7b0114 Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Thu, 15 Jun 2017 00:45:26 +0200
+Subject: [PATCH 26/32] random: silence compiler warnings and fix race
+
+Odd versions of gcc for the sh4 architecture will actually warn about
+flags being used while uninitialized, so we set them to zero. Non crazy
+gccs will optimize that out again, so it doesn't make a difference.
+
+Next, over aggressive gccs could inline the expression that defines
+use_lock, which could then introduce a race resulting in a lock
+imbalance. By using READ_ONCE, we prevent that fate. Finally, we make
+that assignment const, so that gcc can still optimize a nice amount.
+
+Finally, we fix a potential deadlock between primary_crng.lock and
+batched_entropy_reset_lock, where they could be called in opposite
+order. Moving the call to invalidate_batched_entropy to outside the lock
+rectifies this issue.
+
+Fixes: b169c13de473a85b3c859bb36216a4cb5f00a54a
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@vger.kernel.org
+---
+ drivers/char/random.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 6c571ee0d6c4..194cdb02d458 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -812,13 +812,13 @@ static int crng_fast_load(const char *cp, size_t len)
+ 		p[crng_init_cnt % CHACHA20_KEY_SIZE] ^= *cp;
+ 		cp++; crng_init_cnt++; len--;
+ 	}
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 	if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
+ 		invalidate_batched_entropy();
+ 		crng_init = 1;
+ 		wake_up_interruptible(&crng_init_wait);
+ 		pr_notice("random: fast init done\n");
+ 	}
+-	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 	return 1;
+ }
+ 
+@@ -850,6 +850,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	}
+ 	memzero_explicit(&buf, sizeof(buf));
+ 	crng->init_time = jiffies;
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 	if (crng == &primary_crng && crng_init < 2) {
+ 		invalidate_batched_entropy();
+ 		crng_init = 2;
+@@ -857,7 +858,6 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 		wake_up_interruptible(&crng_init_wait);
+ 		pr_notice("random: crng init done\n");
+ 	}
+-	spin_unlock_irqrestore(&primary_crng.lock, flags);
+ }
+ 
+ static inline void crng_wait_ready(void)
+@@ -2093,8 +2093,8 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
+ u64 get_random_u64(void)
+ {
+ 	u64 ret;
+-	bool use_lock = crng_init < 2;
+-	unsigned long flags;
++	bool use_lock = READ_ONCE(crng_init) < 2;
++	unsigned long flags = 0;
+ 	struct batched_entropy *batch;
+ 
+ #if BITS_PER_LONG == 64
+@@ -2125,8 +2125,8 @@ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32);
+ u32 get_random_u32(void)
+ {
+ 	u32 ret;
+-	bool use_lock = crng_init < 2;
+-	unsigned long flags;
++	bool use_lock = READ_ONCE(crng_init) < 2;
++	unsigned long flags = 0;
+ 	struct batched_entropy *batch;
+ 
+ 	if (arch_get_random_int(&ret))
+-- 
+2.16.4
+

+ 118 - 0
board/PSG/iot2000/linux-4.4-patches/0027-random-add-wait_for_random_bytes-API.patch

@@ -0,0 +1,118 @@
+From bab97a70fbb2f35de923e07d1e2377ad43b024af Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Wed, 7 Jun 2017 19:58:56 -0400
+Subject: [PATCH 27/32] random: add wait_for_random_bytes() API
+
+This enables users of get_random_{bytes,u32,u64,int,long} to wait until
+the pool is ready before using this function, in case they actually want
+to have reliable randomness.
+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c  | 41 +++++++++++++++++++++++++++++++----------
+ include/linux/random.h |  1 +
+ 2 files changed, 32 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 194cdb02d458..198ae9df9d9e 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -860,11 +860,6 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ 	}
+ }
+ 
+-static inline void crng_wait_ready(void)
+-{
+-	wait_event_interruptible(crng_init_wait, crng_ready());
+-}
+-
+ static void _extract_crng(struct crng_state *crng,
+ 			  __u8 out[CHACHA20_BLOCK_SIZE])
+ {
+@@ -1499,7 +1494,10 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+  * number of good random numbers, suitable for key generation, seeding
+  * TCP sequence numbers, etc.  It does not rely on the hardware random
+  * number generator.  For random bytes direct from the hardware RNG
+- * (when available), use get_random_bytes_arch().
++ * (when available), use get_random_bytes_arch(). In order to ensure
++ * that the randomness provided by this function is okay, the function
++ * wait_for_random_bytes() should be called and return 0 at least once
++ * at any point prior.
+  */
+ void get_random_bytes(void *buf, int nbytes)
+ {
+@@ -1528,6 +1526,24 @@ void get_random_bytes(void *buf, int nbytes)
+ }
+ EXPORT_SYMBOL(get_random_bytes);
+ 
++/*
++ * Wait for the urandom pool to be seeded and thus guaranteed to supply
++ * cryptographically secure random numbers. This applies to: the /dev/urandom
++ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
++ * family of functions. Using any of these functions without first calling
++ * this function forfeits the guarantee of security.
++ *
++ * Returns: 0 if the urandom pool has been seeded.
++ *          -ERESTARTSYS if the function was interrupted by a signal.
++ */
++int wait_for_random_bytes(void)
++{
++	if (likely(crng_ready()))
++		return 0;
++	return wait_event_interruptible(crng_init_wait, crng_ready());
++}
++EXPORT_SYMBOL(wait_for_random_bytes);
++
+ /*
+  * Add a callback function that will be invoked when the nonblocking
+  * pool is initialised.
+@@ -1893,6 +1909,8 @@ const struct file_operations urandom_fops = {
+ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+ 		unsigned int, flags)
+ {
++	int ret;
++
+ 	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
+ 		return -EINVAL;
+ 
+@@ -1905,9 +1923,9 @@ SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
+ 	if (!crng_ready()) {
+ 		if (flags & GRND_NONBLOCK)
+ 			return -EAGAIN;
+-		crng_wait_ready();
+-		if (signal_pending(current))
+-			return -ERESTARTSYS;
++		ret = wait_for_random_bytes();
++		if (unlikely(ret))
++			return ret;
+ 	}
+ 	return urandom_read(NULL, buf, count, NULL);
+ }
+@@ -2087,7 +2105,10 @@ static rwlock_t batched_entropy_reset_lock = __RW_LOCK_UNLOCKED(batched_entropy_
+ /*
+  * Get a random word for internal kernel use only. The quality of the random
+  * number is either as good as RDRAND or as good as /dev/urandom, with the
+- * goal of being quite fast and not depleting entropy.
++ * goal of being quite fast and not depleting entropy. In order to ensure
++ * that the randomness provided by this function is okay, the function
++ * wait_for_random_bytes() should be called and return 0 at least once
++ * at any point prior.
+  */
+ static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64);
+ u64 get_random_u64(void)
+diff --git a/include/linux/random.h b/include/linux/random.h
+index 39f125ba80bb..b282d7adcacc 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -23,6 +23,7 @@ extern void add_input_randomness(unsigned int type, unsigned int code,
+ extern void add_interrupt_randomness(int irq, int irq_flags);
+ 
+ extern void get_random_bytes(void *buf, int nbytes);
++extern int wait_for_random_bytes(void);
+ extern int add_random_ready_callback(struct random_ready_callback *rdy);
+ extern void del_random_ready_callback(struct random_ready_callback *rdy);
+ extern void get_random_bytes_arch(void *buf, int nbytes);
+-- 
+2.16.4
+

+ 77 - 0
board/PSG/iot2000/linux-4.4-patches/0028-random-fix-crng_ready-test.patch

@@ -0,0 +1,77 @@
+From 24cef0dbc155391db6e2eceba26cba476e54dd15 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 11 Apr 2018 13:27:52 -0400
+Subject: [PATCH 28/32] random: fix crng_ready() test
+
+The crng_init variable has three states:
+
+0: The CRNG is not initialized at all
+1: The CRNG has a small amount of entropy, hopefully good enough for
+   early-boot, non-cryptographical use cases
+2: The CRNG is fully initialized and we are sure it is safe for
+   cryptographic use cases.
+
+The crng_ready() function should only return true once we are in the
+last state.  This addresses CVE-2018-1108.
+
+Reported-by: Jann Horn <jannh@google.com>
+Fixes: e192be9d9a30 ("random: replace non-blocking pool...")
+Cc: stable@kernel.org # 4.8+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Jann Horn <jannh@google.com>
+---
+ drivers/char/random.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 198ae9df9d9e..747b7d6d4f44 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -435,7 +435,7 @@ struct crng_state primary_crng = {
+  * its value (from 0->1->2).
+  */
+ static int crng_init = 0;
+-#define crng_ready() (likely(crng_init > 0))
++#define crng_ready() (likely(crng_init > 1))
+ static int crng_init_cnt = 0;
+ #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
+ static void _extract_crng(struct crng_state *crng,
+@@ -803,7 +803,7 @@ static int crng_fast_load(const char *cp, size_t len)
+ 
+ 	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
+ 		return 0;
+-	if (crng_ready()) {
++	if (crng_init != 0) {
+ 		spin_unlock_irqrestore(&primary_crng.lock, flags);
+ 		return 0;
+ 	}
+@@ -865,7 +865,7 @@ static void _extract_crng(struct crng_state *crng,
+ {
+ 	unsigned long v, flags;
+ 
+-	if (crng_init > 1 &&
++	if (crng_ready() &&
+ 	    time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))
+ 		crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
+ 	spin_lock_irqsave(&crng->lock, flags);
+@@ -1146,7 +1146,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
+ 	fast_mix(fast_pool);
+ 	add_interrupt_bench(cycles);
+ 
+-	if (!crng_ready()) {
++	if (unlikely(crng_init == 0)) {
+ 		if ((fast_pool->count >= 64) &&
+ 		    crng_fast_load((char *) fast_pool->pool,
+ 				   sizeof(fast_pool->pool))) {
+@@ -2213,7 +2213,7 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
+ {
+ 	struct entropy_store *poolp = &input_pool;
+ 
+-	if (!crng_ready()) {
++	if (unlikely(crng_init == 0)) {
+ 		crng_fast_load(buffer, count);
+ 		return;
+ 	}
+-- 
+2.16.4
+

+ 110 - 0
board/PSG/iot2000/linux-4.4-patches/0029-random-use-a-different-mixing-algorithm-for-add_devi.patch

@@ -0,0 +1,110 @@
+From 0e756274490a989fc8a368d0072b20019a5bd53d Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 11 Apr 2018 14:58:27 -0400
+Subject: [PATCH 29/32] random: use a different mixing algorithm for
+ add_device_randomness()
+
+add_device_randomness() use of crng_fast_load() was highly
+problematic.  Some callers of add_device_randomness() can pass in a
+large amount of static information.  This would immediately promote
+the crng_init state from 0 to 1, without really doing much to
+initialize the primary_crng's internal state with something even
+vaguely unpredictable.
+
+Since we don't have the speed constraints of add_interrupt_randomness(),
+we can do a better job mixing in the what unpredictability a device
+driver or architecture maintainer might see fit to give us, and do it
+in a way which does not bump the crng_init_cnt variable.
+
+Also, since add_device_randomness() doesn't bump any entropy
+accounting in crng_init state 0, mix the device randomness into the
+input_pool entropy pool as well.  This is related to CVE-2018-1108.
+
+Reported-by: Jann Horn <jannh@google.com>
+Fixes: ee7998c50c26 ("random: do not ignore early device randomness")
+Cc: stable@kernel.org # 4.13+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 747b7d6d4f44..ca9127abad52 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -796,6 +796,10 @@ static void crng_initialize(struct crng_state *crng)
+ 	crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
+ }
+ 
++/*
++ * crng_fast_load() can be called by code in the interrupt service
++ * path.  So we can't afford to dilly-dally.
++ */
+ static int crng_fast_load(const char *cp, size_t len)
+ {
+ 	unsigned long flags;
+@@ -822,6 +826,51 @@ static int crng_fast_load(const char *cp, size_t len)
+ 	return 1;
+ }
+ 
++/*
++ * crng_slow_load() is called by add_device_randomness, which has two
++ * attributes.  (1) We can't trust the buffer passed to it is
++ * guaranteed to be unpredictable (so it might not have any entropy at
++ * all), and (2) it doesn't have the performance constraints of
++ * crng_fast_load().
++ *
++ * So we do something more comprehensive which is guaranteed to touch
++ * all of the primary_crng's state, and which uses a LFSR with a
++ * period of 255 as part of the mixing algorithm.  Finally, we do
++ * *not* advance crng_init_cnt since buffer we may get may be something
++ * like a fixed DMI table (for example), which might very well be
++ * unique to the machine, but is otherwise unvarying.
++ */
++static int crng_slow_load(const char *cp, size_t len)
++{
++	unsigned long		flags;
++	static unsigned char	lfsr = 1;
++	unsigned char		tmp;
++	unsigned		i, max = CHACHA20_KEY_SIZE;
++	const char *		src_buf = cp;
++	char *			dest_buf = (char *) &primary_crng.state[4];
++
++	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
++		return 0;
++	if (crng_init != 0) {
++		spin_unlock_irqrestore(&primary_crng.lock, flags);
++		return 0;
++	}
++	if (len > max)
++		max = len;
++
++	for (i = 0; i < max ; i++) {
++		tmp = lfsr;
++		lfsr >>= 1;
++		if (tmp & 1)
++			lfsr ^= 0xE1;
++		tmp = dest_buf[i % CHACHA20_KEY_SIZE];
++		dest_buf[i % CHACHA20_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
++		lfsr += (tmp << 3) | (tmp >> 5);
++	}
++	spin_unlock_irqrestore(&primary_crng.lock, flags);
++	return 1;
++}
++
+ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
+ {
+ 	unsigned long	flags;
+@@ -991,6 +1040,9 @@ void add_device_randomness(const void *buf, unsigned int size)
+ 	unsigned long time = random_get_entropy() ^ jiffies;
+ 	unsigned long flags;
+ 
++	if (!crng_ready() && size)
++		crng_slow_load(buf, size);
++
+ 	trace_add_device_randomness(size, _RET_IP_);
+ 	spin_lock_irqsave(&input_pool.lock, flags);
+ 	_mix_pool_bytes(&input_pool, buf, size);
+-- 
+2.16.4
+

+ 163 - 0
board/PSG/iot2000/linux-4.4-patches/0030-random-only-read-from-dev-random-after-its-pool-has-.patch

@@ -0,0 +1,163 @@
+From 6cb95e11da746d51f1defd91d5904f90c15fb743 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 20 Feb 2019 16:06:38 -0500
+Subject: [PATCH 30/32] random: only read from /dev/random after its pool has
+ received 128 bits
+
+Immediately after boot, we allow reads from /dev/random before its
+entropy pool has been fully initialized.  Fix this so that we don't
+allow this until the blocking pool has received 128 bits.
+
+We do this by repurposing the initialized flag in the entropy pool
+struct, and use the initialized flag in the blocking pool to indicate
+whether it is safe to pull from the blocking pool.
+
+To do this, we needed to rework when we decide to push entropy from the
+input pool to the blocking pool, since the initialized flag for the
+input pool was used for this purpose.  To simplify things, we no
+longer use the initialized flag for that purpose, nor do we use the
+entropy_total field any more.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c         | 44 +++++++++++++++++++++----------------------
+ include/trace/events/random.h | 13 +++++--------
+ 2 files changed, 27 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index ca9127abad52..f37a90896821 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -466,7 +466,6 @@ struct entropy_store {
+ 	unsigned short add_ptr;
+ 	unsigned short input_rotate;
+ 	int entropy_count;
+-	int entropy_total;
+ 	unsigned int initialized:1;
+ 	unsigned int limit:1;
+ 	unsigned int last_data_init:1;
+@@ -642,7 +641,7 @@ static void process_random_ready_list(void)
+  */
+ static void credit_entropy_bits(struct entropy_store *r, int nbits)
+ {
+-	int entropy_count, orig;
++	int entropy_count, orig, has_initialized = 0;
+ 	const int pool_size = r->poolinfo->poolfracbits;
+ 	int nfrac = nbits << ENTROPY_SHIFT;
+ 
+@@ -697,23 +696,25 @@ retry:
+ 		entropy_count = 0;
+ 	} else if (entropy_count > pool_size)
+ 		entropy_count = pool_size;
++	if ((r == &blocking_pool) && !r->initialized &&
++	    (entropy_count >> ENTROPY_SHIFT) > 128)
++		has_initialized = 1;
+ 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ 		goto retry;
+ 
+-	r->entropy_total += nbits;
+-	if (!r->initialized && r->entropy_total > 128) {
++	if (has_initialized)
+ 		r->initialized = 1;
+-		r->entropy_total = 0;
+-	}
+ 
+ 	trace_credit_entropy_bits(r->name, nbits,
+-				  entropy_count >> ENTROPY_SHIFT,
+-				  r->entropy_total, _RET_IP_);
++				  entropy_count >> ENTROPY_SHIFT, _RET_IP_);
+ 
+ 	if (r == &input_pool) {
+ 		int entropy_bits = entropy_count >> ENTROPY_SHIFT;
++		struct entropy_store *other = &blocking_pool;
+ 
+-		if (crng_init < 2 && entropy_bits >= 128) {
++		if (crng_init < 2) {
++			if (entropy_bits < 128)
++				return;
+ 			crng_reseed(&primary_crng, r);
+ 			entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
+ 		}
+@@ -723,20 +724,14 @@ retry:
+ 			wake_up_interruptible(&random_read_wait);
+ 			kill_fasync(&fasync, SIGIO, POLL_IN);
+ 		}
+-		/* If the input pool is getting full, send some
+-		 * entropy to the blocking pool until it is 75% full.
++		/* If the input pool is getting full, and the blocking
++		 * pool has room, send some entropy to the blocking
++		 * pool.
+ 		 */
+-		if (entropy_bits > random_write_wakeup_bits &&
+-		    r->initialized &&
+-		    r->entropy_total >= 2*random_read_wakeup_bits) {
+-			struct entropy_store *other = &blocking_pool;
+-
+-			if (other->entropy_count <=
+-			    3 * other->poolinfo->poolfracbits / 4) {
+-				schedule_work(&other->push_work);
+-				r->entropy_total = 0;
+-			}
+-		}
++		if (!work_pending(&other->push_work) &&
++		    (ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) &&
++		    (ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes))
++			schedule_work(&other->push_work);
+ 	}
+ }
+ 
+@@ -1510,6 +1505,11 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+ 	int large_request = (nbytes > 256);
+ 
+ 	trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
++	if (!r->initialized && r->pull) {
++		xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8);
++		if (!r->initialized)
++			return 0;
++	}
+ 	xfer_secondary_pool(r, nbytes);
+ 	nbytes = account(r, nbytes, 0, 0);
+ 
+diff --git a/include/trace/events/random.h b/include/trace/events/random.h
+index 4684de344c5d..d5323630be90 100644
+--- a/include/trace/events/random.h
++++ b/include/trace/events/random.h
+@@ -61,15 +61,14 @@ DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
+ 
+ TRACE_EVENT(credit_entropy_bits,
+ 	TP_PROTO(const char *pool_name, int bits, int entropy_count,
+-		 int entropy_total, unsigned long IP),
++		 unsigned long IP),
+ 
+-	TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
++	TP_ARGS(pool_name, bits, entropy_count, IP),
+ 
+ 	TP_STRUCT__entry(
+ 		__field( const char *,	pool_name		)
+ 		__field(	  int,	bits			)
+ 		__field(	  int,	entropy_count		)
+-		__field(	  int,	entropy_total		)
+ 		__field(unsigned long,	IP			)
+ 	),
+ 
+@@ -77,14 +76,12 @@ TRACE_EVENT(credit_entropy_bits,
+ 		__entry->pool_name	= pool_name;
+ 		__entry->bits		= bits;
+ 		__entry->entropy_count	= entropy_count;
+-		__entry->entropy_total	= entropy_total;
+ 		__entry->IP		= IP;
+ 	),
+ 
+-	TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
+-		  "caller %pS", __entry->pool_name, __entry->bits,
+-		  __entry->entropy_count, __entry->entropy_total,
+-		  (void *)__entry->IP)
++	TP_printk("%s pool: bits %d entropy_count %d caller %pS",
++		  __entry->pool_name, __entry->bits,
++		  __entry->entropy_count, (void *)__entry->IP)
+ );
+ 
+ TRACE_EVENT(push_to_pool,
+-- 
+2.16.4
+

+ 58 - 0
board/PSG/iot2000/linux-4.4-patches/0031-random-fix-soft-lockup-when-trying-to-read-from-an-u.patch

@@ -0,0 +1,58 @@
+From 4fe896ddf122abf98234154db65773db70f0b8a1 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 22 May 2019 12:02:16 -0400
+Subject: [PATCH 31/32] random: fix soft lockup when trying to read from an
+ uninitialized blocking pool
+
+Fixes: eb9d1bf079bb: "random: only read from /dev/random after its pool has received 128 bits"
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+---
+ drivers/char/random.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index f37a90896821..29755924aa45 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -702,8 +702,11 @@ retry:
+ 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ 		goto retry;
+ 
+-	if (has_initialized)
++	if (has_initialized) {
+ 		r->initialized = 1;
++		wake_up_interruptible(&random_read_wait);
++		kill_fasync(&fasync, SIGIO, POLL_IN);
++	}
+ 
+ 	trace_credit_entropy_bits(r->name, nbits,
+ 				  entropy_count >> ENTROPY_SHIFT, _RET_IP_);
+@@ -719,6 +722,13 @@ retry:
+ 			entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
+ 		}
+ 
++		/* initialize the blocking pool if necessary */
++		if (entropy_bits >= random_read_wakeup_bits &&
++		    !other->initialized) {
++			schedule_work(&other->push_work);
++			return;
++		}
++
+ 		/* should we wake readers? */
+ 		if (entropy_bits >= random_read_wakeup_bits) {
+ 			wake_up_interruptible(&random_read_wait);
+@@ -1795,8 +1805,8 @@ _random_read(int nonblock, char __user *buf, size_t nbytes)
+ 			return -EAGAIN;
+ 
+ 		wait_event_interruptible(random_read_wait,
+-			ENTROPY_BITS(&input_pool) >=
+-			random_read_wakeup_bits);
++		    blocking_pool.initialized &&
++		    (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits));
+ 		if (signal_pending(current))
+ 			return -ERESTARTSYS;
+ 	}
+-- 
+2.16.4
+

+ 145 - 0
board/PSG/iot2000/linux-4.4-patches/0032-random-try-to-actively-add-entropy-rather-than-passi.patch

@@ -0,0 +1,145 @@
+From eb0b7b33a7bb77cd54cc4627044a77f1ee002139 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Sat, 28 Sep 2019 16:53:52 -0700
+Subject: [PATCH 32/32] random: try to actively add entropy rather than
+ passively wait for it
+
+For 5.3 we had to revert a nice ext4 IO pattern improvement, because it
+caused a bootup regression due to lack of entropy at bootup together
+with arguably broken user space that was asking for secure random
+numbers when it really didn't need to.
+
+See commit 72dbcf721566 (Revert "ext4: make __ext4_get_inode_loc plug").
+
+This aims to solve the issue by actively generating entropy noise using
+the CPU cycle counter when waiting for the random number generator to
+initialize.  This only works when you have a high-frequency time stamp
+counter available, but that's the case on all modern x86 CPU's, and on
+most other modern CPU's too.
+
+What we do is to generate jitter entropy from the CPU cycle counter
+under a somewhat complex load: calling the scheduler while also
+guaranteeing a certain amount of timing noise by also triggering a
+timer.
+
+I'm sure we can tweak this, and that people will want to look at other
+alternatives, but there's been a number of papers written on jitter
+entropy, and this should really be fairly conservative by crediting one
+bit of entropy for every timer-induced jump in the cycle counter.  Not
+because the timer itself would be all that unpredictable, but because
+the interaction between the timer and the loop is going to be.
+
+Even if (and perhaps particularly if) the timer actually happens on
+another CPU, the cacheline interaction between the loop that reads the
+cycle counter and the timer itself firing is going to add perturbations
+to the cycle counter values that get mixed into the entropy pool.
+
+As Thomas pointed out, with a modern out-of-order CPU, even quite simple
+loops show a fair amount of hard-to-predict timing variability even in
+the absense of external interrupts.  But this tries to take that further
+by actually having a fairly complex interaction.
+
+This is not going to solve the entropy issue for architectures that have
+no CPU cycle counter, but it's not clear how (and if) that is solvable,
+and the hardware in question is largely starting to be irrelevant.  And
+by doing this we can at least avoid some of the even more contentious
+approaches (like making the entropy waiting time out in order to avoid
+the possibly unbounded waiting).
+
+Cc: Ahmed Darwish <darwish.07@gmail.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Theodore Ts'o <tytso@mit.edu>
+Cc: Nicholas Mc Guire <hofrat@opentech.at>
+Cc: Andy Lutomirski <luto@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Willy Tarreau <w@1wt.eu>
+Cc: Alexander E. Patrakov <patrakov@gmail.com>
+Cc: Lennart Poettering <mzxreary@0pointer.de>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+---
+ drivers/char/random.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 61 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 29755924aa45..8bded70230de 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1588,6 +1588,56 @@ void get_random_bytes(void *buf, int nbytes)
+ }
+ EXPORT_SYMBOL(get_random_bytes);
+ 
++
++/*
++ * Each time the timer fires, we expect that we got an unpredictable
++ * jump in the cycle counter. Even if the timer is running on another
++ * CPU, the timer activity will be touching the stack of the CPU that is
++ * generating entropy..
++ *
++ * Note that we don't re-arm the timer in the timer itself - we are
++ * happy to be scheduled away, since that just makes the load more
++ * complex, but we do not want the timer to keep ticking unless the
++ * entropy loop is running.
++ *
++ * So the re-arming always happens in the entropy loop itself.
++ */
++static void entropy_timer(unsigned long unused)
++{
++	credit_entropy_bits(&input_pool, 1);
++}
++
++/*
++ * If we have an actual cycle counter, see if we can
++ * generate enough entropy with timing noise
++ */
++static void try_to_generate_entropy(void)
++{
++	struct {
++		unsigned long now;
++		struct timer_list timer;
++	} stack;
++
++	stack.now = random_get_entropy();
++
++	/* Slow counter - or none. Don't even bother */
++	if (stack.now == random_get_entropy())
++		return;
++
++	setup_timer_on_stack(&stack.timer, entropy_timer, 0);
++	while (!crng_ready()) {
++		if (!timer_pending(&stack.timer))
++			mod_timer(&stack.timer, jiffies+1);
++		mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
++		schedule();
++		stack.now = random_get_entropy();
++	}
++
++	del_timer_sync(&stack.timer);
++	destroy_timer_on_stack(&stack.timer);
++	mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
++}
++
+ /*
+  * Wait for the urandom pool to be seeded and thus guaranteed to supply
+  * cryptographically secure random numbers. This applies to: the /dev/urandom
+@@ -1602,7 +1652,17 @@ int wait_for_random_bytes(void)
+ {
+ 	if (likely(crng_ready()))
+ 		return 0;
+-	return wait_event_interruptible(crng_init_wait, crng_ready());
++
++	do {
++		int ret;
++		ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
++		if (ret)
++			return ret > 0 ? 0 : ret;
++
++		try_to_generate_entropy();
++	} while (!crng_ready());
++
++	return 0;
+ }
+ EXPORT_SYMBOL(wait_for_random_bytes);
+ 
+-- 
+2.16.4
+

+ 90 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0001-stmmac-pci-Make-stmmac_pci_info-structure-constant.patch

@@ -0,0 +1,90 @@
+From 2ca48f47b659edbd5cf4c4e55c420ef40712ce9b Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:17:57 +0200
+Subject: [PATCH 01/18] stmmac: pci: Make stmmac_pci_info structure constant
+
+Commit c5d5287ef0f763e836bf94659b3a6080358373f1 upstream.
+
+By removing the PCI device reference from the structure and passing it
+as parameters to the interested functions, we can make quark_pci_info
+const.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 3491e98bffc5..828d276748e3 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -42,17 +42,17 @@ struct stmmac_pci_dmi_data {
+ };
+ 
+ struct stmmac_pci_info {
+-	struct pci_dev *pdev;
+-	int (*setup)(struct plat_stmmacenet_data *plat,
+-		     struct stmmac_pci_info *info);
++	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
++		     const struct stmmac_pci_info *info);
+ 	struct stmmac_pci_dmi_data *dmi;
+ };
+ 
+-static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info)
++static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
++				    const struct stmmac_pci_info *info)
+ {
+ 	const char *name = dmi_get_system_info(DMI_BOARD_NAME);
+ 	const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG);
+-	unsigned int func = PCI_FUNC(info->pdev->devfn);
++	unsigned int func = PCI_FUNC(pdev->devfn);
+ 	struct stmmac_pci_dmi_data *dmi;
+ 
+ 	/*
+@@ -96,17 +96,17 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
+ 	plat->unicast_filter_entries = 1;
+ }
+ 
+-static int quark_default_data(struct plat_stmmacenet_data *plat,
+-			      struct stmmac_pci_info *info)
++static int quark_default_data(struct pci_dev *pdev,
++			      struct plat_stmmacenet_data *plat,
++			      const struct stmmac_pci_info *info)
+ {
+-	struct pci_dev *pdev = info->pdev;
+ 	int ret;
+ 
+ 	/*
+ 	 * Refuse to load the driver and register net device if MAC controller
+ 	 * does not connect to any PHY interface.
+ 	 */
+-	ret = stmmac_pci_find_phy_addr(info);
++	ret = stmmac_pci_find_phy_addr(pdev, info);
+ 	if (ret < 0)
+ 		return ret;
+ 
+@@ -165,7 +165,7 @@ static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
+ 	{}
+ };
+ 
+-static struct stmmac_pci_info quark_pci_info = {
++static const struct stmmac_pci_info quark_pci_info = {
+ 	.setup = quark_default_data,
+ 	.dmi = quark_pci_dmi_data,
+ };
+@@ -227,9 +227,8 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ 	pci_set_master(pdev);
+ 
+ 	if (info) {
+-		info->pdev = pdev;
+ 		if (info->setup) {
+-			ret = info->setup(plat, info);
++			ret = info->setup(pdev, plat, info);
+ 			if (ret)
+ 				return ret;
+ 		}
+-- 
+2.16.4
+

+ 95 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0002-stmmac-pci-Use-stmmac_pci_info-for-all-devices.patch

@@ -0,0 +1,95 @@
+From 5222a576c02eed33b0499a7e632a56680742a885 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:17:58 +0200
+Subject: [PATCH 02/18] stmmac: pci: Use stmmac_pci_info for all devices
+
+Commit b6a4c8f013ea2dd1ead7ee14b44712189a7bc6c6 upstream.
+
+Make stmmac_default_data compatible with stmmac_pci_info.setup and use
+an info structure for all devices. This allows to make the probing more
+regular.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 36 +++++++++++++++---------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 828d276748e3..a60059032dc6 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -74,7 +74,9 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ 	return -ENODEV;
+ }
+ 
+-static void stmmac_default_data(struct plat_stmmacenet_data *plat)
++static int stmmac_default_data(struct pci_dev *pdev,
++			       struct plat_stmmacenet_data *plat,
++			       const struct stmmac_pci_info *info)
+ {
+ 	plat->bus_id = 1;
+ 	plat->phy_addr = 0;
+@@ -94,8 +96,14 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
+ 
+ 	/* Set default value for unicast filter entries */
+ 	plat->unicast_filter_entries = 1;
++
++	return 0;
+ }
+ 
++static const struct stmmac_pci_info stmmac_pci_info = {
++	.setup = stmmac_default_data,
++};
++
+ static int quark_default_data(struct pci_dev *pdev,
+ 			      struct plat_stmmacenet_data *plat,
+ 			      const struct stmmac_pci_info *info)
+@@ -226,14 +234,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ 
+ 	pci_set_master(pdev);
+ 
+-	if (info) {
+-		if (info->setup) {
+-			ret = info->setup(pdev, plat, info);
+-			if (ret)
+-				return ret;
+-		}
+-	} else
+-		stmmac_default_data(plat);
++	ret = info->setup(pdev, plat, info);
++	if (ret)
++		return ret;
+ 
+ 	pci_enable_msi(pdev);
+ 
+@@ -279,14 +282,21 @@ static int stmmac_pci_resume(struct device *dev)
+ 
+ static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume);
+ 
+-#define STMMAC_VENDOR_ID 0x700
++/* synthetic ID, no official vendor */
++#define PCI_VENDOR_ID_STMMAC 0x700
++
+ #define STMMAC_QUARK_ID  0x0937
+ #define STMMAC_DEVICE_ID 0x1108
+ 
++#define STMMAC_DEVICE(vendor_id, dev_id, info)	{	\
++	PCI_VDEVICE(vendor_id, dev_id),			\
++	.driver_data = (kernel_ulong_t)&info		\
++	}
++
+ static const struct pci_device_id stmmac_id_table[] = {
+-	{PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)},
+-	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)},
+-	{PCI_VDEVICE(INTEL, STMMAC_QUARK_ID), (kernel_ulong_t)&quark_pci_info},
++	STMMAC_DEVICE(STMMAC, STMMAC_DEVICE_ID, stmmac_pci_info),
++	STMMAC_DEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC, stmmac_pci_info),
++	STMMAC_DEVICE(INTEL, STMMAC_QUARK_ID, quark_pci_info),
+ 	{}
+ };
+ 
+-- 
+2.16.4
+

+ 61 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0003-stmmac-pci-Make-stmmac_pci_find_phy_addr-truly-gener.patch

@@ -0,0 +1,61 @@
+From d9478f26f2c620cf284f5022d3d852c47227e8da Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:17:59 +0200
+Subject: [PATCH 03/18] stmmac: pci: Make stmmac_pci_find_phy_addr truly
+ generic
+
+Commit c5f657e49c878756f21349f9e4b0f1c9631d5352 upstream.
+
+Move the special case for the early Galileo firmware into
+quark_default_setup. This allows to use stmmac_pci_find_phy_addr for
+non-quark cases.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index a60059032dc6..19cf9607618a 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -55,12 +55,8 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ 	unsigned int func = PCI_FUNC(pdev->devfn);
+ 	struct stmmac_pci_dmi_data *dmi;
+ 
+-	/*
+-	 * Galileo boards with old firmware don't support DMI. We always return
+-	 * 1 here, so at least first found MAC controller would be probed.
+-	 */
+ 	if (!name)
+-		return 1;
++		return -ENODEV;
+ 
+ 	for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) {
+ 		if (!strcmp(dmi->name, name) && dmi->func == func) {
+@@ -115,8 +111,18 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	 * does not connect to any PHY interface.
+ 	 */
+ 	ret = stmmac_pci_find_phy_addr(pdev, info);
+-	if (ret < 0)
+-		return ret;
++	if (ret < 0) {
++		/* Return error to the caller on DMI enabled boards. */
++		if (dmi_get_system_info(DMI_BOARD_NAME))
++			return ret;
++
++		/*
++		 * Galileo boards with old firmware don't support DMI. We always
++		 * use 1 here as PHY address, so at least the first found MAC
++		 * controller would be probed.
++		 */
++		ret = 1;
++	}
+ 
+ 	plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
+ 	plat->phy_addr = ret;
+-- 
+2.16.4
+

+ 165 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0004-stmmac-pci-Select-quark_pci_dmi_data-from-quark_defa.patch

@@ -0,0 +1,165 @@
+From 0747f34d4be27952be866461c97d386c29000817 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:18:00 +0200
+Subject: [PATCH 04/18] stmmac: pci: Select quark_pci_dmi_data from
+ quark_default_data
+
+Commit 7bc519b3ea04026877242328d2fe73cc8e6102bd upsteam.
+
+No need to carry this reference in stmmac_pci_info - the Quark-specific
+setup handler knows that it needs to use the Quark-specific DMI table.
+This also allows to drop the stmmac_pci_info reference from the setup
+handler parameter list.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 83 +++++++++++-------------
+ 1 file changed, 39 insertions(+), 44 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 19cf9607618a..9fe6368738ec 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -42,13 +42,11 @@ struct stmmac_pci_dmi_data {
+ };
+ 
+ struct stmmac_pci_info {
+-	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat,
+-		     const struct stmmac_pci_info *info);
+-	struct stmmac_pci_dmi_data *dmi;
++	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
+ };
+ 
+ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+-				    const struct stmmac_pci_info *info)
++				    struct stmmac_pci_dmi_data *dmi_data)
+ {
+ 	const char *name = dmi_get_system_info(DMI_BOARD_NAME);
+ 	const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG);
+@@ -58,7 +56,7 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ 	if (!name)
+ 		return -ENODEV;
+ 
+-	for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) {
++	for (dmi = dmi_data; dmi->name && *dmi->name; dmi++) {
+ 		if (!strcmp(dmi->name, name) && dmi->func == func) {
+ 			/* If asset tag is provided, match on it as well. */
+ 			if (dmi->asset_tag && strcmp(dmi->asset_tag, asset_tag))
+@@ -71,8 +69,7 @@ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+ }
+ 
+ static int stmmac_default_data(struct pci_dev *pdev,
+-			       struct plat_stmmacenet_data *plat,
+-			       const struct stmmac_pci_info *info)
++			       struct plat_stmmacenet_data *plat)
+ {
+ 	plat->bus_id = 1;
+ 	plat->phy_addr = 0;
+@@ -100,9 +97,40 @@ static const struct stmmac_pci_info stmmac_pci_info = {
+ 	.setup = stmmac_default_data,
+ };
+ 
++static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
++	{
++		.name = "Galileo",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "GalileoGen2",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "SIMATIC IOT2000",
++		.asset_tag = "6ES7647-0AA00-0YA2",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "SIMATIC IOT2000",
++		.asset_tag = "6ES7647-0AA00-1YA2",
++		.func = 6,
++		.phy_addr = 1,
++	},
++	{
++		.name = "SIMATIC IOT2000",
++		.asset_tag = "6ES7647-0AA00-1YA2",
++		.func = 7,
++		.phy_addr = 1,
++	},
++	{}
++};
++
+ static int quark_default_data(struct pci_dev *pdev,
+-			      struct plat_stmmacenet_data *plat,
+-			      const struct stmmac_pci_info *info)
++			      struct plat_stmmacenet_data *plat)
+ {
+ 	int ret;
+ 
+@@ -110,7 +138,7 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	 * Refuse to load the driver and register net device if MAC controller
+ 	 * does not connect to any PHY interface.
+ 	 */
+-	ret = stmmac_pci_find_phy_addr(pdev, info);
++	ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi_data);
+ 	if (ret < 0) {
+ 		/* Return error to the caller on DMI enabled boards. */
+ 		if (dmi_get_system_info(DMI_BOARD_NAME))
+@@ -147,41 +175,8 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	return 0;
+ }
+ 
+-static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
+-	{
+-		.name = "Galileo",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "GalileoGen2",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-0YA2",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 6,
+-		.phy_addr = 1,
+-	},
+-	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 7,
+-		.phy_addr = 1,
+-	},
+-	{}
+-};
+-
+ static const struct stmmac_pci_info quark_pci_info = {
+ 	.setup = quark_default_data,
+-	.dmi = quark_pci_dmi_data,
+ };
+ 
+ /**
+@@ -240,7 +235,7 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+ 
+ 	pci_set_master(pdev);
+ 
+-	ret = info->setup(pdev, plat, info);
++	ret = info->setup(pdev, plat);
+ 	if (ret)
+ 		return ret;
+ 
+-- 
+2.16.4
+

+ 167 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0005-stmmac-pci-Use-dmi_system_id-table-for-retrieving-PH.patch

@@ -0,0 +1,167 @@
+From 1b2894107ad2d9de45402ecc4ffe14f075a08bbc Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 22 Jun 2017 08:18:01 +0200
+Subject: [PATCH 05/18] stmmac: pci: Use dmi_system_id table for retrieving PHY
+ addresses
+
+Commit 8d78b69091845386b6096f3adae98f28b9bf96ed upstream.
+
+Avoids reimplementation of DMI matching in stmmac_pci_find_phy_addr.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 97 ++++++++++++++++--------
+ 1 file changed, 64 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 9fe6368738ec..279a1355d75f 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -34,36 +34,39 @@
+  * negative value of the address means that MAC controller is not connected
+  * with PHY.
+  */
+-struct stmmac_pci_dmi_data {
+-	const char *name;
+-	const char *asset_tag;
++struct stmmac_pci_func_data {
+ 	unsigned int func;
+ 	int phy_addr;
+ };
+ 
++struct stmmac_pci_dmi_data {
++	const struct stmmac_pci_func_data *func;
++	size_t nfuncs;
++};
++
+ struct stmmac_pci_info {
+ 	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
+ };
+ 
+ static int stmmac_pci_find_phy_addr(struct pci_dev *pdev,
+-				    struct stmmac_pci_dmi_data *dmi_data)
++				    const struct dmi_system_id *dmi_list)
+ {
+-	const char *name = dmi_get_system_info(DMI_BOARD_NAME);
+-	const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG);
+-	unsigned int func = PCI_FUNC(pdev->devfn);
+-	struct stmmac_pci_dmi_data *dmi;
+-
+-	if (!name)
++	const struct stmmac_pci_func_data *func_data;
++	const struct stmmac_pci_dmi_data *dmi_data;
++	const struct dmi_system_id *dmi_id;
++	int func = PCI_FUNC(pdev->devfn);
++	size_t n;
++
++	dmi_id = dmi_first_match(dmi_list);
++	if (!dmi_id)
+ 		return -ENODEV;
+ 
+-	for (dmi = dmi_data; dmi->name && *dmi->name; dmi++) {
+-		if (!strcmp(dmi->name, name) && dmi->func == func) {
+-			/* If asset tag is provided, match on it as well. */
+-			if (dmi->asset_tag && strcmp(dmi->asset_tag, asset_tag))
+-				continue;
+-			return dmi->phy_addr;
+-		}
+-	}
++	dmi_data = dmi_id->driver_data;
++	func_data = dmi_data->func;
++
++	for (n = 0; n < dmi_data->nfuncs; n++, func_data++)
++		if (func_data->func == func)
++			return func_data->phy_addr;
+ 
+ 	return -ENODEV;
+ }
+@@ -97,34 +100,62 @@ static const struct stmmac_pci_info stmmac_pci_info = {
+ 	.setup = stmmac_default_data,
+ };
+ 
+-static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = {
++static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = {
+ 	{
+-		.name = "Galileo",
+ 		.func = 6,
+ 		.phy_addr = 1,
+ 	},
++};
++
++static const struct stmmac_pci_dmi_data galileo_stmmac_dmi_data = {
++	.func = galileo_stmmac_func_data,
++	.nfuncs = ARRAY_SIZE(galileo_stmmac_func_data),
++};
++
++static const struct stmmac_pci_func_data iot2040_stmmac_func_data[] = {
+ 	{
+-		.name = "GalileoGen2",
+ 		.func = 6,
+ 		.phy_addr = 1,
+ 	},
+ 	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-0YA2",
+-		.func = 6,
++		.func = 7,
+ 		.phy_addr = 1,
+ 	},
++};
++
++static const struct stmmac_pci_dmi_data iot2040_stmmac_dmi_data = {
++	.func = iot2040_stmmac_func_data,
++	.nfuncs = ARRAY_SIZE(iot2040_stmmac_func_data),
++};
++
++static const struct dmi_system_id quark_pci_dmi[] = {
+ 	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 6,
+-		.phy_addr = 1,
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"),
++		},
++		.driver_data = (void *)&galileo_stmmac_dmi_data,
+ 	},
+ 	{
+-		.name = "SIMATIC IOT2000",
+-		.asset_tag = "6ES7647-0AA00-1YA2",
+-		.func = 7,
+-		.phy_addr = 1,
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
++		},
++		.driver_data = (void *)&galileo_stmmac_dmi_data,
++	},
++	{
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
++			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
++					"6ES7647-0AA00-0YA2"),
++		},
++		.driver_data = (void *)&galileo_stmmac_dmi_data,
++	},
++	{
++		.matches = {
++			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
++			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
++					"6ES7647-0AA00-1YA2"),
++		},
++		.driver_data = (void *)&iot2040_stmmac_dmi_data,
+ 	},
+ 	{}
+ };
+@@ -138,7 +169,7 @@ static int quark_default_data(struct pci_dev *pdev,
+ 	 * Refuse to load the driver and register net device if MAC controller
+ 	 * does not connect to any PHY interface.
+ 	 */
+-	ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi_data);
++	ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi);
+ 	if (ret < 0) {
+ 		/* Return error to the caller on DMI enabled boards. */
+ 		if (dmi_get_system_info(DMI_BOARD_NAME))
+-- 
+2.16.4
+

+ 47 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0006-stmmac-pci-Adjust-IOT2000-matching.patch

@@ -0,0 +1,47 @@
+From e3ba8c4f83c6c206a20e4645a37612b1e10580c6 Mon Sep 17 00:00:00 2001
+From: Su Bao Cheng <baocheng.su@siemens.com>
+Date: Fri, 12 Oct 2018 15:08:11 +0200
+Subject: [PATCH 06/18] stmmac: pci: Adjust IOT2000 matching
+
+Since there are more IOT2040 variants with identical hardware but
+different asset tags, the asset tag matching should be adjusted to
+support them.
+
+For the board name "SIMATIC IOT2000", currently there are 2 types of
+hardware, IOT2020 and IOT2040. The IOT2020 is identified by its unique
+asset tag. Match on it first. If we then match on the board name only,
+we will catch all IOT2040 variants. In the future there will be no other
+devices with the "SIMATIC IOT2000" DMI board name but different
+hardware.
+
+Signed-off-by: Su Bao Cheng <baocheng.su@siemens.com>
+Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+index 279a1355d75f..ac733d4d3ed4 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+@@ -149,11 +149,15 @@ static const struct dmi_system_id quark_pci_dmi[] = {
+ 		},
+ 		.driver_data = (void *)&galileo_stmmac_dmi_data,
+ 	},
++	/*
++	 * There are 2 types of SIMATIC IOT2000: IOT2020 and IOT2040.
++	 * The asset tag "6ES7647-0AA00-0YA2" is only for IOT2020 which
++	 * has only one pci network device while other asset tags are
++	 * for IOT2040 which has two.
++	 */
+ 	{
+ 		.matches = {
+ 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-1YA2"),
+ 		},
+ 		.driver_data = (void *)&iot2040_stmmac_dmi_data,
+ 	},
+-- 
+2.16.4
+

+ 44 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0007-serial-8250_exar-Adjust-IOT2000-matching.patch

@@ -0,0 +1,44 @@
+From df74e188ffc38176d4caba969e104d2ab2e4e609 Mon Sep 17 00:00:00 2001
+From: Su Bao Cheng <baocheng.su@siemens.com>
+Date: Fri, 12 Oct 2018 15:12:37 +0200
+Subject: [PATCH 07/18] serial: 8250_exar: Adjust IOT2000 matching
+
+Since there are more IOT2040 variants with identical hardware but
+different asset tags, the asset tag matching should be adjusted to
+support them.
+
+As only the IOT2040 variants have the Exar chip on board, matching on
+their board name is enough. In the future there will be no other devices
+with the "SIMATIC IOT2000" DMI board name but different hardware.
+
+Signed-off-by: Su Bao Cheng <baocheng.su@siemens.com>
+Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/tty/serial/8250/8250_exar.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
+index be82707d6cb8..3eb3a7674a0f 100644
+--- a/drivers/tty/serial/8250/8250_exar.c
++++ b/drivers/tty/serial/8250/8250_exar.c
+@@ -338,12 +338,15 @@ static const struct exar8250_platform iot2040_platform = {
+ 	.register_gpio = iot2040_register_gpio,
+ };
+ 
++/*
++ * For SIMATIC IOT2000, only IOT2040 and its variants have the Exar device,
++ * IOT2020 doesn't have. Therefore it is sufficient to match on the common
++ * board name after the device was found.
++ */
+ static const struct dmi_system_id exar_platforms[] = {
+ 	{
+ 		.matches = {
+ 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-1YA2"),
+ 		},
+ 		.driver_data = (void *)&iot2040_platform,
+ 	},
+-- 
+2.16.4
+

+ 45 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0008-mfd-intel_quark_i2c_gpio-Adjust-IOT2000-matching.patch

@@ -0,0 +1,45 @@
+From 6e378b789ebcfcdc4ae957b25f1ac6eb2ef64edc Mon Sep 17 00:00:00 2001
+From: Su Bao Cheng <baocheng.su@siemens.com>
+Date: Fri, 12 Oct 2018 15:05:07 +0200
+Subject: [PATCH 08/18] mfd: intel_quark_i2c_gpio: Adjust IOT2000 matching
+
+Since there are more IOT2040 variants with identical hardware but
+different asset tags, the asset tag matching should be adjusted to
+support them.
+
+For the board name "SIMATIC IOT2000", currently there are 2 types of
+hardware, IOT2020 and IOT2040. Both are identical regarding the
+intel_quark_i2c_gpio. In the future there will be no other devices with
+the "SIMATIC IOT2000" DMI board name but different hardware. So remove
+the asset tag matching from this driver.
+
+Signed-off-by: Su Bao Cheng <baocheng.su@siemens.com>
+Reviewed-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/mfd/intel_quark_i2c_gpio.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c
+index 1c09604978d3..ad70a058bea8 100644
+--- a/drivers/mfd/intel_quark_i2c_gpio.c
++++ b/drivers/mfd/intel_quark_i2c_gpio.c
+@@ -76,16 +76,6 @@ static const struct dmi_system_id dmi_platform_info[] = {
+ 	{
+ 		.matches = {
+ 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-0YA2"),
+-		},
+-		.driver_data = (void *)400000,
+-	},
+-	{
+-		.matches = {
+-			DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
+-			DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG,
+-					"6ES7647-0AA00-1YA2"),
+ 		},
+ 		.driver_data = (void *)400000,
+ 	},
+-- 
+2.16.4
+

+ 86 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0009-gpio-sch-use-gpiochip-data-pointer.patch

@@ -0,0 +1,86 @@
+From cf3d1330c71d47c4cdb9268f68d2ee5931890d93 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Mon, 7 Dec 2015 14:21:49 +0100
+Subject: [PATCH 09/18] gpio: sch: use gpiochip data pointer
+
+This makes the driver use the data pointer added to the gpio_chip
+to store a pointer to the state container instead of relying on
+container_of().
+
+Cc: Chang Rebecca Swee Fun <rebecca.swee.fun.chang@intel.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-sch.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index b72906f5b999..23907fc080a3 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -41,8 +41,6 @@ struct sch_gpio {
+ 	unsigned short resume_base;
+ };
+ 
+-#define to_sch_gpio(gc)	container_of(gc, struct sch_gpio, chip)
+-
+ static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+ 				unsigned reg)
+ {
+@@ -65,7 +63,7 @@ static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
+ 
+ static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -80,7 +78,7 @@ static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
+ static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
+ 			     int val)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -97,7 +95,7 @@ static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
+ 
+ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+ 	sch_gpio_reg_set(gc, gpio_num, GIO, 1);
+@@ -112,7 +110,7 @@ static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+ 
+ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+ 	sch_gpio_reg_set(gc, gpio_num, GLV, val);
+@@ -122,7 +120,7 @@ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 				  int val)
+ {
+-	struct sch_gpio *sch = to_sch_gpio(gc);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+ 	sch_gpio_reg_set(gc, gpio_num, GIO, 0);
+@@ -217,7 +215,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 
+ 	platform_set_drvdata(pdev, sch);
+ 
+-	return gpiochip_add(&sch->chip);
++	return gpiochip_add_data(&sch->chip, sch);
+ }
+ 
+ static int sch_gpio_remove(struct platform_device *pdev)
+-- 
+2.16.4
+

+ 46 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0010-gpio-sch-Use-devm_gpiochip_add_data-for-gpio-registr.patch

@@ -0,0 +1,46 @@
+From 6a930e4d040061edcaf0c3e3e43a10acdc20f09c Mon Sep 17 00:00:00 2001
+From: Laxman Dewangan <ldewangan@nvidia.com>
+Date: Mon, 22 Feb 2016 17:43:28 +0530
+Subject: [PATCH 10/18] gpio: sch: Use devm_gpiochip_add_data() for gpio
+ registration
+
+Use devm_gpiochip_add_data() for GPIO registration and remove the
+need of driver callback .remove.
+
+Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
+---
+ drivers/gpio/gpio-sch.c | 11 +----------
+ 1 file changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 23907fc080a3..bbf9b2a34da8 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -215,15 +215,7 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 
+ 	platform_set_drvdata(pdev, sch);
+ 
+-	return gpiochip_add_data(&sch->chip, sch);
+-}
+-
+-static int sch_gpio_remove(struct platform_device *pdev)
+-{
+-	struct sch_gpio *sch = platform_get_drvdata(pdev);
+-
+-	gpiochip_remove(&sch->chip);
+-	return 0;
++	return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
+ }
+ 
+ static struct platform_driver sch_gpio_driver = {
+@@ -231,7 +223,6 @@ static struct platform_driver sch_gpio_driver = {
+ 		.name = "sch_gpio",
+ 	},
+ 	.probe		= sch_gpio_probe,
+-	.remove		= sch_gpio_remove,
+ };
+ 
+ module_platform_driver(sch_gpio_driver);
+-- 
+2.16.4
+

+ 114 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0011-gpio-sch-Fix-Oops-on-module-load-on-Asus-Eee-PC-1201.patch

@@ -0,0 +1,114 @@
+From 9fd1991d762b6092f462f3cc551b2d7df3009b52 Mon Sep 17 00:00:00 2001
+From: Colin Pitrat <colin.pitrat@gmail.com>
+Date: Sat, 18 Jun 2016 19:05:04 +0100
+Subject: [PATCH 11/18] gpio: sch: Fix Oops on module load on Asus Eee PC 1201
+
+This fixes the issue descirbe in bug 117531
+(https://bugzilla.kernel.org/show_bug.cgi?id=117531).
+It's a regression introduced in linux 4.5 that causes a Oops at load of
+gpio_sch and prevents powering off the computer.
+
+The issue is that sch_gpio_reg_set is called in sch_gpio_probe before
+gpio_chip data is initialized with the pointer to the sch_gpio struct. As
+sch_gpio_reg_set calls gpiochip_get_data, it returns NULL which causes
+the Oops.
+
+The patch follows Mika's advice (https://lkml.org/lkml/2016/5/9/61) and
+consists in modifying sch_gpio_reg_get and sch_gpio_reg_set to take a
+sch_gpio struct directly instead of a gpio_chip, which avoids the call to
+gpiochip_get_data.
+
+Thanks Mika for your patience with me :-)
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Colin Pitrat <colin.pitrat@gmail.com>
+Acked-by: Alexandre Courbot <acourbot@nvidia.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-sch.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index bbf9b2a34da8..5f72b177fc80 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -61,9 +61,8 @@ static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
+ 	return gpio % 8;
+ }
+ 
+-static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
++static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned gpio, unsigned reg)
+ {
+-	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -75,10 +74,9 @@ static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
+ 	return reg_val;
+ }
+ 
+-static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
++static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned gpio, unsigned reg,
+ 			     int val)
+ {
+-	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 	unsigned short offset, bit;
+ 	u8 reg_val;
+ 
+@@ -98,14 +96,15 @@ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+-	sch_gpio_reg_set(gc, gpio_num, GIO, 1);
++	sch_gpio_reg_set(sch, gpio_num, GIO, 1);
+ 	spin_unlock(&sch->lock);
+ 	return 0;
+ }
+ 
+ static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+ {
+-	return sch_gpio_reg_get(gc, gpio_num, GLV);
++	struct sch_gpio *sch = gpiochip_get_data(gc);
++	return sch_gpio_reg_get(sch, gpio_num, GLV);
+ }
+ 
+ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+@@ -113,7 +112,7 @@ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+-	sch_gpio_reg_set(gc, gpio_num, GLV, val);
++	sch_gpio_reg_set(sch, gpio_num, GLV, val);
+ 	spin_unlock(&sch->lock);
+ }
+ 
+@@ -123,7 +122,7 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
+ 
+ 	spin_lock(&sch->lock);
+-	sch_gpio_reg_set(gc, gpio_num, GIO, 0);
++	sch_gpio_reg_set(sch, gpio_num, GIO, 0);
+ 	spin_unlock(&sch->lock);
+ 
+ 	/*
+@@ -182,13 +181,13 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 		 * GPIO7 is configured by the CMC as SLPIOVR
+ 		 * Enable GPIO[9:8] core powered gpios explicitly
+ 		 */
+-		sch_gpio_reg_set(&sch->chip, 8, GEN, 1);
+-		sch_gpio_reg_set(&sch->chip, 9, GEN, 1);
++		sch_gpio_reg_set(sch, 8, GEN, 1);
++		sch_gpio_reg_set(sch, 9, GEN, 1);
+ 		/*
+ 		 * SUS_GPIO[2:0] enabled by default
+ 		 * Enable SUS_GPIO3 resume powered gpio explicitly
+ 		 */
+-		sch_gpio_reg_set(&sch->chip, 13, GEN, 1);
++		sch_gpio_reg_set(sch, 13, GEN, 1);
+ 		break;
+ 
+ 	case PCI_DEVICE_ID_INTEL_ITC_LPC:
+-- 
+2.16.4
+

+ 45 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0012-gpio-sch-Implement-.get_direction.patch

@@ -0,0 +1,45 @@
+From 8fec046f568e2b946abd55a82d5417717a115b21 Mon Sep 17 00:00:00 2001
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Wed, 27 Jun 2018 10:39:31 +0200
+Subject: [PATCH 12/18] gpio: sch: Implement .get_direction()
+
+It's pretty simple to implement the .get_direction() for this
+chip, so let's just do it.
+
+Cc: Denis Turischev <denis.turischev@compulab.co.il>
+Cc: Daniel Krueger <daniel.krueger@systec-electronic.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-sch.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 5f72b177fc80..6715828c3940 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -138,6 +138,13 @@ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 	return 0;
+ }
+ 
++static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num)
++{
++	struct sch_gpio *sch = gpiochip_get_data(gc);
++
++	return sch_gpio_reg_get(sch, gpio_num, GIO);
++}
++
+ static struct gpio_chip sch_gpio_chip = {
+ 	.label			= "sch_gpio",
+ 	.owner			= THIS_MODULE,
+@@ -145,6 +152,7 @@ static struct gpio_chip sch_gpio_chip = {
+ 	.get			= sch_gpio_get,
+ 	.direction_output	= sch_gpio_direction_out,
+ 	.set			= sch_gpio_set,
++	.get_direction		= sch_gpio_get_direction,
+ };
+ 
+ static int sch_gpio_probe(struct platform_device *pdev)
+-- 
+2.16.4
+

+ 230 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0013-gpio-sch-Add-interrupt-support.patch

@@ -0,0 +1,230 @@
+From 53c90b014f54743b5a2180f90b90b1f198535583 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Wed, 17 Apr 2019 22:26:22 +0200
+Subject: [PATCH 13/18] gpio: sch: Add interrupt support
+
+Validated on the Quark platform, this adds interrupt support on rising
+and/or falling edges.
+
+Backported from upstream, skipping clean roll-back or errors due to some
+missing devm_* services.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpio-sch.c | 140 +++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 133 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
+index 6715828c3940..1d1dadebc8c1 100644
+--- a/drivers/gpio/gpio-sch.c
++++ b/drivers/gpio/gpio-sch.c
+@@ -32,6 +32,10 @@
+ #define GEN	0x00
+ #define GIO	0x04
+ #define GLV	0x08
++#define GTPE	0x0c
++#define GTNE	0x10
++#define GGPE	0x14
++#define GTS	0x1c
+ 
+ struct sch_gpio {
+ 	struct gpio_chip chip;
+@@ -39,6 +43,7 @@ struct sch_gpio {
+ 	unsigned short iobase;
+ 	unsigned short core_base;
+ 	unsigned short resume_base;
++	int irq_base;
+ };
+ 
+ static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+@@ -94,10 +99,11 @@ static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned gpio, unsigned reg,
+ static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+ {
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
++	unsigned long flags;
+ 
+-	spin_lock(&sch->lock);
++	spin_lock_irqsave(&sch->lock, flags);
+ 	sch_gpio_reg_set(sch, gpio_num, GIO, 1);
+-	spin_unlock(&sch->lock);
++	spin_unlock_irqrestore(&sch->lock, flags);
+ 	return 0;
+ }
+ 
+@@ -110,20 +116,22 @@ static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+ static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+ {
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
++	unsigned long flags;
+ 
+-	spin_lock(&sch->lock);
++	spin_lock_irqsave(&sch->lock, flags);
+ 	sch_gpio_reg_set(sch, gpio_num, GLV, val);
+-	spin_unlock(&sch->lock);
++	spin_unlock_irqrestore(&sch->lock, flags);
+ }
+ 
+ static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+ 				  int val)
+ {
+ 	struct sch_gpio *sch = gpiochip_get_data(gc);
++	unsigned long flags;
+ 
+-	spin_lock(&sch->lock);
++	spin_lock_irqsave(&sch->lock, flags);
+ 	sch_gpio_reg_set(sch, gpio_num, GIO, 0);
+-	spin_unlock(&sch->lock);
++	spin_unlock_irqrestore(&sch->lock, flags);
+ 
+ 	/*
+ 	 * according to the datasheet, writing to the level register has no
+@@ -145,6 +153,12 @@ static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned gpio_num)
+ 	return sch_gpio_reg_get(sch, gpio_num, GIO);
+ }
+ 
++static int sch_gpio_to_irq(struct gpio_chip *gpio, unsigned int offset)
++{
++	struct sch_gpio *sch = gpiochip_get_data(gpio);
++	return sch->irq_base + offset;
++}
++
+ static struct gpio_chip sch_gpio_chip = {
+ 	.label			= "sch_gpio",
+ 	.owner			= THIS_MODULE,
+@@ -153,12 +167,96 @@ static struct gpio_chip sch_gpio_chip = {
+ 	.direction_output	= sch_gpio_direction_out,
+ 	.set			= sch_gpio_set,
+ 	.get_direction		= sch_gpio_get_direction,
++	.to_irq			= sch_gpio_to_irq,
+ };
+ 
++static u32 sch_sci_handler(void *context)
++{
++	struct sch_gpio *sch = context;
++	unsigned long core_status, resume_status;
++	unsigned int resume_gpios, offset;
++
++	core_status = inl(sch->iobase + GTS);
++	resume_status = inl(sch->iobase + GTS + 0x20);
++
++	if (core_status == 0 && resume_status == 0)
++		return ACPI_INTERRUPT_NOT_HANDLED;
++
++	for_each_set_bit(offset, &core_status, sch->resume_base)
++		generic_handle_irq(sch->irq_base + offset);
++
++	resume_gpios = sch->chip.ngpio - sch->resume_base;
++	for_each_set_bit(offset, &resume_status, resume_gpios)
++		generic_handle_irq(sch->irq_base + sch->resume_base + offset);
++
++	outl(core_status, sch->iobase + GTS);
++	outl(resume_status, sch->iobase + GTS + 0x20);
++
++	return ACPI_INTERRUPT_HANDLED;
++}
++
++static int sch_irq_type(struct irq_data *d, unsigned int type)
++{
++	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
++	struct sch_gpio *sch = gc->private;
++	unsigned int gpio_num = d->irq - sch->irq_base;
++	unsigned long flags;
++	int rising = 0;
++	int falling = 0;
++
++	switch (type & IRQ_TYPE_SENSE_MASK) {
++	case IRQ_TYPE_EDGE_RISING:
++		rising = 1;
++		break;
++	case IRQ_TYPE_EDGE_FALLING:
++		falling = 1;
++		break;
++	case IRQ_TYPE_EDGE_BOTH:
++		rising = 1;
++		falling = 1;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	spin_lock_irqsave(&sch->lock, flags);
++	sch_gpio_reg_set(sch, gpio_num, GTPE, rising);
++	sch_gpio_reg_set(sch, gpio_num, GTNE, falling);
++	spin_unlock_irqrestore(&sch->lock, flags);
++
++	return 0;
++}
++
++static void sch_irq_set_enable(struct irq_data *d, int val)
++{
++	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
++	struct sch_gpio *sch = gc->private;
++	unsigned int gpio_num = d->irq - sch->irq_base;
++	unsigned long flags;
++
++	spin_lock_irqsave(&sch->lock, flags);
++	sch_gpio_reg_set(sch, gpio_num, GGPE, val);
++	spin_unlock_irqrestore(&sch->lock, flags);
++}
++
++static void sch_irq_mask(struct irq_data *d)
++{
++	sch_irq_set_enable(d, 0);
++}
++
++static void sch_irq_unmask(struct irq_data *d)
++{
++	sch_irq_set_enable(d, 1);
++}
++
+ static int sch_gpio_probe(struct platform_device *pdev)
+ {
++	struct irq_chip_generic *gc;
++	struct irq_chip_type *ct;
+ 	struct sch_gpio *sch;
+ 	struct resource *res;
++	acpi_status status;
++	int irq_base, ret;
+ 
+ 	sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
+ 	if (!sch)
+@@ -222,7 +320,35 @@ static int sch_gpio_probe(struct platform_device *pdev)
+ 
+ 	platform_set_drvdata(pdev, sch);
+ 
+-	return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
++	ret = devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
++	if (ret)
++		return ret;
++
++	irq_base = irq_alloc_descs(-1, 0, sch->chip.ngpio, NUMA_NO_NODE);
++	if (irq_base < 0)
++		return irq_base;
++	sch->irq_base = irq_base;
++
++	gc = irq_alloc_generic_chip("sch_gpio", 1, irq_base,
++				    NULL, handle_simple_irq);
++	if (!gc)
++		return -ENOMEM;
++
++	gc->private = sch;
++	ct = gc->chip_types;
++
++	ct->chip.irq_mask = sch_irq_mask;
++	ct->chip.irq_unmask = sch_irq_unmask;
++	ct->chip.irq_set_type = sch_irq_type;
++
++	irq_setup_generic_chip(gc, IRQ_MSK(sch->chip.ngpio),
++			       0, IRQ_NOREQUEST | IRQ_NOPROBE, 0);
++
++	status = acpi_install_sci_handler(sch_sci_handler, sch);
++	if (ACPI_FAILURE(status))
++		return -EINVAL;
++
++	return 0;
+ }
+ 
+ static struct platform_driver sch_gpio_driver = {
+-- 
+2.16.4
+

+ 44 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0014-iot2000-hack-Work-around-DSDT-mistake.patch

@@ -0,0 +1,44 @@
+From f43a54ec8a8b5f070d4b1b59f3d47dc03f74ad32 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 25 May 2017 11:09:42 +0200
+Subject: [PATCH 14/18] iot2000-hack: Work around DSDT mistake
+
+Until we have a new firmware revision, fix up the incorrect GPIO
+interrupt pin in software.
+
+Nothing for upstream.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpiolib-acpi.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
+index 16a7b6816744..304855b3ecb8 100644
+--- a/drivers/gpio/gpiolib-acpi.c
++++ b/drivers/gpio/gpiolib-acpi.c
+@@ -10,6 +10,7 @@
+  * published by the Free Software Foundation.
+  */
+ 
++#include <linux/dmi.h>
+ #include <linux/errno.h>
+ #include <linux/gpio.h>
+ #include <linux/gpio/consumer.h>
+@@ -408,6 +409,13 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
+ 		if (pin_index >= agpio->pin_table_length)
+ 			return 1;
+ 
++		if (!strcmp(dmi_get_system_info(DMI_BOARD_NAME),
++			    "SIMATIC IOT2000") &&
++		    !strcmp(agpio->resource_source.string_ptr,
++			    "\\_SB.PCI0.GIP0.GPO") &&
++		    agpio->pin_table[pin_index] == 9)
++			agpio->pin_table[pin_index] = 1;
++
+ 		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
+ 					      agpio->pin_table[pin_index]);
+ 		lookup->info.gpioint =
+-- 
+2.16.4
+

+ 42 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0015-iot2000-hack-Adjust-pca9685-gpio-base-for-legacy-com.patch

@@ -0,0 +1,42 @@
+From 88f2d0ccdee1f1890af0d049c60fe24f6c6eb048 Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Thu, 25 May 2017 13:05:12 +0200
+Subject: [PATCH 15/18] iot2000-hack: Adjust pca9685-gpio base for legacy
+ compatibility
+
+mraa and the Arduino runtime expect this.
+
+Not for upstream.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/pwm/pwm-pca9685.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
+index d2b92e940e38..611b9263a896 100644
+--- a/drivers/pwm/pwm-pca9685.c
++++ b/drivers/pwm/pwm-pca9685.c
+@@ -19,6 +19,7 @@
+  * this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+ 
++#include <linux/dmi.h>
+ #include <linux/acpi.h>
+ #include <linux/gpio/driver.h>
+ #include <linux/i2c.h>
+@@ -222,7 +223,10 @@ static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
+ 	pca->gpio.direction_output = pca9685_pwm_gpio_direction_output;
+ 	pca->gpio.get = pca9685_pwm_gpio_get;
+ 	pca->gpio.set = pca9685_pwm_gpio_set;
+-	pca->gpio.base = -1;
++	if (!strcmp(dmi_get_system_info(DMI_BOARD_NAME), "SIMATIC IOT2000"))
++		pca->gpio.base = 64;
++	else
++		pca->gpio.base = -1;
+ 	pca->gpio.ngpio = PCA9685_MAXCHAN;
+ 	pca->gpio.can_sleep = true;
+ 
+-- 
+2.16.4
+

+ 99 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0016-iot2000-hack-gpio-pca953x-provide-GPIO-base-based-on.patch

@@ -0,0 +1,99 @@
+From 5c102aea3f4ffea811eec719edd638fc7888e9c3 Mon Sep 17 00:00:00 2001
+From: Yong Li <sdliyong@gmail.com>
+Date: Thu, 31 Mar 2016 15:33:08 +0800
+Subject: [PATCH 16/18] iot2000-hack: gpio: pca953x: provide GPIO base based on
+ _UID
+
+Custom kernel for Intel Galileo Gen2 provides and moreover libmraa relies on
+the continuous GPIO space. To do such we have to configure GPIO base per each
+GPIO expander. The only value we can use is the ACPI _UID.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+Upstream-status: Inappropriate, custom code for legacy userspace
+Signed-off-by: Saul Wold <sgw@linux.intel.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Yong Li <sdliyong@gmail.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpio-pca953x.c | 44 +++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 37 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index b45ba6be69ef..8b467c0db1cb 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -82,12 +82,6 @@ static const struct i2c_device_id pca953x_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, pca953x_id);
+ 
+-static const struct acpi_device_id pca953x_acpi_ids[] = {
+-	{ "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, },
+-	{ }
+-};
+-MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
+-
+ #define MAX_BANK 5
+ #define BANK_SZ 8
+ 
+@@ -119,6 +113,35 @@ static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
+ 	return container_of(gc, struct pca953x_chip, gpio_chip);
+ }
+ 
++struct pca953x_info {
++	kernel_ulong_t driver_data;
++	void (*setup)(struct pca953x_chip *chip);
++};
++
++static void pca953x_setup_int3491(struct pca953x_chip *chip)
++{
++	struct acpi_device *adev = ACPI_COMPANION(&chip->client->dev);
++	unsigned int uid;
++
++	if (kstrtouint(acpi_device_uid(adev), 0, &uid) || !uid--)
++		return;
++
++	chip->gpio_start = 8 /* sch_gpio */ +
++			   8 /* gpio-dwapb */ +
++			  16 /* pca9535 */ * uid;
++}
++
++static const struct pca953x_info pca953x_info_int3491 = {
++	.driver_data = 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL,
++	.setup = pca953x_setup_int3491,
++};
++
++static const struct acpi_device_id pca953x_acpi_ids[] = {
++	{ "INT3491",  (kernel_ulong_t)&pca953x_info_int3491 },
++	{ }
++};
++MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
++
+ static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
+ 				int off)
+ {
+@@ -731,12 +754,19 @@ static int pca953x_probe(struct i2c_client *client,
+ 		chip->driver_data = id->driver_data;
+ 	} else {
+ 		const struct acpi_device_id *id;
++		const struct pca953x_info *info;
+ 
+ 		id = acpi_match_device(pca953x_acpi_ids, &client->dev);
+ 		if (!id)
+ 			return -ENODEV;
+ 
+-		chip->driver_data = id->driver_data;
++		info = (struct pca953x_info *)id->driver_data;
++		if (!info)
++			return -ENODEV;
++
++		chip->driver_data = info->driver_data;
++		if (info->setup)
++			info->setup(chip);
+ 	}
+ 
+ 	chip->chip_type = PCA_CHIP_TYPE(chip->driver_data);
+-- 
+2.16.4
+

+ 334 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0017-iot2000-hack-gpio-pca953x-add-drive-property.patch

@@ -0,0 +1,334 @@
+From a66a980a3520859c1a01fc65f76c4f2abd2a2eed Mon Sep 17 00:00:00 2001
+From: Yong Li <sdliyong@gmail.com>
+Date: Thu, 31 Mar 2016 15:33:09 +0800
+Subject: [PATCH 17/18] iot2000-hack: gpio-pca953x: add "drive" property
+
+Galileo gen 2 has support for setting GPIO modes. Expose these
+properties through the GPIO sysfs interface. This approach is bit hacky,
+since it changes the interface semantics.
+
+The original patch was by Josef Ahmad <josef.ahmad@linux.intel.com> and
+made on top of kernel 3.8.
+
+Not for upstream.
+
+Signed-off-by: Ismo Puustinen <ismo.puustinen@intel.com>
+Signed-off-by: Jussi Laako <jussi.laako@linux.intel.com>
+Signed-off-by: Saul Wold <sgw@linux.intel.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Yong Li <sdliyong@gmail.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/gpio/gpio-pca953x.c   | 42 +++++++++++++++++++++++
+ drivers/gpio/gpiolib-sysfs.c  | 78 +++++++++++++++++++++++++++++++++++++++++++
+ drivers/gpio/gpiolib.c        | 17 ++++++++++
+ drivers/gpio/gpiolib.h        |  4 +++
+ include/asm-generic/gpio.h    |  5 +++
+ include/linux/gpio.h          | 10 ++++++
+ include/linux/gpio/consumer.h | 11 ++++++
+ include/linux/gpio/driver.h   |  2 ++
+ 8 files changed, 169 insertions(+)
+
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index 8b467c0db1cb..ca1f6f4d6f59 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -40,6 +40,8 @@
+ #define PCA957X_INTS		7
+ 
+ #define PCAL953X_IN_LATCH	34
++#define PCAL953X_PUPD_EN	35
++#define PCAL953X_PUPD_SEL	36
+ #define PCAL953X_INT_MASK	37
+ #define PCAL953X_INT_STAT	38
+ 
+@@ -380,6 +382,43 @@ exit:
+ 	mutex_unlock(&chip->i2c_lock);
+ }
+ 
++static int pca953x_gpio_set_drive(struct gpio_chip *gc,
++				 unsigned off, unsigned mode)
++{
++	struct pca953x_chip *chip;
++	int ret = 0;
++	int val;
++
++	chip = container_of(gc, struct pca953x_chip, gpio_chip);
++
++	if (!(chip->driver_data & PCA_PCAL))
++		return -EINVAL;
++
++	mutex_lock(&chip->i2c_lock);
++
++	switch (mode) {
++	case GPIOF_DRIVE_PULLUP:
++		ret = pca953x_write_single(chip, PCAL953X_PUPD_EN, 1, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_SEL, 1, off);
++		break;
++	case GPIOF_DRIVE_PULLDOWN:
++		ret = pca953x_write_single(chip, PCAL953X_PUPD_EN, 1, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_SEL, 0, off);
++		break;
++	case GPIOF_DRIVE_STRONG:
++	case GPIOF_DRIVE_HIZ:
++		ret = pca953x_read_single(chip, PCAL953X_PUPD_EN, &val, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_EN, 0, off) ||
++			pca953x_write_single(chip, PCAL953X_PUPD_SEL, val, off);
++		break;
++	default:
++		ret = -EINVAL;
++	}
++
++	mutex_unlock(&chip->i2c_lock);
++	return ret;
++}
++
+ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+ {
+ 	struct gpio_chip *gc;
+@@ -398,6 +437,9 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+ 	gc->dev = &chip->client->dev;
+ 	gc->owner = THIS_MODULE;
+ 	gc->names = chip->names;
++
++	if (chip->driver_data & PCA_PCAL)
++		gc->set_drive = pca953x_gpio_set_drive;
+ }
+ 
+ #ifdef CONFIG_GPIO_PCA953X_IRQ
+diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
+index b57ed8e55ab5..72a8647146fa 100644
+--- a/drivers/gpio/gpiolib-sysfs.c
++++ b/drivers/gpio/gpiolib-sysfs.c
+@@ -7,6 +7,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/kdev_t.h>
+ #include <linux/slab.h>
++#include <linux/gpio.h>
+ 
+ #include "gpiolib.h"
+ 
+@@ -350,6 +351,82 @@ static ssize_t active_low_store(struct device *dev,
+ }
+ static DEVICE_ATTR_RW(active_low);
+ 
++
++static ssize_t gpio_drive_show(struct device *dev,
++		struct device_attribute *attr, char *buf)
++{
++	const struct gpio_desc	*desc = dev_get_drvdata(dev);
++	ssize_t			status;
++
++	mutex_lock(&sysfs_lock);
++
++	if (!test_bit(FLAG_EXPORT, &desc->flags)) {
++		status = -EIO;
++	} else {
++		if (test_bit(FLAG_PULLUP, &desc->flags))
++			status = sprintf(buf, "pullup\n");
++		else if (test_bit(FLAG_PULLDOWN, &desc->flags))
++			status = sprintf(buf, "pulldown\n");
++		else if (test_bit(FLAG_STRONG, &desc->flags))
++			status = sprintf(buf, "strong\n");
++		else if (test_bit(FLAG_HIZ, &desc->flags))
++			status = sprintf(buf, "hiz\n");
++		else
++			status = -EINVAL;
++	}
++
++	mutex_unlock(&sysfs_lock);
++	return status;
++}
++
++static ssize_t gpio_drive_store(struct device *dev,
++		struct device_attribute *attr, const char *buf, size_t size)
++{
++	struct gpio_desc	*desc = dev_get_drvdata(dev);
++	ssize_t			status;
++
++	mutex_lock(&sysfs_lock);
++
++	if (!test_bit(FLAG_EXPORT, &desc->flags))
++		status = -EIO;
++	else {
++		clear_bit(FLAG_PULLUP, &desc->flags);
++		clear_bit(FLAG_PULLDOWN, &desc->flags);
++		clear_bit(FLAG_STRONG, &desc->flags);
++		clear_bit(FLAG_HIZ, &desc->flags);
++		if (sysfs_streq(buf, "pullup")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_PULLUP);
++			if (!status) {
++				set_bit(FLAG_PULLUP, &desc->flags);
++			}
++		} else if (sysfs_streq(buf, "pulldown")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_PULLDOWN);
++			if (!status) {
++				set_bit(FLAG_PULLDOWN, &desc->flags);
++			}
++		} else if (sysfs_streq(buf, "strong")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_STRONG);
++			if (!status) {
++				set_bit(FLAG_STRONG, &desc->flags);
++			}
++		} else if (sysfs_streq(buf, "hiz")) {
++			status = gpiod_set_drive(desc, GPIOF_DRIVE_HIZ);
++			if (!status) {
++				set_bit(FLAG_HIZ, &desc->flags);
++			}
++		} else {
++			status = -EINVAL;
++		}
++	}
++
++	mutex_unlock(&sysfs_lock);
++	return status ? : size;
++}
++
++static DEVICE_ATTR(drive, 0644,
++		gpio_drive_show, gpio_drive_store);
++
++
+ static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
+ 			       int n)
+ {
+@@ -377,6 +454,7 @@ static struct attribute *gpio_attrs[] = {
+ 	&dev_attr_edge.attr,
+ 	&dev_attr_value.attr,
+ 	&dev_attr_active_low.attr,
++	&dev_attr_drive.attr,
+ 	NULL,
+ };
+ 
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index 827510dbba30..d19928b9a311 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -1315,6 +1315,23 @@ int gpiod_is_active_low(const struct gpio_desc *desc)
+ }
+ EXPORT_SYMBOL_GPL(gpiod_is_active_low);
+ 
++int gpiod_set_drive(struct gpio_desc *desc, unsigned mode)
++{
++	struct gpio_chip	*chip;
++
++	chip = desc->chip;
++	if (!chip || !chip->set || !chip->set_drive)
++		goto fail;
++
++	might_sleep_if(chip->can_sleep);
++
++	return chip->set_drive(chip, gpio_chip_hwgpio(desc), mode);
++
++fail:
++	return -EINVAL;
++}
++EXPORT_SYMBOL_GPL(gpiod_set_drive);
++
+ /* I/O calls are only valid after configuration completed; the relevant
+  * "is this a valid GPIO" error checks should already have been done.
+  *
+diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
+index 07541c5670e6..cfa7406b10fd 100644
+--- a/drivers/gpio/gpiolib.h
++++ b/drivers/gpio/gpiolib.h
+@@ -96,6 +96,10 @@ struct gpio_desc {
+ #define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */
+ #define FLAG_USED_AS_IRQ 9	/* GPIO is connected to an IRQ */
+ #define FLAG_IS_HOGGED	11	/* GPIO is hogged */
++#define FLAG_PULLUP	12	/* Gpio drive is resistive pullup */
++#define FLAG_PULLDOWN	13	/* Gpio drive is resistive pulldown */
++#define FLAG_STRONG	14	/* Gpio drive is strong (fast output) */
++#define FLAG_HIZ	15	/* Gpio drive is Hi-Z (input) */
+ 
+ 	/* Connection label */
+ 	const char		*label;
+diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
+index 40ec1433f05d..519e8d458878 100644
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -76,6 +76,11 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+ 	return gpiod_set_debounce(gpio_to_desc(gpio), debounce);
+ }
+ 
++static inline int gpio_set_drive(unsigned gpio, unsigned mode)
++{
++	return gpiod_set_drive(gpio_to_desc(gpio), mode);
++}
++
+ static inline int gpio_get_value_cansleep(unsigned gpio)
+ {
+ 	return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio));
+diff --git a/include/linux/gpio.h b/include/linux/gpio.h
+index d12b5d566e4b..344e62d27700 100644
+--- a/include/linux/gpio.h
++++ b/include/linux/gpio.h
+@@ -30,6 +30,11 @@
+ #define GPIOF_EXPORT_DIR_FIXED	(GPIOF_EXPORT)
+ #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
+ 
++#define GPIOF_DRIVE_PULLUP	(1 << 7)
++#define GPIOF_DRIVE_PULLDOWN	(1 << 8)
++#define GPIOF_DRIVE_STRONG	(1 << 9)
++#define GPIOF_DRIVE_HIZ		(1 << 10)
++
+ /**
+  * struct gpio - a structure describing a GPIO with configuration
+  * @gpio:	the GPIO number
+@@ -148,6 +153,11 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+ 	return -ENOSYS;
+ }
+ 
++static inline int gpio_set_drive(unsigned gpio, unsigned mode)
++{
++	return -ENOSYS;
++}
++
+ static inline int gpio_get_value(unsigned gpio)
+ {
+ 	/* GPIO can never have been requested or set as {in,out}put */
+diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
+index fb0fde686cb1..17f5f187699b 100644
+--- a/include/linux/gpio/consumer.h
++++ b/include/linux/gpio/consumer.h
+@@ -122,6 +122,8 @@ void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
+ 
+ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
+ 
++int gpiod_set_drive(struct gpio_desc *desc, unsigned mode);
++
+ int gpiod_is_active_low(const struct gpio_desc *desc);
+ int gpiod_cansleep(const struct gpio_desc *desc);
+ 
+@@ -376,6 +378,15 @@ static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
+ 	return -ENOSYS;
+ }
+ 
++
++static inline int gpiod_set_drive(unsigned gpio, unsigned mode)
++{
++	/* GPIO can never have been requested */
++	WARN_ON(1);
++	return -ENOSYS;
++}
++
++
+ static inline int gpiod_is_active_low(const struct gpio_desc *desc)
+ {
+ 	/* GPIO can never have been requested */
+diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
+index de502c7e4171..d59080ba9fec 100644
+--- a/include/linux/gpio/driver.h
++++ b/include/linux/gpio/driver.h
+@@ -116,6 +116,8 @@ struct gpio_chip {
+ 	int			(*set_debounce)(struct gpio_chip *chip,
+ 						unsigned offset,
+ 						unsigned debounce);
++	int			(*set_drive)(struct gpio_chip *chip,
++						unsigned offset, unsigned mode);
+ 
+ 	int			(*to_irq)(struct gpio_chip *chip,
+ 						unsigned offset);
+-- 
+2.16.4
+

+ 105 - 0
board/PSG/iot2000/linux-4.4-patches_orig/linux-4.4-patches/0018-iot2000-hack-pwm-pca-9685-Provide-chip-level-pwm_per.patch

@@ -0,0 +1,105 @@
+From c25a8e605bcbb0ed2adde384587ffcfcf5783eef Mon Sep 17 00:00:00 2001
+From: Jan Kiszka <jan.kiszka@siemens.com>
+Date: Fri, 17 Nov 2017 20:25:54 +0100
+Subject: [PATCH 18/18] iot2000-hack: pwm: pca-9685: Provide chip-level
+ pwm_period attribute
+
+Arduino runtime relies on this path to program the PWM period, rather
+than doing this via the upstream kernel API which is per channel.
+
+Another one not for upstream.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+ drivers/pwm/pwm-pca9685.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 59 insertions(+)
+
+diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c
+index 611b9263a896..ce765f903714 100644
+--- a/drivers/pwm/pwm-pca9685.c
++++ b/drivers/pwm/pwm-pca9685.c
+@@ -444,6 +444,54 @@ static const struct pwm_ops pca9685_pwm_ops = {
+ 	.owner = THIS_MODULE,
+ };
+ 
++static ssize_t pwm_period_show(struct device *parent,
++			       struct device_attribute *attr,
++			       char *buf)
++{
++	struct pwm_chip *chip = dev_get_drvdata(parent);
++
++	return sprintf(buf, "%u\n", to_pca(chip)->period_ns);
++}
++
++static ssize_t pwm_period_store(struct device *parent,
++				struct device_attribute *attr,
++				const char *buf, size_t size)
++{
++	struct pwm_chip *chip = dev_get_drvdata(parent);
++	struct pca9685 *pca = to_pca(chip);
++	int old_period_ns = pca->period_ns;
++	unsigned long long duty_scale, new_duty_ns;
++	unsigned int val, channel;
++	struct pwm_device *pwm;
++	int ret;
++
++	ret = kstrtouint(buf, 0, &val);
++	if (ret)
++		return ret;
++
++	for (channel = 0; channel < PCA9685_MAXCHAN; channel++) {
++		pwm = &chip->pwms[channel];
++
++		if (pca9685_pwm_is_gpio(pca, pwm))
++			continue;
++
++		/* Scale the rise time to maintain duty cycle */
++		duty_scale = val;
++		duty_scale *= 1000000;
++		do_div(duty_scale, old_period_ns);
++		new_duty_ns = duty_scale * pwm_get_duty_cycle(pwm);
++		do_div(new_duty_ns, 1000000);
++		/* Update the duty_cycle */
++		ret = pwm_config(pwm, (int)new_duty_ns, val);
++		if (ret)
++			return ret;
++	}
++
++	return size;
++}
++
++static DEVICE_ATTR_RW(pwm_period);
++
+ static const struct regmap_config pca9685_regmap_i2c_config = {
+ 	.reg_bits = 8,
+ 	.val_bits = 8,
+@@ -504,8 +552,17 @@ static int pca9685_pwm_probe(struct i2c_client *client,
+ 	if (ret < 0)
+ 		return ret;
+ 
++	ret = sysfs_create_file(&pca->chip.dev->kobj,
++				&dev_attr_pwm_period.attr);
++	if (ret < 0) {
++		pwmchip_remove(&pca->chip);
++		return ret;
++	}
++
+ 	ret = pca9685_pwm_gpio_probe(pca);
+ 	if (ret < 0) {
++		sysfs_remove_file(&pca->chip.dev->kobj,
++				  &dev_attr_pwm_period.attr);
+ 		pwmchip_remove(&pca->chip);
+ 		return ret;
+ 	}
+@@ -526,6 +583,8 @@ static int pca9685_pwm_remove(struct i2c_client *client)
+ 	struct pca9685 *pca = i2c_get_clientdata(client);
+ 	int ret;
+ 
++	sysfs_remove_file(&pca->chip.dev->kobj, &dev_attr_pwm_period.attr);
++
+ 	ret = pwmchip_remove(&pca->chip);
+ 	if (ret)
+ 		return ret;
+-- 
+2.16.4
+

BIN
board/PSG/iot2000/rootfs_overlay/lib/libsnap7.so


+ 1 - 1
configs/iot2000_defconfig

@@ -27,7 +27,7 @@ BR2_ROOTFS_POST_BUILD_SCRIPT="../PSG/board/PSG/iot2000/post-build.sh"
 BR2_ROOTFS_POST_IMAGE_SCRIPT="../PSG/board/PSG/iot2000/post-image.sh"
 BR2_ROOTFS_POST_IMAGE_SCRIPT="../PSG/board/PSG/iot2000/post-image.sh"
 BR2_LINUX_KERNEL=y
 BR2_LINUX_KERNEL=y
 BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
 BR2_LINUX_KERNEL_CUSTOM_TARBALL=y
-BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="https://git.kernel.org/pub/scm/linux/kernel/git/cip/linux-cip.git/snapshot/linux-cip-4.4.185-cip35-rt24.tar.gz"
+BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION="https://git.kernel.org/pub/scm/linux/kernel/git/cip/linux-cip.git/snapshot/linux-cip-4.4.208-cip41.tar.gz"
 BR2_LINUX_KERNEL_PATCH="../PSG/board/PSG/iot2000/linux-4.4-patches"
 BR2_LINUX_KERNEL_PATCH="../PSG/board/PSG/iot2000/linux-4.4-patches"
 BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
 BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
 BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="../PSG/board/PSG/iot2000/linux-4.4.config"
 BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="../PSG/board/PSG/iot2000/linux-4.4.config"

+ 6 - 0
package/Snap7/Config.in

@@ -0,0 +1,6 @@
+config BR2_PACKAGE_SNAP7
+	bool "snap7"
+	default y
+	help
+		library to acces S7 (SIEMENS PLS) data
+

+ 24 - 0
package/Snap7/Snap7.mk

@@ -0,0 +1,24 @@
+SNAP7_VERSION:=  b118aefdc184bda1a62c5527424696dbd28bdf05
+SNAP7_SITE:= https://gogs.psg-bgh.de/PSG/snap7-iot-quark-1.4.2.git
+SNAP7_SITE_METHOD:= git
+SNAP7_INSTALL_TARGET:=YES
+SNAP7_INSTALL_STAGING:=YES
+
+define SNAP7_BUILD_CMDS
+	echo `basedir $(TARGET_CC)`
+	echo "============================================="
+	printenv
+	echo "============================================="
+	$(MAKE) -f ./i586_linux.mk CROSS_COMPILE="$(TARGET_CROSS)" -C $(@D)/build/unix all
+endef
+
+define SNAP7_INSTALL_TARGET_CMDS
+	$(INSTALL) -D -m 0755 $(@D)/build/bin/i586-linux/libsnap7.so $(TARGET_DIR)/lib
+endef
+
+define SNAP7_INSTALL_STAGING_CMDS
+	$(INSTALL) -D -m 0755 $(@D)/build/bin/i586-linux/libsnap7.so $(STAGING_DIR)/lib
+endef
+
+
+$(eval $(generic-package))

+ 98 - 0
patches/007-modifications-CrossCompile-Toolchain.patch

@@ -0,0 +1,98 @@
+diff --git a/CrossCompile.sh b/CrossCompile.sh
+index cd87200..a94e25a 100755
+--- a/CrossCompile.sh
++++ b/CrossCompile.sh
+@@ -6,29 +6,83 @@ WRKDIR=`pwd`
+ CMDDIR=`dirname $0`
+ cd $CMDDIR
+ 
++#=== Asssign GNU_TARGET_NAME from .config
++_ARCH=`grep BR2_ARCH\= .config | awk -F\= -F\" '{print $2}'`
++_TARGET_VENDOR=`grep BR2_TOOLCHAIN_BUILDROOT_VENDOR\= .config | awk -F\= -F\" '{print $2}'`
++
++# -- get target os
++_BR2_BINFMT_FLAT=`grep BR2_BINFMT_FLAT\= .config | awk -F\= '{print $2}'`
++if [ "$_BR2_BINFMT_FLAT" = "y" ]; then
++	_TARGET_OS="uclinux"
++	else
++	_TARGET_OS="linux"
++fi	
++
++# -- get libc
++_BR2_TOOLCHAIN_USES_UCLIBC=`grep BR2_TOOLCHAIN_USES_UCLIBC\= .config | awk -F\= '{print $2}'`
++_BR2_TOOLCHAIN_USES_MUSL=`grep BR2_TOOLCHAIN_USES_MUSL\= .config | awk -F\= '{print $2}'`
++
++if [ "$_BR2_TOOLCHAIN_USES_UCLIBC" = "y" ]; then
++	_LIBC="uclibc"
++	else
++	if [ "$_BR2_TOOLCHAIN_USES_MUSL" = "y" ]; then
++		_LIBC="musl"
++		else
++		_LIBC="gnu"
++	fi
++fi	 		
++
++# -- ABI
++_BR2_arm=`grep BR2_arm\= .config | awk -F\= '{print $2}'`
++_BR2_armeb=`grep BR2_armeb\= .config | awk -F\= '{print $2}'`
++_BR2_ARM_EABIHF=`grep BR2_ARM_EABIHF\= .config | awk -F\= '{print $2}'`
++if [ "$_BR2_arm" = "y" ] || [ "$_BR2_armeb" = "y" ]; then
++	if [ "$_LIBC" = "uclibc" ]; then
++		_ABI="gnueabi"
++		else
++		_ABI="eabi"
++	fi
++	if [ "$_BR2_ARM_EABIHF" = "y" ]; then
++		_ABI="${_ABI}hf"
++	fi
++fi
++	
++_GNU_TARGET_NAME="${_ARCH}-${_TARGET_VENDOR}-${_TARGET_OS}-${_LIBC}${_ABI}"
++#===============================================================
++
+ TOOLCHAIN=`grep BR2_HOST_DIR .config | awk -F\= -F\" '{print $2}'`
+ echo $TOOLCHAIN
+ 
+ if [[ $TOOLCHAIN = *\$\(BASE_DIR\)* ]]; then
+-	export SYSROOTBIN=`readlink -f $CMDDIR`/output/host/usr/bin/
++	export SYSROOT=`readlink -f $CMDDIR`/output/host/usr/bin/
+ else
+-	export SYSROOTBIN=$TOOLCHAIN/usr/bin
++	export SYSROOT=$TOOLCHAIN/usr/bin
+ fi
+ 
+-export PATH=$PATH:$SYSROOTBIN
++export PATH=$PATH:$SYSROOT
++
++export CROSS_COMPILE="${_GNU_TARGET_NAME}-"
++export CROSS=${CROSS_COMPILE}
+ 
+-export CROSS_COMPILE=i586-buildroot-linux-gnu-
+-export CROSS=$CROSS_COMPILE
+-export ARCH=i586
+-export KERNELDIR=`pwd`/output/build/linux-linux-4.4.y
++export ARCH=arm
++_KERNELDIR=`grep BR2_LINUX_KERNEL_VERSION\= .config | awk -F\= -F\" '{print $2}'`
++export KERNELDIR=${CMDDIR}/output/build/linux-${_KERNELDIR}
+ export BB_KERNEL_SOURCES=$KERNELDIR
+-export SYSROOT=`grep BR2_HOST_DIR .config | awk -F\= -F\" '{print $2}'`/usr/i586-buildroot-linux-gnu/sysroot
+-export CC_FULLPATH="${SYSROOTBIN}${CROSS_COMPILE}"
++export SYSROOTARM=`grep BR2_HOST_DIR .config | awk -F\= -F\" '{print $2}'`/usr/${_GNU_TARGET_NAME}/sysroot
++export CC_FULLPATH="${SYSROOT}/${CROSS_COMPILE}"
+ export CC=${CROSS_COMPILE}gcc
+ export CXX=${CROSS_COMPILE}g++
+ 
++#--- gnupru
++export PASM=pasm
++##export PSYSROOT=/home/ru/pru/pru-gcc/bin
++export PSYSROOT=/opt/GfA/PRU-ICSS/bin/pru-gcc/bin
++export PATH=$PSYSROOT:$PATH
++
++export PCROSS_COMPILE=pru-
++export PARCH=pru
++
+ cd $WRKDIR
+-echo $CROSS_COMPILE
+ if [ $# -eq "0" ] 
+ then
+ PROMPT_COMMAND='PS1="\[\033[0;31m\]CROSS CC:\[\033[0;32m\]$PS1";unset PROMPT_COMMAND' bash ; reset