summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel
diff options
context:
space:
mode:
authorEd Tanous <ed.tanous@intel.com>2019-04-15 23:42:44 +0300
committerEd Tanous <ed.tanous@intel.com>2019-04-17 19:13:25 +0300
commit816d793003e93c1e5eec0a2e90fbd8b9dde9f7a5 (patch)
tree341534fed9a2de460ded7f8231ca1cbb178bb2ca /meta-openbmc-mods/meta-common/recipes-kernel
parenta75bff085ba9443315222231c42692745e5781e9 (diff)
downloadopenbmc-816d793003e93c1e5eec0a2e90fbd8b9dde9f7a5.tar.xz
Update 4-15-19
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch65
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch7
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch12
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch20
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch (renamed from meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-adpeed-Swap-the-mac-nodes-numbering.patch)2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0036-net-ncsi-backport-ncsi-patches.patch1425
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0038-media-aspeed-backport-ikvm-patches.patch1853
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch65
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch77
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch48
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch43
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0050-media-platform-Fix-a-kernel-warning-on-clk-control.patch177
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend6
20 files changed, 427 insertions, 3472 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch
index 2a94453b3..08498cd01 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-arm-dts-aspeed-g5-add-espi.patch
@@ -1,19 +1,19 @@
-From 2affc8ab570c9d1e6d6e5ecbdbeddbc5e3b15cc5 Mon Sep 17 00:00:00 2001
+From 536b09695117440ed428ff27023cd9167fcf4dfe Mon Sep 17 00:00:00 2001
From: Juston Li <juston.li@intel.com>
Date: Mon, 27 Mar 2017 11:16:00 -0700
Subject: [PATCH] arm: dts: aspeed-g5: add espi
-Change-Id: I0b607657883619a3acefdbf344d39bf01790c4b1
Signed-off-by: Juston Li <juston.li@intel.com>
---
arch/arm/boot/dts/aspeed-g5.dtsi | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index e4c5de3208e0..a3c456ba3f34 100644
+index a79e01ffe9d4..0c74adf739d2 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
-@@ -260,13 +260,22 @@
+@@ -261,7 +261,7 @@
+ #gpio-cells = <2>;
gpio-controller;
compatible = "aspeed,ast2500-gpio";
- reg = <0x1e780000 0x1000>;
@@ -21,7 +21,7 @@ index e4c5de3208e0..a3c456ba3f34 100644
interrupts = <20>;
gpio-ranges = <&pinctrl 0 0 220>;
clocks = <&syscon ASPEED_CLK_APB>;
- interrupt-controller;
+@@ -269,6 +269,15 @@
#interrupt-cells = <2>;
};
@@ -37,7 +37,7 @@ index e4c5de3208e0..a3c456ba3f34 100644
rtc: rtc@1e781000 {
compatible = "aspeed,ast2500-rtc";
reg = <0x1e781000 0x18>;
-@@ -342,6 +351,13 @@
+@@ -344,6 +353,13 @@
status = "disabled";
};
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch
index 2ac429a22..11663c503 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0007-New-flash-map-for-intel.patch
@@ -1,22 +1,23 @@
-From 074f1c74fde88aac3a10059e4928919782cd40d6 Mon Sep 17 00:00:00 2001
+From 3eabb52efdecfc0da896476ac5567060a6b3788a Mon Sep 17 00:00:00 2001
From: Vernon Mauery <vernon.mauery@intel.com>
Date: Mon, 4 Jun 2018 13:45:42 -0700
Subject: [PATCH] New flash map for Intel
- ===================================================================
+Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
+Signed-off-by: Vikram Bodireddy <vikram.bodireddy@intel.com>
---
- .../boot/dts/openbmc-flash-layout-intel-128MB.dtsi | 58 ++++++++++++++++++++++
- .../boot/dts/openbmc-flash-layout-intel-64MB.dtsi | 39 +++++++++++++++
- 2 files changed, 97 insertions(+)
+ .../boot/dts/openbmc-flash-layout-intel-128MB.dtsi | 52 ++++++++++++++++++++++
+ .../boot/dts/openbmc-flash-layout-intel-64MB.dtsi | 39 ++++++++++++++++
+ 2 files changed, 91 insertions(+)
create mode 100644 arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi
create mode 100644 arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi
diff --git a/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi b/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi
new file mode 100644
-index 0000000..23426ac
+index 000000000000..23426acc30c7
--- /dev/null
+++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-128MB.dtsi
-@@ -0,0 +1,58 @@
+@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0+
+// 128MB flash layout: PFR (active + tmp1/tmp2 + extra)
+// image with common RW partition
@@ -31,53 +32,47 @@ index 0000000..23426ac
+ label = "u-boot";
+ };
+
-+ fit-image-a@80000 {
-+ reg = <0x80000 0x1b80000>;
-+ label = "image-a";
++ pfm@80000 {
++ reg = <0x80000 0x20000>;
++ label = "pfm";
+ };
+
-+ sofs@1c00000 {
-+ reg = <0x1c00000 0x200000>;
-+ label = "sofs";
++ u-boot-env@a0000 {
++ reg = <0xa0000 0x20000>;
++ label = "u-boot-env";
+ };
+
-+ rwfs@1e00000 {
-+ reg = <0x1e00000 0x600000>;
-+ label = "rwfs";
++ sofs@c0000 {
++ reg = <0xc0000 0x200000>;
++ label = "sofs";
+ };
+
-+ u-boot-env@2400000 {
-+ reg = <0x2400000 0x20000>;
-+ label = "u-boot-env";
++ rwfs@2c0000 {
++ reg = <0x2c0000 0xe40000>;
++ label = "rwfs";
+ };
+
-+ /*
-+ pfr-resvd@1260000 {
-+ reg = <0x2460000 0x20000>;
-+ label = "pfr-resvd";
++ fit-image-a@1100000 {
++ reg = <0x1100000 0x2500000>;
++ label = "image-a";
+ };
-+ */
+
-+ rc1@2480000 {
-+ reg = <0x2480000 0x1b80000>;
-+ label = "rc1";
++ rc-image@3600000 {
++ reg = <0x3600000 0x2500000>;
++ label = "rc-image";
+ };
+
-+ rc2@4000000 {
-+ reg = <0x4000000 0x1b80000>;
-+ label = "rc2";
++ image-staging@5b00000 {
++ reg = <0x5b00000 0x2500000>;
++ label = "image-stg";
+ };
+
-+ bios-staging@6000000 {
-+ reg = <0x6000000 0x2000000>;
-+ label = "bios-staging";
-+ };
+};
+
+
diff --git a/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi b/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi
new file mode 100644
-index 0000000..6ae8e57
+index 000000000000..6ae8e57087e2
--- /dev/null
+++ b/arch/arm/boot/dts/openbmc-flash-layout-intel-64MB.dtsi
@@ -0,0 +1,39 @@
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch
index 78824dde7..beb5087f5 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0008-Add-ASPEED-SGPIO-driver.patch
@@ -1,4 +1,4 @@
-From 42505ffb3c24b3e7f8182af520ab1c10a3b3f3c4 Mon Sep 17 00:00:00 2001
+From 58adbd18074fbf8005d5d7a5ec116c326252f606 Mon Sep 17 00:00:00 2001
From: "Feist, James" <james.feist@intel.com>
Date: Mon, 5 Jun 2017 11:13:52 -0700
Subject: [PATCH] Add ASPEED SGPIO driver.
@@ -6,7 +6,6 @@ Subject: [PATCH] Add ASPEED SGPIO driver.
Port aspeed sgpio driver to OBMC Kernel and
enable it on Purley config. Based off AST sdk 4.0.
-Change-Id: I8529c3fb001ea6f93e63b269cdcdde3887a84e40
Signed-off-by: James Feist <james.feist@linux.intel.com>
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
@@ -17,7 +16,7 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
create mode 100644 drivers/gpio/sgpio-aspeed.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
-index 71c0ab46f216..a0485be99db7 100644
+index b5a2845347ec..e3ce2b68a1fc 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -124,6 +124,14 @@ config GPIO_ASPEED
@@ -36,7 +35,7 @@ index 71c0ab46f216..a0485be99db7 100644
tristate "Atheros AR71XX/AR724X/AR913X GPIO support"
default y if ATH79
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
-index 1324c8f966a7..23b8d29bef70 100644
+index 37628f8dbf70..069155f1db9e 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_GPIO_AMDPT) += gpio-amdpt.o
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch
index 346b9e3e3..1c5d9ab53 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0009-SGPIO-DT-and-pinctrl-fixup.patch
@@ -1,4 +1,4 @@
-From f4b91f5c6723e56e106a609cdbcc8da48c56499e Mon Sep 17 00:00:00 2001
+From 2f895fe17cd72124b2a04af306f9349e5da90a6c Mon Sep 17 00:00:00 2001
From: Vernon Mauery <vernon.mauery@intel.com>
Date: Wed, 16 May 2018 10:03:14 -0700
Subject: [PATCH] SGPIO DT and pinctrl fixup
@@ -15,11 +15,11 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
4 files changed, 54 insertions(+), 60 deletions(-)
diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
-index 6af12872ee74..9aed0f696a98 100644
+index 3990aed25ee6..19f721118b52 100644
--- a/arch/arm/boot/dts/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
-@@ -201,6 +201,18 @@
- interrupt-controller;
+@@ -203,6 +203,18 @@
+ #interrupt-cells = <2>;
};
+ sgpio: sgpio@1e780200 {
@@ -37,7 +37,7 @@ index 6af12872ee74..9aed0f696a98 100644
timer: timer@1e782000 {
/* This timer is a Faraday FTTMR010 derivative */
compatible = "aspeed,ast2400-timer";
-@@ -1150,44 +1162,14 @@
+@@ -1183,44 +1195,14 @@
groups = "SD2";
};
@@ -89,10 +89,10 @@ index 6af12872ee74..9aed0f696a98 100644
pinctrl_sioonctrl_default: sioonctrl_default {
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index 01e901031bd4..36d72c91a2ad 100644
+index 0c74adf739d2..d4c99b82f7bd 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
-@@ -274,6 +274,9 @@
+@@ -276,6 +276,9 @@
reg = <0x1e780200 0x0100>;
interrupts = <40>;
interrupt-controller;
@@ -101,8 +101,8 @@ index 01e901031bd4..36d72c91a2ad 100644
+ status = "disabled";
};
- timer: timer@1e782000 {
-@@ -1324,6 +1327,11 @@
+ rtc: rtc@1e781000 {
+@@ -1388,6 +1391,11 @@
groups = "SDA2";
};
@@ -207,7 +207,7 @@ index 05b153034517..353af05b8602 100644
ASPEED_PINCTRL_FUNC(SIOPBI),
ASPEED_PINCTRL_FUNC(SIOPBO),
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
-index 187abd7693cf..0c89647f166f 100644
+index 4230e1038a88..13f749e35001 100644
--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g5.c
@@ -577,6 +577,8 @@ SS_PIN_DECL(N3, GPIOJ2, SGPMO);
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch
index 3cd1d9e84..db21250bb 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0010-Update-PECI-drivers-to-sync-with-linux-upstreaming-v.patch
@@ -1,4 +1,4 @@
-From ce7a88017fb2124100c4e5481a205034f34da23c Mon Sep 17 00:00:00 2001
+From 63ccbbe64f7e6560233971b886f6166fc59d20ef Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Mon, 7 Jan 2019 09:56:10 -0800
Subject: [PATCH] Update PECI drivers to sync with linux upstreaming version
@@ -89,10 +89,10 @@ index 821a9258f2e6..a3a3e465c888 100644
+temp[6-*]_crit_hyst Provides the hysteresis value from Tcontrol to Tjmax of
the core.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
-index 9e118d700b48..efe67f7faed3 100644
+index 996e80590b5b..93945eb19261 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
-@@ -1319,7 +1319,7 @@ config SENSORS_PECI_CPUTEMP
+@@ -1321,7 +1321,7 @@ config SENSORS_PECI_CPUTEMP
the PECI Client Command Suite via the processor PECI client.
Check Documentation/hwmon/peci-cputemp for details.
@@ -101,7 +101,7 @@ index 9e118d700b48..efe67f7faed3 100644
will be called peci-cputemp.
config SENSORS_PECI_DIMMTEMP
-@@ -1333,7 +1333,7 @@ config SENSORS_PECI_DIMMTEMP
+@@ -1335,7 +1335,7 @@ config SENSORS_PECI_DIMMTEMP
Suite via the processor PECI client.
Check Documentation/hwmon/peci-dimmtemp for details.
@@ -109,7 +109,7 @@ index 9e118d700b48..efe67f7faed3 100644
+ This driver can also be built as a module. If so, the module
will be called peci-dimmtemp.
- source drivers/hwmon/pmbus/Kconfig
+ source "drivers/hwmon/pmbus/Kconfig"
diff --git a/drivers/hwmon/peci-cputemp.c b/drivers/hwmon/peci-cputemp.c
index 11880c86a854..30ba1638e358 100644
--- a/drivers/hwmon/peci-cputemp.c
@@ -663,10 +663,10 @@ index 6ca1855a86bb..ce6b470eae63 100644
/**
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
-index 66b71a6122d6..28a83b354ea8 100644
+index 9af5730ad7ba..28087e9cd4da 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
-@@ -596,7 +596,7 @@ config MFD_INTEL_MSIC
+@@ -606,7 +606,7 @@ config MFD_INTEL_MSIC
devices used in Intel Medfield platforms.
config MFD_INTEL_PECI_CLIENT
@@ -675,7 +675,7 @@ index 66b71a6122d6..28a83b354ea8 100644
depends on (PECI || COMPILE_TEST)
select MFD_CORE
help
-@@ -609,6 +609,9 @@ config MFD_INTEL_PECI_CLIENT
+@@ -619,6 +619,9 @@ config MFD_INTEL_PECI_CLIENT
Additional drivers must be enabled in order to use the functionality
of the device.
@@ -1940,7 +1940,7 @@ index 51cb2563ceb6..000000000000
-MODULE_DESCRIPTION("ASPEED PECI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/peci/peci-core.c b/drivers/peci/peci-core.c
-index fac8c72dcda8..e2ef013e5002 100644
+index 6f241469ec7e..e2ef013e5002 100644
--- a/drivers/peci/peci-core.c
+++ b/drivers/peci/peci-core.c
@@ -1,38 +1,31 @@
@@ -2851,7 +2851,7 @@ index fac8c72dcda8..e2ef013e5002 100644
- return -ENOTTY;
- }
-
-- if (!access_ok(VERIFY_WRITE, argp, msg_len))
+- if (!access_ok(argp, msg_len))
- return -EFAULT;
-
- msg = memdup_user(argp, msg_len);
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch
index 95302aae8..e6dd44cd7 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0021-Initial-Port-of-Aspeed-LPC-SIO-driver.patch
@@ -111,7 +111,7 @@ index 768278b059c3..de2d5c6d186c 100644
+obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
obj-$(CONFIG_OCXL) += ocxl/
- obj-$(CONFIG_MISC_RTSX) += cardreader/
+ obj-y += cardreader/
diff --git a/drivers/misc/aspeed-lpc-sio.c b/drivers/misc/aspeed-lpc-sio.c
new file mode 100644
index 000000000000..c717a3182320
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
index 120adbbc8..216c750de 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0022-Add-AST2500-eSPI-driver.patch
@@ -1,4 +1,4 @@
-From a01815b4bb983ede71993d6c761dedd22d148b6b Mon Sep 17 00:00:00 2001
+From 3437db37b2f39a69505338546d9f846338de6c88 Mon Sep 17 00:00:00 2001
From: Haiyue Wang <haiyue.wang@linux.intel.com>
Date: Sat, 24 Feb 2018 11:12:32 +0800
Subject: [PATCH] eSPI: add ASPEED AST2500 eSPI driver to boot a host with PCH
@@ -181,10 +181,10 @@ index 000000000000..185acd71bd26
+<https://www.intel.com/content/dam/support/us/en/documents/software/chipset-software/327432-004_espi_base_specification_rev1.0.pdf>`_
+
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index 4a302d745b09..165a2bddc6cd 100644
+index da9e903808bc..01d27e845982 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
-@@ -266,6 +266,7 @@
+@@ -267,6 +267,7 @@
clocks = <&syscon ASPEED_CLK_APB>;
interrupt-controller;
#interrupt-cells = <2>;
@@ -192,7 +192,7 @@ index 4a302d745b09..165a2bddc6cd 100644
};
sgpio: sgpio@1e780200 {
-@@ -360,6 +361,9 @@
+@@ -361,6 +362,9 @@
reg = <0x1e6ee000 0x100>;
interrupts = <23>;
status = "disabled";
@@ -203,7 +203,7 @@ index 4a302d745b09..165a2bddc6cd 100644
lpc: lpc@1e789000 {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index fe1e2a4072a8..f2062546250c 100644
+index d4ed3777462a..8b1fcf741411 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -485,6 +485,14 @@ config VEXPRESS_SYSCFG
@@ -222,7 +222,7 @@ index fe1e2a4072a8..f2062546250c 100644
depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index a2b85ec21d09..bb89694e6b4b 100644
+index 7b018962cad3..89b051f82391 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_GENWQE) += genwqe/
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch
index 860a1ba5d..89a667e95 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0028-Add-AST2500-JTAG-driver.patch
@@ -1,4 +1,4 @@
-From 43470f186979483ba6c1e6374c7ea3a129622862 Mon Sep 17 00:00:00 2001
+From 409ea2cede8588a59badd5dd7cf8721879d4c68a Mon Sep 17 00:00:00 2001
From: "Hunt, Bryan" <bryan.hunt@intel.com>
Date: Fri, 30 Mar 2018 10:48:01 -0700
Subject: [PATCH] Add AST2500d JTAG driver
@@ -21,10 +21,10 @@ Signed-off-by: Hunt, Bryan <bryan.hunt@intel.com>
create mode 100644 include/uapi/linux/jtag_drv.h
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index a7bbc2adecc9..b63003c2c0c7 100644
+index 01d27e845982..adde826ac1d9 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
-@@ -366,6 +366,15 @@
+@@ -367,6 +367,15 @@
pinctrl-0 = <&pinctrl_espi_default>;
};
@@ -41,17 +41,17 @@ index a7bbc2adecc9..b63003c2c0c7 100644
compatible = "aspeed,ast2500-lpc", "simple-mfd";
reg = <0x1e789000 0x1000>;
diff --git a/drivers/Kconfig b/drivers/Kconfig
-index c633db2b41fb..2778a5c33ca5 100644
+index bbb66439a307..a1579d66f47d 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
-@@ -221,4 +221,5 @@ source "drivers/slimbus/Kconfig"
+@@ -230,4 +230,5 @@ source "drivers/slimbus/Kconfig"
source "drivers/peci/Kconfig"
+source "drivers/jtag/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
-index 63c9b425e6e1..714067945fd2 100644
+index 9ec44c032a42..69b201766154 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -187,3 +187,4 @@ obj-$(CONFIG_UNISYS_VISORBUS) += visorbus/
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch
index 539c976c7..e015f2fd9 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch
@@ -1,4 +1,4 @@
-From e39e3a3e54cbe8e5a39b4148a9232f4570d009a6 Mon Sep 17 00:00:00 2001
+From 37b192b278d5ea5da62b2fcff4fce7cf372e4fe6 Mon Sep 17 00:00:00 2001
From: Oskar Senft <osk@google.com>
Date: Wed, 8 Aug 2018 10:15:05 -0400
Subject: [PATCH] misc: aspeed: Add Aspeed UART routing control driver.
@@ -102,10 +102,10 @@ index 000000000000..afaf17cb7eda
+$ cat /sys/bus/platform/drivers/aspeed-uart-routing/*.uart_routing/uart1
+io1 io2 io3 io4 uart2 [uart3] uart4 io6
diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
-index 655bb37e422f..eb05f5a2c480 100644
+index 8aba46cdce46..d184fdf6dda6 100644
--- a/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-intel-purley.dts
-@@ -174,6 +174,10 @@
+@@ -227,6 +227,10 @@
status = "okay";
};
@@ -117,10 +117,10 @@ index 655bb37e422f..eb05f5a2c480 100644
status = "okay";
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index 3bb31c1daf9d..92843cc1a8f4 100644
+index adde826ac1d9..5606ac1d96d5 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
-@@ -482,6 +482,12 @@
+@@ -479,6 +479,12 @@
status = "disabled";
};
};
@@ -134,12 +134,12 @@ index 3bb31c1daf9d..92843cc1a8f4 100644
peci: bus@1e78b000 {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index f2062546250c..8e2fc51dcc44 100644
+index 8b1fcf741411..60f203c04b9b 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
-@@ -537,6 +537,12 @@ config MISC_RTSX
- tristate
- default MISC_RTSX_PCI || MISC_RTSX_USB
+@@ -560,6 +560,12 @@ config NPCM7XX_PCI_MBOX
+ Expose the NPCM750/730/715/705 PCI MBOX registers found on
+ Nuvoton SOCs to userspace.
+config ASPEED_UART_ROUTING
+ tristate "Aspeed ast2500 UART routing control"
@@ -151,7 +151,7 @@ index f2062546250c..8e2fc51dcc44 100644
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index bb89694e6b4b..0f00eb63556c 100644
+index 89b051f82391..8f70b888a9ca 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_CXL_BASE) += cxl/
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-adpeed-Swap-the-mac-nodes-numbering.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch
index eef3bee6f..b819be69b 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-adpeed-Swap-the-mac-nodes-numbering.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch
@@ -1,7 +1,7 @@
From 9c509b9450f641c169ee3aeb60e398c43810dcb2 Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Wed, 3 Oct 2018 10:17:58 -0700
-Subject: [PATCH] arm: dts: adpeed: Swap the mac nodes numbering
+Subject: [PATCH] arm: dts: aspeed: Swap the mac nodes numbering
This patch swaps the numbering of mac0 and mac1 to make a dedicated
nic get assigned the first ethernet device number.
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch
index 51ddbb18e..3863ea8f6 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0035-Implement-a-memory-driver-share-memory.patch
@@ -1,5 +1,5 @@
-From 1d459c15998c9a79ba7a758cef6129ed29f3b958 Mon Sep 17 00:00:00 2001
-From: cyang29 <cheng.c.yang@intel.com>
+From dae410353f8681b58907c61eb2eb056513d86f6d Mon Sep 17 00:00:00 2001
+From: Cheng C Yang <cheng.c.yang@intel.com>
Date: Fri, 9 Nov 2018 10:24:37 +0800
Subject: [PATCH] Implement a memory driver share memory
@@ -8,7 +8,7 @@ The driver is used by MDRV2. In MDRV2 BIOS will send whole
SMBIOS table to VGA memory and BMC can get the table from VGA
memory through this driver.
-Signed-off-by: cyang29 <cheng.c.yang@intel.com>
+Signed-off-by: Cheng C Yang <cheng.c.yang@intel.com>
---
.../devicetree/bindings/misc/vga-shared-memory.txt | 20 +++
drivers/misc/Kconfig | 10 ++
@@ -45,10 +45,10 @@ index 000000000000..03f57c53e844
+ reg = <0x9ff00000 0x100000>;
+};
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index 8e2fc51dcc44..1279a9674537 100644
+index 60f203c04b9b..2d4c6ba87e70 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
-@@ -543,6 +543,16 @@ config ASPEED_UART_ROUTING
+@@ -566,6 +566,16 @@ config ASPEED_UART_ROUTING
If you want to configure UART routing on Aspeed BMC platforms, enable
this option.
@@ -66,14 +66,17 @@ index 8e2fc51dcc44..1279a9674537 100644
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index 0f00eb63556c..f4951a6e435b 100644
+index 8f70b888a9ca..30ee065491ef 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
-@@ -62,3 +62,4 @@ obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
+@@ -59,6 +59,7 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
+ obj-$(CONFIG_ASPEED_UART_ROUTING) += aspeed-uart-routing.o
+ obj-$(CONFIG_ASPEED_LPC_MBOX) += aspeed-lpc-mbox.o
+ obj-$(CONFIG_ASPEED_LPC_SIO) += aspeed-lpc-sio.o
++obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o
obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o
obj-$(CONFIG_OCXL) += ocxl/
- obj-$(CONFIG_MISC_RTSX) += cardreader/
-+obj-$(CONFIG_ASPEED_VGA_SHAREDMEM) += aspeed-vga-sharedmem.o
+ obj-y += cardreader/
diff --git a/drivers/misc/aspeed-vga-sharedmem.c b/drivers/misc/aspeed-vga-sharedmem.c
new file mode 100644
index 000000000000..76f60cd67d3a
@@ -245,5 +248,5 @@ index 000000000000..76f60cd67d3a
+MODULE_DESCRIPTION("Shared VGA memory");
+MODULE_LICENSE("GPL v2");
--
-2.16.2
+2.7.4
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0036-net-ncsi-backport-ncsi-patches.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0036-net-ncsi-backport-ncsi-patches.patch
deleted file mode 100644
index 83717369c..000000000
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0036-net-ncsi-backport-ncsi-patches.patch
+++ /dev/null
@@ -1,1425 +0,0 @@
-From 58c3299017c5e6022fb2a2a74b662b2a4c0306f5 Mon Sep 17 00:00:00 2001
-From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
-Date: Tue, 20 Nov 2018 10:14:47 -0800
-Subject: [PATCH] net/ncsi: backport ncsi patches
-
-net/ncsi: Allow enabling multiple packages & channels
-
-This series extends the NCSI driver to configure multiple packages
-and/or channels simultaneously. Since the RFC series this includes a few
-extra changes to fix areas in the driver that either made this harder or
-were roadblocks due to deviations from the NCSI specification.
-
-Patches 1 & 2 fix two issues where the driver made assumptions about the
-capabilities of the NCSI topology.
-Patches 3 & 4 change some internal semantics slightly to make multi-mode
-easier.
-Patch 5 introduces a cleaner way of reconfiguring the NCSI configuration
-and keeping track of channel states.
-Patch 6 implements the main multi-package/multi-channel configuration,
-configured via the Netlink interface.
-
-Readers who have an interesting NCSI setup - especially multi-package
-with HWA - please test! I think I've covered all permutations but I
-don't have infinite hardware to test on.
-
-net/ncsi: Don't enable all channels when HWA available
-
-NCSI hardware arbitration allows multiple packages to be enabled at once
-and share the same wiring. If the NCSI driver recognises that HWA is
-available it unconditionally enables all packages and channels; but that
-is a configuration decision rather than something required by HWA.
-Additionally the current implementation will not failover on link events
-which can cause connectivity to be lost unless the interface is manually
-bounced.
-
-Retain basic HWA support but remove the separate configuration path to
-enable all channels, leaving this to be handled by a later
-implementation.
-
-net/ncsi: Probe single packages to avoid conflict
-
-Currently the NCSI driver sends a select-package command to all possible
-packages simultaneously to discover what packages are available. However
-at this stage in the probe process the driver does not know if
-hardware arbitration is available: if it isn't then this process could
-cause collisions on the RMII bus when packages try to respond.
-
-Update the probe loop to probe each package one by one, and once
-complete check if HWA is universally supported.
-
-net/ncsi: Don't deselect package in suspend if active
-
-When a package is deselected all channels of that package cease
-communication. If there are other channels active on the package of the
-suspended channel this will disable them as well, so only send a
-deselect-package command if no other channels are active.
-
-net/ncsi: Don't mark configured channels inactive
-
-The concepts of a channel being 'active' and it having link are slightly
-muddled in the NCSI driver. Tweak this slightly so that
-NCSI_CHANNEL_ACTIVE represents a channel that has been configured and
-enabled, and NCSI_CHANNEL_INACTIVE represents a de-configured channel.
-This distinction is important because a channel can be 'active' but have
-its link down; in this case the channel may still need to be configured
-so that it may receive AEN link-state-change packets.
-
-net/ncsi: Reset channel state in ncsi_start_dev()
-
-When the NCSI driver is stopped with ncsi_stop_dev() the channel
-monitors are stopped and the state set to "inactive". However the
-channels are still configured and active from the perspective of the
-network controller. We should suspend each active channel but in the
-context of ncsi_stop_dev() the transmit queue has been or is about to be
-stopped so we won't have time to do so.
-
-Instead when ncsi_start_dev() is called if the NCSI topology has already
-been probed then call ncsi_reset_dev() to suspend any channels that were
-previously active. This resets the network controller to a known state,
-provides an up to date view of channel link state, and makes sure that
-mode flags such as NCSI_MODE_TX_ENABLE are properly reset.
-
-In addition to ncsi_start_dev() use ncsi_reset_dev() in ncsi-netlink.c
-to update the channel configuration more cleanly.
-
-net/ncsi: Configure multi-package, multi-channel modes with failover
-
-This patch extends the ncsi-netlink interface with two new commands and
-three new attributes to configure multiple packages and/or channels at
-once, and configure specific failover modes.
-
-NCSI_CMD_SET_PACKAGE mask and NCSI_CMD_SET_CHANNEL_MASK set a whitelist
-of packages or channels allowed to be configured with the
-NCSI_ATTR_PACKAGE_MASK and NCSI_ATTR_CHANNEL_MASK attributes
-respectively. If one of these whitelists is set only packages or
-channels matching the whitelist are considered for the channel queue in
-ncsi_choose_active_channel().
-
-These commands may also use the NCSI_ATTR_MULTI_FLAG to signal that
-multiple packages or channels may be configured simultaneously. NCSI
-hardware arbitration (HWA) must be available in order to enable
-multi-package mode. Multi-channel mode is always available.
-
-If the NCSI_ATTR_CHANNEL_ID attribute is present in the
-NCSI_CMD_SET_CHANNEL_MASK command the it sets the preferred channel as
-with the NCSI_CMD_SET_INTERFACE command. The combination of preferred
-channel and channel whitelist defines a primary channel and the allowed
-failover channels.
-If the NCSI_ATTR_MULTI_FLAG attribute is also present then the preferred
-channel is configured for Tx/Rx and the other channels are enabled only
-for Rx.
-
-Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
-Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
----
- include/uapi/linux/ncsi.h | 15 ++
- net/ncsi/internal.h | 19 +-
- net/ncsi/ncsi-aen.c | 75 +++++--
- net/ncsi/ncsi-manage.c | 522 ++++++++++++++++++++++++++++++++--------------
- net/ncsi/ncsi-netlink.c | 233 ++++++++++++++++++---
- net/ncsi/ncsi-rsp.c | 2 +-
- 6 files changed, 660 insertions(+), 206 deletions(-)
-
-diff --git a/include/uapi/linux/ncsi.h b/include/uapi/linux/ncsi.h
-index 0a26a5576645..a3f87c54fdb3 100644
---- a/include/uapi/linux/ncsi.h
-+++ b/include/uapi/linux/ncsi.h
-@@ -26,6 +26,12 @@
- * @NCSI_CMD_SEND_CMD: send NC-SI command to network card.
- * Requires NCSI_ATTR_IFINDEX, NCSI_ATTR_PACKAGE_ID
- * and NCSI_ATTR_CHANNEL_ID.
-+ * @NCSI_CMD_SET_PACKAGE_MASK: set a whitelist of allowed packages.
-+ * Requires NCSI_ATTR_IFINDEX and NCSI_ATTR_PACKAGE_MASK.
-+ * @NCSI_CMD_SET_CHANNEL_MASK: set a whitelist of allowed channels.
-+ * Requires NCSI_ATTR_IFINDEX, NCSI_ATTR_PACKAGE_ID, and
-+ * NCSI_ATTR_CHANNEL_MASK. If NCSI_ATTR_CHANNEL_ID is present it sets
-+ * the primary channel.
- * @NCSI_CMD_MAX: highest command number
- */
- enum ncsi_nl_commands {
-@@ -34,6 +40,8 @@ enum ncsi_nl_commands {
- NCSI_CMD_SET_INTERFACE,
- NCSI_CMD_CLEAR_INTERFACE,
- NCSI_CMD_SEND_CMD,
-+ NCSI_CMD_SET_PACKAGE_MASK,
-+ NCSI_CMD_SET_CHANNEL_MASK,
-
- __NCSI_CMD_AFTER_LAST,
- NCSI_CMD_MAX = __NCSI_CMD_AFTER_LAST - 1
-@@ -48,6 +56,10 @@ enum ncsi_nl_commands {
- * @NCSI_ATTR_PACKAGE_ID: package ID
- * @NCSI_ATTR_CHANNEL_ID: channel ID
- * @NCSI_ATTR_DATA: command payload
-+ * @NCSI_ATTR_MULTI_FLAG: flag to signal that multi-mode should be enabled with
-+ * NCSI_CMD_SET_PACKAGE_MASK or NCSI_CMD_SET_CHANNEL_MASK.
-+ * @NCSI_ATTR_PACKAGE_MASK: 32-bit mask of allowed packages.
-+ * @NCSI_ATTR_CHANNEL_MASK: 32-bit mask of allowed channels.
- * @NCSI_ATTR_MAX: highest attribute number
- */
- enum ncsi_nl_attrs {
-@@ -57,6 +69,9 @@ enum ncsi_nl_attrs {
- NCSI_ATTR_PACKAGE_ID,
- NCSI_ATTR_CHANNEL_ID,
- NCSI_ATTR_DATA,
-+ NCSI_ATTR_MULTI_FLAG,
-+ NCSI_ATTR_PACKAGE_MASK,
-+ NCSI_ATTR_CHANNEL_MASK,
-
- __NCSI_ATTR_AFTER_LAST,
- NCSI_ATTR_MAX = __NCSI_ATTR_AFTER_LAST - 1
-diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
-index 1dae77c54009..9e3642b802c4 100644
---- a/net/ncsi/internal.h
-+++ b/net/ncsi/internal.h
-@@ -222,6 +222,10 @@ struct ncsi_package {
- unsigned int channel_num; /* Number of channels */
- struct list_head channels; /* List of chanels */
- struct list_head node; /* Form list of packages */
-+
-+ bool multi_channel; /* Enable multiple channels */
-+ u32 channel_whitelist; /* Channels to configure */
-+ struct ncsi_channel *preferred_channel; /* Primary channel */
- };
-
- struct ncsi_request {
-@@ -287,16 +291,16 @@ struct ncsi_dev_priv {
- #define NCSI_DEV_PROBED 1 /* Finalized NCSI topology */
- #define NCSI_DEV_HWA 2 /* Enabled HW arbitration */
- #define NCSI_DEV_RESHUFFLE 4
-+#define NCSI_DEV_RESET 8 /* Reset state of NC */
- unsigned int gma_flag; /* OEM GMA flag */
- spinlock_t lock; /* Protect the NCSI device */
- #if IS_ENABLED(CONFIG_IPV6)
- unsigned int inet6_addr_num; /* Number of IPv6 addresses */
- #endif
-+ unsigned int package_probe_id;/* Current ID during probe */
- unsigned int package_num; /* Number of packages */
- struct list_head packages; /* List of packages */
- struct ncsi_channel *hot_channel; /* Channel was ever active */
-- struct ncsi_package *force_package; /* Force a specific package */
-- struct ncsi_channel *force_channel; /* Force a specific channel */
- struct ncsi_request requests[256]; /* Request table */
- unsigned int request_id; /* Last used request ID */
- #define NCSI_REQ_START_IDX 1
-@@ -309,6 +313,9 @@ struct ncsi_dev_priv {
- struct list_head node; /* Form NCSI device list */
- #define NCSI_MAX_VLAN_VIDS 15
- struct list_head vlan_vids; /* List of active VLAN IDs */
-+
-+ bool multi_package; /* Enable multiple packages */
-+ u32 package_whitelist; /* Packages to configure */
- };
-
- struct ncsi_cmd_arg {
-@@ -341,6 +348,7 @@ extern spinlock_t ncsi_dev_lock;
- list_for_each_entry_rcu(nc, &np->channels, node)
-
- /* Resources */
-+int ncsi_reset_dev(struct ncsi_dev *nd);
- void ncsi_start_channel_monitor(struct ncsi_channel *nc);
- void ncsi_stop_channel_monitor(struct ncsi_channel *nc);
- struct ncsi_channel *ncsi_find_channel(struct ncsi_package *np,
-@@ -361,6 +369,13 @@ struct ncsi_request *ncsi_alloc_request(struct ncsi_dev_priv *ndp,
- void ncsi_free_request(struct ncsi_request *nr);
- struct ncsi_dev *ncsi_find_dev(struct net_device *dev);
- int ncsi_process_next_channel(struct ncsi_dev_priv *ndp);
-+bool ncsi_channel_has_link(struct ncsi_channel *channel);
-+bool ncsi_channel_is_last(struct ncsi_dev_priv *ndp,
-+ struct ncsi_channel *channel);
-+int ncsi_update_tx_channel(struct ncsi_dev_priv *ndp,
-+ struct ncsi_package *np,
-+ struct ncsi_channel *disable,
-+ struct ncsi_channel *enable);
-
- /* Packet handlers */
- u32 ncsi_calculate_checksum(unsigned char *data, int len);
-diff --git a/net/ncsi/ncsi-aen.c b/net/ncsi/ncsi-aen.c
-index 25e483e8278b..26d67e27551f 100644
---- a/net/ncsi/ncsi-aen.c
-+++ b/net/ncsi/ncsi-aen.c
-@@ -50,13 +50,15 @@ static int ncsi_validate_aen_pkt(struct ncsi_aen_pkt_hdr *h,
- static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
- struct ncsi_aen_pkt_hdr *h)
- {
-- struct ncsi_aen_lsc_pkt *lsc;
-- struct ncsi_channel *nc;
-+ struct ncsi_channel *nc, *tmp;
- struct ncsi_channel_mode *ncm;
-- bool chained;
-- int state;
- unsigned long old_data, data;
-+ struct ncsi_aen_lsc_pkt *lsc;
-+ struct ncsi_package *np;
-+ bool had_link, has_link;
- unsigned long flags;
-+ bool chained;
-+ int state;
-
- /* Find the NCSI channel */
- ncsi_find_package_and_channel(ndp, h->common.channel, NULL, &nc);
-@@ -73,6 +75,9 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
- ncm->data[2] = data;
- ncm->data[4] = ntohl(lsc->oem_status);
-
-+ had_link = !!(old_data & 0x1);
-+ has_link = !!(data & 0x1);
-+
- netdev_dbg(ndp->ndev.dev, "NCSI: LSC AEN - channel %u state %s\n",
- nc->id, data & 0x1 ? "up" : "down");
-
-@@ -80,22 +85,60 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
- state = nc->state;
- spin_unlock_irqrestore(&nc->lock, flags);
-
-- if (!((old_data ^ data) & 0x1) || chained)
-- return 0;
-- if (!(state == NCSI_CHANNEL_INACTIVE && (data & 0x1)) &&
-- !(state == NCSI_CHANNEL_ACTIVE && !(data & 0x1)))
-+ if (state == NCSI_CHANNEL_INACTIVE)
-+ netdev_warn(ndp->ndev.dev,
-+ "NCSI: Inactive channel %u received AEN!\n",
-+ nc->id);
-+
-+ if ((had_link == has_link) || chained)
- return 0;
-
-- if (!(ndp->flags & NCSI_DEV_HWA) &&
-- state == NCSI_CHANNEL_ACTIVE)
-- ndp->flags |= NCSI_DEV_RESHUFFLE;
-+ if (!ndp->multi_package && !nc->package->multi_channel) {
-+ if (had_link) {
-+ ndp->flags |= NCSI_DEV_RESHUFFLE;
-+ ncsi_stop_channel_monitor(nc);
-+ spin_lock_irqsave(&ndp->lock, flags);
-+ list_add_tail_rcu(&nc->link, &ndp->channel_queue);
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+ return ncsi_process_next_channel(ndp);
-+ }
-+ /* Configured channel came up */
-+ return 0;
-+ }
-
-- ncsi_stop_channel_monitor(nc);
-- spin_lock_irqsave(&ndp->lock, flags);
-- list_add_tail_rcu(&nc->link, &ndp->channel_queue);
-- spin_unlock_irqrestore(&ndp->lock, flags);
-+ if (had_link) {
-+ ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
-+ if (ncsi_channel_is_last(ndp, nc)) {
-+ /* No channels left, reconfigure */
-+ return ncsi_reset_dev(&ndp->ndev);
-+ } else if (ncm->enable) {
-+ /* Need to failover Tx channel */
-+ ncsi_update_tx_channel(ndp, nc->package, nc, NULL);
-+ }
-+ } else if (has_link && nc->package->preferred_channel == nc) {
-+ /* Return Tx to preferred channel */
-+ ncsi_update_tx_channel(ndp, nc->package, NULL, nc);
-+ } else if (has_link) {
-+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
-+ NCSI_FOR_EACH_CHANNEL(np, tmp) {
-+ /* Enable Tx on this channel if the current Tx
-+ * channel is down.
-+ */
-+ ncm = &tmp->modes[NCSI_MODE_TX_ENABLE];
-+ if (ncm->enable &&
-+ !ncsi_channel_has_link(tmp)) {
-+ ncsi_update_tx_channel(ndp, nc->package,
-+ tmp, nc);
-+ break;
-+ }
-+ }
-+ }
-+ }
-
-- return ncsi_process_next_channel(ndp);
-+ /* Leave configured channels active in a multi-channel scenario so
-+ * AEN events are still received.
-+ */
-+ return 0;
- }
-
- static int ncsi_aen_handler_cr(struct ncsi_dev_priv *ndp,
-diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
-index bfc43b28c7a6..92e59f07f9a7 100644
---- a/net/ncsi/ncsi-manage.c
-+++ b/net/ncsi/ncsi-manage.c
-@@ -28,6 +28,29 @@
- LIST_HEAD(ncsi_dev_list);
- DEFINE_SPINLOCK(ncsi_dev_lock);
-
-+bool ncsi_channel_has_link(struct ncsi_channel *channel)
-+{
-+ return !!(channel->modes[NCSI_MODE_LINK].data[2] & 0x1);
-+}
-+
-+bool ncsi_channel_is_last(struct ncsi_dev_priv *ndp,
-+ struct ncsi_channel *channel)
-+{
-+ struct ncsi_package *np;
-+ struct ncsi_channel *nc;
-+
-+ NCSI_FOR_EACH_PACKAGE(ndp, np)
-+ NCSI_FOR_EACH_CHANNEL(np, nc) {
-+ if (nc == channel)
-+ continue;
-+ if (nc->state == NCSI_CHANNEL_ACTIVE &&
-+ ncsi_channel_has_link(nc))
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
- static void ncsi_report_link(struct ncsi_dev_priv *ndp, bool force_down)
- {
- struct ncsi_dev *nd = &ndp->ndev;
-@@ -52,7 +75,7 @@ static void ncsi_report_link(struct ncsi_dev_priv *ndp, bool force_down)
- continue;
- }
-
-- if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
-+ if (ncsi_channel_has_link(nc)) {
- spin_unlock_irqrestore(&nc->lock, flags);
- nd->link_up = 1;
- goto report;
-@@ -113,10 +136,8 @@ static void ncsi_channel_monitor(struct timer_list *t)
- default:
- netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n",
- nc->id);
-- if (!(ndp->flags & NCSI_DEV_HWA)) {
-- ncsi_report_link(ndp, true);
-- ndp->flags |= NCSI_DEV_RESHUFFLE;
-- }
-+ ncsi_report_link(ndp, true);
-+ ndp->flags |= NCSI_DEV_RESHUFFLE;
-
- ncsi_stop_channel_monitor(nc);
-
-@@ -269,6 +290,7 @@ struct ncsi_package *ncsi_add_package(struct ncsi_dev_priv *ndp,
- np->ndp = ndp;
- spin_lock_init(&np->lock);
- INIT_LIST_HEAD(&np->channels);
-+ np->channel_whitelist = UINT_MAX;
-
- spin_lock_irqsave(&ndp->lock, flags);
- tmp = ncsi_find_package(ndp, id);
-@@ -442,12 +464,14 @@ static void ncsi_request_timeout(struct timer_list *t)
- static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
- {
- struct ncsi_dev *nd = &ndp->ndev;
-- struct ncsi_package *np = ndp->active_package;
-- struct ncsi_channel *nc = ndp->active_channel;
-+ struct ncsi_package *np;
-+ struct ncsi_channel *nc, *tmp;
- struct ncsi_cmd_arg nca;
- unsigned long flags;
- int ret;
-
-+ np = ndp->active_package;
-+ nc = ndp->active_channel;
- nca.ndp = ndp;
- nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN;
- switch (nd->state) {
-@@ -523,6 +547,15 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
- if (ret)
- goto error;
-
-+ NCSI_FOR_EACH_CHANNEL(np, tmp) {
-+ /* If there is another channel active on this package
-+ * do not deselect the package.
-+ */
-+ if (tmp != nc && tmp->state == NCSI_CHANNEL_ACTIVE) {
-+ nd->state = ncsi_dev_state_suspend_done;
-+ break;
-+ }
-+ }
- break;
- case ncsi_dev_state_suspend_deselect:
- ndp->pending_req_num = 1;
-@@ -541,8 +574,10 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
- spin_lock_irqsave(&nc->lock, flags);
- nc->state = NCSI_CHANNEL_INACTIVE;
- spin_unlock_irqrestore(&nc->lock, flags);
-- ncsi_process_next_channel(ndp);
--
-+ if (ndp->flags & NCSI_DEV_RESET)
-+ ncsi_reset_dev(nd);
-+ else
-+ ncsi_process_next_channel(ndp);
- break;
- default:
- netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n",
-@@ -717,13 +752,144 @@ static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)
-
- #endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
-
-+/* Determine if a given channel from the channel_queue should be used for Tx */
-+static bool ncsi_channel_is_tx(struct ncsi_dev_priv *ndp,
-+ struct ncsi_channel *nc)
-+{
-+ struct ncsi_channel_mode *ncm;
-+ struct ncsi_channel *channel;
-+ struct ncsi_package *np;
-+
-+ /* Check if any other channel has Tx enabled; a channel may have already
-+ * been configured and removed from the channel queue.
-+ */
-+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
-+ if (!ndp->multi_package && np != nc->package)
-+ continue;
-+ NCSI_FOR_EACH_CHANNEL(np, channel) {
-+ ncm = &channel->modes[NCSI_MODE_TX_ENABLE];
-+ if (ncm->enable)
-+ return false;
-+ }
-+ }
-+
-+ /* This channel is the preferred channel and has link */
-+ list_for_each_entry_rcu(channel, &ndp->channel_queue, link) {
-+ np = channel->package;
-+ if (np->preferred_channel &&
-+ ncsi_channel_has_link(np->preferred_channel)) {
-+ return np->preferred_channel == nc;
-+ }
-+ }
-+
-+ /* This channel has link */
-+ if (ncsi_channel_has_link(nc))
-+ return true;
-+
-+ list_for_each_entry_rcu(channel, &ndp->channel_queue, link)
-+ if (ncsi_channel_has_link(channel))
-+ return false;
-+
-+ /* No other channel has link; default to this one */
-+ return true;
-+}
-+
-+/* Change the active Tx channel in a multi-channel setup */
-+int ncsi_update_tx_channel(struct ncsi_dev_priv *ndp,
-+ struct ncsi_package *package,
-+ struct ncsi_channel *disable,
-+ struct ncsi_channel *enable)
-+{
-+ struct ncsi_cmd_arg nca;
-+ struct ncsi_channel *nc;
-+ struct ncsi_package *np;
-+ int ret = 0;
-+
-+ if (!package->multi_channel && !ndp->multi_package)
-+ netdev_warn(ndp->ndev.dev,
-+ "NCSI: Trying to update Tx channel in single-channel mode\n");
-+ nca.ndp = ndp;
-+ nca.req_flags = 0;
-+
-+ /* Find current channel with Tx enabled */
-+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
-+ if (disable)
-+ break;
-+ if (!ndp->multi_package && np != package)
-+ continue;
-+
-+ NCSI_FOR_EACH_CHANNEL(np, nc)
-+ if (nc->modes[NCSI_MODE_TX_ENABLE].enable) {
-+ disable = nc;
-+ break;
-+ }
-+ }
-+
-+ /* Find a suitable channel for Tx */
-+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
-+ if (enable)
-+ break;
-+ if (!ndp->multi_package && np != package)
-+ continue;
-+ if (!(ndp->package_whitelist & (0x1 << np->id)))
-+ continue;
-+
-+ if (np->preferred_channel &&
-+ ncsi_channel_has_link(np->preferred_channel)) {
-+ enable = np->preferred_channel;
-+ break;
-+ }
-+
-+ NCSI_FOR_EACH_CHANNEL(np, nc) {
-+ if (!(np->channel_whitelist & 0x1 << nc->id))
-+ continue;
-+ if (nc->state != NCSI_CHANNEL_ACTIVE)
-+ continue;
-+ if (ncsi_channel_has_link(nc)) {
-+ enable = nc;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (disable == enable)
-+ return -1;
-+
-+ if (!enable)
-+ return -1;
-+
-+ if (disable) {
-+ nca.channel = disable->id;
-+ nca.package = disable->package->id;
-+ nca.type = NCSI_PKT_CMD_DCNT;
-+ ret = ncsi_xmit_cmd(&nca);
-+ if (ret)
-+ netdev_err(ndp->ndev.dev,
-+ "Error %d sending DCNT\n",
-+ ret);
-+ }
-+
-+ netdev_info(ndp->ndev.dev, "NCSI: channel %u enables Tx\n", enable->id);
-+
-+ nca.channel = enable->id;
-+ nca.package = enable->package->id;
-+ nca.type = NCSI_PKT_CMD_ECNT;
-+ ret = ncsi_xmit_cmd(&nca);
-+ if (ret)
-+ netdev_err(ndp->ndev.dev,
-+ "Error %d sending ECNT\n",
-+ ret);
-+
-+ return ret;
-+}
-+
- static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
- {
-- struct ncsi_dev *nd = &ndp->ndev;
-- struct net_device *dev = nd->dev;
- struct ncsi_package *np = ndp->active_package;
- struct ncsi_channel *nc = ndp->active_channel;
- struct ncsi_channel *hot_nc = NULL;
-+ struct ncsi_dev *nd = &ndp->ndev;
-+ struct net_device *dev = nd->dev;
- struct ncsi_cmd_arg nca;
- unsigned char index;
- unsigned long flags;
-@@ -845,20 +1011,29 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
- } else if (nd->state == ncsi_dev_state_config_ebf) {
- nca.type = NCSI_PKT_CMD_EBF;
- nca.dwords[0] = nc->caps[NCSI_CAP_BC].cap;
-- nd->state = ncsi_dev_state_config_ecnt;
-+ if (ncsi_channel_is_tx(ndp, nc))
-+ nd->state = ncsi_dev_state_config_ecnt;
-+ else
-+ nd->state = ncsi_dev_state_config_ec;
- #if IS_ENABLED(CONFIG_IPV6)
- if (ndp->inet6_addr_num > 0 &&
- (nc->caps[NCSI_CAP_GENERIC].cap &
- NCSI_CAP_GENERIC_MC))
- nd->state = ncsi_dev_state_config_egmf;
-- else
-- nd->state = ncsi_dev_state_config_ecnt;
- } else if (nd->state == ncsi_dev_state_config_egmf) {
- nca.type = NCSI_PKT_CMD_EGMF;
- nca.dwords[0] = nc->caps[NCSI_CAP_MC].cap;
-- nd->state = ncsi_dev_state_config_ecnt;
-+ if (ncsi_channel_is_tx(ndp, nc))
-+ nd->state = ncsi_dev_state_config_ecnt;
-+ else
-+ nd->state = ncsi_dev_state_config_ec;
- #endif /* CONFIG_IPV6 */
- } else if (nd->state == ncsi_dev_state_config_ecnt) {
-+ if (np->preferred_channel &&
-+ nc != np->preferred_channel)
-+ netdev_info(ndp->ndev.dev,
-+ "NCSI: Tx failed over to channel %u\n",
-+ nc->id);
- nca.type = NCSI_PKT_CMD_ECNT;
- nd->state = ncsi_dev_state_config_ec;
- } else if (nd->state == ncsi_dev_state_config_ec) {
-@@ -889,6 +1064,16 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
- netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n",
- nc->id);
- spin_lock_irqsave(&nc->lock, flags);
-+ nc->state = NCSI_CHANNEL_ACTIVE;
-+
-+ if (ndp->flags & NCSI_DEV_RESET) {
-+ /* A reset event happened during config, start it now */
-+ nc->reconfigure_needed = false;
-+ spin_unlock_irqrestore(&nc->lock, flags);
-+ ncsi_reset_dev(nd);
-+ break;
-+ }
-+
- if (nc->reconfigure_needed) {
- /* This channel's configuration has been updated
- * part-way during the config state - start the
-@@ -909,10 +1094,8 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
-
- if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
- hot_nc = nc;
-- nc->state = NCSI_CHANNEL_ACTIVE;
- } else {
- hot_nc = NULL;
-- nc->state = NCSI_CHANNEL_INACTIVE;
- netdev_dbg(ndp->ndev.dev,
- "NCSI: channel %u link down after config\n",
- nc->id);
-@@ -940,43 +1123,35 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
-
- static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
- {
-- struct ncsi_package *np, *force_package;
-- struct ncsi_channel *nc, *found, *hot_nc, *force_channel;
-+ struct ncsi_channel *nc, *found, *hot_nc;
- struct ncsi_channel_mode *ncm;
-- unsigned long flags;
-+ unsigned long flags, cflags;
-+ struct ncsi_package *np;
-+ bool with_link;
-
- spin_lock_irqsave(&ndp->lock, flags);
- hot_nc = ndp->hot_channel;
-- force_channel = ndp->force_channel;
-- force_package = ndp->force_package;
- spin_unlock_irqrestore(&ndp->lock, flags);
-
-- /* Force a specific channel whether or not it has link if we have been
-- * configured to do so
-- */
-- if (force_package && force_channel) {
-- found = force_channel;
-- ncm = &found->modes[NCSI_MODE_LINK];
-- if (!(ncm->data[2] & 0x1))
-- netdev_info(ndp->ndev.dev,
-- "NCSI: Channel %u forced, but it is link down\n",
-- found->id);
-- goto out;
-- }
--
-- /* The search is done once an inactive channel with up
-- * link is found.
-+ /* By default the search is done once an inactive channel with up
-+ * link is found, unless a preferred channel is set.
-+ * If multi_package or multi_channel are configured all channels in the
-+ * whitelist are added to the channel queue.
- */
- found = NULL;
-+ with_link = false;
- NCSI_FOR_EACH_PACKAGE(ndp, np) {
-- if (ndp->force_package && np != ndp->force_package)
-+ if (!(ndp->package_whitelist & (0x1 << np->id)))
- continue;
- NCSI_FOR_EACH_CHANNEL(np, nc) {
-- spin_lock_irqsave(&nc->lock, flags);
-+ if (!(np->channel_whitelist & (0x1 << nc->id)))
-+ continue;
-+
-+ spin_lock_irqsave(&nc->lock, cflags);
-
- if (!list_empty(&nc->link) ||
- nc->state != NCSI_CHANNEL_INACTIVE) {
-- spin_unlock_irqrestore(&nc->lock, flags);
-+ spin_unlock_irqrestore(&nc->lock, cflags);
- continue;
- }
-
-@@ -988,32 +1163,49 @@ static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
-
- ncm = &nc->modes[NCSI_MODE_LINK];
- if (ncm->data[2] & 0x1) {
-- spin_unlock_irqrestore(&nc->lock, flags);
- found = nc;
-- goto out;
-+ with_link = true;
- }
-
-- spin_unlock_irqrestore(&nc->lock, flags);
-+ /* If multi_channel is enabled configure all valid
-+ * channels whether or not they currently have link
-+ * so they will have AENs enabled.
-+ */
-+ if (with_link || np->multi_channel) {
-+ spin_lock_irqsave(&ndp->lock, flags);
-+ list_add_tail_rcu(&nc->link,
-+ &ndp->channel_queue);
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+
-+ netdev_dbg(ndp->ndev.dev,
-+ "NCSI: Channel %u added to queue (link %s)\n",
-+ nc->id,
-+ ncm->data[2] & 0x1 ? "up" : "down");
-+ }
-+
-+ spin_unlock_irqrestore(&nc->lock, cflags);
-+
-+ if (with_link && !np->multi_channel)
-+ break;
- }
-+ if (with_link && !ndp->multi_package)
-+ break;
- }
-
-- if (!found) {
-+ if (list_empty(&ndp->channel_queue) && found) {
-+ netdev_info(ndp->ndev.dev,
-+ "NCSI: No channel with link found, configuring channel %u\n",
-+ found->id);
-+ spin_lock_irqsave(&ndp->lock, flags);
-+ list_add_tail_rcu(&found->link, &ndp->channel_queue);
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+ } else if (!found) {
- netdev_warn(ndp->ndev.dev,
-- "NCSI: No channel found with link\n");
-+ "NCSI: No channel found to configure!\n");
- ncsi_report_link(ndp, true);
- return -ENODEV;
- }
-
-- ncm = &found->modes[NCSI_MODE_LINK];
-- netdev_dbg(ndp->ndev.dev,
-- "NCSI: Channel %u added to queue (link %s)\n",
-- found->id, ncm->data[2] & 0x1 ? "up" : "down");
--
--out:
-- spin_lock_irqsave(&ndp->lock, flags);
-- list_add_tail_rcu(&found->link, &ndp->channel_queue);
-- spin_unlock_irqrestore(&ndp->lock, flags);
--
- return ncsi_process_next_channel(ndp);
- }
-
-@@ -1050,35 +1242,6 @@ static bool ncsi_check_hwa(struct ncsi_dev_priv *ndp)
- return false;
- }
-
--static int ncsi_enable_hwa(struct ncsi_dev_priv *ndp)
--{
-- struct ncsi_package *np;
-- struct ncsi_channel *nc;
-- unsigned long flags;
--
-- /* Move all available channels to processing queue */
-- spin_lock_irqsave(&ndp->lock, flags);
-- NCSI_FOR_EACH_PACKAGE(ndp, np) {
-- NCSI_FOR_EACH_CHANNEL(np, nc) {
-- WARN_ON_ONCE(nc->state != NCSI_CHANNEL_INACTIVE ||
-- !list_empty(&nc->link));
-- ncsi_stop_channel_monitor(nc);
-- list_add_tail_rcu(&nc->link, &ndp->channel_queue);
-- }
-- }
-- spin_unlock_irqrestore(&ndp->lock, flags);
--
-- /* We can have no channels in extremely case */
-- if (list_empty(&ndp->channel_queue)) {
-- netdev_err(ndp->ndev.dev,
-- "NCSI: No available channels for HWA\n");
-- ncsi_report_link(ndp, false);
-- return -ENOENT;
-- }
--
-- return ncsi_process_next_channel(ndp);
--}
--
- static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
- {
- struct ncsi_dev *nd = &ndp->ndev;
-@@ -1110,70 +1273,28 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
- nd->state = ncsi_dev_state_probe_package;
- break;
- case ncsi_dev_state_probe_package:
-- ndp->pending_req_num = 16;
-+ ndp->pending_req_num = 1;
-
-- /* Select all possible packages */
- nca.type = NCSI_PKT_CMD_SP;
- nca.bytes[0] = 1;
-+ nca.package = ndp->package_probe_id;
- nca.channel = NCSI_RESERVED_CHANNEL;
-- for (index = 0; index < 8; index++) {
-- nca.package = index;
-- ret = ncsi_xmit_cmd(&nca);
-- if (ret)
-- goto error;
-- }
--
-- /* Disable all possible packages */
-- nca.type = NCSI_PKT_CMD_DP;
-- for (index = 0; index < 8; index++) {
-- nca.package = index;
-- ret = ncsi_xmit_cmd(&nca);
-- if (ret)
-- goto error;
-- }
--
-+ ret = ncsi_xmit_cmd(&nca);
-+ if (ret)
-+ goto error;
- nd->state = ncsi_dev_state_probe_channel;
- break;
- case ncsi_dev_state_probe_channel:
-- if (!ndp->active_package)
-- ndp->active_package = list_first_or_null_rcu(
-- &ndp->packages, struct ncsi_package, node);
-- else if (list_is_last(&ndp->active_package->node,
-- &ndp->packages))
-- ndp->active_package = NULL;
-- else
-- ndp->active_package = list_next_entry(
-- ndp->active_package, node);
--
-- /* All available packages and channels are enumerated. The
-- * enumeration happens for once when the NCSI interface is
-- * started. So we need continue to start the interface after
-- * the enumeration.
-- *
-- * We have to choose an active channel before configuring it.
-- * Note that we possibly don't have active channel in extreme
-- * situation.
-- */
-+ ndp->active_package = ncsi_find_package(ndp,
-+ ndp->package_probe_id);
- if (!ndp->active_package) {
-- ndp->flags |= NCSI_DEV_PROBED;
-- if (ncsi_check_hwa(ndp))
-- ncsi_enable_hwa(ndp);
-- else
-- ncsi_choose_active_channel(ndp);
-- return;
-+ /* No response */
-+ nd->state = ncsi_dev_state_probe_dp;
-+ schedule_work(&ndp->work);
-+ break;
- }
--
-- /* Select the active package */
-- ndp->pending_req_num = 1;
-- nca.type = NCSI_PKT_CMD_SP;
-- nca.bytes[0] = 1;
-- nca.package = ndp->active_package->id;
-- nca.channel = NCSI_RESERVED_CHANNEL;
-- ret = ncsi_xmit_cmd(&nca);
-- if (ret)
-- goto error;
--
- nd->state = ncsi_dev_state_probe_cis;
-+ schedule_work(&ndp->work);
- break;
- case ncsi_dev_state_probe_cis:
- ndp->pending_req_num = NCSI_RESERVED_CHANNEL;
-@@ -1222,22 +1343,35 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
- case ncsi_dev_state_probe_dp:
- ndp->pending_req_num = 1;
-
-- /* Deselect the active package */
-+ /* Deselect the current package */
- nca.type = NCSI_PKT_CMD_DP;
-- nca.package = ndp->active_package->id;
-+ nca.package = ndp->package_probe_id;
- nca.channel = NCSI_RESERVED_CHANNEL;
- ret = ncsi_xmit_cmd(&nca);
- if (ret)
- goto error;
-
-- /* Scan channels in next package */
-- nd->state = ncsi_dev_state_probe_channel;
-+ /* Probe next package */
-+ ndp->package_probe_id++;
-+ if (ndp->package_probe_id >= 8) {
-+ /* Probe finished */
-+ ndp->flags |= NCSI_DEV_PROBED;
-+ break;
-+ }
-+ nd->state = ncsi_dev_state_probe_package;
-+ ndp->active_package = NULL;
- break;
- default:
- netdev_warn(nd->dev, "Wrong NCSI state 0x%0x in enumeration\n",
- nd->state);
- }
-
-+ if (ndp->flags & NCSI_DEV_PROBED) {
-+ /* Check if all packages have HWA support */
-+ ncsi_check_hwa(ndp);
-+ ncsi_choose_active_channel(ndp);
-+ }
-+
- return;
- error:
- netdev_err(ndp->ndev.dev,
-@@ -1556,6 +1690,7 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
- INIT_LIST_HEAD(&ndp->channel_queue);
- INIT_LIST_HEAD(&ndp->vlan_vids);
- INIT_WORK(&ndp->work, ncsi_dev_work);
-+ ndp->package_whitelist = UINT_MAX;
-
- /* Initialize private NCSI device */
- spin_lock_init(&ndp->lock);
-@@ -1592,26 +1727,19 @@ EXPORT_SYMBOL_GPL(ncsi_register_dev);
- int ncsi_start_dev(struct ncsi_dev *nd)
- {
- struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
-- int ret;
-
- if (nd->state != ncsi_dev_state_registered &&
- nd->state != ncsi_dev_state_functional)
- return -ENOTTY;
-
- if (!(ndp->flags & NCSI_DEV_PROBED)) {
-+ ndp->package_probe_id = 0;
- nd->state = ncsi_dev_state_probe;
- schedule_work(&ndp->work);
- return 0;
- }
-
-- if (ndp->flags & NCSI_DEV_HWA) {
-- netdev_info(ndp->ndev.dev, "NCSI: Enabling HWA mode\n");
-- ret = ncsi_enable_hwa(ndp);
-- } else {
-- ret = ncsi_choose_active_channel(ndp);
-- }
--
-- return ret;
-+ return ncsi_reset_dev(nd);
- }
- EXPORT_SYMBOL_GPL(ncsi_start_dev);
-
-@@ -1624,7 +1752,10 @@ void ncsi_stop_dev(struct ncsi_dev *nd)
- int old_state;
- unsigned long flags;
-
-- /* Stop the channel monitor and reset channel's state */
-+ /* Stop the channel monitor on any active channels. Don't reset the
-+ * channel state so we know which were active when ncsi_start_dev()
-+ * is next called.
-+ */
- NCSI_FOR_EACH_PACKAGE(ndp, np) {
- NCSI_FOR_EACH_CHANNEL(np, nc) {
- ncsi_stop_channel_monitor(nc);
-@@ -1632,7 +1763,6 @@ void ncsi_stop_dev(struct ncsi_dev *nd)
- spin_lock_irqsave(&nc->lock, flags);
- chained = !list_empty(&nc->link);
- old_state = nc->state;
-- nc->state = NCSI_CHANNEL_INACTIVE;
- spin_unlock_irqrestore(&nc->lock, flags);
-
- WARN_ON_ONCE(chained ||
-@@ -1645,6 +1775,92 @@ void ncsi_stop_dev(struct ncsi_dev *nd)
- }
- EXPORT_SYMBOL_GPL(ncsi_stop_dev);
-
-+int ncsi_reset_dev(struct ncsi_dev *nd)
-+{
-+ struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
-+ struct ncsi_channel *nc, *active, *tmp;
-+ struct ncsi_package *np;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&ndp->lock, flags);
-+
-+ if (!(ndp->flags & NCSI_DEV_RESET)) {
-+ /* Haven't been called yet, check states */
-+ switch (nd->state & ncsi_dev_state_major) {
-+ case ncsi_dev_state_registered:
-+ case ncsi_dev_state_probe:
-+ /* Not even probed yet - do nothing */
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+ return 0;
-+ case ncsi_dev_state_suspend:
-+ case ncsi_dev_state_config:
-+ /* Wait for the channel to finish its suspend/config
-+ * operation; once it finishes it will check for
-+ * NCSI_DEV_RESET and reset the state.
-+ */
-+ ndp->flags |= NCSI_DEV_RESET;
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+ return 0;
-+ }
-+ } else {
-+ switch (nd->state) {
-+ case ncsi_dev_state_suspend_done:
-+ case ncsi_dev_state_config_done:
-+ case ncsi_dev_state_functional:
-+ /* Ok */
-+ break;
-+ default:
-+ /* Current reset operation happening */
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+ return 0;
-+ }
-+ }
-+
-+ if (!list_empty(&ndp->channel_queue)) {
-+ /* Clear any channel queue we may have interrupted */
-+ list_for_each_entry_safe(nc, tmp, &ndp->channel_queue, link)
-+ list_del_init(&nc->link);
-+ }
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+
-+ active = NULL;
-+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
-+ NCSI_FOR_EACH_CHANNEL(np, nc) {
-+ spin_lock_irqsave(&nc->lock, flags);
-+
-+ if (nc->state == NCSI_CHANNEL_ACTIVE) {
-+ active = nc;
-+ nc->state = NCSI_CHANNEL_INVISIBLE;
-+ spin_unlock_irqrestore(&nc->lock, flags);
-+ ncsi_stop_channel_monitor(nc);
-+ break;
-+ }
-+
-+ spin_unlock_irqrestore(&nc->lock, flags);
-+ }
-+ if (active)
-+ break;
-+ }
-+
-+ if (!active) {
-+ /* Done */
-+ spin_lock_irqsave(&ndp->lock, flags);
-+ ndp->flags &= ~NCSI_DEV_RESET;
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+ return ncsi_choose_active_channel(ndp);
-+ }
-+
-+ spin_lock_irqsave(&ndp->lock, flags);
-+ ndp->flags |= NCSI_DEV_RESET;
-+ ndp->active_channel = active;
-+ ndp->active_package = active->package;
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+
-+ nd->state = ncsi_dev_state_suspend;
-+ schedule_work(&ndp->work);
-+ return 0;
-+}
-+
- void ncsi_unregister_dev(struct ncsi_dev *nd)
- {
- struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd);
-diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c
-index 33314381b4f5..5d782445d2fc 100644
---- a/net/ncsi/ncsi-netlink.c
-+++ b/net/ncsi/ncsi-netlink.c
-@@ -30,6 +30,9 @@ static const struct nla_policy ncsi_genl_policy[NCSI_ATTR_MAX + 1] = {
- [NCSI_ATTR_PACKAGE_ID] = { .type = NLA_U32 },
- [NCSI_ATTR_CHANNEL_ID] = { .type = NLA_U32 },
- [NCSI_ATTR_DATA] = { .type = NLA_BINARY, .len = 2048 },
-+ [NCSI_ATTR_MULTI_FLAG] = { .type = NLA_FLAG },
-+ [NCSI_ATTR_PACKAGE_MASK] = { .type = NLA_U32 },
-+ [NCSI_ATTR_CHANNEL_MASK] = { .type = NLA_U32 },
- };
-
- static struct ncsi_dev_priv *ndp_from_ifindex(struct net *net, u32 ifindex)
-@@ -69,7 +72,7 @@ static int ncsi_write_channel_info(struct sk_buff *skb,
- nla_put_u32(skb, NCSI_CHANNEL_ATTR_LINK_STATE, m->data[2]);
- if (nc->state == NCSI_CHANNEL_ACTIVE)
- nla_put_flag(skb, NCSI_CHANNEL_ATTR_ACTIVE);
-- if (ndp->force_channel == nc)
-+ if (nc == nc->package->preferred_channel)
- nla_put_flag(skb, NCSI_CHANNEL_ATTR_FORCED);
-
- nla_put_u32(skb, NCSI_CHANNEL_ATTR_VERSION_MAJOR, nc->version.version);
-@@ -114,7 +117,7 @@ static int ncsi_write_package_info(struct sk_buff *skb,
- if (!pnest)
- return -ENOMEM;
- nla_put_u32(skb, NCSI_PKG_ATTR_ID, np->id);
-- if (ndp->force_package == np)
-+ if ((0x1 << np->id) == ndp->package_whitelist)
- nla_put_flag(skb, NCSI_PKG_ATTR_FORCED);
- cnest = nla_nest_start(skb, NCSI_PKG_ATTR_CHANNEL_LIST);
- if (!cnest) {
-@@ -290,49 +293,58 @@ static int ncsi_set_interface_nl(struct sk_buff *msg, struct genl_info *info)
- package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]);
- package = NULL;
-
-- spin_lock_irqsave(&ndp->lock, flags);
--
- NCSI_FOR_EACH_PACKAGE(ndp, np)
- if (np->id == package_id)
- package = np;
- if (!package) {
- /* The user has set a package that does not exist */
-- spin_unlock_irqrestore(&ndp->lock, flags);
- return -ERANGE;
- }
-
- channel = NULL;
-- if (!info->attrs[NCSI_ATTR_CHANNEL_ID]) {
-- /* Allow any channel */
-- channel_id = NCSI_RESERVED_CHANNEL;
-- } else {
-+ if (info->attrs[NCSI_ATTR_CHANNEL_ID]) {
- channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]);
- NCSI_FOR_EACH_CHANNEL(package, nc)
-- if (nc->id == channel_id)
-+ if (nc->id == channel_id) {
- channel = nc;
-+ break;
-+ }
-+ if (!channel) {
-+ netdev_info(ndp->ndev.dev,
-+ "NCSI: Channel %u does not exist!\n",
-+ channel_id);
-+ return -ERANGE;
-+ }
- }
-
-- if (channel_id != NCSI_RESERVED_CHANNEL && !channel) {
-- /* The user has set a channel that does not exist on this
-- * package
-- */
-- spin_unlock_irqrestore(&ndp->lock, flags);
-- netdev_info(ndp->ndev.dev, "NCSI: Channel %u does not exist!\n",
-- channel_id);
-- return -ERANGE;
-- }
--
-- ndp->force_package = package;
-- ndp->force_channel = channel;
-+ spin_lock_irqsave(&ndp->lock, flags);
-+ ndp->package_whitelist = 0x1 << package->id;
-+ ndp->multi_package = false;
- spin_unlock_irqrestore(&ndp->lock, flags);
-
-- netdev_info(ndp->ndev.dev, "Set package 0x%x, channel 0x%x%s as preferred\n",
-- package_id, channel_id,
-- channel_id == NCSI_RESERVED_CHANNEL ? " (any)" : "");
-+ spin_lock_irqsave(&package->lock, flags);
-+ package->multi_channel = false;
-+ if (channel) {
-+ package->channel_whitelist = 0x1 << channel->id;
-+ package->preferred_channel = channel;
-+ } else {
-+ /* Allow any channel */
-+ package->channel_whitelist = UINT_MAX;
-+ package->preferred_channel = NULL;
-+ }
-+ spin_unlock_irqrestore(&package->lock, flags);
-+
-+ if (channel)
-+ netdev_info(ndp->ndev.dev,
-+ "Set package 0x%x, channel 0x%x as preferred\n",
-+ package_id, channel_id);
-+ else
-+ netdev_info(ndp->ndev.dev, "Set package 0x%x as preferred\n",
-+ package_id);
-
-- /* Bounce the NCSI channel to set changes */
-- ncsi_stop_dev(&ndp->ndev);
-- ncsi_start_dev(&ndp->ndev);
-+ /* Update channel configuration */
-+ if (!(ndp->flags & NCSI_DEV_RESET))
-+ ncsi_reset_dev(&ndp->ndev);
-
- return 0;
- }
-@@ -340,6 +352,7 @@ static int ncsi_set_interface_nl(struct sk_buff *msg, struct genl_info *info)
- static int ncsi_clear_interface_nl(struct sk_buff *msg, struct genl_info *info)
- {
- struct ncsi_dev_priv *ndp;
-+ struct ncsi_package *np;
- unsigned long flags;
-
- if (!info || !info->attrs)
-@@ -353,16 +366,24 @@ static int ncsi_clear_interface_nl(struct sk_buff *msg, struct genl_info *info)
- if (!ndp)
- return -ENODEV;
-
-- /* Clear any override */
-+ /* Reset any whitelists and disable multi mode */
- spin_lock_irqsave(&ndp->lock, flags);
-- ndp->force_package = NULL;
-- ndp->force_channel = NULL;
-+ ndp->package_whitelist = UINT_MAX;
-+ ndp->multi_package = false;
- spin_unlock_irqrestore(&ndp->lock, flags);
-+
-+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
-+ spin_lock_irqsave(&np->lock, flags);
-+ np->multi_channel = false;
-+ np->channel_whitelist = UINT_MAX;
-+ np->preferred_channel = NULL;
-+ spin_unlock_irqrestore(&np->lock, flags);
-+ }
- netdev_info(ndp->ndev.dev, "NCSI: Cleared preferred package/channel\n");
-
-- /* Bounce the NCSI channel to set changes */
-- ncsi_stop_dev(&ndp->ndev);
-- ncsi_start_dev(&ndp->ndev);
-+ /* Update channel configuration */
-+ if (!(ndp->flags & NCSI_DEV_RESET))
-+ ncsi_reset_dev(&ndp->ndev);
-
- return 0;
- }
-@@ -563,6 +584,138 @@ int ncsi_send_netlink_err(struct net_device *dev,
- return nlmsg_unicast(net->genl_sock, skb, snd_portid);
- }
-
-+static int ncsi_set_package_mask_nl(struct sk_buff *msg,
-+ struct genl_info *info)
-+{
-+ struct ncsi_dev_priv *ndp;
-+ unsigned long flags;
-+ int rc;
-+
-+ if (!info || !info->attrs)
-+ return -EINVAL;
-+
-+ if (!info->attrs[NCSI_ATTR_IFINDEX])
-+ return -EINVAL;
-+
-+ if (!info->attrs[NCSI_ATTR_PACKAGE_MASK])
-+ return -EINVAL;
-+
-+ ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)),
-+ nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
-+ if (!ndp)
-+ return -ENODEV;
-+
-+ spin_lock_irqsave(&ndp->lock, flags);
-+ if (nla_get_flag(info->attrs[NCSI_ATTR_MULTI_FLAG])) {
-+ if (ndp->flags & NCSI_DEV_HWA) {
-+ ndp->multi_package = true;
-+ rc = 0;
-+ } else {
-+ netdev_err(ndp->ndev.dev,
-+ "NCSI: Can't use multiple packages without HWA\n");
-+ rc = -EPERM;
-+ }
-+ } else {
-+ ndp->multi_package = false;
-+ rc = 0;
-+ }
-+
-+ if (!rc)
-+ ndp->package_whitelist =
-+ nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_MASK]);
-+ spin_unlock_irqrestore(&ndp->lock, flags);
-+
-+ if (!rc) {
-+ /* Update channel configuration */
-+ if (!(ndp->flags & NCSI_DEV_RESET))
-+ ncsi_reset_dev(&ndp->ndev);
-+ }
-+
-+ return rc;
-+}
-+
-+static int ncsi_set_channel_mask_nl(struct sk_buff *msg,
-+ struct genl_info *info)
-+{
-+ struct ncsi_package *np, *package;
-+ struct ncsi_channel *nc, *channel;
-+ u32 package_id, channel_id;
-+ struct ncsi_dev_priv *ndp;
-+ unsigned long flags;
-+
-+ if (!info || !info->attrs)
-+ return -EINVAL;
-+
-+ if (!info->attrs[NCSI_ATTR_IFINDEX])
-+ return -EINVAL;
-+
-+ if (!info->attrs[NCSI_ATTR_PACKAGE_ID])
-+ return -EINVAL;
-+
-+ if (!info->attrs[NCSI_ATTR_CHANNEL_MASK])
-+ return -EINVAL;
-+
-+ ndp = ndp_from_ifindex(get_net(sock_net(msg->sk)),
-+ nla_get_u32(info->attrs[NCSI_ATTR_IFINDEX]));
-+ if (!ndp)
-+ return -ENODEV;
-+
-+ package_id = nla_get_u32(info->attrs[NCSI_ATTR_PACKAGE_ID]);
-+ package = NULL;
-+ NCSI_FOR_EACH_PACKAGE(ndp, np)
-+ if (np->id == package_id) {
-+ package = np;
-+ break;
-+ }
-+ if (!package)
-+ return -ERANGE;
-+
-+ spin_lock_irqsave(&package->lock, flags);
-+
-+ channel = NULL;
-+ if (info->attrs[NCSI_ATTR_CHANNEL_ID]) {
-+ channel_id = nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_ID]);
-+ NCSI_FOR_EACH_CHANNEL(np, nc)
-+ if (nc->id == channel_id) {
-+ channel = nc;
-+ break;
-+ }
-+ if (!channel) {
-+ spin_unlock_irqrestore(&package->lock, flags);
-+ return -ERANGE;
-+ }
-+ netdev_dbg(ndp->ndev.dev,
-+ "NCSI: Channel %u set as preferred channel\n",
-+ channel->id);
-+ }
-+
-+ package->channel_whitelist =
-+ nla_get_u32(info->attrs[NCSI_ATTR_CHANNEL_MASK]);
-+ if (package->channel_whitelist == 0)
-+ netdev_dbg(ndp->ndev.dev,
-+ "NCSI: Package %u set to all channels disabled\n",
-+ package->id);
-+
-+ package->preferred_channel = channel;
-+
-+ if (nla_get_flag(info->attrs[NCSI_ATTR_MULTI_FLAG])) {
-+ package->multi_channel = true;
-+ netdev_info(ndp->ndev.dev,
-+ "NCSI: Multi-channel enabled on package %u\n",
-+ package_id);
-+ } else {
-+ package->multi_channel = false;
-+ }
-+
-+ spin_unlock_irqrestore(&package->lock, flags);
-+
-+ /* Update channel configuration */
-+ if (!(ndp->flags & NCSI_DEV_RESET))
-+ ncsi_reset_dev(&ndp->ndev);
-+
-+ return 0;
-+}
-+
- static const struct genl_ops ncsi_ops[] = {
- {
- .cmd = NCSI_CMD_PKG_INFO,
-@@ -589,6 +742,18 @@ static const struct genl_ops ncsi_ops[] = {
- .doit = ncsi_send_cmd_nl,
- .flags = GENL_ADMIN_PERM,
- },
-+ {
-+ .cmd = NCSI_CMD_SET_PACKAGE_MASK,
-+ .policy = ncsi_genl_policy,
-+ .doit = ncsi_set_package_mask_nl,
-+ .flags = GENL_ADMIN_PERM,
-+ },
-+ {
-+ .cmd = NCSI_CMD_SET_CHANNEL_MASK,
-+ .policy = ncsi_genl_policy,
-+ .doit = ncsi_set_channel_mask_nl,
-+ .flags = GENL_ADMIN_PERM,
-+ },
- };
-
- static struct genl_family ncsi_genl_family __ro_after_init = {
-diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
-index 77e07ba3f493..de7737a27889 100644
---- a/net/ncsi/ncsi-rsp.c
-+++ b/net/ncsi/ncsi-rsp.c
-@@ -256,7 +256,7 @@ static int ncsi_rsp_handler_dcnt(struct ncsi_request *nr)
- if (!ncm->enable)
- return 0;
-
-- ncm->enable = 1;
-+ ncm->enable = 0;
- return 0;
- }
-
---
-2.7.4
-
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0038-media-aspeed-backport-ikvm-patches.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0038-media-aspeed-backport-ikvm-patches.patch
index 02e423057..92d0a045d 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0038-media-aspeed-backport-ikvm-patches.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0038-media-aspeed-backport-ikvm-patches.patch
@@ -1,16 +1,8 @@
-From feb75b023dfd0ebe3e8ca46f0e74603f07542c29 Mon Sep 17 00:00:00 2001
+From 13d6fd0f71b3d0d69370878613bf7eb78fefa18f Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Fri, 9 Nov 2018 11:32:27 -0800
Subject: [PATCH] Add Aspeed Video Engine Driver
-The Video Engine (VE) embedded in the Aspeed AST2400 and AST2500 SOCs
-can capture and compress video data from digital or analog sources. With
-the Aspeed chip acting a service processor, the Video Engine can capture
-the host processor graphics output.
-
-Add a V4L2 driver to capture video data and compress it to JPEG images.
-Make the video frames available through the V4L2 streaming interface.
-
media: platform: Fix missing spin_lock_init()
The driver allocates the spinlock but not initialize it.
@@ -27,71 +19,14 @@ Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>
---
- .../devicetree/bindings/media/aspeed-video.txt | 26 +
- MAINTAINERS | 8 +
- arch/arm/boot/dts/aspeed-g5.dtsi | 11 +
- drivers/clk/clk-aspeed.c | 41 +-
- drivers/media/platform/Kconfig | 9 +
- drivers/media/platform/Makefile | 1 +
- drivers/media/platform/aspeed-video.c | 1730 ++++++++++++++++++++
- include/dt-bindings/clock/aspeed-clock.h | 1 +
- 8 files changed, 1825 insertions(+), 2 deletions(-)
- create mode 100644 Documentation/devicetree/bindings/media/aspeed-video.txt
- create mode 100644 drivers/media/platform/aspeed-video.c
+ arch/arm/boot/dts/aspeed-g5.dtsi | 11 +++++++++
+ drivers/clk/clk-aspeed.c | 41 ++++++++++++++++++++++++++++++--
+ drivers/media/platform/aspeed-video.c | 1 +
+ include/dt-bindings/clock/aspeed-clock.h | 1 +
+ 4 files changed, 52 insertions(+), 2 deletions(-)
-diff --git a/Documentation/devicetree/bindings/media/aspeed-video.txt b/Documentation/devicetree/bindings/media/aspeed-video.txt
-new file mode 100644
-index 000000000000..78b464ae2672
---- /dev/null
-+++ b/Documentation/devicetree/bindings/media/aspeed-video.txt
-@@ -0,0 +1,26 @@
-+* Device tree bindings for Aspeed Video Engine
-+
-+The Video Engine (VE) embedded in the Aspeed AST2400 and AST2500 SOCs can
-+capture and compress video data from digital or analog sources.
-+
-+Required properties:
-+ - compatible: "aspeed,ast2400-video-engine" or
-+ "aspeed,ast2500-video-engine"
-+ - reg: contains the offset and length of the VE memory region
-+ - clocks: clock specifiers for the syscon clocks associated with
-+ the VE (ordering must match the clock-names property)
-+ - clock-names: "vclk" and "eclk"
-+ - resets: reset specifier for the syscon reset associated with
-+ the VE
-+ - interrupts: the interrupt associated with the VE on this platform
-+
-+Example:
-+
-+video-engine@1e700000 {
-+ compatible = "aspeed,ast2500-video-engine";
-+ reg = <0x1e700000 0x20000>;
-+ clocks = <&syscon ASPEED_CLK_GATE_VCLK>, <&syscon ASPEED_CLK_GATE_ECLK>;
-+ clock-names = "vclk", "eclk";
-+ resets = <&syscon ASPEED_RESET_VIDEO>;
-+ interrupts = <7>;
-+};
-diff --git a/MAINTAINERS b/MAINTAINERS
-index b98a5763f6c1..cdd8f824b6da 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -2358,6 +2358,14 @@ S: Maintained
- F: Documentation/hwmon/asc7621
- F: drivers/hwmon/asc7621.c
-
-+ASPEED VIDEO ENGINE DRIVER
-+M: Eddie James <eajames@linux.ibm.com>
-+L: linux-media@vger.kernel.org
-+L: openbmc@lists.ozlabs.org (moderated for non-subscribers)
-+S: Maintained
-+F: drivers/media/platform/aspeed-video.c
-+F: Documentation/devicetree/bindings/media/aspeed-video.txt
-+
- ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
- M: Corentin Chary <corentin.chary@gmail.com>
- L: acpi4asus-user@lists.sourceforge.net
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index 69330ae2efd3..946c13eaa1d4 100644
+index 6f26e0d323d6..d5783eaf30ae 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -243,6 +243,17 @@
@@ -211,1774 +146,18 @@ index 3bbb4fbf00c9..6cea55de485f 100644
*/
/* Get the uart clock source configuration from SCU4C*/
-diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
-index 54fe90acb5b2..d6edf2d28f9b 100644
---- a/drivers/media/platform/Kconfig
-+++ b/drivers/media/platform/Kconfig
-@@ -32,6 +32,15 @@ source "drivers/media/platform/davinci/Kconfig"
-
- source "drivers/media/platform/omap/Kconfig"
-
-+config VIDEO_ASPEED
-+ tristate "Aspeed AST2400 and AST2500 Video Engine driver"
-+ depends on VIDEO_V4L2
-+ select VIDEOBUF2_DMA_CONTIG
-+ help
-+ Support for the Aspeed Video Engine (VE) embedded in the Aspeed
-+ AST2400 and AST2500 SOCs. The VE can capture and compress video data
-+ from digital or analog sources.
-+
- config VIDEO_SH_VOU
- tristate "SuperH VOU video output driver"
- depends on MEDIA_CAMERA_SUPPORT
-diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
-index 41322ab65802..205c33a004fc 100644
---- a/drivers/media/platform/Makefile
-+++ b/drivers/media/platform/Makefile
-@@ -3,6 +3,7 @@
- # Makefile for the video capture/playback device drivers.
- #
-
-+obj-$(CONFIG_VIDEO_ASPEED) += aspeed-video.o
- obj-$(CONFIG_VIDEO_CADENCE) += cadence/
- obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
- obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
-new file mode 100644
-index 000000000000..692e08ef38c0
---- /dev/null
+index dfec813f50a9..692e08ef38c0 100644
+--- a/drivers/media/platform/aspeed-video.c
+++ b/drivers/media/platform/aspeed-video.c
-@@ -0,0 +1,1730 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+
-+#include <linux/atomic.h>
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/interrupt.h>
-+#include <linux/jiffies.h>
-+#include <linux/module.h>
-+#include <linux/mutex.h>
-+#include <linux/of.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_reserved_mem.h>
-+#include <linux/platform_device.h>
-+#include <linux/reset.h>
-+#include <linux/sched.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+#include <linux/v4l2-controls.h>
-+#include <linux/videodev2.h>
-+#include <linux/wait.h>
-+#include <linux/workqueue.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-dev.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-dv-timings.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-ioctl.h>
-+#include <media/videobuf2-dma-contig.h>
-+
-+#define DEVICE_NAME "aspeed-video"
-+
-+#define ASPEED_VIDEO_JPEG_NUM_QUALITIES 12
-+#define ASPEED_VIDEO_JPEG_HEADER_SIZE 10
-+#define ASPEED_VIDEO_JPEG_QUANT_SIZE 116
-+#define ASPEED_VIDEO_JPEG_DCT_SIZE 34
-+
-+#define MAX_FRAME_RATE 60
-+#define MAX_HEIGHT 1200
-+#define MAX_WIDTH 1920
-+#define MIN_HEIGHT 480
-+#define MIN_WIDTH 640
-+
-+#define NUM_POLARITY_CHECKS 10
-+#define INVALID_RESOLUTION_RETRIES 2
-+#define INVALID_RESOLUTION_DELAY msecs_to_jiffies(250)
-+#define RESOLUTION_CHANGE_DELAY msecs_to_jiffies(500)
-+#define MODE_DETECT_TIMEOUT msecs_to_jiffies(500)
-+#define STOP_TIMEOUT msecs_to_jiffies(1000)
-+#define DIRECT_FETCH_THRESHOLD 0x0c0000 /* 1024 * 768 */
-+
-+#define VE_MAX_SRC_BUFFER_SIZE 0x8ca000 /* 1920 * 1200, 32bpp */
-+#define VE_JPEG_HEADER_SIZE 0x006000 /* 512 * 12 * 4 */
-+
-+#define VE_PROTECTION_KEY 0x000
-+#define VE_PROTECTION_KEY_UNLOCK 0x1a038aa8
-+
-+#define VE_SEQ_CTRL 0x004
-+#define VE_SEQ_CTRL_TRIG_MODE_DET BIT(0)
-+#define VE_SEQ_CTRL_TRIG_CAPTURE BIT(1)
-+#define VE_SEQ_CTRL_FORCE_IDLE BIT(2)
-+#define VE_SEQ_CTRL_MULT_FRAME BIT(3)
-+#define VE_SEQ_CTRL_TRIG_COMP BIT(4)
-+#define VE_SEQ_CTRL_AUTO_COMP BIT(5)
-+#define VE_SEQ_CTRL_EN_WATCHDOG BIT(7)
-+#define VE_SEQ_CTRL_YUV420 BIT(10)
-+#define VE_SEQ_CTRL_COMP_FMT GENMASK(11, 10)
-+#define VE_SEQ_CTRL_HALT BIT(12)
-+#define VE_SEQ_CTRL_EN_WATCHDOG_COMP BIT(14)
-+#define VE_SEQ_CTRL_TRIG_JPG BIT(15)
-+#define VE_SEQ_CTRL_CAP_BUSY BIT(16)
-+#define VE_SEQ_CTRL_COMP_BUSY BIT(18)
-+
-+#ifdef CONFIG_MACH_ASPEED_G5
-+#define VE_SEQ_CTRL_JPEG_MODE BIT(13) /* AST2500 */
-+#else
-+#define VE_SEQ_CTRL_JPEG_MODE BIT(8) /* AST2400 */
-+#endif /* CONFIG_MACH_ASPEED_G5 */
-+
-+#define VE_CTRL 0x008
-+#define VE_CTRL_HSYNC_POL BIT(0)
-+#define VE_CTRL_VSYNC_POL BIT(1)
-+#define VE_CTRL_SOURCE BIT(2)
-+#define VE_CTRL_INT_DE BIT(4)
-+#define VE_CTRL_DIRECT_FETCH BIT(5)
-+#define VE_CTRL_YUV BIT(6)
-+#define VE_CTRL_RGB BIT(7)
-+#define VE_CTRL_CAPTURE_FMT GENMASK(7, 6)
-+#define VE_CTRL_AUTO_OR_CURSOR BIT(8)
-+#define VE_CTRL_CLK_INVERSE BIT(11)
-+#define VE_CTRL_CLK_DELAY GENMASK(11, 9)
-+#define VE_CTRL_INTERLACE BIT(14)
-+#define VE_CTRL_HSYNC_POL_CTRL BIT(15)
-+#define VE_CTRL_FRC GENMASK(23, 16)
-+
-+#define VE_TGS_0 0x00c
-+#define VE_TGS_1 0x010
-+#define VE_TGS_FIRST GENMASK(28, 16)
-+#define VE_TGS_LAST GENMASK(12, 0)
-+
-+#define VE_SCALING_FACTOR 0x014
-+#define VE_SCALING_FILTER0 0x018
-+#define VE_SCALING_FILTER1 0x01c
-+#define VE_SCALING_FILTER2 0x020
-+#define VE_SCALING_FILTER3 0x024
-+
-+#define VE_CAP_WINDOW 0x030
-+#define VE_COMP_WINDOW 0x034
-+#define VE_COMP_PROC_OFFSET 0x038
-+#define VE_COMP_OFFSET 0x03c
-+#define VE_JPEG_ADDR 0x040
-+#define VE_SRC0_ADDR 0x044
-+#define VE_SRC_SCANLINE_OFFSET 0x048
-+#define VE_SRC1_ADDR 0x04c
-+#define VE_COMP_ADDR 0x054
-+
-+#define VE_STREAM_BUF_SIZE 0x058
-+#define VE_STREAM_BUF_SIZE_N_PACKETS GENMASK(5, 3)
-+#define VE_STREAM_BUF_SIZE_P_SIZE GENMASK(2, 0)
-+
-+#define VE_COMP_CTRL 0x060
-+#define VE_COMP_CTRL_VQ_DCT_ONLY BIT(0)
-+#define VE_COMP_CTRL_VQ_4COLOR BIT(1)
-+#define VE_COMP_CTRL_QUANTIZE BIT(2)
-+#define VE_COMP_CTRL_EN_BQ BIT(4)
-+#define VE_COMP_CTRL_EN_CRYPTO BIT(5)
-+#define VE_COMP_CTRL_DCT_CHR GENMASK(10, 6)
-+#define VE_COMP_CTRL_DCT_LUM GENMASK(15, 11)
-+#define VE_COMP_CTRL_EN_HQ BIT(16)
-+#define VE_COMP_CTRL_RSVD BIT(19)
-+#define VE_COMP_CTRL_ENCODE GENMASK(21, 20)
-+#define VE_COMP_CTRL_HQ_DCT_CHR GENMASK(26, 22)
-+#define VE_COMP_CTRL_HQ_DCT_LUM GENMASK(31, 27)
-+
-+#define VE_OFFSET_COMP_STREAM 0x078
-+
-+#define VE_SRC_LR_EDGE_DET 0x090
-+#define VE_SRC_LR_EDGE_DET_LEFT GENMASK(11, 0)
-+#define VE_SRC_LR_EDGE_DET_NO_V BIT(12)
-+#define VE_SRC_LR_EDGE_DET_NO_H BIT(13)
-+#define VE_SRC_LR_EDGE_DET_NO_DISP BIT(14)
-+#define VE_SRC_LR_EDGE_DET_NO_CLK BIT(15)
-+#define VE_SRC_LR_EDGE_DET_RT_SHF 16
-+#define VE_SRC_LR_EDGE_DET_RT GENMASK(27, VE_SRC_LR_EDGE_DET_RT_SHF)
-+#define VE_SRC_LR_EDGE_DET_INTERLACE BIT(31)
-+
-+#define VE_SRC_TB_EDGE_DET 0x094
-+#define VE_SRC_TB_EDGE_DET_TOP GENMASK(12, 0)
-+#define VE_SRC_TB_EDGE_DET_BOT_SHF 16
-+#define VE_SRC_TB_EDGE_DET_BOT GENMASK(28, VE_SRC_TB_EDGE_DET_BOT_SHF)
-+
-+#define VE_MODE_DETECT_STATUS 0x098
-+#define VE_MODE_DETECT_H_PIXELS GENMASK(11, 0)
-+#define VE_MODE_DETECT_V_LINES_SHF 16
-+#define VE_MODE_DETECT_V_LINES GENMASK(27, VE_MODE_DETECT_V_LINES_SHF)
-+#define VE_MODE_DETECT_STATUS_VSYNC BIT(28)
-+#define VE_MODE_DETECT_STATUS_HSYNC BIT(29)
-+
-+#define VE_SYNC_STATUS 0x09c
-+#define VE_SYNC_STATUS_HSYNC GENMASK(11, 0)
-+#define VE_SYNC_STATUS_VSYNC_SHF 16
-+#define VE_SYNC_STATUS_VSYNC GENMASK(27, VE_SYNC_STATUS_VSYNC_SHF)
-+
-+#define VE_INTERRUPT_CTRL 0x304
-+#define VE_INTERRUPT_STATUS 0x308
-+#define VE_INTERRUPT_MODE_DETECT_WD BIT(0)
-+#define VE_INTERRUPT_CAPTURE_COMPLETE BIT(1)
-+#define VE_INTERRUPT_COMP_READY BIT(2)
-+#define VE_INTERRUPT_COMP_COMPLETE BIT(3)
-+#define VE_INTERRUPT_MODE_DETECT BIT(4)
-+#define VE_INTERRUPT_FRAME_COMPLETE BIT(5)
-+#define VE_INTERRUPT_DECODE_ERR BIT(6)
-+#define VE_INTERRUPT_HALT_READY BIT(8)
-+#define VE_INTERRUPT_HANG_WD BIT(9)
-+#define VE_INTERRUPT_STREAM_DESC BIT(10)
-+#define VE_INTERRUPT_VSYNC_DESC BIT(11)
-+
-+#define VE_MODE_DETECT 0x30c
-+#define VE_MEM_RESTRICT_START 0x310
-+#define VE_MEM_RESTRICT_END 0x314
-+
-+enum {
-+ VIDEO_MODE_DETECT_DONE,
-+ VIDEO_RES_CHANGE,
-+ VIDEO_RES_DETECT,
-+ VIDEO_STREAMING,
-+ VIDEO_FRAME_INPRG,
-+ VIDEO_STOPPED,
-+};
-+
-+struct aspeed_video_addr {
-+ unsigned int size;
-+ dma_addr_t dma;
-+ void *virt;
-+};
-+
-+struct aspeed_video_buffer {
-+ struct vb2_v4l2_buffer vb;
-+ struct list_head link;
-+};
-+
-+#define to_aspeed_video_buffer(x) \
-+ container_of((x), struct aspeed_video_buffer, vb)
-+
-+struct aspeed_video {
-+ void __iomem *base;
-+ struct clk *eclk;
-+ struct clk *vclk;
-+ struct reset_control *rst;
-+
-+ struct device *dev;
-+ struct v4l2_ctrl_handler ctrl_handler;
-+ struct v4l2_device v4l2_dev;
-+ struct v4l2_pix_format pix_fmt;
-+ struct v4l2_bt_timings active_timings;
-+ struct v4l2_bt_timings detected_timings;
-+ u32 v4l2_input_status;
-+ struct vb2_queue queue;
-+ struct video_device vdev;
-+ struct mutex video_lock; /* v4l2 and videobuf2 lock */
-+
-+ wait_queue_head_t wait;
-+ spinlock_t lock; /* buffer list lock */
-+ struct delayed_work res_work;
-+ struct list_head buffers;
-+ unsigned long flags;
-+ unsigned int sequence;
-+
-+ unsigned int max_compressed_size;
-+ struct aspeed_video_addr srcs[2];
-+ struct aspeed_video_addr jpeg;
-+
-+ bool yuv420;
-+ unsigned int frame_rate;
-+ unsigned int jpeg_quality;
-+
-+ unsigned int frame_bottom;
-+ unsigned int frame_left;
-+ unsigned int frame_right;
-+ unsigned int frame_top;
-+};
-+
-+#define to_aspeed_video(x) container_of((x), struct aspeed_video, v4l2_dev)
-+
-+static const u32 aspeed_video_jpeg_header[ASPEED_VIDEO_JPEG_HEADER_SIZE] = {
-+ 0xe0ffd8ff, 0x464a1000, 0x01004649, 0x60000101, 0x00006000, 0x0f00feff,
-+ 0x00002d05, 0x00000000, 0x00000000, 0x00dbff00
-+};
-+
-+static const u32 aspeed_video_jpeg_quant[ASPEED_VIDEO_JPEG_QUANT_SIZE] = {
-+ 0x081100c0, 0x00000000, 0x00110103, 0x03011102, 0xc4ff0111, 0x00001f00,
-+ 0x01010501, 0x01010101, 0x00000000, 0x00000000, 0x04030201, 0x08070605,
-+ 0xff0b0a09, 0x10b500c4, 0x03010200, 0x03040203, 0x04040505, 0x7d010000,
-+ 0x00030201, 0x12051104, 0x06413121, 0x07615113, 0x32147122, 0x08a19181,
-+ 0xc1b14223, 0xf0d15215, 0x72623324, 0x160a0982, 0x1a191817, 0x28272625,
-+ 0x35342a29, 0x39383736, 0x4544433a, 0x49484746, 0x5554534a, 0x59585756,
-+ 0x6564635a, 0x69686766, 0x7574736a, 0x79787776, 0x8584837a, 0x89888786,
-+ 0x9493928a, 0x98979695, 0xa3a29a99, 0xa7a6a5a4, 0xb2aaa9a8, 0xb6b5b4b3,
-+ 0xbab9b8b7, 0xc5c4c3c2, 0xc9c8c7c6, 0xd4d3d2ca, 0xd8d7d6d5, 0xe2e1dad9,
-+ 0xe6e5e4e3, 0xeae9e8e7, 0xf4f3f2f1, 0xf8f7f6f5, 0xc4fffaf9, 0x00011f00,
-+ 0x01010103, 0x01010101, 0x00000101, 0x00000000, 0x04030201, 0x08070605,
-+ 0xff0b0a09, 0x11b500c4, 0x02010200, 0x04030404, 0x04040507, 0x77020100,
-+ 0x03020100, 0x21050411, 0x41120631, 0x71610751, 0x81322213, 0x91421408,
-+ 0x09c1b1a1, 0xf0523323, 0xd1726215, 0x3424160a, 0x17f125e1, 0x261a1918,
-+ 0x2a292827, 0x38373635, 0x44433a39, 0x48474645, 0x54534a49, 0x58575655,
-+ 0x64635a59, 0x68676665, 0x74736a69, 0x78777675, 0x83827a79, 0x87868584,
-+ 0x928a8988, 0x96959493, 0x9a999897, 0xa5a4a3a2, 0xa9a8a7a6, 0xb4b3b2aa,
-+ 0xb8b7b6b5, 0xc3c2bab9, 0xc7c6c5c4, 0xd2cac9c8, 0xd6d5d4d3, 0xdad9d8d7,
-+ 0xe5e4e3e2, 0xe9e8e7e6, 0xf4f3f2ea, 0xf8f7f6f5, 0xdafffaf9, 0x01030c00,
-+ 0x03110200, 0x003f0011
-+};
-+
-+static const u32 aspeed_video_jpeg_dct[ASPEED_VIDEO_JPEG_NUM_QUALITIES]
-+ [ASPEED_VIDEO_JPEG_DCT_SIZE] = {
-+ { 0x0d140043, 0x0c0f110f, 0x11101114, 0x17141516, 0x1e20321e,
-+ 0x3d1e1b1b, 0x32242e2b, 0x4b4c3f48, 0x44463f47, 0x61735a50,
-+ 0x566c5550, 0x88644644, 0x7a766c65, 0x4d808280, 0x8c978d60,
-+ 0x7e73967d, 0xdbff7b80, 0x1f014300, 0x272d2121, 0x3030582d,
-+ 0x697bb958, 0xb8b9b97b, 0xb9b8a6a6, 0xb9b9b9b9, 0xb9b9b9b9,
-+ 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9,
-+ 0xb9b9b9b9, 0xb9b9b9b9, 0xb9b9b9b9, 0xffb9b9b9 },
-+ { 0x0c110043, 0x0a0d0f0d, 0x0f0e0f11, 0x14111213, 0x1a1c2b1a,
-+ 0x351a1818, 0x2b1f2826, 0x4142373f, 0x3c3d373e, 0x55644e46,
-+ 0x4b5f4a46, 0x77573d3c, 0x6b675f58, 0x43707170, 0x7a847b54,
-+ 0x6e64836d, 0xdbff6c70, 0x1b014300, 0x22271d1d, 0x2a2a4c27,
-+ 0x5b6ba04c, 0xa0a0a06b, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0,
-+ 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0,
-+ 0xa0a0a0a0, 0xa0a0a0a0, 0xa0a0a0a0, 0xffa0a0a0 },
-+ { 0x090e0043, 0x090a0c0a, 0x0c0b0c0e, 0x110e0f10, 0x15172415,
-+ 0x2c151313, 0x241a211f, 0x36372e34, 0x31322e33, 0x4653413a,
-+ 0x3e4e3d3a, 0x62483231, 0x58564e49, 0x385d5e5d, 0x656d6645,
-+ 0x5b536c5a, 0xdbff595d, 0x16014300, 0x1c201818, 0x22223f20,
-+ 0x4b58853f, 0x85858558, 0x85858585, 0x85858585, 0x85858585,
-+ 0x85858585, 0x85858585, 0x85858585, 0x85858585, 0x85858585,
-+ 0x85858585, 0x85858585, 0x85858585, 0xff858585 },
-+ { 0x070b0043, 0x07080a08, 0x0a090a0b, 0x0d0b0c0c, 0x11121c11,
-+ 0x23110f0f, 0x1c141a19, 0x2b2b2429, 0x27282428, 0x3842332e,
-+ 0x313e302e, 0x4e392827, 0x46443e3a, 0x2c4a4a4a, 0x50565137,
-+ 0x48425647, 0xdbff474a, 0x12014300, 0x161a1313, 0x1c1c331a,
-+ 0x3d486c33, 0x6c6c6c48, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c,
-+ 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c,
-+ 0x6c6c6c6c, 0x6c6c6c6c, 0x6c6c6c6c, 0xff6c6c6c },
-+ { 0x06090043, 0x05060706, 0x07070709, 0x0a09090a, 0x0d0e160d,
-+ 0x1b0d0c0c, 0x16101413, 0x21221c20, 0x1e1f1c20, 0x2b332824,
-+ 0x26302624, 0x3d2d1f1e, 0x3735302d, 0x22393a39, 0x3f443f2b,
-+ 0x38334338, 0xdbff3739, 0x0d014300, 0x11130e0e, 0x15152613,
-+ 0x2d355026, 0x50505035, 0x50505050, 0x50505050, 0x50505050,
-+ 0x50505050, 0x50505050, 0x50505050, 0x50505050, 0x50505050,
-+ 0x50505050, 0x50505050, 0x50505050, 0xff505050 },
-+ { 0x04060043, 0x03040504, 0x05040506, 0x07060606, 0x09090f09,
-+ 0x12090808, 0x0f0a0d0d, 0x16161315, 0x14151315, 0x1d221b18,
-+ 0x19201918, 0x281e1514, 0x2423201e, 0x17262726, 0x2a2d2a1c,
-+ 0x25222d25, 0xdbff2526, 0x09014300, 0x0b0d0a0a, 0x0e0e1a0d,
-+ 0x1f25371a, 0x37373725, 0x37373737, 0x37373737, 0x37373737,
-+ 0x37373737, 0x37373737, 0x37373737, 0x37373737, 0x37373737,
-+ 0x37373737, 0x37373737, 0x37373737, 0xff373737 },
-+ { 0x02030043, 0x01020202, 0x02020203, 0x03030303, 0x04040704,
-+ 0x09040404, 0x07050606, 0x0b0b090a, 0x0a0a090a, 0x0e110d0c,
-+ 0x0c100c0c, 0x140f0a0a, 0x1211100f, 0x0b131313, 0x1516150e,
-+ 0x12111612, 0xdbff1213, 0x04014300, 0x05060505, 0x07070d06,
-+ 0x0f121b0d, 0x1b1b1b12, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b,
-+ 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b,
-+ 0x1b1b1b1b, 0x1b1b1b1b, 0x1b1b1b1b, 0xff1b1b1b },
-+ { 0x01020043, 0x01010101, 0x01010102, 0x02020202, 0x03030503,
-+ 0x06030202, 0x05030404, 0x07070607, 0x06070607, 0x090b0908,
-+ 0x080a0808, 0x0d0a0706, 0x0c0b0a0a, 0x070c0d0c, 0x0e0f0e09,
-+ 0x0c0b0f0c, 0xdbff0c0c, 0x03014300, 0x03040303, 0x04040804,
-+ 0x0a0c1208, 0x1212120c, 0x12121212, 0x12121212, 0x12121212,
-+ 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212,
-+ 0x12121212, 0x12121212, 0x12121212, 0xff121212 },
-+ { 0x01020043, 0x01010101, 0x01010102, 0x02020202, 0x03030503,
-+ 0x06030202, 0x05030404, 0x07070607, 0x06070607, 0x090b0908,
-+ 0x080a0808, 0x0d0a0706, 0x0c0b0a0a, 0x070c0d0c, 0x0e0f0e09,
-+ 0x0c0b0f0c, 0xdbff0c0c, 0x02014300, 0x03030202, 0x04040703,
-+ 0x080a0f07, 0x0f0f0f0a, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f,
-+ 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f,
-+ 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f0f0f, 0xff0f0f0f },
-+ { 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x02020302,
-+ 0x04020202, 0x03020303, 0x05050405, 0x05050405, 0x07080606,
-+ 0x06080606, 0x0a070505, 0x09080807, 0x05090909, 0x0a0b0a07,
-+ 0x09080b09, 0xdbff0909, 0x02014300, 0x02030202, 0x03030503,
-+ 0x07080c05, 0x0c0c0c08, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
-+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c,
-+ 0x0c0c0c0c, 0x0c0c0c0c, 0x0c0c0c0c, 0xff0c0c0c },
-+ { 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x01010201,
-+ 0x03010101, 0x02010202, 0x03030303, 0x03030303, 0x04050404,
-+ 0x04050404, 0x06050303, 0x06050505, 0x03060606, 0x07070704,
-+ 0x06050706, 0xdbff0606, 0x01014300, 0x01020101, 0x02020402,
-+ 0x05060904, 0x09090906, 0x09090909, 0x09090909, 0x09090909,
-+ 0x09090909, 0x09090909, 0x09090909, 0x09090909, 0x09090909,
-+ 0x09090909, 0x09090909, 0x09090909, 0xff090909 },
-+ { 0x01010043, 0x01010101, 0x01010101, 0x01010101, 0x01010101,
-+ 0x01010101, 0x01010101, 0x01010101, 0x01010101, 0x02020202,
-+ 0x02020202, 0x03020101, 0x03020202, 0x01030303, 0x03030302,
-+ 0x03020303, 0xdbff0403, 0x01014300, 0x01010101, 0x01010201,
-+ 0x03040602, 0x06060604, 0x06060606, 0x06060606, 0x06060606,
-+ 0x06060606, 0x06060606, 0x06060606, 0x06060606, 0x06060606,
-+ 0x06060606, 0x06060606, 0x06060606, 0xff060606 }
-+};
-+
-+static const struct v4l2_dv_timings_cap aspeed_video_timings_cap = {
-+ .type = V4L2_DV_BT_656_1120,
-+ .bt = {
-+ .min_width = MIN_WIDTH,
-+ .max_width = MAX_WIDTH,
-+ .min_height = MIN_HEIGHT,
-+ .max_height = MAX_HEIGHT,
-+ .min_pixelclock = 6574080, /* 640 x 480 x 24Hz */
-+ .max_pixelclock = 138240000, /* 1920 x 1200 x 60Hz */
-+ .standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
-+ V4L2_DV_BT_STD_CVT | V4L2_DV_BT_STD_GTF,
-+ .capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
-+ V4L2_DV_BT_CAP_REDUCED_BLANKING |
-+ V4L2_DV_BT_CAP_CUSTOM,
-+ },
-+};
-+
-+static void aspeed_video_init_jpeg_table(u32 *table, bool yuv420)
-+{
-+ int i;
-+ unsigned int base;
-+
-+ for (i = 0; i < ASPEED_VIDEO_JPEG_NUM_QUALITIES; i++) {
-+ base = 256 * i; /* AST HW requires this header spacing */
-+ memcpy(&table[base], aspeed_video_jpeg_header,
-+ sizeof(aspeed_video_jpeg_header));
-+
-+ base += ASPEED_VIDEO_JPEG_HEADER_SIZE;
-+ memcpy(&table[base], aspeed_video_jpeg_dct[i],
-+ sizeof(aspeed_video_jpeg_dct[i]));
-+
-+ base += ASPEED_VIDEO_JPEG_DCT_SIZE;
-+ memcpy(&table[base], aspeed_video_jpeg_quant,
-+ sizeof(aspeed_video_jpeg_quant));
-+
-+ if (yuv420)
-+ table[base + 2] = 0x00220103;
-+ }
-+}
-+
-+static void aspeed_video_update(struct aspeed_video *video, u32 reg, u32 clear,
-+ u32 bits)
-+{
-+ u32 t = readl(video->base + reg);
-+ u32 before = t;
-+
-+ t &= ~clear;
-+ t |= bits;
-+ writel(t, video->base + reg);
-+ dev_dbg(video->dev, "update %03x[%08x -> %08x]\n", reg, before,
-+ readl(video->base + reg));
-+}
-+
-+static u32 aspeed_video_read(struct aspeed_video *video, u32 reg)
-+{
-+ u32 t = readl(video->base + reg);
-+
-+ dev_dbg(video->dev, "read %03x[%08x]\n", reg, t);
-+ return t;
-+}
-+
-+static void aspeed_video_write(struct aspeed_video *video, u32 reg, u32 val)
-+{
-+ writel(val, video->base + reg);
-+ dev_dbg(video->dev, "write %03x[%08x]\n", reg,
-+ readl(video->base + reg));
-+}
-+
-+static int aspeed_video_start_frame(struct aspeed_video *video)
-+{
-+ dma_addr_t addr;
-+ unsigned long flags;
-+ struct aspeed_video_buffer *buf;
-+ u32 seq_ctrl = aspeed_video_read(video, VE_SEQ_CTRL);
-+
-+ if (video->v4l2_input_status) {
-+ dev_dbg(video->dev, "No signal; don't start frame\n");
-+ return 0;
-+ }
-+
-+ if (!(seq_ctrl & VE_SEQ_CTRL_COMP_BUSY) ||
-+ !(seq_ctrl & VE_SEQ_CTRL_CAP_BUSY)) {
-+ dev_err(video->dev, "Engine busy; don't start frame\n");
-+ return -EBUSY;
-+ }
-+
-+ spin_lock_irqsave(&video->lock, flags);
-+ buf = list_first_entry_or_null(&video->buffers,
-+ struct aspeed_video_buffer, link);
-+ if (!buf) {
-+ spin_unlock_irqrestore(&video->lock, flags);
-+ dev_dbg(video->dev, "No buffers; don't start frame\n");
-+ return -EPROTO;
-+ }
-+
-+ set_bit(VIDEO_FRAME_INPRG, &video->flags);
-+ addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
-+ spin_unlock_irqrestore(&video->lock, flags);
-+
-+ aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
-+ aspeed_video_write(video, VE_COMP_OFFSET, 0);
-+ aspeed_video_write(video, VE_COMP_ADDR, addr);
-+
-+ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
-+ VE_INTERRUPT_COMP_COMPLETE |
-+ VE_INTERRUPT_CAPTURE_COMPLETE);
-+
-+ aspeed_video_update(video, VE_SEQ_CTRL, 0,
-+ VE_SEQ_CTRL_TRIG_CAPTURE | VE_SEQ_CTRL_TRIG_COMP);
-+
-+ return 0;
-+}
-+
-+static void aspeed_video_enable_mode_detect(struct aspeed_video *video)
-+{
-+ /* Enable mode detect interrupts */
-+ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
-+ VE_INTERRUPT_MODE_DETECT);
-+
-+ /* Trigger mode detect */
-+ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET);
-+}
-+
-+static void aspeed_video_reset(struct aspeed_video *video)
-+{
-+ /* Reset the engine */
-+ reset_control_assert(video->rst);
-+
-+ /* Don't usleep here; function may be called in interrupt context */
-+ udelay(100);
-+ reset_control_deassert(video->rst);
-+}
-+
-+static void aspeed_video_off(struct aspeed_video *video)
-+{
-+ aspeed_video_reset(video);
-+
-+ /* Turn off the relevant clocks */
-+ clk_disable_unprepare(video->vclk);
-+ clk_disable_unprepare(video->eclk);
-+}
-+
-+static void aspeed_video_on(struct aspeed_video *video)
-+{
-+ /* Turn on the relevant clocks */
-+ clk_prepare_enable(video->eclk);
-+ clk_prepare_enable(video->vclk);
-+
-+ aspeed_video_reset(video);
-+}
-+
-+static void aspeed_video_bufs_done(struct aspeed_video *video,
-+ enum vb2_buffer_state state)
-+{
-+ unsigned long flags;
-+ struct aspeed_video_buffer *buf;
-+
-+ spin_lock_irqsave(&video->lock, flags);
-+ list_for_each_entry(buf, &video->buffers, link)
-+ vb2_buffer_done(&buf->vb.vb2_buf, state);
-+ INIT_LIST_HEAD(&video->buffers);
-+ spin_unlock_irqrestore(&video->lock, flags);
-+}
-+
-+static void aspeed_video_irq_res_change(struct aspeed_video *video)
-+{
-+ dev_dbg(video->dev, "Resolution changed; resetting\n");
-+
-+ set_bit(VIDEO_RES_CHANGE, &video->flags);
-+ clear_bit(VIDEO_FRAME_INPRG, &video->flags);
-+
-+ aspeed_video_off(video);
-+ aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);
-+
-+ schedule_delayed_work(&video->res_work, RESOLUTION_CHANGE_DELAY);
-+}
-+
-+static irqreturn_t aspeed_video_irq(int irq, void *arg)
-+{
-+ struct aspeed_video *video = arg;
-+ u32 sts = aspeed_video_read(video, VE_INTERRUPT_STATUS);
-+
-+ /*
-+ * Resolution changed or signal was lost; reset the engine and
-+ * re-initialize
-+ */
-+ if (sts & VE_INTERRUPT_MODE_DETECT_WD) {
-+ aspeed_video_irq_res_change(video);
-+ return IRQ_HANDLED;
-+ }
-+
-+ if (sts & VE_INTERRUPT_MODE_DETECT) {
-+ if (test_bit(VIDEO_RES_DETECT, &video->flags)) {
-+ aspeed_video_update(video, VE_INTERRUPT_CTRL,
-+ VE_INTERRUPT_MODE_DETECT, 0);
-+ aspeed_video_write(video, VE_INTERRUPT_STATUS,
-+ VE_INTERRUPT_MODE_DETECT);
-+
-+ set_bit(VIDEO_MODE_DETECT_DONE, &video->flags);
-+ wake_up_interruptible_all(&video->wait);
-+ } else {
-+ /*
-+ * Signal acquired while NOT doing resolution
-+ * detection; reset the engine and re-initialize
-+ */
-+ aspeed_video_irq_res_change(video);
-+ return IRQ_HANDLED;
-+ }
-+ }
-+
-+ if ((sts & VE_INTERRUPT_COMP_COMPLETE) &&
-+ (sts & VE_INTERRUPT_CAPTURE_COMPLETE)) {
-+ struct aspeed_video_buffer *buf;
-+ u32 frame_size = aspeed_video_read(video,
-+ VE_OFFSET_COMP_STREAM);
-+
-+ spin_lock(&video->lock);
-+ clear_bit(VIDEO_FRAME_INPRG, &video->flags);
-+ buf = list_first_entry_or_null(&video->buffers,
-+ struct aspeed_video_buffer,
-+ link);
-+ if (buf) {
-+ vb2_set_plane_payload(&buf->vb.vb2_buf, 0, frame_size);
-+
-+ if (!list_is_last(&buf->link, &video->buffers)) {
-+ buf->vb.vb2_buf.timestamp = ktime_get_ns();
-+ buf->vb.sequence = video->sequence++;
-+ buf->vb.field = V4L2_FIELD_NONE;
-+ vb2_buffer_done(&buf->vb.vb2_buf,
-+ VB2_BUF_STATE_DONE);
-+ list_del(&buf->link);
-+ }
-+ }
-+ spin_unlock(&video->lock);
-+
-+ aspeed_video_update(video, VE_SEQ_CTRL,
-+ VE_SEQ_CTRL_TRIG_CAPTURE |
-+ VE_SEQ_CTRL_FORCE_IDLE |
-+ VE_SEQ_CTRL_TRIG_COMP, 0);
-+ aspeed_video_update(video, VE_INTERRUPT_CTRL,
-+ VE_INTERRUPT_COMP_COMPLETE |
-+ VE_INTERRUPT_CAPTURE_COMPLETE, 0);
-+ aspeed_video_write(video, VE_INTERRUPT_STATUS,
-+ VE_INTERRUPT_COMP_COMPLETE |
-+ VE_INTERRUPT_CAPTURE_COMPLETE);
-+
-+ if (test_bit(VIDEO_STREAMING, &video->flags) && buf)
-+ aspeed_video_start_frame(video);
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static void aspeed_video_check_and_set_polarity(struct aspeed_video *video)
-+{
-+ int i;
-+ int hsync_counter = 0;
-+ int vsync_counter = 0;
-+ u32 sts;
-+
-+ for (i = 0; i < NUM_POLARITY_CHECKS; ++i) {
-+ sts = aspeed_video_read(video, VE_MODE_DETECT_STATUS);
-+ if (sts & VE_MODE_DETECT_STATUS_VSYNC)
-+ vsync_counter--;
-+ else
-+ vsync_counter++;
-+
-+ if (sts & VE_MODE_DETECT_STATUS_HSYNC)
-+ hsync_counter--;
-+ else
-+ hsync_counter++;
-+ }
-+
-+ if (hsync_counter < 0 || vsync_counter < 0) {
-+ u32 ctrl;
-+
-+ if (hsync_counter < 0) {
-+ ctrl = VE_CTRL_HSYNC_POL;
-+ video->detected_timings.polarities &=
-+ ~V4L2_DV_HSYNC_POS_POL;
-+ } else {
-+ video->detected_timings.polarities |=
-+ V4L2_DV_HSYNC_POS_POL;
-+ }
-+
-+ if (vsync_counter < 0) {
-+ ctrl = VE_CTRL_VSYNC_POL;
-+ video->detected_timings.polarities &=
-+ ~V4L2_DV_VSYNC_POS_POL;
-+ } else {
-+ video->detected_timings.polarities |=
-+ V4L2_DV_VSYNC_POS_POL;
-+ }
-+
-+ aspeed_video_update(video, VE_CTRL, 0, ctrl);
-+ }
-+}
-+
-+static bool aspeed_video_alloc_buf(struct aspeed_video *video,
-+ struct aspeed_video_addr *addr,
-+ unsigned int size)
-+{
-+ addr->virt = dma_alloc_coherent(video->dev, size, &addr->dma,
-+ GFP_KERNEL);
-+ if (!addr->virt)
-+ return false;
-+
-+ addr->size = size;
-+ return true;
-+}
-+
-+static void aspeed_video_free_buf(struct aspeed_video *video,
-+ struct aspeed_video_addr *addr)
-+{
-+ dma_free_coherent(video->dev, addr->size, addr->virt, addr->dma);
-+ addr->size = 0;
-+ addr->dma = 0ULL;
-+ addr->virt = NULL;
-+}
-+
-+/*
-+ * Get the minimum HW-supported compression buffer size for the frame size.
-+ * Assume worst-case JPEG compression size is 1/8 raw size. This should be
-+ * plenty even for maximum quality; any worse and the engine will simply return
-+ * incomplete JPEGs.
-+ */
-+static void aspeed_video_calc_compressed_size(struct aspeed_video *video,
-+ unsigned int frame_size)
-+{
-+ int i, j;
-+ u32 compression_buffer_size_reg = 0;
-+ unsigned int size;
-+ const unsigned int num_compression_packets = 4;
-+ const unsigned int compression_packet_size = 1024;
-+ const unsigned int max_compressed_size = frame_size / 2; /* 4bpp / 8 */
-+
-+ video->max_compressed_size = UINT_MAX;
-+
-+ for (i = 0; i < 6; ++i) {
-+ for (j = 0; j < 8; ++j) {
-+ size = (num_compression_packets << i) *
-+ (compression_packet_size << j);
-+ if (size < max_compressed_size)
-+ continue;
-+
-+ if (size < video->max_compressed_size) {
-+ compression_buffer_size_reg = (i << 3) | j;
-+ video->max_compressed_size = size;
-+ }
-+ }
-+ }
-+
-+ aspeed_video_write(video, VE_STREAM_BUF_SIZE,
-+ compression_buffer_size_reg);
-+
-+ dev_dbg(video->dev, "Max compressed size: %x\n",
-+ video->max_compressed_size);
-+}
-+
-+#define res_check(v) test_and_clear_bit(VIDEO_MODE_DETECT_DONE, &(v)->flags)
-+
-+static void aspeed_video_get_resolution(struct aspeed_video *video)
-+{
-+ bool invalid_resolution = true;
-+ int rc;
-+ int tries = 0;
-+ u32 mds;
-+ u32 src_lr_edge;
-+ u32 src_tb_edge;
-+ u32 sync;
-+ struct v4l2_bt_timings *det = &video->detected_timings;
-+
-+ det->width = MIN_WIDTH;
-+ det->height = MIN_HEIGHT;
-+ video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
-+
-+ /*
-+ * Since we need max buffer size for detection, free the second source
-+ * buffer first.
-+ */
-+ if (video->srcs[1].size)
-+ aspeed_video_free_buf(video, &video->srcs[1]);
-+
-+ if (video->srcs[0].size < VE_MAX_SRC_BUFFER_SIZE) {
-+ if (video->srcs[0].size)
-+ aspeed_video_free_buf(video, &video->srcs[0]);
-+
-+ if (!aspeed_video_alloc_buf(video, &video->srcs[0],
-+ VE_MAX_SRC_BUFFER_SIZE)) {
-+ dev_err(video->dev,
-+ "Failed to allocate source buffers\n");
-+ return;
-+ }
-+ }
-+
-+ aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);
-+
-+ do {
-+ if (tries) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ if (schedule_timeout(INVALID_RESOLUTION_DELAY))
-+ return;
-+ }
-+
-+ set_bit(VIDEO_RES_DETECT, &video->flags);
-+ aspeed_video_enable_mode_detect(video);
-+
-+ rc = wait_event_interruptible_timeout(video->wait,
-+ res_check(video),
-+ MODE_DETECT_TIMEOUT);
-+ if (!rc) {
-+ dev_err(video->dev, "Timed out; first mode detect\n");
-+ clear_bit(VIDEO_RES_DETECT, &video->flags);
-+ return;
-+ }
-+
-+ /* Disable mode detect in order to re-trigger */
-+ aspeed_video_update(video, VE_SEQ_CTRL,
-+ VE_SEQ_CTRL_TRIG_MODE_DET, 0);
-+
-+ aspeed_video_check_and_set_polarity(video);
-+
-+ aspeed_video_enable_mode_detect(video);
-+
-+ rc = wait_event_interruptible_timeout(video->wait,
-+ res_check(video),
-+ MODE_DETECT_TIMEOUT);
-+ clear_bit(VIDEO_RES_DETECT, &video->flags);
-+ if (!rc) {
-+ dev_err(video->dev, "Timed out; second mode detect\n");
-+ return;
-+ }
-+
-+ src_lr_edge = aspeed_video_read(video, VE_SRC_LR_EDGE_DET);
-+ src_tb_edge = aspeed_video_read(video, VE_SRC_TB_EDGE_DET);
-+ mds = aspeed_video_read(video, VE_MODE_DETECT_STATUS);
-+ sync = aspeed_video_read(video, VE_SYNC_STATUS);
-+
-+ video->frame_bottom = (src_tb_edge & VE_SRC_TB_EDGE_DET_BOT) >>
-+ VE_SRC_TB_EDGE_DET_BOT_SHF;
-+ video->frame_top = src_tb_edge & VE_SRC_TB_EDGE_DET_TOP;
-+ det->vfrontporch = video->frame_top;
-+ det->vbackporch = ((mds & VE_MODE_DETECT_V_LINES) >>
-+ VE_MODE_DETECT_V_LINES_SHF) - video->frame_bottom;
-+ det->vsync = (sync & VE_SYNC_STATUS_VSYNC) >>
-+ VE_SYNC_STATUS_VSYNC_SHF;
-+ if (video->frame_top > video->frame_bottom)
-+ continue;
-+
-+ video->frame_right = (src_lr_edge & VE_SRC_LR_EDGE_DET_RT) >>
-+ VE_SRC_LR_EDGE_DET_RT_SHF;
-+ video->frame_left = src_lr_edge & VE_SRC_LR_EDGE_DET_LEFT;
-+ det->hfrontporch = video->frame_left;
-+ det->hbackporch = (mds & VE_MODE_DETECT_H_PIXELS) -
-+ video->frame_right;
-+ det->hsync = sync & VE_SYNC_STATUS_HSYNC;
-+ if (video->frame_left > video->frame_right)
-+ continue;
-+
-+ invalid_resolution = false;
-+ } while (invalid_resolution && (tries++ < INVALID_RESOLUTION_RETRIES));
-+
-+ if (invalid_resolution) {
-+ dev_err(video->dev, "Invalid resolution detected\n");
-+ return;
-+ }
-+
-+ det->height = (video->frame_bottom - video->frame_top) + 1;
-+ det->width = (video->frame_right - video->frame_left) + 1;
-+ video->v4l2_input_status = 0;
-+
-+ /*
-+ * Enable mode-detect watchdog, resolution-change watchdog and
-+ * automatic compression after frame capture.
-+ */
-+ aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
-+ VE_INTERRUPT_MODE_DETECT_WD);
-+ aspeed_video_update(video, VE_SEQ_CTRL, 0,
-+ VE_SEQ_CTRL_AUTO_COMP | VE_SEQ_CTRL_EN_WATCHDOG);
-+
-+ dev_dbg(video->dev, "Got resolution: %dx%d\n", det->width,
-+ det->height);
-+}
-+
-+static void aspeed_video_set_resolution(struct aspeed_video *video)
-+{
-+ struct v4l2_bt_timings *act = &video->active_timings;
-+ unsigned int size = act->width * act->height;
-+
-+ aspeed_video_calc_compressed_size(video, size);
-+
-+ /* Don't use direct mode below 1024 x 768 (irqs don't fire) */
-+ if (size < DIRECT_FETCH_THRESHOLD) {
-+ aspeed_video_write(video, VE_TGS_0,
-+ FIELD_PREP(VE_TGS_FIRST,
-+ video->frame_left - 1) |
-+ FIELD_PREP(VE_TGS_LAST,
-+ video->frame_right));
-+ aspeed_video_write(video, VE_TGS_1,
-+ FIELD_PREP(VE_TGS_FIRST, video->frame_top) |
-+ FIELD_PREP(VE_TGS_LAST,
-+ video->frame_bottom + 1));
-+ aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_INT_DE);
-+ } else {
-+ aspeed_video_update(video, VE_CTRL, 0, VE_CTRL_DIRECT_FETCH);
-+ }
-+
-+ /* Set capture/compression frame sizes */
-+ aspeed_video_write(video, VE_CAP_WINDOW,
-+ act->width << 16 | act->height);
-+ aspeed_video_write(video, VE_COMP_WINDOW,
-+ act->width << 16 | act->height);
-+ aspeed_video_write(video, VE_SRC_SCANLINE_OFFSET, act->width * 4);
-+
-+ size *= 4;
-+
-+ if (size == video->srcs[0].size / 2) {
-+ aspeed_video_write(video, VE_SRC1_ADDR,
-+ video->srcs[0].dma + size);
-+ } else if (size == video->srcs[0].size) {
-+ if (!aspeed_video_alloc_buf(video, &video->srcs[1], size))
-+ goto err_mem;
-+
-+ aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);
-+ } else {
-+ aspeed_video_free_buf(video, &video->srcs[0]);
-+
-+ if (!aspeed_video_alloc_buf(video, &video->srcs[0], size))
-+ goto err_mem;
-+
-+ if (!aspeed_video_alloc_buf(video, &video->srcs[1], size))
-+ goto err_mem;
-+
-+ aspeed_video_write(video, VE_SRC0_ADDR, video->srcs[0].dma);
-+ aspeed_video_write(video, VE_SRC1_ADDR, video->srcs[1].dma);
-+ }
-+
-+ return;
-+
-+err_mem:
-+ dev_err(video->dev, "Failed to allocate source buffers\n");
-+
-+ if (video->srcs[0].size)
-+ aspeed_video_free_buf(video, &video->srcs[0]);
-+}
-+
-+static void aspeed_video_init_regs(struct aspeed_video *video)
-+{
-+ u32 comp_ctrl = VE_COMP_CTRL_RSVD |
-+ FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
-+ FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
-+ u32 ctrl = VE_CTRL_AUTO_OR_CURSOR;
-+ u32 seq_ctrl = VE_SEQ_CTRL_JPEG_MODE;
-+
-+ if (video->frame_rate)
-+ ctrl |= FIELD_PREP(VE_CTRL_FRC, video->frame_rate);
-+
-+ if (video->yuv420)
-+ seq_ctrl |= VE_SEQ_CTRL_YUV420;
-+
-+ /* Unlock VE registers */
-+ aspeed_video_write(video, VE_PROTECTION_KEY, VE_PROTECTION_KEY_UNLOCK);
-+
-+ /* Disable interrupts */
-+ aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);
-+ aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
-+
-+ /* Clear the offset */
-+ aspeed_video_write(video, VE_COMP_PROC_OFFSET, 0);
-+ aspeed_video_write(video, VE_COMP_OFFSET, 0);
-+
-+ aspeed_video_write(video, VE_JPEG_ADDR, video->jpeg.dma);
-+
-+ /* Set control registers */
-+ aspeed_video_write(video, VE_SEQ_CTRL, seq_ctrl);
-+ aspeed_video_write(video, VE_CTRL, ctrl);
-+ aspeed_video_write(video, VE_COMP_CTRL, comp_ctrl);
-+
-+ /* Don't downscale */
-+ aspeed_video_write(video, VE_SCALING_FACTOR, 0x10001000);
-+ aspeed_video_write(video, VE_SCALING_FILTER0, 0x00200000);
-+ aspeed_video_write(video, VE_SCALING_FILTER1, 0x00200000);
-+ aspeed_video_write(video, VE_SCALING_FILTER2, 0x00200000);
-+ aspeed_video_write(video, VE_SCALING_FILTER3, 0x00200000);
-+
-+ /* Set mode detection defaults */
-+ aspeed_video_write(video, VE_MODE_DETECT, 0x22666500);
-+}
-+
-+static void aspeed_video_start(struct aspeed_video *video)
-+{
-+ aspeed_video_on(video);
-+
-+ aspeed_video_init_regs(video);
-+
-+ /* Resolution set to 640x480 if no signal found */
-+ aspeed_video_get_resolution(video);
-+
-+ /* Set timings since the device is being opened for the first time */
-+ video->active_timings = video->detected_timings;
-+ aspeed_video_set_resolution(video);
-+
-+ video->pix_fmt.width = video->active_timings.width;
-+ video->pix_fmt.height = video->active_timings.height;
-+ video->pix_fmt.sizeimage = video->max_compressed_size;
-+}
-+
-+static void aspeed_video_stop(struct aspeed_video *video)
-+{
-+ set_bit(VIDEO_STOPPED, &video->flags);
-+ cancel_delayed_work_sync(&video->res_work);
-+
-+ aspeed_video_off(video);
-+
-+ if (video->srcs[0].size)
-+ aspeed_video_free_buf(video, &video->srcs[0]);
-+
-+ if (video->srcs[1].size)
-+ aspeed_video_free_buf(video, &video->srcs[1]);
-+
-+ video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
-+ video->flags = 0;
-+}
-+
-+static int aspeed_video_querycap(struct file *file, void *fh,
-+ struct v4l2_capability *cap)
-+{
-+ strscpy(cap->driver, DEVICE_NAME, sizeof(cap->driver));
-+ strscpy(cap->card, "Aspeed Video Engine", sizeof(cap->card));
-+ snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-+ DEVICE_NAME);
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_enum_format(struct file *file, void *fh,
-+ struct v4l2_fmtdesc *f)
-+{
-+ if (f->index)
-+ return -EINVAL;
-+
-+ f->pixelformat = V4L2_PIX_FMT_JPEG;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_get_format(struct file *file, void *fh,
-+ struct v4l2_format *f)
-+{
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ f->fmt.pix = video->pix_fmt;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_enum_input(struct file *file, void *fh,
-+ struct v4l2_input *inp)
-+{
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ if (inp->index)
-+ return -EINVAL;
-+
-+ strscpy(inp->name, "Host VGA capture", sizeof(inp->name));
-+ inp->type = V4L2_INPUT_TYPE_CAMERA;
-+ inp->capabilities = V4L2_IN_CAP_DV_TIMINGS;
-+ inp->status = video->v4l2_input_status;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_get_input(struct file *file, void *fh, unsigned int *i)
-+{
-+ *i = 0;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_set_input(struct file *file, void *fh, unsigned int i)
-+{
-+ if (i)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_get_parm(struct file *file, void *fh,
-+ struct v4l2_streamparm *a)
-+{
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
-+ a->parm.capture.readbuffers = 3;
-+ a->parm.capture.timeperframe.numerator = 1;
-+ if (!video->frame_rate)
-+ a->parm.capture.timeperframe.denominator = MAX_FRAME_RATE;
-+ else
-+ a->parm.capture.timeperframe.denominator = video->frame_rate;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_set_parm(struct file *file, void *fh,
-+ struct v4l2_streamparm *a)
-+{
-+ unsigned int frame_rate = 0;
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ a->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
-+ a->parm.capture.readbuffers = 3;
-+
-+ if (a->parm.capture.timeperframe.numerator)
-+ frame_rate = a->parm.capture.timeperframe.denominator /
-+ a->parm.capture.timeperframe.numerator;
-+
-+ if (!frame_rate || frame_rate > MAX_FRAME_RATE) {
-+ frame_rate = 0;
-+ a->parm.capture.timeperframe.denominator = MAX_FRAME_RATE;
-+ a->parm.capture.timeperframe.numerator = 1;
-+ }
-+
-+ if (video->frame_rate != frame_rate) {
-+ video->frame_rate = frame_rate;
-+ aspeed_video_update(video, VE_CTRL, VE_CTRL_FRC,
-+ FIELD_PREP(VE_CTRL_FRC, frame_rate));
-+ }
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_enum_framesizes(struct file *file, void *fh,
-+ struct v4l2_frmsizeenum *fsize)
-+{
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ if (fsize->index)
-+ return -EINVAL;
-+
-+ if (fsize->pixel_format != V4L2_PIX_FMT_JPEG)
-+ return -EINVAL;
-+
-+ fsize->discrete.width = video->pix_fmt.width;
-+ fsize->discrete.height = video->pix_fmt.height;
-+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_enum_frameintervals(struct file *file, void *fh,
-+ struct v4l2_frmivalenum *fival)
-+{
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ if (fival->index)
-+ return -EINVAL;
-+
-+ if (fival->width != video->detected_timings.width ||
-+ fival->height != video->detected_timings.height)
-+ return -EINVAL;
-+
-+ if (fival->pixel_format != V4L2_PIX_FMT_JPEG)
-+ return -EINVAL;
-+
-+ fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
-+
-+ fival->stepwise.min.denominator = MAX_FRAME_RATE;
-+ fival->stepwise.min.numerator = 1;
-+ fival->stepwise.max.denominator = 1;
-+ fival->stepwise.max.numerator = 1;
-+ fival->stepwise.step = fival->stepwise.max;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_set_dv_timings(struct file *file, void *fh,
-+ struct v4l2_dv_timings *timings)
-+{
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ if (timings->bt.width == video->active_timings.width &&
-+ timings->bt.height == video->active_timings.height)
-+ return 0;
-+
-+ if (vb2_is_busy(&video->queue))
-+ return -EBUSY;
-+
-+ video->active_timings = timings->bt;
-+
-+ aspeed_video_set_resolution(video);
-+
-+ video->pix_fmt.width = timings->bt.width;
-+ video->pix_fmt.height = timings->bt.height;
-+ video->pix_fmt.sizeimage = video->max_compressed_size;
-+
-+ timings->type = V4L2_DV_BT_656_1120;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_get_dv_timings(struct file *file, void *fh,
-+ struct v4l2_dv_timings *timings)
-+{
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ timings->type = V4L2_DV_BT_656_1120;
-+ timings->bt = video->active_timings;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_query_dv_timings(struct file *file, void *fh,
-+ struct v4l2_dv_timings *timings)
-+{
-+ int rc;
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ /*
-+ * This blocks only if the driver is currently in the process of
-+ * detecting a new resolution; in the event of no signal or timeout
-+ * this function is woken up.
-+ */
-+ if (file->f_flags & O_NONBLOCK) {
-+ if (test_bit(VIDEO_RES_CHANGE, &video->flags))
-+ return -EAGAIN;
-+ } else {
-+ rc = wait_event_interruptible(video->wait,
-+ !test_bit(VIDEO_RES_CHANGE,
-+ &video->flags));
-+ if (rc)
-+ return -EINTR;
-+ }
-+
-+ timings->type = V4L2_DV_BT_656_1120;
-+ timings->bt = video->detected_timings;
-+
-+ return video->v4l2_input_status ? -ENOLINK : 0;
-+}
-+
-+static int aspeed_video_enum_dv_timings(struct file *file, void *fh,
-+ struct v4l2_enum_dv_timings *timings)
-+{
-+ return v4l2_enum_dv_timings_cap(timings, &aspeed_video_timings_cap,
-+ NULL, NULL);
-+}
-+
-+static int aspeed_video_dv_timings_cap(struct file *file, void *fh,
-+ struct v4l2_dv_timings_cap *cap)
-+{
-+ *cap = aspeed_video_timings_cap;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_sub_event(struct v4l2_fh *fh,
-+ const struct v4l2_event_subscription *sub)
-+{
-+ switch (sub->type) {
-+ case V4L2_EVENT_SOURCE_CHANGE:
-+ return v4l2_src_change_event_subscribe(fh, sub);
-+ }
-+
-+ return v4l2_ctrl_subscribe_event(fh, sub);
-+}
-+
-+static const struct v4l2_ioctl_ops aspeed_video_ioctl_ops = {
-+ .vidioc_querycap = aspeed_video_querycap,
-+
-+ .vidioc_enum_fmt_vid_cap = aspeed_video_enum_format,
-+ .vidioc_g_fmt_vid_cap = aspeed_video_get_format,
-+ .vidioc_s_fmt_vid_cap = aspeed_video_get_format,
-+ .vidioc_try_fmt_vid_cap = aspeed_video_get_format,
-+
-+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
-+ .vidioc_querybuf = vb2_ioctl_querybuf,
-+ .vidioc_qbuf = vb2_ioctl_qbuf,
-+ .vidioc_expbuf = vb2_ioctl_expbuf,
-+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
-+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
-+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
-+ .vidioc_streamon = vb2_ioctl_streamon,
-+ .vidioc_streamoff = vb2_ioctl_streamoff,
-+
-+ .vidioc_enum_input = aspeed_video_enum_input,
-+ .vidioc_g_input = aspeed_video_get_input,
-+ .vidioc_s_input = aspeed_video_set_input,
-+
-+ .vidioc_g_parm = aspeed_video_get_parm,
-+ .vidioc_s_parm = aspeed_video_set_parm,
-+ .vidioc_enum_framesizes = aspeed_video_enum_framesizes,
-+ .vidioc_enum_frameintervals = aspeed_video_enum_frameintervals,
-+
-+ .vidioc_s_dv_timings = aspeed_video_set_dv_timings,
-+ .vidioc_g_dv_timings = aspeed_video_get_dv_timings,
-+ .vidioc_query_dv_timings = aspeed_video_query_dv_timings,
-+ .vidioc_enum_dv_timings = aspeed_video_enum_dv_timings,
-+ .vidioc_dv_timings_cap = aspeed_video_dv_timings_cap,
-+
-+ .vidioc_subscribe_event = aspeed_video_sub_event,
-+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-+};
-+
-+static void aspeed_video_update_jpeg_quality(struct aspeed_video *video)
-+{
-+ u32 comp_ctrl = FIELD_PREP(VE_COMP_CTRL_DCT_LUM, video->jpeg_quality) |
-+ FIELD_PREP(VE_COMP_CTRL_DCT_CHR, video->jpeg_quality | 0x10);
-+
-+ aspeed_video_update(video, VE_COMP_CTRL,
-+ VE_COMP_CTRL_DCT_LUM | VE_COMP_CTRL_DCT_CHR,
-+ comp_ctrl);
-+}
-+
-+static void aspeed_video_update_subsampling(struct aspeed_video *video)
-+{
-+ if (video->jpeg.virt)
-+ aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
-+
-+ if (video->yuv420)
-+ aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_YUV420);
-+ else
-+ aspeed_video_update(video, VE_SEQ_CTRL, VE_SEQ_CTRL_YUV420, 0);
-+}
-+
-+static int aspeed_video_set_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+ struct aspeed_video *video = container_of(ctrl->handler,
-+ struct aspeed_video,
-+ ctrl_handler);
-+
-+ switch (ctrl->id) {
-+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-+ video->jpeg_quality = ctrl->val;
-+ aspeed_video_update_jpeg_quality(video);
-+ break;
-+ case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
-+ if (ctrl->val == V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
-+ video->yuv420 = true;
-+ aspeed_video_update_subsampling(video);
-+ } else {
-+ video->yuv420 = false;
-+ aspeed_video_update_subsampling(video);
-+ }
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct v4l2_ctrl_ops aspeed_video_ctrl_ops = {
-+ .s_ctrl = aspeed_video_set_ctrl,
-+};
-+
-+static void aspeed_video_resolution_work(struct work_struct *work)
-+{
-+ struct delayed_work *dwork = to_delayed_work(work);
-+ struct aspeed_video *video = container_of(dwork, struct aspeed_video,
-+ res_work);
-+ u32 input_status = video->v4l2_input_status;
-+
-+ aspeed_video_on(video);
-+
-+ /* Exit early in case no clients remain */
-+ if (test_bit(VIDEO_STOPPED, &video->flags))
-+ goto done;
-+
-+ aspeed_video_init_regs(video);
-+
-+ aspeed_video_get_resolution(video);
-+
-+ if (video->detected_timings.width != video->active_timings.width ||
-+ video->detected_timings.height != video->active_timings.height ||
-+ input_status != video->v4l2_input_status) {
-+ static const struct v4l2_event ev = {
-+ .type = V4L2_EVENT_SOURCE_CHANGE,
-+ .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
-+ };
-+
-+ v4l2_event_queue(&video->vdev, &ev);
-+ } else if (test_bit(VIDEO_STREAMING, &video->flags)) {
-+ /* No resolution change so just restart streaming */
-+ aspeed_video_start_frame(video);
-+ }
-+
-+done:
-+ clear_bit(VIDEO_RES_CHANGE, &video->flags);
-+ wake_up_interruptible_all(&video->wait);
-+}
-+
-+static int aspeed_video_open(struct file *file)
-+{
-+ int rc;
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ mutex_lock(&video->video_lock);
-+
-+ rc = v4l2_fh_open(file);
-+ if (rc) {
-+ mutex_unlock(&video->video_lock);
-+ return rc;
-+ }
-+
-+ if (v4l2_fh_is_singular_file(file))
-+ aspeed_video_start(video);
-+
-+ mutex_unlock(&video->video_lock);
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_release(struct file *file)
-+{
-+ int rc;
-+ struct aspeed_video *video = video_drvdata(file);
-+
-+ mutex_lock(&video->video_lock);
-+
-+ if (v4l2_fh_is_singular_file(file))
-+ aspeed_video_stop(video);
-+
-+ rc = _vb2_fop_release(file, NULL);
-+
-+ mutex_unlock(&video->video_lock);
-+
-+ return rc;
-+}
-+
-+static const struct v4l2_file_operations aspeed_video_v4l2_fops = {
-+ .owner = THIS_MODULE,
-+ .read = vb2_fop_read,
-+ .poll = vb2_fop_poll,
-+ .unlocked_ioctl = video_ioctl2,
-+ .mmap = vb2_fop_mmap,
-+ .open = aspeed_video_open,
-+ .release = aspeed_video_release,
-+};
-+
-+static int aspeed_video_queue_setup(struct vb2_queue *q,
-+ unsigned int *num_buffers,
-+ unsigned int *num_planes,
-+ unsigned int sizes[],
-+ struct device *alloc_devs[])
-+{
-+ struct aspeed_video *video = vb2_get_drv_priv(q);
-+
-+ if (*num_planes) {
-+ if (sizes[0] < video->max_compressed_size)
-+ return -EINVAL;
-+
-+ return 0;
-+ }
-+
-+ *num_planes = 1;
-+ sizes[0] = video->max_compressed_size;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_buf_prepare(struct vb2_buffer *vb)
-+{
-+ struct aspeed_video *video = vb2_get_drv_priv(vb->vb2_queue);
-+
-+ if (vb2_plane_size(vb, 0) < video->max_compressed_size)
-+ return -EINVAL;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_start_streaming(struct vb2_queue *q,
-+ unsigned int count)
-+{
-+ int rc;
-+ struct aspeed_video *video = vb2_get_drv_priv(q);
-+
-+ video->sequence = 0;
-+
-+ rc = aspeed_video_start_frame(video);
-+ if (rc) {
-+ aspeed_video_bufs_done(video, VB2_BUF_STATE_QUEUED);
-+ return rc;
-+ }
-+
-+ set_bit(VIDEO_STREAMING, &video->flags);
-+ return 0;
-+}
-+
-+static void aspeed_video_stop_streaming(struct vb2_queue *q)
-+{
-+ int rc;
-+ struct aspeed_video *video = vb2_get_drv_priv(q);
-+
-+ clear_bit(VIDEO_STREAMING, &video->flags);
-+
-+ rc = wait_event_timeout(video->wait,
-+ !test_bit(VIDEO_FRAME_INPRG, &video->flags),
-+ STOP_TIMEOUT);
-+ if (!rc) {
-+ dev_err(video->dev, "Timed out when stopping streaming\n");
-+
-+ /*
-+ * Need to force stop any DMA and try and get HW into a good
-+ * state for future calls to start streaming again.
-+ */
-+ aspeed_video_reset(video);
-+ aspeed_video_init_regs(video);
-+
-+ aspeed_video_get_resolution(video);
-+ }
-+
-+ aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);
-+}
-+
-+static void aspeed_video_buf_queue(struct vb2_buffer *vb)
-+{
-+ bool empty;
-+ struct aspeed_video *video = vb2_get_drv_priv(vb->vb2_queue);
-+ struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-+ struct aspeed_video_buffer *avb = to_aspeed_video_buffer(vbuf);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&video->lock, flags);
-+ empty = list_empty(&video->buffers);
-+ list_add_tail(&avb->link, &video->buffers);
-+ spin_unlock_irqrestore(&video->lock, flags);
-+
-+ if (test_bit(VIDEO_STREAMING, &video->flags) &&
-+ !test_bit(VIDEO_FRAME_INPRG, &video->flags) && empty)
-+ aspeed_video_start_frame(video);
-+}
-+
-+static const struct vb2_ops aspeed_video_vb2_ops = {
-+ .queue_setup = aspeed_video_queue_setup,
-+ .wait_prepare = vb2_ops_wait_prepare,
-+ .wait_finish = vb2_ops_wait_finish,
-+ .buf_prepare = aspeed_video_buf_prepare,
-+ .start_streaming = aspeed_video_start_streaming,
-+ .stop_streaming = aspeed_video_stop_streaming,
-+ .buf_queue = aspeed_video_buf_queue,
-+};
-+
-+static int aspeed_video_setup_video(struct aspeed_video *video)
-+{
-+ const u64 mask = ~(BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_444) |
-+ BIT(V4L2_JPEG_CHROMA_SUBSAMPLING_420));
-+ struct v4l2_device *v4l2_dev = &video->v4l2_dev;
-+ struct vb2_queue *vbq = &video->queue;
-+ struct video_device *vdev = &video->vdev;
-+ int rc;
-+
-+ video->pix_fmt.pixelformat = V4L2_PIX_FMT_JPEG;
-+ video->pix_fmt.field = V4L2_FIELD_NONE;
-+ video->pix_fmt.colorspace = V4L2_COLORSPACE_SRGB;
-+ video->pix_fmt.quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+ video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
-+
-+ rc = v4l2_device_register(video->dev, v4l2_dev);
-+ if (rc) {
-+ dev_err(video->dev, "Failed to register v4l2 device\n");
-+ return rc;
-+ }
-+
-+ v4l2_ctrl_handler_init(&video->ctrl_handler, 2);
-+ v4l2_ctrl_new_std(&video->ctrl_handler, &aspeed_video_ctrl_ops,
-+ V4L2_CID_JPEG_COMPRESSION_QUALITY, 0,
-+ ASPEED_VIDEO_JPEG_NUM_QUALITIES - 1, 1, 0);
-+ v4l2_ctrl_new_std_menu(&video->ctrl_handler, &aspeed_video_ctrl_ops,
-+ V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
-+ V4L2_JPEG_CHROMA_SUBSAMPLING_420, mask,
-+ V4L2_JPEG_CHROMA_SUBSAMPLING_444);
-+
-+ if (video->ctrl_handler.error) {
-+ v4l2_ctrl_handler_free(&video->ctrl_handler);
-+ v4l2_device_unregister(v4l2_dev);
-+
-+ dev_err(video->dev, "Failed to init controls: %d\n",
-+ video->ctrl_handler.error);
-+ return rc;
-+ }
-+
-+ v4l2_dev->ctrl_handler = &video->ctrl_handler;
-+
-+ vbq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+ vbq->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
-+ vbq->dev = v4l2_dev->dev;
-+ vbq->lock = &video->video_lock;
-+ vbq->ops = &aspeed_video_vb2_ops;
-+ vbq->mem_ops = &vb2_dma_contig_memops;
-+ vbq->drv_priv = video;
-+ vbq->buf_struct_size = sizeof(struct aspeed_video_buffer);
-+ vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-+ vbq->min_buffers_needed = 3;
-+
-+ rc = vb2_queue_init(vbq);
-+ if (rc) {
-+ v4l2_ctrl_handler_free(&video->ctrl_handler);
-+ v4l2_device_unregister(v4l2_dev);
-+
-+ dev_err(video->dev, "Failed to init vb2 queue\n");
-+ return rc;
-+ }
-+
-+ vdev->queue = vbq;
-+ vdev->fops = &aspeed_video_v4l2_fops;
-+ vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-+ V4L2_CAP_STREAMING;
-+ vdev->v4l2_dev = v4l2_dev;
-+ strscpy(vdev->name, DEVICE_NAME, sizeof(vdev->name));
-+ vdev->vfl_type = VFL_TYPE_GRABBER;
-+ vdev->vfl_dir = VFL_DIR_RX;
-+ vdev->release = video_device_release_empty;
-+ vdev->ioctl_ops = &aspeed_video_ioctl_ops;
-+ vdev->lock = &video->video_lock;
-+
-+ video_set_drvdata(vdev, video);
-+ rc = video_register_device(vdev, VFL_TYPE_GRABBER, 0);
-+ if (rc) {
-+ vb2_queue_release(vbq);
-+ v4l2_ctrl_handler_free(&video->ctrl_handler);
-+ v4l2_device_unregister(v4l2_dev);
-+
-+ dev_err(video->dev, "Failed to register video device\n");
-+ return rc;
-+ }
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_init(struct aspeed_video *video)
-+{
-+ int irq;
-+ int rc;
-+ struct device *dev = video->dev;
-+
-+ irq = irq_of_parse_and_map(dev->of_node, 0);
-+ if (!irq) {
-+ dev_err(dev, "Unable to find IRQ\n");
-+ return -ENODEV;
-+ }
-+
-+ rc = devm_request_irq(dev, irq, aspeed_video_irq, IRQF_SHARED,
-+ DEVICE_NAME, video);
-+ if (rc < 0) {
-+ dev_err(dev, "Unable to request IRQ %d\n", irq);
-+ return rc;
-+ }
-+
-+ video->eclk = devm_clk_get(dev, "eclk");
-+ if (IS_ERR(video->eclk)) {
-+ dev_err(dev, "Unable to get ECLK\n");
-+ return PTR_ERR(video->eclk);
-+ }
-+
-+ video->vclk = devm_clk_get(dev, "vclk");
-+ if (IS_ERR(video->vclk)) {
-+ dev_err(dev, "Unable to get VCLK\n");
-+ return PTR_ERR(video->vclk);
-+ }
-+
-+ video->rst = devm_reset_control_get_exclusive(dev, NULL);
-+ if (IS_ERR(video->rst)) {
-+ dev_err(dev, "Unable to get VE reset\n");
-+ return PTR_ERR(video->rst);
-+ }
-+
-+ rc = of_reserved_mem_device_init(dev);
-+ if (rc) {
-+ dev_err(dev, "Unable to reserve memory\n");
-+ return rc;
-+ }
-+
-+ rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-+ if (rc) {
-+ dev_err(dev, "Failed to set DMA mask\n");
-+ of_reserved_mem_device_release(dev);
-+ return rc;
-+ }
-+
-+ if (!aspeed_video_alloc_buf(video, &video->jpeg,
-+ VE_JPEG_HEADER_SIZE)) {
-+ dev_err(dev, "Failed to allocate DMA for JPEG header\n");
-+ of_reserved_mem_device_release(dev);
-+ return rc;
-+ }
-+
-+ aspeed_video_init_jpeg_table(video->jpeg.virt, video->yuv420);
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_probe(struct platform_device *pdev)
-+{
-+ int rc;
-+ struct resource *res;
-+ struct aspeed_video *video = kzalloc(sizeof(*video), GFP_KERNEL);
-+
-+ if (!video)
-+ return -ENOMEM;
-+
-+ video->frame_rate = 30;
-+ video->dev = &pdev->dev;
+@@ -1661,6 +1661,7 @@ static int aspeed_video_probe(struct platform_device *pdev)
+
+ video->frame_rate = 30;
+ video->dev = &pdev->dev;
+ spin_lock_init(&video->lock);
-+ mutex_init(&video->video_lock);
-+ init_waitqueue_head(&video->wait);
-+ INIT_DELAYED_WORK(&video->res_work, aspeed_video_resolution_work);
-+ INIT_LIST_HEAD(&video->buffers);
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+
-+ video->base = devm_ioremap_resource(video->dev, res);
-+
-+ if (IS_ERR(video->base))
-+ return PTR_ERR(video->base);
-+
-+ rc = aspeed_video_init(video);
-+ if (rc)
-+ return rc;
-+
-+ rc = aspeed_video_setup_video(video);
-+ if (rc)
-+ return rc;
-+
-+ return 0;
-+}
-+
-+static int aspeed_video_remove(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
-+ struct aspeed_video *video = to_aspeed_video(v4l2_dev);
-+
-+ video_unregister_device(&video->vdev);
-+
-+ vb2_queue_release(&video->queue);
-+
-+ v4l2_ctrl_handler_free(&video->ctrl_handler);
-+
-+ v4l2_device_unregister(v4l2_dev);
-+
-+ dma_free_coherent(video->dev, VE_JPEG_HEADER_SIZE, video->jpeg.virt,
-+ video->jpeg.dma);
-+
-+ of_reserved_mem_device_release(dev);
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id aspeed_video_of_match[] = {
-+ { .compatible = "aspeed,ast2400-video-engine" },
-+ { .compatible = "aspeed,ast2500-video-engine" },
-+ {}
-+};
-+MODULE_DEVICE_TABLE(of, aspeed_video_of_match);
-+
-+static struct platform_driver aspeed_video_driver = {
-+ .driver = {
-+ .name = DEVICE_NAME,
-+ .of_match_table = aspeed_video_of_match,
-+ },
-+ .probe = aspeed_video_probe,
-+ .remove = aspeed_video_remove,
-+};
-+
-+module_platform_driver(aspeed_video_driver);
-+
-+MODULE_DESCRIPTION("ASPEED Video Engine Driver");
-+MODULE_AUTHOR("Eddie James");
-+MODULE_LICENSE("GPL v2");
+ mutex_init(&video->video_lock);
+ init_waitqueue_head(&video->wait);
+ INIT_DELAYED_WORK(&video->res_work, aspeed_video_resolution_work);
diff --git a/include/dt-bindings/clock/aspeed-clock.h b/include/dt-bindings/clock/aspeed-clock.h
index 335879505a72..0b0f3a0ebe9b 100644
--- a/include/dt-bindings/clock/aspeed-clock.h
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch
index 7400e2848..02ca65e9f 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch
@@ -1,4 +1,4 @@
-From a771e5448ed259f768434d498daf8d8b292713de Mon Sep 17 00:00:00 2001
+From 95bae3d3051ee13627e5ef92bb9d60cfb5731118 Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Mon, 11 Feb 2019 17:02:35 -0800
Subject: [PATCH] Add Aspeed PWM driver which uses FTTMR010 timer IP
@@ -12,17 +12,16 @@ Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
arch/arm/boot/dts/aspeed-g5.dtsi | 2 +-
drivers/clocksource/timer-fttmr010.c | 25 ++
- drivers/input/misc/pwm-beeper.c | 8 +-
drivers/pwm/Kconfig | 9 +
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-fttmr010.c | 465 +++++++++++++++++++++++++++++++++++
include/clocksource/timer-fttmr010.h | 17 ++
- 7 files changed, 522 insertions(+), 5 deletions(-)
+ 6 files changed, 514 insertions(+), 5 deletions(-)
create mode 100644 drivers/pwm/pwm-fttmr010.c
create mode 100644 include/clocksource/timer-fttmr010.h
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
-index 6686a13a5354..ccf2845cd788 100644
+index d5783eaf30ae..992de63d7a19 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -301,7 +301,7 @@
@@ -35,7 +34,7 @@ index 6686a13a5354..ccf2845cd788 100644
interrupts = <16 17 18 35 36 37 38 39>;
clocks = <&syscon ASPEED_CLK_APB>;
diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c
-index cf93f6419b51..8226ccf5cc2c 100644
+index fadff7915dd9..49a790924360 100644
--- a/drivers/clocksource/timer-fttmr010.c
+++ b/drivers/clocksource/timer-fttmr010.c
@@ -20,6 +20,8 @@
@@ -45,9 +44,9 @@ index cf93f6419b51..8226ccf5cc2c 100644
+#include <clocksource/timer-fttmr010.h>
+
/*
- * Register definitions for the timers
+ * Register definitions common for all the timer variants.
*/
-@@ -77,6 +79,9 @@
+@@ -91,6 +93,9 @@
#define TIMER_3_INT_OVERFLOW BIT(8)
#define TIMER_INT_ALL_MASK 0x1ff
@@ -57,7 +56,7 @@ index cf93f6419b51..8226ccf5cc2c 100644
struct fttmr010 {
void __iomem *base;
unsigned int tick_rate;
-@@ -123,8 +128,11 @@ static int fttmr010_timer_set_next_event(unsigned long cycles,
+@@ -137,8 +142,11 @@ static int fttmr010_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
struct fttmr010 *fttmr010 = to_fttmr010(evt);
@@ -69,7 +68,7 @@ index cf93f6419b51..8226ccf5cc2c 100644
/* Stop */
cr = readl(fttmr010->base + TIMER_CR);
cr &= ~fttmr010->t1_enable_val;
-@@ -147,27 +155,37 @@ static int fttmr010_timer_set_next_event(unsigned long cycles,
+@@ -161,27 +169,37 @@ static int fttmr010_timer_set_next_event(unsigned long cycles,
cr |= fttmr010->t1_enable_val;
writel(cr, fttmr010->base + TIMER_CR);
@@ -107,16 +106,16 @@ index cf93f6419b51..8226ccf5cc2c 100644
/* Stop */
cr = readl(fttmr010->base + TIMER_CR);
cr &= ~fttmr010->t1_enable_val;
-@@ -186,6 +204,8 @@ static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
- cr |= TIMER_1_INT_MATCH1;
- writel(cr, fttmr010->base + TIMER_INTR_MASK);
+@@ -201,6 +219,8 @@ static int fttmr010_timer_set_oneshot(struct clock_event_device *evt)
+ writel(cr, fttmr010->base + TIMER_INTR_MASK);
+ }
+ spin_unlock_irqrestore(&timer_fttmr010_lock, flags);
+
return 0;
}
-@@ -193,8 +213,11 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
+@@ -208,8 +228,11 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
{
struct fttmr010 *fttmr010 = to_fttmr010(evt);
u32 period = DIV_ROUND_CLOSEST(fttmr010->tick_rate, HZ);
@@ -128,7 +127,7 @@ index cf93f6419b51..8226ccf5cc2c 100644
/* Stop */
cr = readl(fttmr010->base + TIMER_CR);
cr &= ~fttmr010->t1_enable_val;
-@@ -221,6 +244,8 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
+@@ -235,6 +258,8 @@ static int fttmr010_timer_set_periodic(struct clock_event_device *evt)
cr |= fttmr010->t1_enable_val;
writel(cr, fttmr010->base + TIMER_CR);
@@ -137,45 +136,11 @@ index cf93f6419b51..8226ccf5cc2c 100644
return 0;
}
-diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
-index edca0d737750..a3baa52f187f 100644
---- a/drivers/input/misc/pwm-beeper.c
-+++ b/drivers/input/misc/pwm-beeper.c
-@@ -52,7 +52,7 @@ static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)
- if (error)
- return error;
-
-- if (!beeper->amplifier_on) {
-+ if (beeper->amplifier && !beeper->amplifier_on) {
- error = regulator_enable(beeper->amplifier);
- if (error) {
- pwm_disable(beeper->pwm);
-@@ -67,7 +67,7 @@ static int pwm_beeper_on(struct pwm_beeper *beeper, unsigned long period)
-
- static void pwm_beeper_off(struct pwm_beeper *beeper)
- {
-- if (beeper->amplifier_on) {
-+ if (beeper->amplifier && beeper->amplifier_on) {
- regulator_disable(beeper->amplifier);
- beeper->amplifier_on = false;
- }
-@@ -163,9 +163,9 @@ static int pwm_beeper_probe(struct platform_device *pdev)
- if (IS_ERR(beeper->amplifier)) {
- error = PTR_ERR(beeper->amplifier);
- if (error != -EPROBE_DEFER)
-- dev_err(dev, "Failed to get 'amp' regulator: %d\n",
-+ dev_dbg(dev, "Failed to get 'amp' regulator: %d\n",
- error);
-- return error;
-+ beeper->amplifier = NULL;
- }
-
- INIT_WORK(&beeper->work, pwm_beeper_work);
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
-index 504d252716f2..9d4642c668c9 100644
+index a8f47df0655a..92a8fbebe2d9 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
-@@ -168,6 +168,15 @@ config PWM_FSL_FTM
+@@ -170,6 +170,15 @@ config PWM_FSL_FTM
To compile this driver as a module, choose M here: the module
will be called pwm-fsl-ftm.
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch
index 85b2f45a1..1b86e9c04 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0040-i2c-Add-mux-hold-unhold-msg-types.patch
@@ -1,4 +1,4 @@
-From 38ba0a960fcd17f7b3480fe3025c261fd60fe979 Mon Sep 17 00:00:00 2001
+From 80ea6461d77e5b415d9f83fa2f4708fc21eab09b Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Fri, 15 Feb 2019 16:05:09 -0800
Subject: [PATCH] i2c: Add mux hold/unhold msg types
@@ -39,19 +39,19 @@ in downstream only.
Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
---
- drivers/i2c/i2c-core-base.c | 79 +++++++++++++++++++++++++++----
+ drivers/i2c/i2c-core-base.c | 99 ++++++++++++++++++++++++++++++++++-----
drivers/i2c/i2c-core-smbus.c | 17 ++++++-
drivers/i2c/i2c-mux.c | 109 +++++++++++++++++++++++++++++++++++++++----
include/linux/i2c-mux.h | 3 ++
include/linux/i2c.h | 25 ++++++++++
include/uapi/linux/i2c.h | 1 +
- 6 files changed, 215 insertions(+), 19 deletions(-)
+ 6 files changed, 233 insertions(+), 21 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
-index 9200e349f29e..728b818501b1 100644
+index 28460f6a60cc..009b0507768e 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
-@@ -1211,6 +1211,25 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)
+@@ -1210,6 +1210,25 @@ int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)
}
EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
@@ -77,7 +77,7 @@ index 9200e349f29e..728b818501b1 100644
static int i2c_register_adapter(struct i2c_adapter *adap)
{
int res = -EINVAL;
-@@ -1292,6 +1311,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
+@@ -1291,6 +1310,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);
mutex_unlock(&core_lock);
@@ -87,7 +87,7 @@ index 9200e349f29e..728b818501b1 100644
return 0;
out_reg:
-@@ -1512,6 +1534,8 @@ void i2c_del_adapter(struct i2c_adapter *adap)
+@@ -1511,6 +1533,8 @@ void i2c_del_adapter(struct i2c_adapter *adap)
idr_remove(&i2c_adapter_idr, adap->nr);
mutex_unlock(&core_lock);
@@ -96,7 +96,7 @@ index 9200e349f29e..728b818501b1 100644
/* Clear the device structure in case this adapter is ever going to be
added again */
memset(&adap->dev, 0, sizeof(adap->dev));
-@@ -1861,7 +1885,9 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
+@@ -1860,7 +1884,9 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
*/
int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
@@ -106,7 +106,7 @@ index 9200e349f29e..728b818501b1 100644
int ret, try;
if (WARN_ON(!msgs || num < 1))
-@@ -1870,6 +1896,25 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+@@ -1869,6 +1895,25 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (adap->quirks && i2c_check_for_quirks(adap, msgs, num))
return -EOPNOTSUPP;
@@ -132,7 +132,7 @@ index 9200e349f29e..728b818501b1 100644
/*
* i2c_trace_msg_key gets enabled when tracepoint i2c_transfer gets
* enabled. This is an efficient way of keeping the for-loop from
-@@ -1902,6 +1947,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+@@ -1901,6 +1946,9 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
trace_i2c_result(adap, num, ret);
}
@@ -142,26 +142,39 @@ index 9200e349f29e..728b818501b1 100644
return ret;
}
EXPORT_SYMBOL(__i2c_transfer);
-@@ -1920,6 +1968,7 @@ EXPORT_SYMBOL(__i2c_transfer);
+@@ -1919,6 +1967,7 @@ EXPORT_SYMBOL(__i2c_transfer);
*/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
+ bool do_bus_lock = true;
int ret;
- /* REVISIT the fault reporting model here is weak:
-@@ -1949,18 +1998,30 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
- (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
- }
- #endif
--
-- if (in_atomic() || irqs_disabled()) {
-- ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
-- if (!ret)
-- /* I2C activity is ongoing. */
-- return -EAGAIN;
-- } else {
-- i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
+ if (!adap->algo->master_xfer) {
+@@ -1942,19 +1991,47 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ * one (discarding status on the second message) or errno
+ * (discarding status on the first one).
+ */
+- if (in_atomic() || irqs_disabled()) {
+- ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT);
+- if (!ret)
+- /* I2C activity is ongoing. */
+- return -EAGAIN;
+- } else {
+- i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
+- }
+
+- ret = __i2c_transfer(adap, msgs, num);
+- i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
++ if (adap->algo->master_xfer) {
++#ifdef DEBUG
++ for (ret = 0; ret < num; ret++) {
++ dev_dbg(&adap->dev,
++ "master_xfer[%d] %c, addr=0x%02x, len=%d%s\n",
++ ret, (msgs[ret].flags & I2C_M_RD) ? 'R' : 'W',
++ msgs[ret].addr, msgs[ret].len,
++ (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");
++ }
++#endif
+ /*
+ * Do not lock a bus for delivering an unhold msg to a mux
+ * adpater. This is just for a single length unhold msg case.
@@ -181,15 +194,21 @@ index 9200e349f29e..728b818501b1 100644
+ } else {
+ i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
+ }
- }
++ }
- ret = __i2c_transfer(adap, msgs, num);
-- i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
+- return ret;
++ ret = __i2c_transfer(adap, msgs, num);
+ if (do_bus_lock)
+ i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
++
++ return ret;
++ } else {
++ dev_dbg(&adap->dev, "I2C level transfers not supported\n");
++ return -EOPNOTSUPP;
++ }
+ }
+ EXPORT_SYMBOL(i2c_transfer);
- return ret;
- } else {
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index 9cd66cabb84f..64c58911bf21 100644
--- a/drivers/i2c/i2c-core-smbus.c
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch
index 9e7757011..9aee6f0c0 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0041-Enable-passthrough-based-gpio-character-device.patch
@@ -1,20 +1,20 @@
-From d34efc982a9206db87da49be3d9b1e20f59be56f Mon Sep 17 00:00:00 2001
+From 554bc7a7c7aa6e0c0ec49a24063102e17954d06c Mon Sep 17 00:00:00 2001
From: Kuiying Wang <kuiying.wang@intel.com>
Date: Thu, 31 Jan 2019 17:47:39 +0800
Subject: [PATCH] Enable passthrough based gpio character device.
Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
---
- drivers/gpio/gpio-aspeed.c | 47 ++++++++++++++++++++++-
- drivers/gpio/gpiolib.c | 51 +++++++++++++++++++++++--
+ drivers/gpio/gpio-aspeed.c | 47 ++++++++++++++++++++++++++++--
+ drivers/gpio/gpiolib.c | 51 +++++++++++++++++++++++++++++++--
drivers/gpio/gpiolib.h | 1 +
- include/linux/gpio/consumer.h | 9 +++++
- include/linux/pinctrl/pinconf-generic.h | 2 +
+ include/linux/gpio/consumer.h | 9 ++++++
+ include/linux/pinctrl/pinconf-generic.h | 2 ++
include/uapi/linux/gpio.h | 1 +
6 files changed, 106 insertions(+), 5 deletions(-)
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
-index 2342e154029b..06fd95197684 100644
+index 854bce4fb9e7..5f1bce3a9274 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -17,9 +17,11 @@
@@ -115,10 +115,10 @@ index 2342e154029b..06fd95197684 100644
gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
-index a8e01d99919c..21eeca17583d 100644
+index d1adfdf50fb3..4f9fdd25c6d7 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
-@@ -419,6 +419,7 @@ struct linehandle_state {
+@@ -428,6 +428,7 @@ struct linehandle_state {
GPIOHANDLE_REQUEST_OUTPUT | \
GPIOHANDLE_REQUEST_ACTIVE_LOW | \
GPIOHANDLE_REQUEST_OPEN_DRAIN | \
@@ -126,7 +126,7 @@ index a8e01d99919c..21eeca17583d 100644
GPIOHANDLE_REQUEST_OPEN_SOURCE)
static long linehandle_ioctl(struct file *filep, unsigned int cmd,
-@@ -519,7 +520,6 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
+@@ -530,7 +531,6 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
return -EINVAL;
lflags = handlereq.flags;
@@ -134,7 +134,7 @@ index a8e01d99919c..21eeca17583d 100644
/* Return an error if an unknown flag is set */
if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS)
return -EINVAL;
-@@ -579,6 +579,8 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
+@@ -590,6 +590,8 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
@@ -143,7 +143,7 @@ index a8e01d99919c..21eeca17583d 100644
ret = gpiod_set_transitory(desc, false);
if (ret < 0)
-@@ -598,6 +600,11 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
+@@ -609,6 +611,11 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
ret = gpiod_direction_input(desc);
if (ret)
goto out_free_descs;
@@ -155,7 +155,7 @@ index a8e01d99919c..21eeca17583d 100644
}
dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
offset);
-@@ -1010,7 +1017,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+@@ -1027,7 +1034,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
struct gpio_device *gdev = filp->private_data;
struct gpio_chip *chip = gdev->chip;
void __user *ip = (void __user *)arg;
@@ -163,7 +163,7 @@ index a8e01d99919c..21eeca17583d 100644
/* We fail any subsequent ioctl():s when the chip is gone */
if (!chip)
return -ENODEV;
-@@ -1018,7 +1024,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+@@ -1035,7 +1041,6 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
/* Fill in the struct and pass to userspace */
if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
struct gpiochip_info chipinfo;
@@ -171,11 +171,10 @@ index a8e01d99919c..21eeca17583d 100644
memset(&chipinfo, 0, sizeof(chipinfo));
strncpy(chipinfo.name, dev_name(&gdev->dev),
-@@ -2643,6 +2648,46 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
- }
+@@ -2709,6 +2714,46 @@ int gpiod_direction_output(struct gpio_desc *desc, int value)
EXPORT_SYMBOL_GPL(gpiod_direction_output);
-+/**
+ /**
+ * gpiod_direction_pass_through - set the GPIO direction to pass-through
+ * @desc: GPIO to set to pass-through
+ *
@@ -215,14 +214,15 @@ index a8e01d99919c..21eeca17583d 100644
+}
+EXPORT_SYMBOL_GPL(gpiod_direction_pass_through);
+
- /**
++/**
* gpiod_set_debounce - sets @debounce time for a GPIO
* @desc: descriptor of the GPIO for which to set debounce time
+ * @debounce: debounce time in microseconds
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
-index a7e49fef73d4..b143ee47870a 100644
+index bc57f0dc5953..a821a04fc04b 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
-@@ -210,6 +210,7 @@ struct gpio_desc {
+@@ -212,6 +212,7 @@ struct gpio_desc {
#define FLAG_IS_OUT 1
#define FLAG_EXPORT 2 /* protected by sysfs_lock */
#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
@@ -231,10 +231,10 @@ index a7e49fef73d4..b143ee47870a 100644
#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
-index 21ddbe440030..96551839c191 100644
+index 9ddcf50a3c59..f9775be5a46a 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
-@@ -99,6 +99,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
+@@ -110,6 +110,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
int gpiod_get_direction(struct gpio_desc *desc);
int gpiod_direction_input(struct gpio_desc *desc);
int gpiod_direction_output(struct gpio_desc *desc, int value);
@@ -242,7 +242,7 @@ index 21ddbe440030..96551839c191 100644
int gpiod_direction_output_raw(struct gpio_desc *desc, int value);
/* Value get/set from non-sleeping context */
-@@ -314,6 +315,14 @@ static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
+@@ -348,6 +349,14 @@ static inline int gpiod_direction_output(struct gpio_desc *desc, int value)
WARN_ON(1);
return -ENOSYS;
}
@@ -271,7 +271,7 @@ index 6c0680641108..59f0cbabb685 100644
PIN_CONFIG_MAX = 0xFF,
};
diff --git a/include/uapi/linux/gpio.h b/include/uapi/linux/gpio.h
-index 1bf6e6df084b..384ced158412 100644
+index 4ebfe0ac6c5b..99864572b7d9 100644
--- a/include/uapi/linux/gpio.h
+++ b/include/uapi/linux/gpio.h
@@ -62,6 +62,7 @@ struct gpioline_info {
@@ -283,5 +283,5 @@ index 1bf6e6df084b..384ced158412 100644
/**
* struct gpiohandle_request - Information about a GPIO handle request
--
-2.19.1
+2.7.4
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch
index 901d63645..3588d62d9 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0042-Add-bus-timeout-ms-and-retries-device-tree-propertie.patch
@@ -1,4 +1,4 @@
-From ca4f6555620212ffccd943ea4c58e7ee7b1b0571 Mon Sep 17 00:00:00 2001
+From 6515a2134f90f33dbbea8ede5de598d17bb00c12 Mon Sep 17 00:00:00 2001
From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
Date: Thu, 7 Mar 2019 15:17:40 -0800
Subject: [PATCH] Add bus-timeout-ms and #retries device tree properties
@@ -42,7 +42,7 @@ index 8fbd8633a387..7da7e813b2b0 100644
Example:
diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt b/Documentation/devicetree/bindings/i2c/i2c.txt
-index 11263982470e..bdead91f82a4 100644
+index 44efafdfd7f5..e382931cf3d6 100644
--- a/Documentation/devicetree/bindings/i2c/i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c.txt
@@ -80,6 +80,12 @@ wants to support one of the below features, it should adapt the bindings below.
@@ -71,10 +71,10 @@ index 506d867b43d9..84237c5d0aca 100644
bus->adap.dev.parent = &pdev->dev;
bus->adap.dev.of_node = pdev->dev.of_node;
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
-index 728b818501b1..17cf0fb037ac 100644
+index 009b0507768e..386aa2dad908 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
-@@ -1232,6 +1232,7 @@ static void i2c_adapter_hold_timer_callback(struct timer_list *t)
+@@ -1231,6 +1231,7 @@ static void i2c_adapter_hold_timer_callback(struct timer_list *t)
static int i2c_register_adapter(struct i2c_adapter *adap)
{
@@ -82,7 +82,7 @@ index 728b818501b1..17cf0fb037ac 100644
int res = -EINVAL;
/* Can't register until after driver model init */
-@@ -1258,8 +1259,15 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
+@@ -1257,8 +1258,15 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
INIT_LIST_HEAD(&adap->userspace_clients);
/* Set default timeout to 1 second if not already set */
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch
new file mode 100644
index 000000000..d0f98b9c1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0049-Suppress-excessive-HID-gadget-error-logs.patch
@@ -0,0 +1,43 @@
+From 7dd0a7c62e5885bb726ef2bd5007e79a50932c38 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 18 Mar 2019 14:06:36 -0700
+Subject: [PATCH] Suppress excessive HID gadget error logs
+
+HID events can be sent even when the host disconnects the HID
+device according to the current graphic mode. For an example, if
+KVM mouse events are sent when the host is in text mode, queueing
+of end point messages will be dropped with this message:
+
+configfs-gadget gadget: usb_ep_queue error on int endpoint -108
+
+This case is very usual case in BMC since BMC can control power
+status of the host, so this commit suppress the error printing outs
+with making HID gadget driver drop events quietly in the case.
+
+This should be a downstream only customization. Do not upstream it.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ drivers/usb/gadget/function/f_hid.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
+index f3816a5c861e..3a94584a9dbc 100644
+--- a/drivers/usb/gadget/function/f_hid.c
++++ b/drivers/usb/gadget/function/f_hid.c
+@@ -395,8 +395,10 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
+
+ status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
+ if (status < 0) {
+- ERROR(hidg->func.config->cdev,
+- "usb_ep_queue error on int endpoint %zd\n", status);
++ if (status != -ESHUTDOWN)
++ ERROR(hidg->func.config->cdev,
++ "usb_ep_queue error on int endpoint %zd\n",
++ status);
+ goto release_write_pending;
+ } else {
+ status = count;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0050-media-platform-Fix-a-kernel-warning-on-clk-control.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0050-media-platform-Fix-a-kernel-warning-on-clk-control.patch
new file mode 100644
index 000000000..a0168c889
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0050-media-platform-Fix-a-kernel-warning-on-clk-control.patch
@@ -0,0 +1,177 @@
+From 1775e41d085b24a672dc271d08bfc83401288f0b Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 22 Mar 2019 16:34:54 -0700
+Subject: [PATCH] media: platform: Fix a kernel warning on clk control
+
+Video engine clock control functions in the Aspeed video engine driver are
+being called from multiple context without any protection so video clocks
+can be disabled twice and eventually it causes a kernel warning with stack
+dump printing out like below:
+
+[ 120.034729] WARNING: CPU: 0 PID: 1334 at drivers/clk/clk.c:684 clk_core_unprepare+0x13c/0x170
+[ 120.043252] eclk-gate already unprepared
+[ 120.047283] CPU: 0 PID: 1334 Comm: obmc-ikvm Tainted: G W 5.0.3-b94b74e8b52db91fe4e99e0bb481ec8bf2b5b47c #1
+[ 120.058417] Hardware name: Generic DT based system
+[ 120.063219] Backtrace:
+[ 120.065787] [<80107cdc>] (dump_backtrace) from [<80107f10>] (show_stack+0x20/0x24)
+[ 120.073371] r7:803a4ff0 r6:00000009 r5:00000000 r4:96197e1c
+[ 120.079152] [<80107ef0>] (show_stack) from [<8068f7d8>] (dump_stack+0x20/0x28)
+[ 120.086479] [<8068f7b8>] (dump_stack) from [<8011604c>] (__warn.part.3+0xb4/0xdc)
+[ 120.094068] [<80115f98>] (__warn.part.3) from [<801160e0>] (warn_slowpath_fmt+0x6c/0x90)
+[ 120.102164] r6:000002ac r5:8080c0b8 r4:80a07008
+[ 120.106893] [<80116078>] (warn_slowpath_fmt) from [<803a4ff0>] (clk_core_unprepare+0x13c/0x170)
+[ 120.115686] r3:8080cf8c r2:8080c17c
+[ 120.119276] r7:97d68e58 r6:9df23200 r5:9668c260 r4:96459260
+[ 120.125046] [<803a4eb4>] (clk_core_unprepare) from [<803a707c>] (clk_unprepare+0x34/0x3c)
+[ 120.133226] r5:9668c260 r4:96459260
+[ 120.136932] [<803a7048>] (clk_unprepare) from [<804f34bc>] (aspeed_video_off+0x44/0x48)
+[ 120.145031] r5:9668c260 r4:9668cbc0
+[ 120.148647] [<804f3478>] (aspeed_video_off) from [<804f3fd0>] (aspeed_video_release+0x94/0x118)
+[ 120.157435] r5:966a0cb8 r4:966a0800
+[ 120.161049] [<804f3f3c>] (aspeed_video_release) from [<804d2c58>] (v4l2_release+0xd4/0xe8)
+[ 120.169404] r7:97d68e58 r6:9d087810 r5:9df23200 r4:966a0b20
+[ 120.175168] [<804d2b84>] (v4l2_release) from [<80236224>] (__fput+0x98/0x1c4)
+[ 120.182316] r5:96698e78 r4:9df23200
+[ 120.185994] [<8023618c>] (__fput) from [<802363b8>] (____fput+0x18/0x1c)
+[ 120.192712] r9:80a0700c r8:801011e4 r7:00000000 r6:80a64bbc r5:961dd560 r4:961dd89c
+[ 120.200562] [<802363a0>] (____fput) from [<80131c08>] (task_work_run+0x7c/0xa4)
+[ 120.207994] [<80131b8c>] (task_work_run) from [<80106884>] (do_work_pending+0x4a8/0x578)
+[ 120.216163] r7:801011e4 r6:80a07008 r5:96197fb0 r4:ffffe000
+[ 120.221856] [<801063dc>] (do_work_pending) from [<8010106c>] (slow_work_pending+0xc/0x20)
+[ 120.230116] Exception stack(0x96197fb0 to 0x96197ff8)
+[ 120.235254] 7fa0: 00000000 76ccf094 00000000 00000000
+[ 120.243438] 7fc0: 00000008 00a11978 7eab3c30 00000006 00000000 00000000 475b0fa4 00000000
+[ 120.251692] 7fe0: 00000002 7eab3a40 00000000 47720e38 80000010 00000008
+[ 120.258396] r10:00000000 r9:96196000 r8:801011e4 r7:00000006 r6:7eab3c30 r5:00a11978
+[ 120.266291] r4:00000008
+
+To prevent this issue, this commit adds spinlock protection and clock
+status checking logic into the Aspeed video engine driver.
+
+Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver")
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Cc: Eddie James <eajames@linux.ibm.com>
+Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
+Cc: Joel Stanley <joel@jms.id.au>
+Cc: Andrew Jeffery <andrew@aj.id.au>
+---
+ drivers/media/platform/aspeed-video.c | 32 +++++++++++++++++++++++++++++---
+ 1 file changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/platform/aspeed-video.c b/drivers/media/platform/aspeed-video.c
+index 8144fe36ad48..e70be8fdbde5 100644
+--- a/drivers/media/platform/aspeed-video.c
++++ b/drivers/media/platform/aspeed-video.c
+@@ -187,6 +187,7 @@ enum {
+ VIDEO_STREAMING,
+ VIDEO_FRAME_INPRG,
+ VIDEO_STOPPED,
++ VIDEO_CLOCKS_ON,
+ };
+
+ struct aspeed_video_addr {
+@@ -483,19 +484,29 @@ static void aspeed_video_enable_mode_detect(struct aspeed_video *video)
+
+ static void aspeed_video_off(struct aspeed_video *video)
+ {
++ if (!test_bit(VIDEO_CLOCKS_ON, &video->flags))
++ return;
++
+ /* Disable interrupts */
+ aspeed_video_write(video, VE_INTERRUPT_CTRL, 0);
+
+ /* Turn off the relevant clocks */
+ clk_disable_unprepare(video->vclk);
+ clk_disable_unprepare(video->eclk);
++
++ clear_bit(VIDEO_CLOCKS_ON, &video->flags);
+ }
+
+ static void aspeed_video_on(struct aspeed_video *video)
+ {
++ if (test_bit(VIDEO_CLOCKS_ON, &video->flags))
++ return;
++
+ /* Turn on the relevant clocks */
+ clk_prepare_enable(video->eclk);
+ clk_prepare_enable(video->vclk);
++
++ set_bit(VIDEO_CLOCKS_ON, &video->flags);
+ }
+
+ static void aspeed_video_bufs_done(struct aspeed_video *video,
+@@ -513,12 +524,14 @@ static void aspeed_video_bufs_done(struct aspeed_video *video,
+
+ static void aspeed_video_irq_res_change(struct aspeed_video *video)
+ {
++ spin_lock(&video->lock);
+ dev_dbg(video->dev, "Resolution changed; resetting\n");
+
+ set_bit(VIDEO_RES_CHANGE, &video->flags);
+ clear_bit(VIDEO_FRAME_INPRG, &video->flags);
+
+ aspeed_video_off(video);
++ spin_unlock(&video->lock);
+ aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);
+
+ schedule_delayed_work(&video->res_work, RESOLUTION_CHANGE_DELAY);
+@@ -938,9 +951,13 @@ static void aspeed_video_init_regs(struct aspeed_video *video)
+
+ static void aspeed_video_start(struct aspeed_video *video)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&video->lock, flags);
+ aspeed_video_on(video);
+
+ aspeed_video_init_regs(video);
++ spin_unlock_irqrestore(&video->lock, flags);
+
+ /* Resolution set to 640x480 if no signal found */
+ aspeed_video_get_resolution(video);
+@@ -956,6 +973,9 @@ static void aspeed_video_start(struct aspeed_video *video)
+
+ static void aspeed_video_stop(struct aspeed_video *video)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&video->lock, flags);
+ set_bit(VIDEO_STOPPED, &video->flags);
+ cancel_delayed_work_sync(&video->res_work);
+
+@@ -969,6 +989,7 @@ static void aspeed_video_stop(struct aspeed_video *video)
+
+ video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
+ video->flags = 0;
++ spin_unlock_irqrestore(&video->lock, flags);
+ }
+
+ static int aspeed_video_querycap(struct file *file, void *fh,
+@@ -1306,16 +1327,21 @@ static void aspeed_video_resolution_work(struct work_struct *work)
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct aspeed_video *video = container_of(dwork, struct aspeed_video,
+ res_work);
+- u32 input_status = video->v4l2_input_status;
++ unsigned long flags;
++ u32 input_status;
+
++ spin_lock_irqsave(&video->lock, flags);
++ input_status = video->v4l2_input_status;
+ aspeed_video_on(video);
+
+ /* Exit early in case no clients remain */
+- if (test_bit(VIDEO_STOPPED, &video->flags))
++ if (test_bit(VIDEO_STOPPED, &video->flags)) {
++ spin_unlock_irqrestore(&video->lock, flags);
+ goto done;
++ }
+
+ aspeed_video_init_regs(video);
+-
++ spin_unlock_irqrestore(&video->lock, flags);
+ aspeed_video_get_resolution(video);
+
+ if (video->detected_timings.width != video->active_timings.width ||
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
index 1e25709a9..2a9984661 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -21,10 +21,8 @@ SRC_URI += " \
file://0030-Add-dump-debug-code-into-I2C-drivers.patch \
file://0031-Add-high-speed-baud-rate-support-for-UART.patch \
file://0032-misc-aspeed-Add-Aspeed-UART-routing-control-driver.patch \
- file://0034-arm-dts-adpeed-Swap-the-mac-nodes-numbering.patch \
+ file://0034-arm-dts-aspeed-Swap-the-mac-nodes-numbering.patch \
file://0035-Implement-a-memory-driver-share-memory.patch \
- file://0036-net-ncsi-backport-ncsi-patches.patch \
- file://0038-media-aspeed-backport-ikvm-patches.patch \
file://0039-Add-Aspeed-PWM-driver-which-uses-FTTMR010-timer-IP.patch \
file://0040-i2c-Add-mux-hold-unhold-msg-types.patch \
file://0041-Enable-passthrough-based-gpio-character-device.patch \
@@ -35,4 +33,6 @@ SRC_URI += " \
file://0046-misc-Add-clock-control-logic-into-Aspeed-LPC-MBOX-dr.patch \
file://0047-misc-Block-error-printing-on-probe-defer-case-in-Asp.patch \
file://0048-ARM-dts-aspeed-Set-default-status-of-LPC-BT-as-disab.patch \
+ file://0049-Suppress-excessive-HID-gadget-error-logs.patch \
+ file://0050-media-platform-Fix-a-kernel-warning-on-clk-control.patch \
"