All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/3] arm64: allwinner: dts: h6: add pinmux for MMC1
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: linux-arm-kernel, devicetree, linux-kernel, linux-sunxi,
	Icenowy Zheng
In-Reply-To: <20180724011551.49603-1-icenowy@aosc.io>

The MMC1 controller on H6, in the reference design and most third party
design, is used to connect SDIO Wi-Fi.

Add pinmux for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index cfa5fffcf62b..ba1a3a3e2149 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -134,6 +134,14 @@
 				bias-pull-up;
 			};
 
+			mmc1_pins: mmc1-pins {
+				pins = "PG0", "PG1", "PG2", "PG3",
+				       "PG4", "PG5";
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
 			mmc2_pins: mmc2-pins {
 				pins = "PC1", "PC4", "PC5", "PC6",
 				       "PC7", "PC8", "PC9", "PC10",
-- 
2.18.0


^ permalink raw reply related

* [PATCH 3/3] arm64: allwinner: dts: h6: add Wi-Fi support for Pine H64 model A/B
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: linux-arm-kernel, devicetree, linux-kernel, linux-sunxi,
	Icenowy Zheng
In-Reply-To: <20180724011551.49603-1-icenowy@aosc.io>

The Pine H64 model A has a Wi-Fi module connector and the model B has an
on-board RTL8723BS Wi-Fi module.

Add support for them. For model A, as it's not defaultly present, keep
it disabled now.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 .../allwinner/sun50i-h6-pine-h64-model-b.dts  |  8 +++++
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 29 +++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
index d0fcc25efb00..d0f775613c9b 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
@@ -18,3 +18,11 @@
 		};
 	};
 };
+
+&mmc1 {
+	status = "okay";
+};
+
+&wifi_pwrseq {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index a85867f8b684..75db6d4139bf 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -40,6 +40,12 @@
 			gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
 		};
 	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PL2 */
+		status = "disabled";
+	};
 };
 
 &mmc0 {
@@ -50,6 +56,17 @@
 	status = "okay";
 };
 
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&reg_cldo2>;
+	vqmmc-supply = <&reg_bldo2>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "disabled";
+};
+
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_pins>;
@@ -128,12 +145,24 @@
 			};
 
 			reg_cldo2: cldo2 {
+				/*
+				 * This regulator is connected with CLDO3.
+				 * Before the kernel can support synchronized
+				 * enable of coupled regulators, keep them
+				 * both always on as a ugly hack.
+				 */
+				regulator-always-on;
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-name = "vcc-wifi-1";
 			};
 
 			reg_cldo3: cldo3 {
+				/*
+				 * This regulator is connected with CLDO2.
+				 * See the comments for CLDO2.
+				 */
+				regulator-always-on;
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-name = "vcc-wifi-2";
-- 
2.18.0

^ permalink raw reply related

* [PATCH 3/3] arm64: allwinner: dts: h6: add Wi-Fi support for Pine H64 model A/B
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180724011551.49603-1-icenowy@aosc.io>

The Pine H64 model A has a Wi-Fi module connector and the model B has an
on-board RTL8723BS Wi-Fi module.

Add support for them. For model A, as it's not defaultly present, keep
it disabled now.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 .../allwinner/sun50i-h6-pine-h64-model-b.dts  |  8 +++++
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 29 +++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
index d0fcc25efb00..d0f775613c9b 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
@@ -18,3 +18,11 @@
 		};
 	};
 };
+
+&mmc1 {
+	status = "okay";
+};
+
+&wifi_pwrseq {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index a85867f8b684..75db6d4139bf 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -40,6 +40,12 @@
 			gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
 		};
 	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PL2 */
+		status = "disabled";
+	};
 };
 
 &mmc0 {
@@ -50,6 +56,17 @@
 	status = "okay";
 };
 
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>;
+	vmmc-supply = <&reg_cldo2>;
+	vqmmc-supply = <&reg_bldo2>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "disabled";
+};
+
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_pins>;
@@ -128,12 +145,24 @@
 			};
 
 			reg_cldo2: cldo2 {
+				/*
+				 * This regulator is connected with CLDO3.
+				 * Before the kernel can support synchronized
+				 * enable of coupled regulators, keep them
+				 * both always on as a ugly hack.
+				 */
+				regulator-always-on;
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-name = "vcc-wifi-1";
 			};
 
 			reg_cldo3: cldo3 {
+				/*
+				 * This regulator is connected with CLDO2.
+				 * See the comments for CLDO2.
+				 */
+				regulator-always-on;
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-name = "vcc-wifi-2";
-- 
2.18.0

^ permalink raw reply related

* [PATCH 2/3] arm64: allwinner: dts: h6: add pinmux for MMC1
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20180724011551.49603-1-icenowy-h8G6r0blFSE@public.gmane.org>

The MMC1 controller on H6, in the reference design and most third party
design, is used to connect SDIO Wi-Fi.

Add pinmux for it.

Signed-off-by: Icenowy Zheng <icenowy-h8G6r0blFSE@public.gmane.org>
---
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index cfa5fffcf62b..ba1a3a3e2149 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -134,6 +134,14 @@
 				bias-pull-up;
 			};
 
+			mmc1_pins: mmc1-pins {
+				pins = "PG0", "PG1", "PG2", "PG3",
+				       "PG4", "PG5";
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
 			mmc2_pins: mmc2-pins {
 				pins = "PC1", "PC4", "PC5", "PC6",
 				       "PC7", "PC8", "PC9", "PC10",
-- 
2.18.0

^ permalink raw reply related

* [PATCH 2/3] arm64: allwinner: dts: h6: add pinmux for MMC1
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180724011551.49603-1-icenowy@aosc.io>

The MMC1 controller on H6, in the reference design and most third party
design, is used to connect SDIO Wi-Fi.

Add pinmux for it.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index cfa5fffcf62b..ba1a3a3e2149 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -134,6 +134,14 @@
 				bias-pull-up;
 			};
 
+			mmc1_pins: mmc1-pins {
+				pins = "PG0", "PG1", "PG2", "PG3",
+				       "PG4", "PG5";
+				function = "mmc1";
+				drive-strength = <30>;
+				bias-pull-up;
+			};
+
 			mmc2_pins: mmc2-pins {
 				pins = "PC1", "PC4", "PC5", "PC6",
 				       "PC7", "PC8", "PC9", "PC10",
-- 
2.18.0

^ permalink raw reply related

* [PATCH 1/3] arm64: allwinner: dts: h6: add Pine H64 model B
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: linux-arm-kernel, devicetree, linux-kernel, linux-sunxi,
	Icenowy Zheng
In-Reply-To: <20180724011551.49603-1-icenowy@aosc.io>

Pine H64 model B is another variant of Pine H64 by Pine64. It features a
smaller board footprint (of RPi size) and drops PCIe. It also have WLAN
on board (rather than via expansion connector on the original model A)
and some LED changes.

Add an initial device tree for it. Only LED difference is considered
now, as functionalities related to other changes are still not available
now.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 arch/arm64/boot/dts/allwinner/Makefile        |  1 +
 .../allwinner/sun50i-h6-pine-h64-model-b.dts  | 20 +++++++++++++++++++
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts |  5 +++--
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 9ffa7a038791..330b5fb3715b 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -16,3 +16,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
new file mode 100644
index 000000000000..d0fcc25efb00
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include "sun50i-h6-pine-h64.dts"
+
+/ {
+	model = "Pine H64 Model B";
+	compatible = "pine64,pine-h64-model-b", "pine64,pine-h64",
+		     "allwinner,sun50i-h6";
+
+	leds {
+		/delete-node/ heartbeat;
+
+		status {
+			label = "pine-h64:red:status";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index ceffc40810ee..a85867f8b684 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -10,8 +10,9 @@
 #include <dt-bindings/gpio/gpio.h>
 
 / {
-	model = "Pine H64";
-	compatible = "pine64,pine-h64", "allwinner,sun50i-h6";
+	model = "Pine H64 Model A";
+	compatible = "pine64,pine-h64-model-a", "pine64,pine-h64",
+		     "allwinner,sun50i-h6";
 
 	aliases {
 		serial0 = &uart0;
-- 
2.18.0

^ permalink raw reply related

* [PATCH 1/3] arm64: allwinner: dts: h6: add Pine H64 model B
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180724011551.49603-1-icenowy@aosc.io>

Pine H64 model B is another variant of Pine H64 by Pine64. It features a
smaller board footprint (of RPi size) and drops PCIe. It also have WLAN
on board (rather than via expansion connector on the original model A)
and some LED changes.

Add an initial device tree for it. Only LED difference is considered
now, as functionalities related to other changes are still not available
now.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 arch/arm64/boot/dts/allwinner/Makefile        |  1 +
 .../allwinner/sun50i-h6-pine-h64-model-b.dts  | 20 +++++++++++++++++++
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts |  5 +++--
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 9ffa7a038791..330b5fb3715b 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -16,3 +16,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
new file mode 100644
index 000000000000..d0fcc25efb00
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include "sun50i-h6-pine-h64.dts"
+
+/ {
+	model = "Pine H64 Model B";
+	compatible = "pine64,pine-h64-model-b", "pine64,pine-h64",
+		     "allwinner,sun50i-h6";
+
+	leds {
+		/delete-node/ heartbeat;
+
+		status {
+			label = "pine-h64:red:status";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index ceffc40810ee..a85867f8b684 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -10,8 +10,9 @@
 #include <dt-bindings/gpio/gpio.h>
 
 / {
-	model = "Pine H64";
-	compatible = "pine64,pine-h64", "allwinner,sun50i-h6";
+	model = "Pine H64 Model A";
+	compatible = "pine64,pine-h64-model-a", "pine64,pine-h64",
+		     "allwinner,sun50i-h6";
 
 	aliases {
 		serial0 = &uart0;
-- 
2.18.0

^ permalink raw reply related

* [PATCH 0/3] Add support for Pine H64 model B w/ Wi-Fi support
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: linux-arm-kernel, devicetree, linux-kernel, linux-sunxi,
	Icenowy Zheng

Pine H64 has made a new "model B", on which "Euler bus" and "EXP bus"
are dropped, one LED is stripped and the Wi-Fi become an on-board
RTL8723BS.

Add support for this board, with the Wi-Fi support.

Wi-Fi support is also introduced for model A, but disabled.

Icenowy Zheng (3):
  arm64: allwinner: dts: h6: add Pine H64 model B
  arm64: allwinner: dts: h6: add pinmux for MMC1
  arm64: allwinner: dts: h6: add Wi-Fi support for Pine H64 model A/B

 arch/arm64/boot/dts/allwinner/Makefile        |  1 +
 .../allwinner/sun50i-h6-pine-h64-model-b.dts  | 28 +++++++++++++++
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 34 +++++++++++++++++--
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi  |  8 +++++
 4 files changed, 69 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts

-- 
2.18.0

^ permalink raw reply

* [PATCH 0/3] Add support for Pine H64 model B w/ Wi-Fi support
From: Icenowy Zheng @ 2018-07-24  1:15 UTC (permalink / raw)
  To: linux-arm-kernel

Pine H64 has made a new "model B", on which "Euler bus" and "EXP bus"
are dropped, one LED is stripped and the Wi-Fi become an on-board
RTL8723BS.

Add support for this board, with the Wi-Fi support.

Wi-Fi support is also introduced for model A, but disabled.

Icenowy Zheng (3):
  arm64: allwinner: dts: h6: add Pine H64 model B
  arm64: allwinner: dts: h6: add pinmux for MMC1
  arm64: allwinner: dts: h6: add Wi-Fi support for Pine H64 model A/B

 arch/arm64/boot/dts/allwinner/Makefile        |  1 +
 .../allwinner/sun50i-h6-pine-h64-model-b.dts  | 28 +++++++++++++++
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts | 34 +++++++++++++++++--
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi  |  8 +++++
 4 files changed, 69 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64-model-b.dts

-- 
2.18.0

^ permalink raw reply

* [PATCH v6] media: dvb-frontends: add Socionext MN88443x ISDB-S/T demodulator driver
From: Katsuhiro Suzuki @ 2018-07-24  0:09 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, linux-media
  Cc: Masami Hiramatsu, Jassi Brar, linux-arm-kernel, linux-kernel,
	Katsuhiro Suzuki

This patch adds a frontend driver for the Socionext/Panasonic
MN884434 and MN884433 ISDB-S/T demodulators.

The maximum and minimum frequency of MN88443x comes from
ISDB-S and ISDB-T so frequency range is the following:
  - ISDB-S (BS/CS110 IF frequency, Local freq 10.678GHz)
    - Min: BS-1: 1032MHz
    - Max: ND24: 2070MHz
  - ISDB-T
    - Min: ch13: 470MHz
    - Max: ch62: 770MHz

Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>

---

Changes since v5:
  - Fix include of header.

Changes since v4:
  - Remove SC1501A support.
    This driver is written and tested for MN88443x, I misunderstood
    spec of SC1501A. SC1501A has not compatibility with MN88443x.

Changes since v3:
  - Add symbol rate for ISDB-S
  - Describe max/min frequency in Hz (not kHz)
  - Depends on Mauro's DVB core fixes
    https://patchwork.linuxtv.org/patch/50886/
    https://patchwork.linuxtv.org/patch/50887/
    https://patchwork.linuxtv.org/patch/50888/

Changes since v2:
  - Fix frequency max and min

Changes since v1:
  - Fix sparse warning about type of constant
  - Use div_s64() instead of divide operator
---
 drivers/media/dvb-frontends/Kconfig    |  10 +
 drivers/media/dvb-frontends/Makefile   |   1 +
 drivers/media/dvb-frontends/mn88443x.c | 802 +++++++++++++++++++++++++
 drivers/media/dvb-frontends/mn88443x.h |  27 +
 4 files changed, 840 insertions(+)
 create mode 100644 drivers/media/dvb-frontends/mn88443x.c
 create mode 100644 drivers/media/dvb-frontends/mn88443x.h

diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 9ecaa9d0744a..048285134cdf 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -739,6 +739,16 @@ config DVB_TC90522
 	  Toshiba TC90522 2xISDB-S 8PSK + 2xISDB-T OFDM demodulator.
 	  Say Y when you want to support this frontend.
 
+config DVB_MN88443X
+	tristate "Socionext MN88443x"
+	depends on DVB_CORE && I2C
+	select REGMAP_I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A driver for Socionext/Panasonic MN884433 and MN884434
+	  ISDB-S + ISDB-T demodulator.
+	  Say Y when you want to support this frontend.
+
 comment "Digital terrestrial only tuners/PLL"
 	depends on DVB_CORE
 
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index 67a783fd5ed0..779dfd027b24 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -125,6 +125,7 @@ obj-$(CONFIG_DVB_AF9033) += af9033.o
 obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o
 obj-$(CONFIG_DVB_GP8PSK_FE) += gp8psk-fe.o
 obj-$(CONFIG_DVB_TC90522) += tc90522.o
+obj-$(CONFIG_DVB_MN88443X) += mn88443x.o
 obj-$(CONFIG_DVB_HORUS3A) += horus3a.o
 obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
 obj-$(CONFIG_DVB_HELENE) += helene.o
diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c
new file mode 100644
index 000000000000..9ec1aeef03d5
--- /dev/null
+++ b/drivers/media/dvb-frontends/mn88443x.c
@@ -0,0 +1,802 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext MN88443x series demodulator driver for ISDB-S/ISDB-T.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <media/dvb_math.h>
+
+#include "mn88443x.h"
+
+/* ISDB-S registers */
+#define ATSIDU_S                                    0x2f
+#define ATSIDL_S                                    0x30
+#define TSSET_S                                     0x31
+#define AGCREAD_S                                   0x5a
+#define CPMON1_S                                    0x5e
+#define   CPMON1_S_FSYNC                              BIT(5)
+#define   CPMON1_S_ERRMON                             BIT(4)
+#define   CPMON1_S_SIGOFF                             BIT(3)
+#define   CPMON1_S_W2LOCK                             BIT(2)
+#define   CPMON1_S_W1LOCK                             BIT(1)
+#define   CPMON1_S_DW1LOCK                            BIT(0)
+#define TRMON_S                                     0x60
+#define BERCNFLG_S                                  0x68
+#define   BERCNFLG_S_BERVRDY                          BIT(5)
+#define   BERCNFLG_S_BERVCHK                          BIT(4)
+#define   BERCNFLG_S_BERDRDY                          BIT(3)
+#define   BERCNFLG_S_BERDCHK                          BIT(2)
+#define CNRDXU_S                                    0x69
+#define CNRDXL_S                                    0x6a
+#define CNRDYU_S                                    0x6b
+#define CNRDYL_S                                    0x6c
+#define BERVRDU_S                                   0x71
+#define BERVRDL_S                                   0x72
+#define DOSET1_S                                    0x73
+
+/* Primary ISDB-T */
+#define PLLASET1                                    0x00
+#define PLLASET2                                    0x01
+#define PLLBSET1                                    0x02
+#define PLLBSET2                                    0x03
+#define PLLSET                                      0x04
+#define OUTCSET                                     0x08
+#define   OUTCSET_CHDRV_8MA                           0xff
+#define   OUTCSET_CHDRV_4MA                           0x00
+#define PLDWSET                                     0x09
+#define   PLDWSET_NORMAL                             0x00
+#define   PLDWSET_PULLDOWN                           0xff
+#define HIZSET1                                     0x0a
+#define HIZSET2                                     0x0b
+
+/* Secondary ISDB-T (for MN884434 only) */
+#define RCVSET                                      0x00
+#define TSSET1_M                                    0x01
+#define TSSET2_M                                    0x02
+#define TSSET3_M                                    0x03
+#define INTACSET                                    0x08
+#define HIZSET3                                     0x0b
+
+/* ISDB-T registers */
+#define TSSET1                                      0x05
+#define   TSSET1_TSASEL_MASK                          GENMASK(4, 3)
+#define   TSSET1_TSASEL_ISDBT                         (0x0 << 3)
+#define   TSSET1_TSASEL_ISDBS                         (0x1 << 3)
+#define   TSSET1_TSASEL_NONE                          (0x2 << 3)
+#define   TSSET1_TSBSEL_MASK                          GENMASK(2, 1)
+#define   TSSET1_TSBSEL_ISDBS                         (0x0 << 1)
+#define   TSSET1_TSBSEL_ISDBT                         (0x1 << 1)
+#define   TSSET1_TSBSEL_NONE                          (0x2 << 1)
+#define TSSET2                                      0x06
+#define TSSET3                                      0x07
+#define   TSSET3_INTASEL_MASK                         GENMASK(7, 6)
+#define   TSSET3_INTASEL_T                            (0x0 << 6)
+#define   TSSET3_INTASEL_S                            (0x1 << 6)
+#define   TSSET3_INTASEL_NONE                         (0x2 << 6)
+#define   TSSET3_INTBSEL_MASK                         GENMASK(5, 4)
+#define   TSSET3_INTBSEL_S                            (0x0 << 4)
+#define   TSSET3_INTBSEL_T                            (0x1 << 4)
+#define   TSSET3_INTBSEL_NONE                         (0x2 << 4)
+#define OUTSET2                                     0x0d
+#define PWDSET                                      0x0f
+#define   PWDSET_OFDMPD_MASK                          GENMASK(3, 2)
+#define   PWDSET_OFDMPD_DOWN                          BIT(3)
+#define   PWDSET_PSKPD_MASK                           GENMASK(1, 0)
+#define   PWDSET_PSKPD_DOWN                           BIT(1)
+#define CLKSET1_T                                   0x11
+#define MDSET_T                                     0x13
+#define   MDSET_T_MDAUTO_MASK                         GENMASK(7, 4)
+#define   MDSET_T_MDAUTO_AUTO                         (0xf << 4)
+#define   MDSET_T_MDAUTO_MANUAL                       (0x0 << 4)
+#define   MDSET_T_FFTS_MASK                           GENMASK(3, 2)
+#define   MDSET_T_FFTS_MODE1                          (0x0 << 2)
+#define   MDSET_T_FFTS_MODE2                          (0x1 << 2)
+#define   MDSET_T_FFTS_MODE3                          (0x2 << 2)
+#define   MDSET_T_GI_MASK                             GENMASK(1, 0)
+#define   MDSET_T_GI_1_32                             (0x0 << 0)
+#define   MDSET_T_GI_1_16                             (0x1 << 0)
+#define   MDSET_T_GI_1_8                              (0x2 << 0)
+#define   MDSET_T_GI_1_4                              (0x3 << 0)
+#define MDASET_T                                    0x14
+#define ADCSET1_T                                   0x20
+#define   ADCSET1_T_REFSEL_MASK                       GENMASK(1, 0)
+#define   ADCSET1_T_REFSEL_2V                         (0x3 << 0)
+#define   ADCSET1_T_REFSEL_1_5V                       (0x2 << 0)
+#define   ADCSET1_T_REFSEL_1V                         (0x1 << 0)
+#define NCOFREQU_T                                  0x24
+#define NCOFREQM_T                                  0x25
+#define NCOFREQL_T                                  0x26
+#define FADU_T                                      0x27
+#define FADM_T                                      0x28
+#define FADL_T                                      0x29
+#define AGCSET2_T                                   0x2c
+#define   AGCSET2_T_IFPOLINV_INC                      BIT(0)
+#define   AGCSET2_T_RFPOLINV_INC                      BIT(1)
+#define AGCV3_T                                     0x3e
+#define MDRD_T                                      0xa2
+#define   MDRD_T_SEGID_MASK                           GENMASK(5, 4)
+#define   MDRD_T_SEGID_13                             (0x0 << 4)
+#define   MDRD_T_SEGID_1                              (0x1 << 4)
+#define   MDRD_T_SEGID_3                              (0x2 << 4)
+#define   MDRD_T_FFTS_MASK                            GENMASK(3, 2)
+#define   MDRD_T_FFTS_MODE1                           (0x0 << 2)
+#define   MDRD_T_FFTS_MODE2                           (0x1 << 2)
+#define   MDRD_T_FFTS_MODE3                           (0x2 << 2)
+#define   MDRD_T_GI_MASK                              GENMASK(1, 0)
+#define   MDRD_T_GI_1_32                              (0x0 << 0)
+#define   MDRD_T_GI_1_16                              (0x1 << 0)
+#define   MDRD_T_GI_1_8                               (0x2 << 0)
+#define   MDRD_T_GI_1_4                               (0x3 << 0)
+#define SSEQRD_T                                    0xa3
+#define   SSEQRD_T_SSEQSTRD_MASK                      GENMASK(3, 0)
+#define   SSEQRD_T_SSEQSTRD_RESET                     (0x0 << 0)
+#define   SSEQRD_T_SSEQSTRD_TUNING                    (0x1 << 0)
+#define   SSEQRD_T_SSEQSTRD_AGC                       (0x2 << 0)
+#define   SSEQRD_T_SSEQSTRD_SEARCH                    (0x3 << 0)
+#define   SSEQRD_T_SSEQSTRD_CLOCK_SYNC                (0x4 << 0)
+#define   SSEQRD_T_SSEQSTRD_FREQ_SYNC                 (0x8 << 0)
+#define   SSEQRD_T_SSEQSTRD_FRAME_SYNC                (0x9 << 0)
+#define   SSEQRD_T_SSEQSTRD_SYNC                      (0xa << 0)
+#define   SSEQRD_T_SSEQSTRD_LOCK                      (0xb << 0)
+#define AGCRDU_T                                    0xa8
+#define AGCRDL_T                                    0xa9
+#define CNRDU_T                                     0xbe
+#define CNRDL_T                                     0xbf
+#define BERFLG_T                                    0xc0
+#define   BERFLG_T_BERDRDY                            BIT(7)
+#define   BERFLG_T_BERDCHK                            BIT(6)
+#define   BERFLG_T_BERVRDYA                           BIT(5)
+#define   BERFLG_T_BERVCHKA                           BIT(4)
+#define   BERFLG_T_BERVRDYB                           BIT(3)
+#define   BERFLG_T_BERVCHKB                           BIT(2)
+#define   BERFLG_T_BERVRDYC                           BIT(1)
+#define   BERFLG_T_BERVCHKC                           BIT(0)
+#define BERRDU_T                                    0xc1
+#define BERRDM_T                                    0xc2
+#define BERRDL_T                                    0xc3
+#define BERLENRDU_T                                 0xc4
+#define BERLENRDL_T                                 0xc5
+#define ERRFLG_T                                    0xc6
+#define   ERRFLG_T_BERDOVF                            BIT(7)
+#define   ERRFLG_T_BERVOVFA                           BIT(6)
+#define   ERRFLG_T_BERVOVFB                           BIT(5)
+#define   ERRFLG_T_BERVOVFC                           BIT(4)
+#define   ERRFLG_T_NERRFA                             BIT(3)
+#define   ERRFLG_T_NERRFB                             BIT(2)
+#define   ERRFLG_T_NERRFC                             BIT(1)
+#define   ERRFLG_T_NERRF                              BIT(0)
+#define DOSET1_T                                    0xcf
+
+#define CLK_LOW            4000000
+#define CLK_DIRECT         20200000
+#define CLK_MAX            25410000
+
+#define S_T_FREQ           8126984 /* 512 / 63 MHz */
+
+struct mn88443x_spec {
+	bool primary;
+};
+
+struct mn88443x_priv {
+	const struct mn88443x_spec *spec;
+
+	struct dvb_frontend fe;
+	struct clk *mclk;
+	struct gpio_desc *reset_gpio;
+	u32 clk_freq;
+	u32 if_freq;
+
+	/* Common */
+	bool use_clkbuf;
+
+	/* ISDB-S */
+	struct i2c_client *client_s;
+	struct regmap *regmap_s;
+
+	/* ISDB-T */
+	struct i2c_client *client_t;
+	struct regmap *regmap_t;
+};
+
+static void mn88443x_cmn_power_on(struct mn88443x_priv *chip)
+{
+	struct regmap *r_t = chip->regmap_t;
+
+	clk_prepare_enable(chip->mclk);
+
+	gpiod_set_value_cansleep(chip->reset_gpio, 1);
+	usleep_range(100, 1000);
+	gpiod_set_value_cansleep(chip->reset_gpio, 0);
+
+	if (chip->spec->primary) {
+		regmap_write(r_t, OUTCSET, OUTCSET_CHDRV_8MA);
+		regmap_write(r_t, PLDWSET, PLDWSET_NORMAL);
+		regmap_write(r_t, HIZSET1, 0x80);
+		regmap_write(r_t, HIZSET2, 0xe0);
+	} else {
+		regmap_write(r_t, HIZSET3, 0x8f);
+	}
+}
+
+static void mn88443x_cmn_power_off(struct mn88443x_priv *chip)
+{
+	gpiod_set_value_cansleep(chip->reset_gpio, 1);
+
+	clk_disable_unprepare(chip->mclk);
+}
+
+static void mn88443x_s_sleep(struct mn88443x_priv *chip)
+{
+	struct regmap *r_t = chip->regmap_t;
+
+	regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK,
+			   PWDSET_PSKPD_DOWN);
+}
+
+static void mn88443x_s_wake(struct mn88443x_priv *chip)
+{
+	struct regmap *r_t = chip->regmap_t;
+
+	regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK, 0);
+}
+
+static void mn88443x_s_tune(struct mn88443x_priv *chip,
+			    struct dtv_frontend_properties *c)
+{
+	struct regmap *r_s = chip->regmap_s;
+
+	regmap_write(r_s, ATSIDU_S, c->stream_id >> 8);
+	regmap_write(r_s, ATSIDL_S, c->stream_id);
+	regmap_write(r_s, TSSET_S, 0);
+}
+
+static int mn88443x_s_read_status(struct mn88443x_priv *chip,
+				  struct dtv_frontend_properties *c,
+				  enum fe_status *status)
+{
+	struct regmap *r_s = chip->regmap_s;
+	u32 cpmon, tmpu, tmpl, flg;
+	u64 tmp;
+
+	/* Sync detection */
+	regmap_read(r_s, CPMON1_S, &cpmon);
+
+	*status = 0;
+	if (cpmon & CPMON1_S_FSYNC)
+		*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+	if (cpmon & CPMON1_S_W2LOCK)
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+	/* Signal strength */
+	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+	if (*status & FE_HAS_SIGNAL) {
+		u32 agc;
+
+		regmap_read(r_s, AGCREAD_S, &tmpu);
+		agc = tmpu << 8;
+
+		c->strength.len = 1;
+		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+		c->strength.stat[0].uvalue = agc;
+	}
+
+	/* C/N rate */
+	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+	if (*status & FE_HAS_VITERBI) {
+		u32 cnr = 0, x, y, d;
+		u64 d_3 = 0;
+
+		regmap_read(r_s, CNRDXU_S, &tmpu);
+		regmap_read(r_s, CNRDXL_S, &tmpl);
+		x = (tmpu << 8) | tmpl;
+		regmap_read(r_s, CNRDYU_S, &tmpu);
+		regmap_read(r_s, CNRDYL_S, &tmpl);
+		y = (tmpu << 8) | tmpl;
+
+		/* CNR[dB]: 10 * log10(D) - 30.74 / D^3 - 3 */
+		/*   D = x^2 / (2^15 * y - x^2) */
+		d = (y << 15) - x * x;
+		if (d > 0) {
+			/* (2^4 * D)^3 = 2^12 * D^3 */
+			/* 3.074 * 2^(12 + 24) = 211243671486 */
+			d_3 = div_u64(16 * x * x, d);
+			d_3 = d_3 * d_3 * d_3;
+			if (d_3)
+				d_3 = div_u64(211243671486ULL, d_3);
+		}
+
+		if (d_3) {
+			/* 0.3 * 2^24 = 5033164 */
+			tmp = (s64)2 * intlog10(x) - intlog10(abs(d)) - d_3
+				- 5033164;
+			cnr = div_u64(tmp * 10000, 1 << 24);
+		}
+
+		if (cnr) {
+			c->cnr.len = 1;
+			c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+			c->cnr.stat[0].uvalue = cnr;
+		}
+	}
+
+	/* BER */
+	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+	regmap_read(r_s, BERCNFLG_S, &flg);
+
+	if ((*status & FE_HAS_VITERBI) && (flg & BERCNFLG_S_BERVRDY)) {
+		u32 bit_err, bit_cnt;
+
+		regmap_read(r_s, BERVRDU_S, &tmpu);
+		regmap_read(r_s, BERVRDL_S, &tmpl);
+		bit_err = (tmpu << 8) | tmpl;
+		bit_cnt = (1 << 13) * 204;
+
+		if (bit_cnt) {
+			c->post_bit_error.len = 1;
+			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+			c->post_bit_error.stat[0].uvalue = bit_err;
+			c->post_bit_count.len = 1;
+			c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+			c->post_bit_count.stat[0].uvalue = bit_cnt;
+		}
+	}
+
+	return 0;
+}
+
+static void mn88443x_t_sleep(struct mn88443x_priv *chip)
+{
+	struct regmap *r_t = chip->regmap_t;
+
+	regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK,
+			   PWDSET_OFDMPD_DOWN);
+}
+
+static void mn88443x_t_wake(struct mn88443x_priv *chip)
+{
+	struct regmap *r_t = chip->regmap_t;
+
+	regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK, 0);
+}
+
+static bool mn88443x_t_is_valid_clk(u32 adckt, u32 if_freq)
+{
+	if (if_freq == DIRECT_IF_57MHZ) {
+		if (adckt >= CLK_DIRECT && adckt <= 21000000)
+			return true;
+		if (adckt >= 25300000 && adckt <= CLK_MAX)
+			return true;
+	} else if (if_freq == DIRECT_IF_44MHZ) {
+		if (adckt >= 25000000 && adckt <= CLK_MAX)
+			return true;
+	} else if (if_freq >= LOW_IF_4MHZ && if_freq < DIRECT_IF_44MHZ) {
+		if (adckt >= CLK_DIRECT && adckt <= CLK_MAX)
+			return true;
+	}
+
+	return false;
+}
+
+static int mn88443x_t_set_freq(struct mn88443x_priv *chip)
+{
+	struct device *dev = &chip->client_s->dev;
+	struct regmap *r_t = chip->regmap_t;
+	s64 adckt, nco, ad_t;
+	u32 m, v;
+
+	/* Clock buffer (but not supported) or XTAL */
+	if (chip->clk_freq >= CLK_LOW && chip->clk_freq < CLK_DIRECT) {
+		chip->use_clkbuf = true;
+		regmap_write(r_t, CLKSET1_T, 0x07);
+
+		adckt = 0;
+	} else {
+		chip->use_clkbuf = false;
+		regmap_write(r_t, CLKSET1_T, 0x00);
+
+		adckt = chip->clk_freq;
+	}
+	if (!mn88443x_t_is_valid_clk(adckt, chip->if_freq)) {
+		dev_err(dev, "Invalid clock, CLK:%d, ADCKT:%lld, IF:%d\n",
+			chip->clk_freq, adckt, chip->if_freq);
+		return -EINVAL;
+	}
+
+	/* Direct IF or Low IF */
+	if (chip->if_freq == DIRECT_IF_57MHZ ||
+	    chip->if_freq == DIRECT_IF_44MHZ)
+		nco = adckt * 2 - chip->if_freq;
+	else
+		nco = -((s64)chip->if_freq);
+	nco = div_s64(nco << 24, adckt);
+	ad_t = div_s64(adckt << 22, S_T_FREQ);
+
+	regmap_write(r_t, NCOFREQU_T, nco >> 16);
+	regmap_write(r_t, NCOFREQM_T, nco >> 8);
+	regmap_write(r_t, NCOFREQL_T, nco);
+	regmap_write(r_t, FADU_T, ad_t >> 16);
+	regmap_write(r_t, FADM_T, ad_t >> 8);
+	regmap_write(r_t, FADL_T, ad_t);
+
+	/* Level of IF */
+	m = ADCSET1_T_REFSEL_MASK;
+	v = ADCSET1_T_REFSEL_1_5V;
+	regmap_update_bits(r_t, ADCSET1_T, m, v);
+
+	/* Polarity of AGC */
+	v = AGCSET2_T_IFPOLINV_INC | AGCSET2_T_RFPOLINV_INC;
+	regmap_update_bits(r_t, AGCSET2_T, v, v);
+
+	/* Lower output level of AGC */
+	regmap_write(r_t, AGCV3_T, 0x00);
+
+	regmap_write(r_t, MDSET_T, 0xfa);
+
+	return 0;
+}
+
+static void mn88443x_t_tune(struct mn88443x_priv *chip,
+			    struct dtv_frontend_properties *c)
+{
+	struct regmap *r_t = chip->regmap_t;
+	u32 m, v;
+
+	m = MDSET_T_MDAUTO_MASK | MDSET_T_FFTS_MASK | MDSET_T_GI_MASK;
+	v = MDSET_T_MDAUTO_AUTO | MDSET_T_FFTS_MODE3 | MDSET_T_GI_1_8;
+	regmap_update_bits(r_t, MDSET_T, m, v);
+
+	regmap_write(r_t, MDASET_T, 0);
+}
+
+static int mn88443x_t_read_status(struct mn88443x_priv *chip,
+				  struct dtv_frontend_properties *c,
+				  enum fe_status *status)
+{
+	struct regmap *r_t = chip->regmap_t;
+	u32 seqrd, st, flg, tmpu, tmpm, tmpl;
+	u64 tmp;
+
+	/* Sync detection */
+	regmap_read(r_t, SSEQRD_T, &seqrd);
+	st = seqrd & SSEQRD_T_SSEQSTRD_MASK;
+
+	*status = 0;
+	if (st >= SSEQRD_T_SSEQSTRD_SYNC)
+		*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+	if (st >= SSEQRD_T_SSEQSTRD_FRAME_SYNC)
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+	/* Signal strength */
+	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+	if (*status & FE_HAS_SIGNAL) {
+		u32 agc;
+
+		regmap_read(r_t, AGCRDU_T, &tmpu);
+		regmap_read(r_t, AGCRDL_T, &tmpl);
+		agc = (tmpu << 8) | tmpl;
+
+		c->strength.len = 1;
+		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+		c->strength.stat[0].uvalue = agc;
+	}
+
+	/* C/N rate */
+	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+	if (*status & FE_HAS_VITERBI) {
+		u32 cnr;
+
+		regmap_read(r_t, CNRDU_T, &tmpu);
+		regmap_read(r_t, CNRDL_T, &tmpl);
+
+		if (tmpu || tmpl) {
+			/* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */
+			/* intlog10(65536) = 80807124, 0.2 * 2^24 = 3355443 */
+			tmp = (u64)80807124 - intlog10((tmpu << 8) | tmpl)
+				+ 3355443;
+			cnr = div_u64(tmp * 10000, 1 << 24);
+		} else {
+			cnr = 0;
+		}
+
+		c->cnr.len = 1;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+		c->cnr.stat[0].uvalue = cnr;
+	}
+
+	/* BER */
+	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+	regmap_read(r_t, BERFLG_T, &flg);
+
+	if ((*status & FE_HAS_VITERBI) && (flg & BERFLG_T_BERVRDYA)) {
+		u32 bit_err, bit_cnt;
+
+		regmap_read(r_t, BERRDU_T, &tmpu);
+		regmap_read(r_t, BERRDM_T, &tmpm);
+		regmap_read(r_t, BERRDL_T, &tmpl);
+		bit_err = (tmpu << 16) | (tmpm << 8) | tmpl;
+
+		regmap_read(r_t, BERLENRDU_T, &tmpu);
+		regmap_read(r_t, BERLENRDL_T, &tmpl);
+		bit_cnt = ((tmpu << 8) | tmpl) * 203 * 8;
+
+		if (bit_cnt) {
+			c->post_bit_error.len = 1;
+			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+			c->post_bit_error.stat[0].uvalue = bit_err;
+			c->post_bit_count.len = 1;
+			c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+			c->post_bit_count.stat[0].uvalue = bit_cnt;
+		}
+	}
+
+	return 0;
+}
+
+static int mn88443x_sleep(struct dvb_frontend *fe)
+{
+	struct mn88443x_priv *chip = fe->demodulator_priv;
+
+	mn88443x_s_sleep(chip);
+	mn88443x_t_sleep(chip);
+
+	return 0;
+}
+
+static int mn88443x_set_frontend(struct dvb_frontend *fe)
+{
+	struct mn88443x_priv *chip = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct regmap *r_s = chip->regmap_s;
+	struct regmap *r_t = chip->regmap_t;
+	u8 tssel = 0, intsel = 0;
+
+	if (c->delivery_system == SYS_ISDBS) {
+		mn88443x_s_wake(chip);
+		mn88443x_t_sleep(chip);
+
+		tssel = TSSET1_TSASEL_ISDBS;
+		intsel = TSSET3_INTASEL_S;
+	} else if (c->delivery_system == SYS_ISDBT) {
+		mn88443x_s_sleep(chip);
+		mn88443x_t_wake(chip);
+
+		mn88443x_t_set_freq(chip);
+
+		tssel = TSSET1_TSASEL_ISDBT;
+		intsel = TSSET3_INTASEL_T;
+	}
+
+	regmap_update_bits(r_t, TSSET1,
+			   TSSET1_TSASEL_MASK | TSSET1_TSBSEL_MASK,
+			   tssel | TSSET1_TSBSEL_NONE);
+	regmap_write(r_t, TSSET2, 0);
+	regmap_update_bits(r_t, TSSET3,
+			   TSSET3_INTASEL_MASK | TSSET3_INTBSEL_MASK,
+			   intsel | TSSET3_INTBSEL_NONE);
+
+	regmap_write(r_t, DOSET1_T, 0x95);
+	regmap_write(r_s, DOSET1_S, 0x80);
+
+	if (c->delivery_system == SYS_ISDBS)
+		mn88443x_s_tune(chip, c);
+	else if (c->delivery_system == SYS_ISDBT)
+		mn88443x_t_tune(chip, c);
+
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	return 0;
+}
+
+static int mn88443x_get_tune_settings(struct dvb_frontend *fe,
+				      struct dvb_frontend_tune_settings *s)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	s->min_delay_ms = 850;
+
+	if (c->delivery_system == SYS_ISDBS) {
+		s->max_drift = 30000 * 2 + 1;
+		s->step_size = 30000;
+	} else if (c->delivery_system == SYS_ISDBT) {
+		s->max_drift = 142857 * 2 + 1;
+		s->step_size = 142857 * 2;
+	}
+
+	return 0;
+}
+
+static int mn88443x_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+	struct mn88443x_priv *chip = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	if (c->delivery_system == SYS_ISDBS)
+		return mn88443x_s_read_status(chip, c, status);
+
+	if (c->delivery_system == SYS_ISDBT)
+		return mn88443x_t_read_status(chip, c, status);
+
+	return -EINVAL;
+}
+
+static const struct dvb_frontend_ops mn88443x_ops = {
+	.delsys = { SYS_ISDBS, SYS_ISDBT },
+	.info = {
+		.name = "Socionext MN88443x",
+		.frequency_min_hz =  470 * MHz,
+		.frequency_max_hz = 2071 * MHz,
+		.symbol_rate_min  = 28860000,
+		.symbol_rate_max  = 28860000,
+		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.sleep                   = mn88443x_sleep,
+	.set_frontend            = mn88443x_set_frontend,
+	.get_tune_settings       = mn88443x_get_tune_settings,
+	.read_status             = mn88443x_read_status,
+};
+
+static const struct regmap_config regmap_config = {
+	.reg_bits   = 8,
+	.val_bits   = 8,
+	.cache_type = REGCACHE_NONE,
+};
+
+static int mn88443x_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct mn88443x_config *conf = client->dev.platform_data;
+	struct mn88443x_priv *chip;
+	struct device *dev = &client->dev;
+	int ret;
+
+	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	if (dev->of_node)
+		chip->spec = of_device_get_match_data(dev);
+	else
+		chip->spec = (struct mn88443x_spec *)id->driver_data;
+	if (!chip->spec)
+		return -EINVAL;
+
+	chip->mclk = devm_clk_get(dev, "mclk");
+	if (IS_ERR(chip->mclk) && !conf) {
+		dev_err(dev, "Failed to request mclk: %ld\n",
+			PTR_ERR(chip->mclk));
+		return PTR_ERR(chip->mclk);
+	}
+
+	ret = of_property_read_u32(dev->of_node, "if-frequency",
+				   &chip->if_freq);
+	if (ret && !conf) {
+		dev_err(dev, "Failed to load IF frequency: %d.\n", ret);
+		return ret;
+	}
+
+	chip->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+						   GPIOD_OUT_HIGH);
+	if (IS_ERR(chip->reset_gpio)) {
+		dev_err(dev, "Failed to request reset_gpio: %ld\n",
+			PTR_ERR(chip->reset_gpio));
+		return PTR_ERR(chip->reset_gpio);
+	}
+
+	if (conf) {
+		chip->mclk = conf->mclk;
+		chip->if_freq = conf->if_freq;
+		chip->reset_gpio = conf->reset_gpio;
+
+		*conf->fe = &chip->fe;
+	}
+
+	chip->client_s = client;
+	chip->regmap_s = devm_regmap_init_i2c(chip->client_s, &regmap_config);
+	if (IS_ERR(chip->regmap_s))
+		return PTR_ERR(chip->regmap_s);
+
+	/*
+	 * Chip has two I2C addresses for each satellite/terrestrial system.
+	 * ISDB-T uses address ISDB-S + 4, so we register a dummy client.
+	 */
+	chip->client_t = i2c_new_dummy(client->adapter, client->addr + 4);
+	if (!chip->client_t)
+		return -ENODEV;
+
+	chip->regmap_t = devm_regmap_init_i2c(chip->client_t, &regmap_config);
+	if (IS_ERR(chip->regmap_t)) {
+		ret = PTR_ERR(chip->regmap_t);
+		goto err_i2c_t;
+	}
+
+	chip->clk_freq = clk_get_rate(chip->mclk);
+
+	memcpy(&chip->fe.ops, &mn88443x_ops, sizeof(mn88443x_ops));
+	chip->fe.demodulator_priv = chip;
+	i2c_set_clientdata(client, chip);
+
+	mn88443x_cmn_power_on(chip);
+	mn88443x_s_sleep(chip);
+	mn88443x_t_sleep(chip);
+
+	return 0;
+
+err_i2c_t:
+	i2c_unregister_device(chip->client_t);
+
+	return ret;
+}
+
+static int mn88443x_remove(struct i2c_client *client)
+{
+	struct mn88443x_priv *chip = i2c_get_clientdata(client);
+
+	mn88443x_cmn_power_off(chip);
+
+	i2c_unregister_device(chip->client_t);
+
+	return 0;
+}
+
+static const struct mn88443x_spec mn88443x_spec_pri = {
+	.primary = true,
+};
+
+static const struct mn88443x_spec mn88443x_spec_sec = {
+	.primary = false,
+};
+
+static const struct of_device_id mn88443x_of_match[] = {
+	{ .compatible = "socionext,mn884433",   .data = &mn88443x_spec_pri, },
+	{ .compatible = "socionext,mn884434-0", .data = &mn88443x_spec_pri, },
+	{ .compatible = "socionext,mn884434-1", .data = &mn88443x_spec_sec, },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mn88443x_of_match);
+
+static const struct i2c_device_id mn88443x_i2c_id[] = {
+	{ "mn884433",   (kernel_ulong_t)&mn88443x_spec_pri },
+	{ "mn884434-0", (kernel_ulong_t)&mn88443x_spec_pri },
+	{ "mn884434-1", (kernel_ulong_t)&mn88443x_spec_sec },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, mn88443x_i2c_id);
+
+static struct i2c_driver mn88443x_driver = {
+	.driver = {
+		.name = "mn88443x",
+		.of_match_table = of_match_ptr(mn88443x_of_match),
+	},
+	.probe    = mn88443x_probe,
+	.remove   = mn88443x_remove,
+	.id_table = mn88443x_i2c_id,
+};
+
+module_i2c_driver(mn88443x_driver);
+
+MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
+MODULE_DESCRIPTION("Socionext MN88443x series demodulator driver.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/mn88443x.h b/drivers/media/dvb-frontends/mn88443x.h
new file mode 100644
index 000000000000..b19aaf6a1ea3
--- /dev/null
+++ b/drivers/media/dvb-frontends/mn88443x.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Socionext MN88443x series demodulator driver for ISDB-S/ISDB-T.
+ *
+ * Copyright (c) 2018 Socionext Inc.
+ */
+
+#ifndef MN88443X_H
+#define MN88443X_H
+
+#include <media/dvb_frontend.h>
+
+/* ISDB-T IF frequency */
+#define DIRECT_IF_57MHZ    57000000
+#define DIRECT_IF_44MHZ    44000000
+#define LOW_IF_4MHZ        4000000
+
+struct mn88443x_config {
+	struct clk *mclk;
+	u32 if_freq;
+	struct gpio_desc *reset_gpio;
+
+	/* Everything after that is returned by the driver. */
+	struct dvb_frontend **fe;
+};
+
+#endif /* MN88443X_H */
-- 
2.18.0

^ permalink raw reply related

* Re: [PATCH] stop_machine: Disable preemption after queueing stopper threads
From: isaacm @ 2018-07-24  1:13 UTC (permalink / raw)
  To: peterz, matt, mingo, tglx, bigeasy
  Cc: linux-kernel, psodagud, gregkh, pkondeti, stable
In-Reply-To: <1531856129-9871-1-git-send-email-isaacm@codeaurora.org>

Hi all,

Are there any comments about this patch?

Thanks,
Isaac Manjarres
On 2018-07-17 12:35, Isaac J. Manjarres wrote:
> This commit:
> 
> 9fb8d5dc4b64 ("stop_machine, Disable preemption when
> waking two stopper threads")
> 
> does not fully address the race condition that can occur
> as follows:
> 
> On one CPU, call it CPU 3, thread 1 invokes
> cpu_stop_queue_two_works(2, 3,...), and the execution is such
> that thread 1 queues the works for migration/2 and migration/3,
> and is preempted after releasing the locks for migration/2 and
> migration/3, but before waking the threads.
> 
> Then, On CPU 2, a kworker, call it thread 2, is running,
> and it invokes cpu_stop_queue_two_works(1, 2,...), such that
> thread 2 queues the works for migration/1 and migration/2.
> Meanwhile, on CPU 3, thread 1 resumes execution, and wakes
> migration/2 and migration/3. This means that when CPU 2
> releases the locks for migration/1 and migration/2, but before
> it wakes those threads, it can be preempted by migration/2.
> 
> If thread 2 is preempted by migration/2, then migration/2 will
> execute the first work item successfully, since migration/3
> was woken up by CPU 3, but when it goes to execute the second
> work item, it disables preemption, calls multi_cpu_stop(),
> and thus, CPU 2 will wait forever for migration/1, which should
> have been woken up by thread 2. However migration/1 cannot be
> woken up by thread 2, since it is a kworker, so it is affine to
> CPU 2, but CPU 2 is running migration/2 with preemption
> disabled, so thread 2 will never run.
> 
> Disable preemption after queueing works for stopper threads
> to ensure that the operation of queueing the works and waking
> the stopper threads is atomic.
> 
> Fixes: 9fb8d5dc4b64 ("stop_machine, Disable preemption when waking two
> stopper threads")
> Co-Developed-by: Prasad Sodagudi <psodagud@codeaurora.org>
> Co-Developed-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
> Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
> Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
> Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
> Cc: stable@vger.kernel.org
> ---
>  kernel/stop_machine.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
> index 1ff523d..e190d1e 100644
> --- a/kernel/stop_machine.c
> +++ b/kernel/stop_machine.c
> @@ -260,6 +260,15 @@ static int cpu_stop_queue_two_works(int cpu1,
> struct cpu_stop_work *work1,
>  	err = 0;
>  	__cpu_stop_queue_work(stopper1, work1, &wakeq);
>  	__cpu_stop_queue_work(stopper2, work2, &wakeq);
> +	/*
> +	 * The waking up of stopper threads has to happen
> +	 * in the same scheduling context as the queueing.
> +	 * Otherwise, there is a possibility of one of the
> +	 * above stoppers being woken up by another CPU,
> +	 * and preempting us. This will cause us to n ot
> +	 * wake up the other stopper forever.
> +	 */
> +	preempt_disable();
>  unlock:
>  	raw_spin_unlock(&stopper2->lock);
>  	raw_spin_unlock_irq(&stopper1->lock);
> @@ -271,7 +280,6 @@ static int cpu_stop_queue_two_works(int cpu1,
> struct cpu_stop_work *work1,
>  	}
> 
>  	if (!err) {
> -		preempt_disable();
>  		wake_up_q(&wakeq);
>  		preempt_enable();
>  	}

^ permalink raw reply

* Re: [PATCH v5] media: dvb-frontends: add Socionext MN88443x ISDB-S/T demodulator driver
From: Katsuhiro Suzuki @ 2018-07-24  0:09 UTC (permalink / raw)
  To: 'kbuild test robot'
  Cc: kbuild-all, Mauro Carvalho Chehab, linux-media, Masami Hiramatsu,
	Jassi Brar, linux-arm-kernel, linux-kernel,
	Suzuki, Katsuhiro/鈴木 勝博
In-Reply-To: <201807240508.gpMy7uIR%fengguang.wu@intel.com>

Ugh, sorry. I'll fix it...

Regards,
--
Katsuhiro Suzuki


> -----Original Message-----
> From: kbuild test robot <lkp@intel.com>
> Sent: Tuesday, July 24, 2018 7:15 AM
> To: Suzuki, Katsuhiro/鈴木 勝博 <suzuki.katsuhiro@socionext.com>
> Cc: kbuild-all@01.org; Mauro Carvalho Chehab <mchehab+samsung@kernel.org>;
> linux-media@vger.kernel.org; Masami Hiramatsu <masami.hiramatsu@linaro.org>;
> Jassi Brar <jaswinder.singh@linaro.org>; linux-arm-kernel@lists.infradead.org;
> linux-kernel@vger.kernel.org; Suzuki, Katsuhiro/鈴木 勝博
> <suzuki.katsuhiro@socionext.com>
> Subject: Re: [PATCH v5] media: dvb-frontends: add Socionext MN88443x ISDB-S/T
> demodulator driver
> 
> Hi Katsuhiro,
> 
> I love your patch! Yet something to improve:
> 
> [auto build test ERROR on linuxtv-media/master]
> [also build test ERROR on v4.18-rc6 next-20180723]
> [if your patch is applied to the wrong git tree, please drop us a note to help
improve
> the system]
> 
> url:
> https://github.com/0day-ci/linux/commits/Katsuhiro-Suzuki/media-dvb-frontends-a
> dd-Socionext-MN88443x-ISDB-S-T-demodulator-driver/20180724-050011
> base:   git://linuxtv.org/media_tree.git master
> config: i386-randconfig-i1-201829 (attached as .config)
> compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386
> 
> All errors (new ones prefixed by >>):
> 
> >> drivers/media/dvb-frontends/mn88443x.c:15:10: fatal error: sc1501a.h: No
such
> file or directory
>     #include "sc1501a.h"
>              ^~~~~~~~~~~
>    compilation terminated.
> 
> vim +15 drivers/media/dvb-frontends/mn88443x.c
> 
>     14
>   > 15	#include "sc1501a.h"
>     16
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

^ permalink raw reply

* [PATCH net-next] cbs: Add support for the graft function
From: Vinicius Costa Gomes @ 2018-07-24  0:08 UTC (permalink / raw)
  To: netdev
  Cc: Vinicius Costa Gomes, jesus.sanchez-palencia, henrik,
	richardcochran, jhs, xiyou.wangcong, jiri, ilias.apalodimas

This will allow to install a child qdisc under cbs. The main use case
is to install ETF (Earliest TxTime First) qdisc under cbs, so there's
another level of control for time-sensitive traffic.

Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
---
 net/sched/sch_cbs.c | 134 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 125 insertions(+), 9 deletions(-)

diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c
index cdd96b9a27bc..e26a24017faa 100644
--- a/net/sched/sch_cbs.c
+++ b/net/sched/sch_cbs.c
@@ -78,18 +78,42 @@ struct cbs_sched_data {
 	s64 sendslope; /* in bytes/s */
 	s64 idleslope; /* in bytes/s */
 	struct qdisc_watchdog watchdog;
-	int (*enqueue)(struct sk_buff *skb, struct Qdisc *sch);
+	int (*enqueue)(struct sk_buff *skb, struct Qdisc *sch,
+		       struct sk_buff **to_free);
 	struct sk_buff *(*dequeue)(struct Qdisc *sch);
+	struct Qdisc *qdisc;
 };
 
-static int cbs_enqueue_offload(struct sk_buff *skb, struct Qdisc *sch)
+static int cbs_child_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+			     struct Qdisc *child,
+			     struct sk_buff **to_free)
 {
-	return qdisc_enqueue_tail(skb, sch);
+	int err;
+
+	err = child->ops->enqueue(skb, child, to_free);
+	if (err != NET_XMIT_SUCCESS)
+		return err;
+
+	qdisc_qstats_backlog_inc(sch, skb);
+	sch->q.qlen++;
+
+	return NET_XMIT_SUCCESS;
 }
 
-static int cbs_enqueue_soft(struct sk_buff *skb, struct Qdisc *sch)
+static int cbs_enqueue_offload(struct sk_buff *skb, struct Qdisc *sch,
+			       struct sk_buff **to_free)
 {
 	struct cbs_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *qdisc = q->qdisc;
+
+	return cbs_child_enqueue(skb, sch, qdisc, to_free);
+}
+
+static int cbs_enqueue_soft(struct sk_buff *skb, struct Qdisc *sch,
+			    struct sk_buff **to_free)
+{
+	struct cbs_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *qdisc = q->qdisc;
 
 	if (sch->q.qlen == 0 && q->credits > 0) {
 		/* We need to stop accumulating credits when there's
@@ -99,7 +123,7 @@ static int cbs_enqueue_soft(struct sk_buff *skb, struct Qdisc *sch)
 		q->last = ktime_get_ns();
 	}
 
-	return qdisc_enqueue_tail(skb, sch);
+	return cbs_child_enqueue(skb, sch, qdisc, to_free);
 }
 
 static int cbs_enqueue(struct sk_buff *skb, struct Qdisc *sch,
@@ -107,7 +131,7 @@ static int cbs_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 {
 	struct cbs_sched_data *q = qdisc_priv(sch);
 
-	return q->enqueue(skb, sch);
+	return q->enqueue(skb, sch, to_free);
 }
 
 /* timediff is in ns, slope is in bytes/s */
@@ -132,9 +156,25 @@ static s64 credits_from_len(unsigned int len, s64 slope, s64 port_rate)
 	return div64_s64(len * slope, port_rate);
 }
 
+static struct sk_buff *cbs_child_dequeue(struct Qdisc *sch, struct Qdisc *child)
+{
+	struct sk_buff *skb;
+
+	skb = child->ops->dequeue(child);
+	if (!skb)
+		return NULL;
+
+	qdisc_qstats_backlog_dec(sch, skb);
+	qdisc_bstats_update(sch, skb);
+	sch->q.qlen--;
+
+	return skb;
+}
+
 static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch)
 {
 	struct cbs_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *qdisc = q->qdisc;
 	s64 now = ktime_get_ns();
 	struct sk_buff *skb;
 	s64 credits;
@@ -157,8 +197,7 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch)
 			return NULL;
 		}
 	}
-
-	skb = qdisc_dequeue_head(sch);
+	skb = cbs_child_dequeue(sch, qdisc);
 	if (!skb)
 		return NULL;
 
@@ -178,7 +217,10 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch)
 
 static struct sk_buff *cbs_dequeue_offload(struct Qdisc *sch)
 {
-	return qdisc_dequeue_head(sch);
+	struct cbs_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *qdisc = q->qdisc;
+
+	return cbs_child_dequeue(sch, qdisc);
 }
 
 static struct sk_buff *cbs_dequeue(struct Qdisc *sch)
@@ -310,6 +352,13 @@ static int cbs_init(struct Qdisc *sch, struct nlattr *opt,
 		return -EINVAL;
 	}
 
+	q->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+				     sch->handle, extack);
+	if (!q->qdisc)
+		return -ENOMEM;
+
+	qdisc_hash_add(q->qdisc, false);
+
 	q->queue = sch->dev_queue - netdev_get_tx_queue(dev, 0);
 
 	q->enqueue = cbs_enqueue_soft;
@@ -328,6 +377,9 @@ static void cbs_destroy(struct Qdisc *sch)
 	qdisc_watchdog_cancel(&q->watchdog);
 
 	cbs_disable_offload(dev, q);
+
+	if (q->qdisc)
+		qdisc_destroy(q->qdisc);
 }
 
 static int cbs_dump(struct Qdisc *sch, struct sk_buff *skb)
@@ -356,8 +408,72 @@ static int cbs_dump(struct Qdisc *sch, struct sk_buff *skb)
 	return -1;
 }
 
+static int cbs_dump_class(struct Qdisc *sch, unsigned long cl,
+			  struct sk_buff *skb, struct tcmsg *tcm)
+{
+	struct cbs_sched_data *q = qdisc_priv(sch);
+
+	if (cl != 1 || !q->qdisc)	/* only one class */
+		return -ENOENT;
+
+	tcm->tcm_handle |= TC_H_MIN(1);
+	tcm->tcm_info = q->qdisc->handle;
+
+	return 0;
+}
+
+static int cbs_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+		     struct Qdisc **old, struct netlink_ext_ack *extack)
+{
+	struct cbs_sched_data *q = qdisc_priv(sch);
+
+	if (!new) {
+		new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+					sch->handle, NULL);
+		if (!new)
+			new = &noop_qdisc;
+	}
+
+	*old = qdisc_replace(sch, new, &q->qdisc);
+	return 0;
+}
+
+static struct Qdisc *cbs_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	struct cbs_sched_data *q = qdisc_priv(sch);
+
+	return q->qdisc;
+}
+
+static unsigned long cbs_find(struct Qdisc *sch, u32 classid)
+{
+	return 1;
+}
+
+static void cbs_walk(struct Qdisc *sch, struct qdisc_walker *walker)
+{
+	if (!walker->stop) {
+		if (walker->count >= walker->skip) {
+			if (walker->fn(sch, 1, walker) < 0) {
+				walker->stop = 1;
+				return;
+			}
+		}
+		walker->count++;
+	}
+}
+
+static const struct Qdisc_class_ops cbs_class_ops = {
+	.graft		=	cbs_graft,
+	.leaf		=	cbs_leaf,
+	.find		=	cbs_find,
+	.walk		=	cbs_walk,
+	.dump		=	cbs_dump_class,
+};
+
 static struct Qdisc_ops cbs_qdisc_ops __read_mostly = {
 	.id		=	"cbs",
+	.cl_ops		=	&cbs_class_ops,
 	.priv_size	=	sizeof(struct cbs_sched_data),
 	.enqueue	=	cbs_enqueue,
 	.dequeue	=	cbs_dequeue,
-- 
2.18.0

^ permalink raw reply related

* Re: [PATCH] sched/numa: do not balance tasks onto isolated cpus
From: jiang.biao2 @ 2018-07-24  1:11 UTC (permalink / raw)
  To: peterz
  Cc: chen.lin130, mingo, linux-kernel, zhong.weidong, tan.hu,
	cheng.lin130, tan.hu
In-Reply-To: <20180723084031.GX2494@hirez.programming.kicks-ass.net>


[-- Attachment #1.1: Type: text/plain, Size: 1345 bytes --]

>
> On Mon, Jul 23, 2018 at 01:39:30PM +0800, Chen Lin wrote:
>> From: Chen Lin <cheng.lin130@zte.com.cn>
>>
>> NUMA balancing has not taken *isolcpus(isolated cpus)* into
>> consideration. It may migrate tasks onto isolated cpus and the
>> migrated tasks will never escape from the isolated cpus, which will
>> break the isolation provided by *isolcpus* boot parameter and
>> intrduce various problems.
>>
>> This patch ensure NUMA balancing not to balance tasks onto iaolated
>> cpus.
>
> I'm not sure what kernel you're patching, but cpu_isolated_map doesn't
> exist anymore. Also, if it steps on isolated CPUs, this is the wrong fix
> anyway. Load-balancing should be constrained to the current root domain.
Indeed, we used 4.14 version and made wrong assumption, sorry for that.
We will retest on latest mainline version, rework the patch and send another
version.

>> Signed-off-by: Cheng Lin <cheng.lin130@zte.com.cn>
>> Signed-off-by: Tan Hu <tan.hu@zte.com.cn>
>> Signed-off-by: Jiang Biao <jiang.biao2@zte.com.cn>
> 
>This SoB chain is invalid.
Mm, we don't quite understand what the *Signed-off-by* precisely means,
Does it only mean DCO(developer certificate of origin)?
As we understood, multiple SoBs could be used to indicate co-authors.
If SoB only means DCO, how can the patches reflect co-authors?

Thanks a lot.
Jiang,
Regards

^ permalink raw reply

* Re: [PATCH 0/4 V2] Remove a few macros
From: Eric Sandeen @ 2018-07-24  0:06 UTC (permalink / raw)
  To: Carlos Maiolino, linux-xfs
In-Reply-To: <20180307090506.30199-1-cmaiolino@redhat.com>

On 3/7/18 1:05 AM, Carlos Maiolino wrote:
> Hi,
> 
> this is a second version of the patchset aimed to clean up some old macros from
> xfsprogs, as the objective to bring xfs_buf handling code closer to kernel code.
> 
> It fixes some pointer castings Dave mentioned on the V1 patch, also, it removes
> a few unneeded castings I spotted while reviewing the ones Dave mentioned.
> 
> Cheers

Ok, I'll take this, with the explicit char * casts (seems to be the popular
vote, and TBH I guess I prefer the explicit nature of that approach).

There are a couple of extra ones now in your first patch though,
i.e.

ptr = (char *)bp->b_addr;

is not needed.

I fixed up minor conflicts, no need to resend.

-Eric
 
> Carlos Maiolino (4):
>   Get rid of XFS_BUF_PTR() macro
>   Get rid of XFS_BUF_TARGET() macro
>   get rid of XFS_BUF_COUNT() macro
>   Get rid of XFS_BUF_SET_COUNT() macro
> 
>  libxfs/libxfs_io.h        |  6 +-----
>  libxfs/logitem.c          |  2 +-
>  libxfs/rdwr.c             | 10 +++++-----
>  libxfs/trans.c            |  2 +-
>  libxlog/xfs_log_recover.c |  2 +-
>  logprint/log_print_all.c  |  4 ++--
>  mkfs/proto.c              |  8 ++++----
>  mkfs/xfs_mkfs.c           | 14 +++++++-------
>  repair/agheader.c         |  8 ++++----
>  repair/attr_repair.c      |  4 ++--
>  repair/dino_chunks.c      |  2 +-
>  repair/phase6.c           |  4 ++--
>  repair/prefetch.c         |  4 ++--
>  13 files changed, 33 insertions(+), 37 deletions(-)
> 

^ permalink raw reply

* Re: [Qemu-devel] [PATCH] qstring: Fix integer overflow
From: liujunjie (A) @ 2018-07-24  1:08 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: wangxin (U), Gonglei (Arei), Huangweidong (C),
	qemu-devel@nongnu.org
In-Reply-To: <87k1pm551g.fsf@dusky.pond.sub.org>

The stack backtrace is as follows:
(gdb) bt
#0  0x00007f1dc3c7b091 in _g_log_abort () from /usr/lib64/libglib-2.0.so.0
#1  0x00007f1dc3c7c0bd in g_log_default_handler () from /usr/lib64/libglib-2.0.so.0
#2  0x00007f1dc3c7c341 in g_logv () from /usr/lib64/libglib-2.0.so.0
#3  0x00007f1dc3c7c5cf in g_log () from /usr/lib64/libglib-2.0.so.0
#4  0x00007f1dc3c7ac4c in g_malloc () from /usr/lib64/libglib-2.0.so.0
#5  0x00000000008300b7 in qstring_from_substr (
    str=0x7f13a2e67010 "00000000777b8000: 0000000003083000 ----A--U-\r\n00000000777b9000: 0000000005984000 ----A--U-\r\n00000000777ba000: 0000000005985000 ----A--U-\r\n00000000777bb000: 0000000003086000 ----A--U-\r\n00000000777bc000"..., start=start@entry=0, end=<optimized out>) at qobject/qstring.c:51
#6  0x0000000000830113 in qstring_from_str (str=<optimized out>) at qobject/qstring.c:66
#7  0x000000000082be98 in qobject_output_type_str (v=<optimized out>, name=0x89703b "unused", obj=0x7ffff0135f98, errp=<optimized out>)
    at qapi/qobject_output_visitor.c:172
#8  0x0000000000829d2c in visit_type_str (v=v@entry=0x4d9d940, name=name@entry=0x89703b "unused", obj=obj@entry=0x7ffff0135f98, errp=errp@entry=0x7ffff0135fa8)
    at qapi/qapi_visit_core.c:291
#9  0x0000000000576135 in qmp_marshal_output_str (
    ret_in=0x7f13a2e67010 "00000000777b8000: 0000000003083000 ----A--U-\r\n00000000777b9000: 0000000005984000 ----A--U-\r\n00000000777ba000: 0000000005985000 ----A--U-\r\n00000000777bb000: 0000000003086000 ----A--U-\r\n00000000777bc000"..., ret_out=ret_out@entry=0x7ffff0136068, errp=errp@entry=0x7ffff0135fe8) at qmp-marshal.c:2022
#10 0x00000000005762cb in qmp_marshal_human_monitor_command (args=<optimized out>, ret=0x7ffff0136068, errp=0x7ffff0136060) at qmp-marshal.c:2059
#11 0x000000000082c897 in do_qmp_dispatch (request=request@entry=0x1fcda50, errp=errp@entry=0x7ffff01360b8) at qapi/qmp_dispatch.c:114
#12 0x000000000082caeb in qmp_dispatch (request=request@entry=0x1fcda50) at qapi/qmp_dispatch.c:141
#13 0x000000000045e0d2 in handle_qmp_command (parser=<optimized out>, tokens=<optimized out>) at /usr/src/debug/qemu-kvm-2.8.1/monitor.c:3907
#14 0x000000000083355e in json_message_process_token (lexer=0x1a608e8, input=0x19f26e0, type=JSON_RCURLY, x=94, y=263) at qobject/json_streamer.c:105
#15 0x0000000000861650 in json_lexer_feed_char (lexer=lexer@entry=0x1a608e8, ch=125 '}', flush=flush@entry=false) at qobject/json_lexer.c:319
#16 0x0000000000861766 in json_lexer_feed (lexer=0x1a608e8, buffer=<optimized out>, size=<optimized out>) at qobject/json_lexer.c:369
#17 0x0000000000833661 in json_message_parser_feed (parser=<optimized out>, buffer=<optimized out>, size=<optimized out>) at qobject/json_streamer.c:124
#18 0x000000000045cc32 in monitor_qmp_read (opaque=<optimized out>, buf=<optimized out>, size=<optimized out>) at /usr/src/debug/qemu-kvm-2.8.1/monitor.c:3937
#19 0x00000000005652f3 in tcp_chr_read (chan=<optimized out>, cond=<optimized out>, opaque=0x1a5c020) at qemu_char.c:3253
#20 0x00007f1dc3c75609 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#21 0x0000000000779a06 in glib_pollfds_poll () at main_loop.c:228
#22 0x0000000000779aab in os_host_main_loop_wait (timeout=4830848) at main_loop.c:273
#23 0x0000000000779bd5 in main_loop_wait (nonblocking=nonblocking@entry=0) at main_loop.c:521
#24 0x0000000000570851 in main_loop () at vl.c:2100
#25 0x0000000000420d1e in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4980

> -----Original Message-----
> From: Markus Armbruster [mailto:armbru@redhat.com]
> Sent: Monday, July 23, 2018 11:46 PM
> To: liujunjie (A) <liujunjie23@huawei.com>
> Cc: wangxin (U) <wangxinxin.wang@huawei.com>; Gonglei (Arei)
> <arei.gonglei@huawei.com>; Huangweidong (C)
> <weidong.huang@huawei.com>; qemu-devel@nongnu.org
> Subject: Re: [Qemu-devel] [PATCH] qstring: Fix integer overflow
> 
> "liujunjie (A)" <liujunjie23@huawei.com> writes:
> 
> > Thanks for your reply.
> >> Really?  How exactly can this happen?  Please explain step by step.
> > There exist a qemu core related to this. You have mention that "The
> conversion truncates when strlen(str) - 1 exceeds INT_MAX".
> > Later in function qstring_from_substr, this truncated "end" will be assigned
> to "qstring->length" again, which is size_t. This is the key point why qemu
> coredumped.
> > Because when "end" is truncated, it can be negative number. If we assign a
> negative number to a size_t variable, this size_t variable can become very
> large.
> > At last, we call g_malloc to try to alloc a large number of member which
> cannot success. So qemu coredump.
> > In my example, use gdb to debug function qstring_from_substr, I can get the
> following message.
> > (gdb) p	qstring->length
> > $4 = 18446744072383980732  (too large to allocate)
> > (gdb) p	(int) (qstring->length)
> > $5 = -1325570884
> > (gdb) p/x (int)	qstring->length
> > $6 = 0xb0fd64bc
> > (gdb) p/x qstring->length
> > $7 = 0xffffffffb0fd64bc
> > (gdb) p	end
> > $8 = <optimized out>
> 
> Can you provide a stack backtrace, too?

^ permalink raw reply

* Re: [PATCH v5 1/2] leds: core: Introduce generic pattern interface
From: Bjorn Andersson @ 2018-07-24  1:06 UTC (permalink / raw)
  To: Baolin Wang
  Cc: jacek.anaszewski, pavel, david, broonie, linux-leds, linux-kernel
In-Reply-To: <05c235df7bbcc4b898e7b263bf38338d9c822005.1531711385.git.baolin.wang@linaro.org>

On Mon 16 Jul 04:10 PDT 2018, Baolin Wang wrote:

> From: Bjorn Andersson <bjorn.andersson@linaro.org>
> 
> Some LED controllers have support for autonomously controlling
> brightness over time, according to some preprogrammed pattern or
> function.
> 
> This adds a new optional operator that LED class drivers can implement
> if they support such functionality as well as a new device attribute to
> configure the pattern for a given LED.
> 
> [Baolin Wang did some improvements.]
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Signed-off-by: Baolin Wang <baolin.wang@linaro.org>

I'm happy to see that you found this patch useful and think the patch
looks good.

> ---
> Changes from v4:
>  - Fix some typos.
>  - Check if pattern_clear() is initialized.
> 
> Changes from v3:
>  - Move the check in pattern_show() to of_led_classdev_register().
>  - Add more documentation to explain how to set/clear one pattern.
> 
> Changes from v2:
>  - Change kernel version to 4.19.
>  - Force user to return error pointer if failed to issue pattern_get().
>  - Use strstrip() to trim trailing newline.
>  - Other optimization.
> 
> Changes from v1:
>  - Add some comments suggested by Pavel.
>  - Change 'delta_t' can be 0.
> 
> Note: I removed the pattern repeat check and will get the repeat number by adding
> one extra file named 'pattern_repeat' according to previous discussion.

In the Qualcomm LPG it's possible to specify if the pattern should be
run through once of repeated continuously, so if you provide the means
to control this by a separately I don't see a problem with this.

Regards,
Bjorn

> ---
>  Documentation/ABI/testing/sysfs-class-led |   20 +++++
>  drivers/leds/led-class.c                  |  118 +++++++++++++++++++++++++++++
>  include/linux/leds.h                      |   19 +++++
>  3 files changed, 157 insertions(+)
> 
> diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/testing/sysfs-class-led
> index 5f67f7a..a040fd0 100644
> --- a/Documentation/ABI/testing/sysfs-class-led
> +++ b/Documentation/ABI/testing/sysfs-class-led
> @@ -61,3 +61,23 @@ Description:
>  		gpio and backlight triggers. In case of the backlight trigger,
>  		it is useful when driving a LED which is intended to indicate
>  		a device in a standby like state.
> +
> +What: /sys/class/leds/<led>/pattern
> +Date:		July 2018
> +KernelVersion:	4.19
> +Description:
> +		Specify a pattern for the LED, for LED hardware that support
> +		altering the brightness as a function of time.
> +
> +		The pattern is given by a series of tuples, of brightness and
> +		duration (ms). The LED is expected to traverse the series and
> +		each brightness value for the specified duration. Duration of
> +		0 means brightness should immediately change to new value.
> +
> +		As LED hardware might have different capabilities and precision
> +		the requested pattern might be slighly adjusted by the driver
> +		and the resulting pattern of such operation should be returned
> +		when this file is read.
> +
> +		Writing non-empty string to this file will activate the pattern,
> +		and empty string will disable the pattern.
> diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
> index 3c7e348..5c6d2e9 100644
> --- a/drivers/leds/led-class.c
> +++ b/drivers/leds/led-class.c
> @@ -74,6 +74,118 @@ static ssize_t max_brightness_show(struct device *dev,
>  }
>  static DEVICE_ATTR_RO(max_brightness);
>  
> +static ssize_t pattern_show(struct device *dev,
> +			    struct device_attribute *attr, char *buf)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_pattern *pattern;
> +	size_t offset = 0;
> +	int count, n, i;
> +
> +	pattern = led_cdev->pattern_get(led_cdev, &count);
> +	if (IS_ERR(pattern))
> +		return PTR_ERR(pattern);
> +
> +	for (i = 0; i < count; i++) {
> +		n = snprintf(buf + offset, PAGE_SIZE - offset, "%d %d ",
> +			     pattern[i].brightness, pattern[i].delta_t);
> +
> +		if (offset + n >= PAGE_SIZE)
> +			goto err_nospc;
> +
> +		offset += n;
> +	}
> +
> +	buf[offset - 1] = '\n';
> +
> +	kfree(pattern);
> +	return offset;
> +
> +err_nospc:
> +	kfree(pattern);
> +	return -ENOSPC;
> +}
> +
> +static ssize_t pattern_store(struct device *dev,
> +			     struct device_attribute *attr,
> +			     const char *buf, size_t size)
> +{
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +	struct led_pattern *pattern = NULL;
> +	char *sbegin, *elem, *s;
> +	unsigned long val;
> +	int ret = 0, len = 0;
> +	bool odd = true;
> +
> +	sbegin = kstrndup(buf, size, GFP_KERNEL);
> +	if (!sbegin)
> +		return -ENOMEM;
> +
> +	/*
> +	 * Trim trailing newline, if the remaining string is empty,
> +	 * clear the pattern.
> +	 */
> +	s = strstrip(sbegin);
> +	if (!*s) {
> +		ret = led_cdev->pattern_clear(led_cdev);
> +		goto out;
> +	}
> +
> +	pattern = kcalloc(size, sizeof(*pattern), GFP_KERNEL);
> +	if (!pattern) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	/* Parse out the brightness & delta_t touples */
> +	while ((elem = strsep(&s, " ")) != NULL) {
> +		ret = kstrtoul(elem, 10, &val);
> +		if (ret)
> +			goto out;
> +
> +		if (odd) {
> +			pattern[len].brightness = val;
> +		} else {
> +			pattern[len].delta_t = val;
> +			len++;
> +		}
> +
> +		odd = !odd;
> +	}
> +
> +	/*
> +	 * Fail if we didn't find any data points or last data point was partial
> +	 */
> +	if (!len || !odd) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	ret = led_cdev->pattern_set(led_cdev, pattern, len);
> +
> +out:
> +	kfree(pattern);
> +	kfree(sbegin);
> +	return ret < 0 ? ret : size;
> +}
> +static DEVICE_ATTR_RW(pattern);
> +
> +static umode_t led_class_attrs_mode(struct kobject *kobj,
> +				    struct attribute *attr, int index)
> +{
> +	struct device *dev = container_of(kobj, struct device, kobj);
> +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
> +
> +	if (attr == &dev_attr_brightness.attr)
> +		return attr->mode;
> +	if (attr == &dev_attr_max_brightness.attr)
> +		return attr->mode;
> +	if (attr == &dev_attr_pattern.attr && led_cdev->pattern_set)
> +		return attr->mode;
> +
> +	return 0;
> +}
> +
>  #ifdef CONFIG_LEDS_TRIGGERS
>  static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
>  static struct attribute *led_trigger_attrs[] = {
> @@ -88,11 +200,13 @@ static ssize_t max_brightness_show(struct device *dev,
>  static struct attribute *led_class_attrs[] = {
>  	&dev_attr_brightness.attr,
>  	&dev_attr_max_brightness.attr,
> +	&dev_attr_pattern.attr,
>  	NULL,
>  };
>  
>  static const struct attribute_group led_group = {
>  	.attrs = led_class_attrs,
> +	.is_visible = led_class_attrs_mode,
>  };
>  
>  static const struct attribute_group *led_groups[] = {
> @@ -256,6 +370,10 @@ int of_led_classdev_register(struct device *parent, struct device_node *np,
>  	char name[LED_MAX_NAME_SIZE];
>  	int ret;
>  
> +	if (led_cdev->pattern_set &&
> +	    (!led_cdev->pattern_get || !led_cdev->pattern_clear))
> +		return -EINVAL;
> +
>  	ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
>  	if (ret < 0)
>  		return ret;
> diff --git a/include/linux/leds.h b/include/linux/leds.h
> index b7e8255..5f1c751 100644
> --- a/include/linux/leds.h
> +++ b/include/linux/leds.h
> @@ -22,6 +22,7 @@
>  #include <linux/workqueue.h>
>  
>  struct device;
> +struct led_pattern;
>  /*
>   * LED Core
>   */
> @@ -88,6 +89,14 @@ struct led_classdev {
>  				     unsigned long *delay_on,
>  				     unsigned long *delay_off);
>  
> +	int (*pattern_set)(struct led_classdev *led_cdev,
> +			   struct led_pattern *pattern, int len);
> +
> +	int (*pattern_clear)(struct led_classdev *led_cdev);
> +
> +	struct led_pattern *(*pattern_get)(struct led_classdev *led_cdev,
> +					   int *len);
> +
>  	struct device		*dev;
>  	const struct attribute_group	**groups;
>  
> @@ -446,4 +455,14 @@ static inline void led_classdev_notify_brightness_hw_changed(
>  	struct led_classdev *led_cdev, enum led_brightness brightness) { }
>  #endif
>  
> +/**
> + * struct led_pattern - brightness value in a pattern
> + * @delta_t: delay until next entry, in milliseconds
> + * @brightness: brightness at time = 0
> + */
> +struct led_pattern {
> +	int delta_t;
> +	int brightness;
> +};
> +
>  #endif		/* __LINUX_LEDS_H_INCLUDED */
> -- 
> 1.7.9.5
> 

^ permalink raw reply

* Re: Zram writeback feature unstable with heavy swap utilization - BUG: Bad page state in process...
From: Minchan Kim @ 2018-07-24  1:03 UTC (permalink / raw)
  To: Tino Lehnig; +Cc: ngupta, linux-kernel, Sergey Senozhatsky, Andrew Morton
In-Reply-To: <0516ae2d-b0fd-92c5-aa92-112ba7bd32fc@contabo.de>

Hi Tino,

Thanks for the report.

On Mon, Jul 23, 2018 at 02:29:32PM +0200, Tino Lehnig wrote:
> Hello,
> 
> after enabling the writeback feature in zram, I encountered the kernel bug
> below with heavy swap utilization. There is one specific workload that
> triggers the bug reliably and that is running Windows in KVM while
> overcommitting memory. The Windows VMs would fill all allocated memory with
> zero pages while booting. A few seconds after the host hits zram swap, the
> console on the host is flooded with the bug message. A few more seconds
> later I also encountered filesystem errors on the host causing the root
> filesystem to be mounted read-only. The filesystem errors do not occur when
> leaving RAM available for the host OS by limiting physical memory of the
> QEMU processes via cgroups.
> 
> I started three KVM instances with the following commands in my tests. Any
> Windows ISO or disk image can be used. Less instances and smaller allocated
> memory will also trigger the bug as long as swapping occurs. The type of
> writeback device does not seem to matter. I have tried a SATA SSD and an
> NVMe Optane drive so far. My test machine has 256 GB of RAM and one CPU. I
> saw the same behavior on another machine with two CPUs and 128 GB of RAM.
> 
> The bug does not occur when using zram as swap without "backing_dev" being
> set, but I had even more severe problems when running the same test on
> Ubuntu Kernels 4.15 and 4.17. Regardless of the writeback feature being used
> or not, the host would eventually lock up entirely when swap is in use on
> zram. The lockups may not be related directly to zram though and were
> apparently fixed in 4.18. I had absolutely no problems on Ubuntu Kernel 4.13
> either, before the writeback feature was introduced.

We didn't release v4.18 yet. Could you say what kernel tree/what version
you used?

Now I don't have enough time to dig in.

Sergey, I really appreciate if you could have availabe time to look into.
Anyway, I could try to see it asap if Sergey is not available.
No worry.

Thanks.


> 
> Thank you for your attention.
> 
> --
> 
> commands used:
> 
> modprobe zram
> echo 1 > /sys/block/zram0/reset
> echo lz4 > /sys/block/zram0/comp_algorithm
> echo /dev/nvme0n1 > /sys/block/zram0/backing_dev
> echo 256G > /sys/block/zram0/disksize
> mkswap /dev/zram0
> swapon /dev/zram0
> 
> kvm -nographic -smp 20 -m 131072 -cdrom winpe.iso
> 
> --
> 
> log message:
> 
> BUG: Bad page state in process qemu-system-x86  pfn:3dfab21
> page:ffffdfb137eac840 count:0 mapcount:0 mapping:0000000000000000 index:0x1
> flags: 0x17fffc000000008(uptodate)
> raw: 017fffc000000008 dead000000000100 dead000000000200 0000000000000000
> raw: 0000000000000001 0000000000000000 00000000ffffffff 0000000000000000
> page dumped because: PAGE_FLAGS_CHECK_AT_PREP flag set
> bad because of flags: 0x8(uptodate)
> Modules linked in: lz4 lz4_compress zram zsmalloc intel_rapl sb_edac
> x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass
> crct10dif_pclmul crc32_pclmul ghash_clmulni_intel bin
> fmt_misc pcbc aesni_intel aes_x86_64 crypto_simd cryptd iTCO_wdt glue_helper
> iTCO_vendor_support intel_cstate lpc_ich mei_me intel_uncore intel_rapl_perf
> pcspkr joydev sg mfd_core ioatdma mei wmi evdev ipmi_si ipmi_devintf
> ipmi_msghandler
> acpi_power_meter acpi_pad button ip_tables x_tables autofs4 ext4
> crc32c_generic crc16 mbcache jbd2 fscrypto hid_generic usbhid hid sd_mod
> xhci_pci ehci_pci ahci libahci xhci_hcd ehci_hcd libata igb i2c_algo_bit
> crc32c_intel scsi_mod i2c_i8
> 01 dca usbcore
> CPU: 4 PID: 1039 Comm: qemu-system-x86 Tainted: G    B 4.18.0-rc5+ #1
> Hardware name: Supermicro Super Server/X10SRL-F, BIOS 2.0b 05/02/2017
> Call Trace:
>  dump_stack+0x5c/0x7b
>  bad_page+0xba/0x120
>  get_page_from_freelist+0x1016/0x1250
>  __alloc_pages_nodemask+0xfa/0x250
>  alloc_pages_vma+0x7c/0x1c0
>  do_swap_page+0x347/0x920
>  ? __update_load_avg_se.isra.38+0x1eb/0x1f0
>  ? cpumask_next_wrap+0x3d/0x60
>  __handle_mm_fault+0x7b4/0x1110
>  ? update_load_avg+0x5ea/0x720
>  handle_mm_fault+0xfc/0x1f0
>  __get_user_pages+0x12f/0x690
>  get_user_pages_unlocked+0x148/0x1f0
>  __gfn_to_pfn_memslot+0xff/0x3c0 [kvm]
>  try_async_pf+0x87/0x230 [kvm]
>  tdp_page_fault+0x132/0x290 [kvm]
>  ? vmexit_fill_RSB+0xc/0x30 [kvm_intel]
>  kvm_mmu_page_fault+0x74/0x570 [kvm]
>  ? vmexit_fill_RSB+0xc/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0x18/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0xc/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0x18/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0xc/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0x18/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0xc/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0x18/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0xc/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0x18/0x30 [kvm_intel]
>  ? vmexit_fill_RSB+0xc/0x30 [kvm_intel]
>  ? vmx_vcpu_run+0x375/0x620 [kvm_intel]
>  kvm_arch_vcpu_ioctl_run+0x9b3/0x1990 [kvm]
>  ? __update_load_avg_se.isra.38+0x1eb/0x1f0
>  ? kvm_vcpu_ioctl+0x388/0x5d0 [kvm]
>  kvm_vcpu_ioctl+0x388/0x5d0 [kvm]
>  ? __switch_to+0x395/0x450
>  ? __switch_to+0x395/0x450
>  do_vfs_ioctl+0xa2/0x630
>  ? __schedule+0x3fd/0x890
>  ksys_ioctl+0x70/0x80
>  ? exit_to_usermode_loop+0xca/0xf0
>  __x64_sys_ioctl+0x16/0x20
>  do_syscall_64+0x55/0x100
>  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> RIP: 0033:0x7fb30361add7
> Code: 00 00 00 48 8b 05 c1 80 2b 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff
> ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff
> 73 01 c3 48 8b 0d 91 80 2b 00 f7 d8 64 89 01 48
> RSP: 002b:00007fb2e97f98b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
> RAX: ffffffffffffffda RBX: 000000000000ae80 RCX: 00007fb30361add7
> RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 0000000000000015
> RBP: 00005652b984e0f0 R08: 00005652b7d513d0 R09: 0000000000000001
> R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
> R13: 00007fb308c66000 R14: 0000000000000000 R15: 00005652b984e0f0
> 
> --
> 
> ver_linux: Debian 9.5 with Kernel 4.18.0-rc5+
> 
> GNU C               	6.3.0
> GNU Make            	4.1
> Binutils            	2.28
> Util-linux          	2.29.2
> Mount               	2.29.2
> Module-init-tools   	23
> E2fsprogs           	1.43.4
> Linux C Library     	2.24
> Dynamic linker (ldd)	2.24
> Linux C++ Library   	6.0.22
> Procps              	3.3.12
> Kbd                 	2.0.3
> Console-tools       	2.0.3
> Sh-utils            	8.26
> Udev                	232
> 
> --
> 
> cpuinfo:
> 
> processor	: 0
> vendor_id	: GenuineIntel
> cpu family	: 6
> model		: 79
> model name	: Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz
> stepping	: 1
> microcode	: 0xb000021
> cpu MHz		: 1200.632
> cache size	: 25600 KB
> physical id	: 0
> siblings	: 20
> core id		: 0
> cpu cores	: 10
> apicid		: 0
> initial apicid	: 0
> fpu		: yes
> fpu_exception	: yes
> cpuid level	: 20
> wp		: yes
> flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat
> pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb
> rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology
> nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est
> tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt
> tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch
> cpuid_fault epb cat_l3 cdp_l3 invpcid_single pti intel_ppin tpr_shadow vnmi
> flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms
> invpcid rtm cqm rdt_a rdseed adx smap intel_pt xsaveopt cqm_llc
> cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
> bugs		: cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass
> bogomips	: 4400.00
> clflush size	: 64
> cache_alignment	: 64
> address sizes	: 46 bits physical, 48 bits virtual
> power management:
> 
> --
> Kind regards,
> 
> Tino Lehnig



^ permalink raw reply

* [U-Boot] [PATCH] imx8qxp_mek: add README
From: Peng Fan @ 2018-07-24  1:02 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <CAOMZO5D__jgYx3gV-SnDWn1NpSK85xYgAMgMUskyyfzqYPh+cw@mail.gmail.com>



> -----Original Message-----
> From: Fabio Estevam [mailto:festevam at gmail.com]
> Sent: 2018年7月23日 21:44
> To: Peng Fan <peng.fan@nxp.com>
> Cc: Stefano Babic <sbabic@denx.de>; Fabio Estevam
> <fabio.estevam@nxp.com>; U-Boot-Denx <u-boot@lists.denx.de>; Diego Dorta
> <diego.dorta@nxp.com>
> Subject: Re: [U-Boot] [PATCH] imx8qxp_mek: add README
> 
> Hi Peng,
> 
> On Mon, Jul 23, 2018 at 7:00 AM, Peng Fan <peng.fan@nxp.com> wrote:
> > Add README file for i.MX8QXP MEK board.
> 
> Thanks for submitting the README file.
> 
> >
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > Cc: Stefano Babic <sbabic@denx.de>
> > Cc: Fabio Estevam <fabio.estevam@nxp.com>
> > Cc: Anatolij Gustschin <agust@denx.de>
> > ---
> >
> > This patch is for testing i.MX8QXP patchset [PATCH V2 00/32] i.MX: Add
> > i.MX8QXP support
> > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flis
> >
> ts.denx.de%2Fpipermail%2Fu-boot%2F2018-July%2F335079.html&amp;data=0
> 2%
> >
> 7C01%7Cpeng.fan%40nxp.com%7Ca0880385d7064b72028108d5f0a262b5%7C6
> 86ea1d
> >
> 3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636679502587918095&amp;sdata
> =a%2FO
> > Mb17xmtxbjSaXbNpkOnHWERFkrH4Y0jA8EkqF8ic%3D&amp;reserved=0
> > The board is using B0 chip, A0 chip is not being supported.
> > Please help test if you are interested. I'll post out V3 after
> > collecting more comments.
> > Sadly, I do not know where to download scfw_tcm.bin in public for B0 QXP.
> 
> Could you please check how to make this binary available to the users?

Need to wait external releases for i.MX8QXP B0. Hope soon.

> 
> Users need to have access to the firmware, otherwise it is a blocking issue for
> upstreaming mx8qxp support.

Different boards needs different scfw, there will be a porting kit for users when external release.
I just do not know where to download scfw_tcm.bin for i.MX8QXP MEK board (:

Thanks,
Peng.
> 
> Thanks

^ permalink raw reply

* Re: [PATCH] plugin: Don't unload external plugins too early
From: Denis Kenzior @ 2018-07-24  0:58 UTC (permalink / raw)
  To: ofono
In-Reply-To: <1532108123-23886-1-git-send-email-slava.monich@jolla.com>

[-- Attachment #1: Type: text/plain, Size: 370 bytes --]

Hi Slava,

On 07/20/2018 12:35 PM, Slava Monich wrote:
> Plugins may reference data structures allocated by each other.
> They all need to be deinitialized first, only then it should be
> safe to unload the libraries.
> ---
>   src/plugin.c | 15 ++++++++++++---
>   1 file changed, 12 insertions(+), 3 deletions(-)
> 

Applied, thanks.

Regards,
-Denis


^ permalink raw reply

* [U-Boot] [PATCH 11/17] fs: add mkdir interface
From: AKASHI Takahiro @ 2018-07-24  0:56 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <ad5d0bb1-1d01-a29d-c37f-79459aa10ad9@gmx.de>

On Fri, Jul 20, 2018 at 07:35:18PM +0200, Heinrich Schuchardt wrote:
> On 07/20/2018 04:57 AM, AKASHI Takahiro wrote:
> > "mkdir" interface is added to file operations.
> > This is a preparatory change as mkdir support for FAT file system
> > will be added in next patch.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  fs/fs.c      | 45 +++++++++++++++++++++++++++++++++++++++++++++
> >  include/fs.h | 10 ++++++++++
> >  2 files changed, 55 insertions(+)
> > 
> > diff --git a/fs/fs.c b/fs/fs.c
> > index 33808d549e..3cb6b21fe9 100644
> > --- a/fs/fs.c
> > +++ b/fs/fs.c
> > @@ -105,6 +105,11 @@ static inline int fs_opendir_unsupported(const char *filename,
> >  	return -EACCES;
> >  }
> >  
> > +static inline int fs_mkdir_unsupported(const char *dirname)
> > +{
> > +	return -1;
> > +}
> > +
> >  struct fstype_info {
> >  	int fstype;
> >  	char *name;
> > @@ -142,6 +147,7 @@ struct fstype_info {
> >  	int (*readdir)(struct fs_dir_stream *dirs, struct fs_dirent **dentp);
> >  	/* see fs_closedir() */
> >  	void (*closedir)(struct fs_dir_stream *dirs);
> > +	int (*mkdir)(const char *dirname);
> >  };
> >  
> >  static struct fstype_info fstypes[] = {
> > @@ -165,6 +171,7 @@ static struct fstype_info fstypes[] = {
> >  		.opendir = fat_opendir,
> >  		.readdir = fat_readdir,
> >  		.closedir = fat_closedir,
> > +		.mkdir = fs_mkdir_unsupported,
> 
> Why should we create a dummy function? Just use NULL as an indicator

because I followed coding style of the existing code here.

> that the interface method is not implemented. See the use of structures
> for the driver model.

Can any file system ever be based on driver model?

> @Simon
> The array fstypes[] should be replaced by a linker list to match the
> driver model.
> 
> >  	},
> >  #endif
> >  #ifdef CONFIG_FS_EXT4
> > @@ -185,6 +192,7 @@ static struct fstype_info fstypes[] = {
> >  #endif
> >  		.uuid = ext4fs_uuid,
> >  		.opendir = fs_opendir_unsupported,
> > +		.mkdir = fs_mkdir_unsupported,
> >  	},
> >  #endif
> >  #ifdef CONFIG_SANDBOX
> > @@ -201,6 +209,7 @@ static struct fstype_info fstypes[] = {
> >  		.write = fs_write_sandbox,
> >  		.uuid = fs_uuid_unsupported,
> >  		.opendir = fs_opendir_unsupported,
> > +		.mkdir = fs_mkdir_unsupported,
> >  	},
> >  #endif
> >  #ifdef CONFIG_CMD_UBIFS
> > @@ -217,6 +226,7 @@ static struct fstype_info fstypes[] = {
> >  		.write = fs_write_unsupported,
> >  		.uuid = fs_uuid_unsupported,
> >  		.opendir = fs_opendir_unsupported,
> > +		.mkdir = fs_mkdir_unsupported,
> >  	},
> >  #endif
> >  #ifdef CONFIG_FS_BTRFS
> > @@ -233,6 +243,7 @@ static struct fstype_info fstypes[] = {
> >  		.write = fs_write_unsupported,
> >  		.uuid = btrfs_uuid,
> >  		.opendir = fs_opendir_unsupported,
> > +		.mkdir = fs_mkdir_unsupported,
> >  	},
> >  #endif
> >  	{
> > @@ -248,6 +259,7 @@ static struct fstype_info fstypes[] = {
> >  		.write = fs_write_unsupported,
> >  		.uuid = fs_uuid_unsupported,
> >  		.opendir = fs_opendir_unsupported,
> > +		.mkdir = fs_mkdir_unsupported,
> >  	},
> >  };
> >  
> > @@ -498,6 +510,20 @@ void fs_closedir(struct fs_dir_stream *dirs)
> >  }
> >  
> >  
> > +int fs_mkdir(const char *dirname)
> > +{
> > +	int ret;
> > +
> > +	struct fstype_info *info = fs_get_info(fs_type);
> > +
> > +	ret = info->mkdir(dirname);
> 
> Please, check if mkdir is NULL before calling.

No other place checks for NULL. Is this really required?

> > +
> > +	fs_type = FS_TYPE_ANY;
> > +	fs_close();
> 
> What do you want to close here if mkdir() is not implemented by the file
> system?

I'm not quite confident here but ->close() be paired with ->probe(),
which is set to be called in fs_set_blk_dev().

Thanks,
-Takahiro AKASHI


> Best regards
> 
> Heinrich
> 
> > +
> > +	return ret;
> > +}
> > +
> >  int do_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
> >  		int fstype)
> >  {
> > @@ -700,3 +726,22 @@ int do_fs_type(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> >  	return CMD_RET_SUCCESS;
> >  }
> >  
> > +int do_mkdir(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
> > +								int fstype)
> > +{
> > +	int ret;
> > +
> > +	if (argc != 4)
> > +		return CMD_RET_USAGE;
> > +
> > +	if (fs_set_blk_dev(argv[1], argv[2], fstype))
> > +		return 1;
> > +
> > +	ret = fs_mkdir(argv[3]);
> > +	if (ret) {
> > +		printf("** Unable to create a directory \"%s\" **\n", argv[3]);
> > +		return 1;
> > +	}
> > +
> > +	return 0;
> > +}
> > diff --git a/include/fs.h b/include/fs.h
> > index 163da103b4..fbaee154dd 100644
> > --- a/include/fs.h
> > +++ b/include/fs.h
> > @@ -155,6 +155,14 @@ struct fs_dirent *fs_readdir(struct fs_dir_stream *dirs);
> >   */
> >  void fs_closedir(struct fs_dir_stream *dirs);
> >  
> > +/*
> > + * fs_mkdir - Create a directory
> > + *
> > + * @filename: Name of directory to create
> > + * @return 0 on success, -1 on error conditions
> > + */
> > +int fs_mkdir(const char *filename);
> > +
> >  /*
> >   * Common implementation for various filesystem commands, optionally limited
> >   * to a specific filesystem type via the fstype parameter.
> > @@ -169,6 +177,8 @@ int file_exists(const char *dev_type, const char *dev_part, const char *file,
> >  		int fstype);
> >  int do_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
> >  		int fstype);
> > +int do_mkdir(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
> > +		int fstype);
> >  
> >  /*
> >   * Determine the UUID of the specified filesystem and print it. Optionally it is
> > 
> 

^ permalink raw reply

* Re: [PATCH v3 1/2] leds: core: Introduce generic pattern interface
From: Bjorn Andersson @ 2018-07-24  0:55 UTC (permalink / raw)
  To: Jacek Anaszewski
  Cc: David Lechner, Pavel Machek, Baolin Wang, Mark Brown,
	Linux LED Subsystem, LKML
In-Reply-To: <8e51d2f1-0fc0-a968-4f97-3a4e09dd99e0@gmail.com>

On Fri 20 Jul 12:11 PDT 2018, Jacek Anaszewski wrote:

> Hi David,
> 
> On 07/18/2018 07:00 PM, David Lechner wrote:
> > 
> > 
> > On 7/18/18 7:08 AM, Pavel Machek wrote:
> > > On Wed 2018-07-18 19:32:01, Baolin Wang wrote:
> > > > On 18 July 2018 at 15:56, Pavel Machek <pavel@ucw.cz> wrote:
> > > > > Hi!
> > > > > 
> > > > > > > > > > I believe I meant "changing patterns
> > > > > > > > > > from kernel in response to events
> > > > > > > > > > is probably overkill"... or something like that.
> > > > > > > > > 
> > > > > > > > > Anyway -- to clean up the confusion -- I'd like to see
> > > > > > > > > 
> > > > > > > > > echo pattern > trigger
> > > > > > > > > echo "1 2 3 4 5 6 7 8" > somewhere
> > > > > > > > 
> > > > > > > > s/somewhere/pattern/
> > > > > > > > 
> > > > > > > > pattern trigger should create "pattern" file
> > > > > > > > similarly how ledtrig-timer
> > > > > > > > creates delay_{on|off} files.
> > > > > 
> > > > > Yes, that sounds reasonable. v5 still says
> > > > > 
> > > > > +               Writing non-empty string to this file will
> > > > > activate the pattern,
> > > > > +               and empty string will disable the pattern.
> > > > > 
> > > > > I'd deactivate the pattern by simply writing something else to the
> > > > > trigger file.
> > > > 
> > > > For the case we met in patch 2, it is not related with trigger things.
> > > > We just set some series of tuples including brightness and duration
> > > > (ms) to the hardware to enable the breath mode of the LED, we did not
> > > > trigger anything. So it is weird to write something to trigger file to
> > > > deactive the pattern.
> > > 
> > > Confused. I thought that "breathing mode" would be handled similar way
> > > to hardware blinking: userland selects pattern trigger, pattern file
> > > appears (similar way to delay_on/delay_off files with blinking), he
> > > configures it, hardware brightness follows the pattern ("breathing
> > > mode"). If pattern is no longer required, echo none > trigger stops
> > > it.
> > >                                     Pavel
> > > 
> > 
> > I was confused too when I first read this thread. But after reviewing
> > v5, it is clear that this is _not_ a trigger (and it should not be a
> > trigger). This is basically the equivalent the brightness attribute -
> > except that now the brightness changes over time instead of being a
> > constant value.
> 
> Pattern trigger would be just more flexible version of existing
> ledtrig-timer.c, which also changes brightness over time.
> 
> Trigger, by definition, is a kernel based source of LED events,
> so timer trigger falls under this definition, same way as pattern
> trigger would.
> 
> What may cause confusion is the possibility of exploiting hardware
> capabilities, in case the requested settings fit in.
> ledtrig-timer fathom the hardware capabilities using blink_set op,
> and pattern trigger would use pattern_set op for that purpose.
> 

For the use cases I had in mind it's perfectly fine to describe this as
a trigger.

But that said, I rather quickly started playing around with associating
patterns to trigger events; e.g. having a continuous pulse associated
with the bluetooth "power" trigger or defining a smooth rampdown for the
mmc activity trigger.

> > This way, the pattern can be used in conjunction with triggers.
> > 
> > For example, one might want to set the _pattern_ to something like a
> > "breathe" pattern and set the _trigger_ to the power supply charging
> > full trigger. This way, the LED will be off until the battery is full
> > and then the LED will "breath" when the battery is full.
> 
> AFAICS you comprehend "pattern trigger" notion as a LED trigger that
> activates pattern functionality. I'd say that you'd need a specialized
> "battery" trigger for that purpose, that instead of calling
> led_set_brightness_nosleep() would schedule call to
> led_trigger_set(led_cdev "pattern"), assuming that pattern trigger
> would be implemented as I explained above.
> 

Presumably the battery logic has a number of states; low batter
discharging, low battery charging, full battery, levels in-between.

Defining the levels for these and an appropriate UX seems like a job for
something with a little bit of configurability and product specific
logic. The transitions here would need to reconfigure the pattern, so it
doesn't seem unreasonable for it to also set the pattern trigger.


I'm not sure this logic does belong in the kernel, but I think that
question is of less importance for the design of this.

Regards,
Bjorn

^ permalink raw reply

* [U-Boot] [PATCH V2 29/32] fsl_esdhc: Update usdhc driver to support i.MX8
From: Fabio Estevam @ 2018-07-24  0:51 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <AM0PR04MB4481B5AFC7C3D10BDBDC683B88550@AM0PR04MB4481.eurprd04.prod.outlook.com>

Hi Peng,

On Mon, Jul 23, 2018 at 9:45 PM, Peng Fan <peng.fan@nxp.com> wrote:

> In V1, I use CONFIG_IMX8, but I think there is no need to use it, because
> CONFIG_ARCH_IMX8 could do same thing.

Yes, I prefer to drop "ARCH" for consistency.

> I could revert to use CONFIG_IMX8, since you prefer it.

Yes, that would be better.

>> Also, for consistency: should CONFIG_MX8M be changed to CONFIG_IMX8M?
>
> Yes. CONFIG_MX8M also need to be changed to CONFIG_IMX8M, but not in this patchset.

Correct.

Thanks

^ permalink raw reply

* Re: [PATCH v2 1/6] net/mlx5: lay groundwork for switch offloads
From: Stephen Hemminger @ 2018-07-24  0:50 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: Adrien Mazarguil, Shahaf Shuler, Nelio Laranjeiro, Yongseok Koh,
	dev
In-Reply-To: <e0d79ae3-e9ee-2483-10ad-a4e668d687ea@intel.com>

On Mon, 23 Jul 2018 22:40:47 +0100
Ferruh Yigit <ferruh.yigit@intel.com> wrote:

> On 7/13/2018 10:40 AM, Adrien Mazarguil wrote:
> > With mlx5, unlike normal flow rules implemented through Verbs for traffic
> > emitted and received by the application, those targeting different logical
> > ports of the device (VF representors for instance) are offloaded at the
> > switch level and must be configured through Netlink (TC interface).
> > 
> > This patch adds preliminary support to manage such flow rules through the
> > flow API (rte_flow).
> > 
> > Instead of rewriting tons of Netlink helpers and as previously suggested by
> > Stephen [1], this patch introduces a new dependency to libmnl [2]
> > (LGPL-2.1) when compiling mlx5.
> > 
> > [1] https://mails.dpdk.org/archives/dev/2018-March/092676.html
> > [2] https://netfilter.org/projects/libmnl/  
> 
> Just to highlight this new PMD level dependency to libmnl.
> 
> tap pmd also uses netlink and vdev_netvsc also does nl communication, perhaps we
> can discuss unifying netlink usage around this new library.
> 
> > 
> > Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
> > Acked-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
> > Cc: Yongseok Koh <yskoh@mellanox.com>
> > --
> > v2 changes:
> > 
> > - Added NETLINK_CAP_ACK definition if missing from the host system. This
> >   parameter is also not mandatory anymore and won't prevent creation of
> >   NL sockets when not supported.
> > - Modified mlx5_nl_flow_nl_ack() and mlx5_nl_flow_init() to consume the
> >   least amount of stack space based on message size, instead of the fixed
> >   MNL_SOCKET_BUFFER_SIZE which is quite large.  
> 
> <...>
> 

I am concerned that this won't work on FreeBSD and it will end up
farther behind.

^ permalink raw reply

* Re: [PATCH] MIPS: jz4740: Bump zload address
From: Paul Burton @ 2018-07-24  0:48 UTC (permalink / raw)
  To: Paul Cercueil; +Cc: Ralf Baechle, James Hogan, linux-mips, linux-kernel
In-Reply-To: <20180708150712.7404-1-paul@crapouillou.net>

Hi Paul,

On Sun, Jul 08, 2018 at 05:07:12PM +0200, Paul Cercueil wrote:
> Having the zload address at 0x8060.0000 means the size of the
> uncompressed kernel cannot be bigger than around 6 MiB, as it is
> deflated at address 0x8001.0000.
> 
> This limit is too small; a kernel with some built-in drivers and things
> like debugfs enabled will already be over 6 MiB in size, and so will
> fail to extract properly.
> 
> To fix this, we bump the zload address from 0x8060.0000 to 0x8100.0000.
> 
> This is fine, as all the boards featuring Ingenic JZ SoCs have at least
> 32 MiB of RAM, and use u-boot or compatible bootloaders which won't
> hardcode the load address but read it from the uImage's header.
> 
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>  arch/mips/jz4740/Platform | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Thanks - applied to mips-next for 4.19 (and tested on Ci20).

Paul

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.