* Applied "spi: fix ctrl->num_chipselect constraint" to the spi tree
From: Mark Brown @ 2019-06-20 13:32 UTC (permalink / raw)
To: Tudor Ambarus
Cc: broonie, linus.walleij, linux-kernel, linux-spi, Mark Brown,
Nicolas.Ferre, Tudor.Ambarus
In-Reply-To: <20190619143820.4045-1-tudor.ambarus@microchip.com>
The patch
spi: fix ctrl->num_chipselect constraint
has been applied to the spi tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-5.3
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
From f9481b08220d7dc1ff21e296a330ee8b721b44e4 Mon Sep 17 00:00:00 2001
From: Tudor Ambarus <tudor.ambarus@microchip.com>
Date: Wed, 19 Jun 2019 14:38:28 +0000
Subject: [PATCH] spi: fix ctrl->num_chipselect constraint
at91sam9g25ek showed the following error at probe:
atmel_spi f0000000.spi: Using dma0chan2 (tx) and dma0chan3 (rx)
for DMA transfers
atmel_spi: probe of f0000000.spi failed with error -22
Commit 0a919ae49223 ("spi: Don't call spi_get_gpio_descs() before device name is set")
moved the calling of spi_get_gpio_descs() after ctrl->dev is set,
but didn't move the !ctrl->num_chipselect check. When there are
chip selects in the device tree, the spi-atmel driver lets the
SPI core discover them when registering the SPI master.
The ctrl->num_chipselect is thus expected to be set by
spi_get_gpio_descs().
Move the !ctlr->num_chipselect after spi_get_gpio_descs() as it was
before the aforementioned commit. While touching this block, get rid
of the explicit comparison with 0 and update the commenting style.
Fixes: 0a919ae49223 ("spi: Don't call spi_get_gpio_descs() before device name is set")
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/spi/spi.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a31e1e291335..80d2d14f6294 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2375,11 +2375,6 @@ int spi_register_controller(struct spi_controller *ctlr)
if (status)
return status;
- /* even if it's just one always-selected device, there must
- * be at least one chipselect
- */
- if (ctlr->num_chipselect == 0)
- return -EINVAL;
if (ctlr->bus_num >= 0) {
/* devices with a fixed bus num must check-in with the num */
mutex_lock(&board_lock);
@@ -2450,6 +2445,13 @@ int spi_register_controller(struct spi_controller *ctlr)
}
}
+ /*
+ * Even if it's just one always-selected device, there must
+ * be at least one chipselect.
+ */
+ if (!ctlr->num_chipselect)
+ return -EINVAL;
+
status = device_add(&ctlr->dev);
if (status < 0) {
/* free bus id */
--
2.20.1
^ permalink raw reply related
* Applied "regulator: s2mps11: Fix ERR_PTR dereference on GPIO lookup failure" to the regulator tree
From: Mark Brown @ 2019-06-20 13:32 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Bartlomiej Zolnierkiewicz, Georg Waibel, Liam Girdwood,
linux-kernel, linux-samsung-soc, Marek Szyprowski, Mark Brown,
Sangbeom Kim, stable, stable
In-Reply-To: <1560948159-21926-1-git-send-email-krzk@kernel.org>
The patch
regulator: s2mps11: Fix ERR_PTR dereference on GPIO lookup failure
has been applied to the regulator tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-5.2
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
From 70ca117b02f3b1c8830fe95e4e3dea2937038e11 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <krzk@kernel.org>
Date: Wed, 19 Jun 2019 14:42:39 +0200
Subject: [PATCH] regulator: s2mps11: Fix ERR_PTR dereference on GPIO lookup
failure
If devm_gpiod_get_from_of_node() call returns ERR_PTR, it is assigned
into an array of GPIO descriptors and used later because such error is
not treated as critical thus it is not propagated back to the probe
function.
All code later expects that such GPIO descriptor is either a NULL or
proper value. This later might lead to dereference of ERR_PTR.
Only devices with S2MPS14 flavor are affected (other do not control
regulators with GPIOs).
Fixes: 1c984942f0a4 ("regulator: s2mps11: Pass descriptor instead of GPIO number")
Cc: <stable@vger.kernel.org>
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/regulator/s2mps11.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 134c62db36c5..af9bf10b4c33 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -824,6 +824,7 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
if (IS_ERR(gpio[reg])) {
dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n",
reg, rdata[reg].name);
+ gpio[reg] = NULL;
continue;
}
if (gpio[reg])
--
2.20.1
^ permalink raw reply related
* [RFC PATCH] arm64: dts: fsl: wandboard: Add a device tree for the PICO-PI-IMX8M
From: Andra Danciu @ 2019-06-20 13:32 UTC (permalink / raw)
To: robh+dt, mark.rutland, shawnguo
Cc: leoyang.li, aisheng.dong, sriram.dash, pramod.kumar_1,
bhaskar.upadhaya, vabhav.sharma, pankaj.bansal, richard.hu,
l.stach, ping.bai, manivannan.sadhasivam, devicetree,
linux-kernel, daniel.baluta
From: Richard Hu <richard.hu@technexion.com>
The current level of support yields a working console and is able to boot
userspace from an initial ramdisk copied via u-boot in RAM.
Additional subsystems that are active :
- Ethernet
- USB
Cc: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Richard Hu <richard.hu@technexion.com>
Signed-off-by: Andra Danciu <andradanciu1997@gmail.com>
---
I am using pico-pi-8mxm board to work on my project for Google Summer of Code.
This is based on patches from https://github.com/wandboard-org.
arch/arm64/boot/dts/freescale/Makefile | 1 +
arch/arm64/boot/dts/freescale/wand-pi-8m.dts | 590 +++++++++++++++++++++++++++
2 files changed, 591 insertions(+)
create mode 100644 arch/arm64/boot/dts/freescale/wand-pi-8m.dts
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 984554343c83..5904d6a8a033 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -23,3 +23,4 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-lx2160a-rdb.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8qxp-mek.dtb
+dtb-$(CONFIG_ARCH_MXC) += wand-pi-8m.dtb
diff --git a/arch/arm64/boot/dts/freescale/wand-pi-8m.dts b/arch/arm64/boot/dts/freescale/wand-pi-8m.dts
new file mode 100644
index 000000000000..9f7121014722
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/wand-pi-8m.dts
@@ -0,0 +1,590 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Wandboard, Org.
+ * Copyright 2017 NXP
+ *
+ * Author: Richard Hu <hakahu@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "imx8mq.dtsi"
+
+/ {
+ model = "WAND-PI-8M";
+ compatible = "wand,imx8mq-wand-pi", "fsl,imx8mq";
+
+ chosen {
+ bootargs = "console=ttymxc0,115200 earlycon=ec_imx6q,0x30860000,115200";
+ stdout-path = &uart1;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_usb_otg_vbus: usb_otg_vbus {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_otg_vbus>;
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 14 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ regulator-virtuals {
+ compatible = "simple-bus";
+
+ virt-buck1 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck1";
+ };
+ virt-buck2 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck2";
+ };
+ virt-buck3 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck3";
+ };
+ virt-buck4 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck4";
+ };
+ virt-buck5 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck5";
+ };
+ virt-buck6 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck6";
+ };
+ virt-buck7 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck7";
+ };
+ virt-buck8 {
+ compatible = "regulator-virtual";
+ virtual-supply = "buck8";
+ };
+ virt-ldo1 {
+ compatible = "regulator-virtual";
+ virtual-supply = "ldo1";
+ };
+ virt-ldo2 {
+ compatible = "regulator-virtual";
+ virtual-supply = "ldo2";
+ };
+ virt-ldo3 {
+ compatible = "regulator-virtual";
+ virtual-supply = "ldo3";
+ };
+ virt-ldo4 {
+ compatible = "regulator-virtual";
+ virtual-supply = "ldo4";
+ };
+ virt-ldo5 {
+ compatible = "regulator-virtual";
+ virtual-supply = "ldo5";
+ };
+ virt-ldo6 {
+ compatible = "regulator-virtual";
+ virtual-supply = "ldo6";
+ };
+ virt-ldo7 {
+ compatible = "regulator-virtual";
+ virtual-supply = "ldo7";
+ };
+ };
+
+ gpio-edm {
+ compatible = "gpio-edm";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi_ctrl>;
+
+ gpio_wifi_wl_reg_on {
+ label = "WL_REG_ON";
+ gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+ dir = "out";
+ };
+
+ gpio_wifi_pwr_en {
+ label = "WIFI_PWR_EN";
+ gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
+ dir = "out";
+ };
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+
+ wand-pi-8m {
+ pinctrl_otg_vbus: otgvbusgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_DQS_GPIO3_IO14 0x19 /* USB OTG VBUS Enable */
+ >;
+ };
+
+ pinctrl_csi1: csi1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_DATA01_GPIO3_IO7 0x19 /* CSI P1 PWDN */
+ MX8MQ_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x19 /* CSI nRST */
+ MX8MQ_IOMUXC_GPIO1_IO15_CCMSRCGPCMIX_CLKO2 0x59
+ >;
+ };
+
+ pinctrl_enet_3v3: enet3v3grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x19
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3
+ MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23
+ MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f
+ MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49
+ MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49
+ MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49
+ MX8MQ_IOMUXC_UART4_RXD_UART2_DCE_CTS_B 0x49
+ MX8MQ_IOMUXC_UART4_TXD_UART2_DCE_RTS_B 0x49
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x85
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc5
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc5
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc5
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc5
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc5
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc5
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc5
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc5
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc5
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x85
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x87
+ MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc7
+ MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc7
+ MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc7
+ MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc7
+ MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc7
+ MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc7
+ MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc7
+ MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc7
+ MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc7
+ MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x87
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpio {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x85
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc5
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc5
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc5
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc5
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc5
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+ fsl,pins = <
+ MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x87
+ MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc7
+ MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc7
+ MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc7
+ MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc7
+ MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc7
+ MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+
+ pinctrl_pmic: pmicirq {
+ fsl,pins = <
+ MX8MQ_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
+ >;
+ };
+
+ pinctrl_wifi_ctrl: wifi_ctrlgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_ALE_GPIO3_IO0 0x19 /* WL_REG_ON */
+ MX8MQ_IOMUXC_NAND_RE_B_GPIO3_IO15 0x19 /* WIFI_PWR_EN */
+ >;
+ };
+
+ pinctrl_tusb320_irq: tusb320_irqgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_DATA00_GPIO3_IO6 0x41
+ >;
+ };
+
+ pinctrl_typec_ss_sel: typec_ss_selgrp {
+ fsl,pins = <
+ MX8MQ_IOMUXC_NAND_CLE_GPIO3_IO5 0x19
+ >;
+ };
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1 &pinctrl_enet_3v3>;
+ phy-mode = "rgmii-id";
+ pinctrl-assert-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+ phy-handle = <ðphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ at803x,led-act-blind-workaround;
+ at803x,eee-disabled;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ typec_tusb320:tusb320@47 {
+ compatible = "ti,tusb320";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tusb320_irq &pinctrl_typec_ss_sel>;
+ reg = <0x47>;
+ vbus-supply = <®_usb_otg_vbus>;
+ ss-sel-gpios = <&gpio3 5 GPIO_ACTIVE_HIGH>;
+ tusb320,int-gpio = <&gpio3 6 GPIO_ACTIVE_LOW>;
+ tusb320,select-mode = <0>;
+ tusb320,dfp-power = <0>;
+ };
+
+ pmic: bd71837@4b {
+ reg = <0x4b>;
+ compatible = "rohm,bd71837";
+ /* PMIC BD71837 PMIC_nINT GPIO1_IO12 */
+ pinctrl-0 = <&pinctrl_pmic>;
+ gpio_intr = <&gpio1 3 GPIO_ACTIVE_LOW>;
+
+ bd71837,pmic-buck1-uses-i2c-dvs;
+ bd71837,pmic-buck1-dvs-voltage = <900000>, <850000>, <800000>; /* VDD_SOC: Run-Idle-Suspend */
+ bd71837,pmic-buck2-uses-i2c-dvs;
+ bd71837,pmic-buck2-dvs-voltage = <1000000>, <900000>, <0>; /* VDD_ARM: Run-Idle */
+ bd71837,pmic-buck3-uses-i2c-dvs;
+ bd71837,pmic-buck3-dvs-voltage = <1000000>, <0>, <0>; /* VDD_GPU: Run */
+ bd71837,pmic-buck4-uses-i2c-dvs;
+ bd71837,pmic-buck4-dvs-voltage = <1000000>, <0>, <0>; /* VDD_VPU: Run */
+
+ gpo {
+ rohm,drv = <0x0C>; /* 0b0000_1100 all gpos with cmos output mode */
+ };
+
+ regulators {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ buck1_reg: regulator@0 {
+ reg = <0>;
+ regulator-compatible = "buck1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck2_reg: regulator@1 {
+ reg = <1>;
+ regulator-compatible = "buck2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ };
+
+ buck3_reg: regulator@2 {
+ reg = <2>;
+ regulator-compatible = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck4_reg: regulator@3 {
+ reg = <3>;
+ regulator-compatible = "buck4";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5_reg: regulator@4 {
+ reg = <4>;
+ regulator-compatible = "buck5";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6_reg: regulator@5 {
+ reg = <5>;
+ regulator-compatible = "buck6";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck7_reg: regulator@6 {
+ reg = <6>;
+ regulator-compatible = "buck7";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck8_reg: regulator@7 {
+ reg = <7>;
+ regulator-compatible = "buck8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: regulator@8 {
+ reg = <8>;
+ regulator-compatible = "ldo1";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2_reg: regulator@9 {
+ reg = <9>;
+ regulator-compatible = "ldo2";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3_reg: regulator@10 {
+ reg = <10>;
+ regulator-compatible = "ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4_reg: regulator@11 {
+ reg = <11>;
+ regulator-compatible = "ldo4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo5_reg: regulator@12 {
+ reg = <12>;
+ regulator-compatible = "ldo5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo6_reg: regulator@13 {
+ reg = <13>;
+ regulator-compatible = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo7_reg: regulator@14 {
+ reg = <14>;
+ regulator-compatible = "ldo7";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&uart1 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&usb3_phy0 {
+ status = "okay";
+};
+
+&usb_dwc3_0 {
+ extcon = <&typec_tusb320>;
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usb3_phy1 {
+ status = "okay";
+};
+
+&usb_dwc3_1 {
+ status = "okay";
+ dr_mode = "host";
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&A53_0 {
+ operating-points = <
+ /* kHz uV */
+ 1500000 1000000
+ 1300000 1000000
+ 1000000 900000
+ 800000 900000
+ >;
+};
--
2.11.0
^ permalink raw reply related
* Applied "regulator: da9061/62: Adjust LDO voltage selection minimum value" to the regulator tree
From: Mark Brown @ 2019-06-20 13:32 UTC (permalink / raw)
To: Felix Riemann
Cc: Felix Riemann, Lee Jones, Liam Girdwood, linux-kernel, LKML,
Mark Brown, Steve Twiss, Support Opensource
In-Reply-To: <20190620074042.E1E803FB4A@swsrvapps-01.diasemi.com>
The patch
regulator: da9061/62: Adjust LDO voltage selection minimum value
has been applied to the regulator tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-5.3
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
From fd5d10059d5ead12dd12f05ae6d96e70d1fac3df Mon Sep 17 00:00:00 2001
From: Felix Riemann <felix.riemann@sma.de>
Date: Thu, 20 Jun 2019 08:45:00 +0100
Subject: [PATCH] regulator: da9061/62: Adjust LDO voltage selection minimum
value
According to the DA9061 and DA9062 datasheets the LDO voltage selection
registers have a lower value of 0x02. This applies to voltage registers
VLDO1_A, VLDO2_A, VLDO3_A and VLDO4_A. This linear offset of 0x02 was
previously not observed by the driver, causing the LDO output voltage to
be systematically lower by two steps (= 0.1V).
This patch fixes the minimum linear selector offset by setting it to a
value of 2 and increases the n_voltages by the same amount allowing
voltages in the range 0x02 -> 0.9V to 0x38 -> 3.6V to be correctly
selected. Also fixes an incorrect calculaton for the n_voltages value in
the regulator LDO2.
These fixes effect all LDO regulators for DA9061 and DA9062.
Acked-by: Steve Twiss <stwiss.opensource@diasemi.com>
Tested-by: Steve Twiss <stwiss.opensource@diasemi.com>
Signed-off-by: Felix Riemann <felix.riemann@sma.de>
Signed-off-by: Steve Twiss <stwiss.opensource@diasemi.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
drivers/regulator/da9062-regulator.c | 40 +++++++++++++++++-----------
include/linux/mfd/da9062/registers.h | 3 +++
2 files changed, 27 insertions(+), 16 deletions(-)
diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c
index a02e0488410f..2ffc64622451 100644
--- a/drivers/regulator/da9062-regulator.c
+++ b/drivers/regulator/da9062-regulator.c
@@ -493,12 +493,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (900))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO1_CONT,
.desc.enable_mask = DA9062AA_LDO1_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO1_A,
.desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO1_A,
__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -525,12 +526,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (600))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO2_CONT,
.desc.enable_mask = DA9062AA_LDO2_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO2_A,
.desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO2_A,
__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -557,12 +559,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (900))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO3_CONT,
.desc.enable_mask = DA9062AA_LDO3_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO3_A,
.desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO3_A,
__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -589,12 +592,13 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (900))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO4_CONT,
.desc.enable_mask = DA9062AA_LDO4_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO4_A,
.desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO4_A,
__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -769,12 +773,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (900))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO1_CONT,
.desc.enable_mask = DA9062AA_LDO1_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO1_A,
.desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO1_A,
__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -801,12 +806,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (600))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO2_CONT,
.desc.enable_mask = DA9062AA_LDO2_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO2_A,
.desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO2_A,
__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -833,12 +839,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (900))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO3_CONT,
.desc.enable_mask = DA9062AA_LDO3_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO3_A,
.desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO3_A,
__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
@@ -865,12 +872,13 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
- .desc.n_voltages = ((3600) - (900))/(50) + 1,
+ .desc.n_voltages = ((3600) - (900))/(50) + 1
+ + DA9062AA_VLDO_A_MIN_SEL,
.desc.enable_reg = DA9062AA_LDO4_CONT,
.desc.enable_mask = DA9062AA_LDO4_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO4_A,
.desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
- .desc.linear_min_sel = 0,
+ .desc.linear_min_sel = DA9062AA_VLDO_A_MIN_SEL,
.sleep = REG_FIELD(DA9062AA_VLDO4_A,
__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
diff --git a/include/linux/mfd/da9062/registers.h b/include/linux/mfd/da9062/registers.h
index fe04b708742b..2906bf6160fb 100644
--- a/include/linux/mfd/da9062/registers.h
+++ b/include/linux/mfd/da9062/registers.h
@@ -797,6 +797,9 @@
#define DA9062AA_BUCK3_SL_A_SHIFT 7
#define DA9062AA_BUCK3_SL_A_MASK BIT(7)
+/* DA9062AA_VLDO[1-4]_A common */
+#define DA9062AA_VLDO_A_MIN_SEL 2
+
/* DA9062AA_VLDO1_A = 0x0A9 */
#define DA9062AA_VLDO1_A_SHIFT 0
#define DA9062AA_VLDO1_A_MASK 0x3f
--
2.20.1
^ permalink raw reply related
* Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP Platform Tap Delays Setup
From: Ulf Hansson @ 2019-06-20 13:33 UTC (permalink / raw)
To: Manish Narani
Cc: Michal Simek, Rob Herring, Mark Rutland, Adrian Hunter,
Rajan Vaja, Jolly Shah, Nava kishore Manne, Olof Johansson,
linux-mmc@vger.kernel.org, DTML, Linux Kernel Mailing List,
Linux ARM
In-Reply-To: <MN2PR02MB602935234A2A779B5A05CD63C1E40@MN2PR02MB6029.namprd02.prod.outlook.com>
On Thu, 20 Jun 2019 at 10:14, Manish Narani <MNARANI@xilinx.com> wrote:
>
> Hi Uffe,
>
>
> > -----Original Message-----
> > From: Ulf Hansson <ulf.hansson@linaro.org>
> > Sent: Wednesday, June 19, 2019 7:09 PM
> > To: Manish Narani <MNARANI@xilinx.com>
> > Cc: Michal Simek <michals@xilinx.com>; Rob Herring <robh+dt@kernel.org>;
> > Mark Rutland <mark.rutland@arm.com>; Adrian Hunter
> > <adrian.hunter@intel.com>; Rajan Vaja <RAJANV@xilinx.com>; Jolly Shah
> > <JOLLYS@xilinx.com>; Nava kishore Manne <navam@xilinx.com>; Olof
> > Johansson <olof@lixom.net>; linux-mmc@vger.kernel.org; DTML
> > <devicetree@vger.kernel.org>; Linux Kernel Mailing List <linux-
> > kernel@vger.kernel.org>; Linux ARM <linux-arm-kernel@lists.infradead.org>
> > Subject: Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP
> > Platform Tap Delays Setup
> >
> > On Wed, 19 Jun 2019 at 10:40, Manish Narani <MNARANI@xilinx.com> wrote:
> > >
> > > Hi Uffe,
> > >
> > >
> > > > -----Original Message-----
> > > > From: Ulf Hansson <ulf.hansson@linaro.org>
> > > > Sent: Monday, June 17, 2019 5:51 PM
> > > [...]
> > > >
> > > > The "const struct zynqmp_eemi_ops *eemi_ops; should then be moved into
> > > > a clock provider specific struct, which is assigned when calling
> > > > sdhci_arasan_register_sdclk. I understand that all the clock data is
> > > > folded into struct sdhci_arasan_data today, but I think that should be
> > > > moved into a "sub-struct" for the clock specifics.
> > > >
> > > > Moreover, when registering the clock, we should convert from using
> > > > devm_clk_register() into devm_clk_hw_register() as the first one is
> > > > now deprecated.
> > >
> > > Just a query here:
> > > When we switch to using devm_clk_hw_register() here, it will register the
> > clk_hw and return int.
> > > Is there a way we can get the clk (related to the clk_hw registered) from the
> > > clock framework?
> > > I am asking this because we will need that clk pointer while calling
> > clk_set_phase() function.
> >
> > I assume devm_clk_get() should work fine?
>
> This clock does not come through ZynqMP Clock framework. We are initializing it in this 'sdhci-of-arasan' driver and getting only the clock name from "clock_output_names" property. So I think devm_clk_get() will not work here for our case.
Well, I guess you need to register an OF clock provider to allow the
clock lookup to work. Apologize, but I don't have the time, currently
to point you in the exact direction.
However, in principle, my point is, there should be no difference
whether the clock is registered via the "ZynqMP Clock framework" or
via the mmc driver. The *clk_get() thing need to work, otherwise I
consider the clock registration in the mmc driver to be a hack. If you
see what I mean.
> I have gone through the clock framework and I found one function which may be used to create clock from clock hw, that is ' clk_hw_create_clk()' which can be used from our driver, however this needs change in the clock framework as below :
>
> ---
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index aa51756..4dc69ff 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -3420,6 +3420,7 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
>
> return clk;
> }
> +EXPORT_SYMBOL_GPL(clk_hw_create_clk);
>
> static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
> {
> diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
> index d8400d6..2319899 100644
> --- a/drivers/clk/clk.h
> +++ b/drivers/clk/clk.h
> @@ -22,17 +22,9 @@ static inline struct clk_hw *of_clk_get_hw(struct device_node *np,
> struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id);
>
> #ifdef CONFIG_COMMON_CLK
> -struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> - const char *dev_id, const char *con_id);
> void __clk_put(struct clk *clk);
> #else
> /* All these casts to avoid ifdefs in clkdev... */
> -static inline struct clk *
> -clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> - const char *con_id)
> -{
> - return (struct clk *)hw;
> -}
> static struct clk_hw *__clk_get_hw(struct clk *clk)
> {
> return (struct clk_hw *)clk;
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index f689fc5..d3f60fe 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -18,6 +18,7 @@
>
> struct device;
> struct clk;
> +struct clk_hw;
> struct device_node;
> struct of_phandle_args;
>
> @@ -934,4 +935,15 @@ static inline struct clk *of_clk_get_from_provider(struct of_phandle_args *clksp
> }
> #endif
>
> +#ifdef CONFIG_COMMON_CLK
> +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> + const char *dev_id, const char *con_id);
> +#else
> +static inline struct clk *
> +clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> + const char *con_id)
> +{
> + return (struct clk *)hw;
> +}
> +#endif
> #endif
> ---
>
> This change should help other drivers (outside 'drivers/clk/') as well for getting the clock created from clk_hw.
> Is this fine to do?
I think this is the wrong approach, see why further above.
Kind regards
Uffe
^ permalink raw reply
* Re: [PATCH] mfd: da9063: occupy second I2C address, too
From: Lee Jones @ 2019-06-20 13:33 UTC (permalink / raw)
To: Steve Twiss
Cc: wsa+renesas@sang-engineering.com, bgolaszewski@baylibre.com,
kieran.bingham+renesas@ideasonboard.com,
linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
peda@axentia.se, Support Opensource
In-Reply-To: <AM6PR10MB2181D2A08D98FB9F8092EC8DFEE40@AM6PR10MB2181.EURPRD10.PROD.OUTLOOK.COM>
On Thu, 20 Jun 2019, Steve Twiss wrote:
> On 20 June 2019 13:29, Lee Jones wrote:
>
> > Subject: Re: [PATCH] mfd: da9063: occupy second I2C address, too
> >
> > Why isn't this reply attached (threaded) to the patch.
>
> My apologies. It wasn't my intention to split Wolfram's original e-mail thread.
>
> I don't usually reply using the mailto: link from lore when creating e-mails.
> Outlook mustn't support the In-Reply-To header.
>
> I'll figure out a different way to reply in future.
>
> > Is your mailer broken?
>
> It's Windows
Say no more. ;)
--
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [dpdk-dev] [PATCH v3 2/3] net/ice: add generic flow API
From: Aaron Conole @ 2019-06-20 13:33 UTC (permalink / raw)
To: Qiming Yang; +Cc: dev
In-Reply-To: <20190620053449.32959-3-qiming.yang@intel.com>
Qiming Yang <qiming.yang@intel.com> writes:
> This patch adds ice_flow_create, ice_flow_destroy,
> ice_flow_flush and ice_flow_validate support,
> these are used to handle all the generic filters.
>
> Signed-off-by: Qiming Yang <qiming.yang@intel.com>
> ---
> drivers/net/ice/Makefile | 1 +
> drivers/net/ice/ice_ethdev.c | 44 +++
> drivers/net/ice/ice_ethdev.h | 5 +
> drivers/net/ice/ice_generic_flow.c | 682 +++++++++++++++++++++++++++++++++++++
> drivers/net/ice/ice_generic_flow.h | 654 +++++++++++++++++++++++++++++++++++
> drivers/net/ice/meson.build | 1 +
> 6 files changed, 1387 insertions(+)
> create mode 100644 drivers/net/ice/ice_generic_flow.c
> create mode 100644 drivers/net/ice/ice_generic_flow.h
>
> diff --git a/drivers/net/ice/Makefile b/drivers/net/ice/Makefile
> index b10d826..32abeb6 100644
> --- a/drivers/net/ice/Makefile
> +++ b/drivers/net/ice/Makefile
> @@ -79,5 +79,6 @@ endif
> ifeq ($(CC_AVX2_SUPPORT), 1)
> SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_rxtx_vec_avx2.c
> endif
> +SRCS-$(CONFIG_RTE_LIBRTE_ICE_PMD) += ice_generic_flow.c
>
> include $(RTE_SDK)/mk/rte.lib.mk
> diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c
> index a94aa7e..8ee06d1 100644
> --- a/drivers/net/ice/ice_ethdev.c
> +++ b/drivers/net/ice/ice_ethdev.c
> @@ -15,6 +15,7 @@
> #include "base/ice_dcb.h"
> #include "ice_ethdev.h"
> #include "ice_rxtx.h"
> +#include "ice_switch_filter.h"
>
> #define ICE_MAX_QP_NUM "max_queue_pair_num"
> #define ICE_DFLT_OUTER_TAG_TYPE ICE_AQ_VSI_OUTER_TAG_VLAN_9100
> @@ -83,6 +84,10 @@ static int ice_xstats_get(struct rte_eth_dev *dev,
> static int ice_xstats_get_names(struct rte_eth_dev *dev,
> struct rte_eth_xstat_name *xstats_names,
> unsigned int limit);
> +static int ice_dev_filter_ctrl(struct rte_eth_dev *dev,
> + enum rte_filter_type filter_type,
> + enum rte_filter_op filter_op,
> + void *arg);
>
> static const struct rte_pci_id pci_id_ice_map[] = {
> { RTE_PCI_DEVICE(ICE_INTEL_VENDOR_ID, ICE_DEV_ID_E810C_BACKPLANE) },
> @@ -141,6 +146,7 @@ static const struct eth_dev_ops ice_eth_dev_ops = {
> .xstats_get = ice_xstats_get,
> .xstats_get_names = ice_xstats_get_names,
> .xstats_reset = ice_stats_reset,
> + .filter_ctrl = ice_dev_filter_ctrl,
> };
>
> /* store statistics names and its offset in stats structure */
> @@ -1478,6 +1484,8 @@ ice_dev_init(struct rte_eth_dev *dev)
> /* get base queue pairs index in the device */
> ice_base_queue_get(pf);
>
> + TAILQ_INIT(&pf->flow_list);
> +
> return 0;
>
> err_pf_setup:
> @@ -1620,6 +1628,8 @@ ice_dev_uninit(struct rte_eth_dev *dev)
> {
> struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
> struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
> + struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> + struct rte_flow *p_flow;
>
> ice_dev_close(dev);
>
> @@ -1637,6 +1647,13 @@ ice_dev_uninit(struct rte_eth_dev *dev)
> rte_intr_callback_unregister(intr_handle,
> ice_interrupt_handler, dev);
>
> + /* Remove all flows */
> + while ((p_flow = TAILQ_FIRST(&pf->flow_list))) {
> + TAILQ_REMOVE(&pf->flow_list, p_flow, node);
> + ice_free_switch_filter_rule(p_flow->rule);
> + rte_free(p_flow);
> + }
> +
> return 0;
> }
>
> @@ -3622,6 +3639,33 @@ static int ice_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
> }
>
> static int
> +ice_dev_filter_ctrl(struct rte_eth_dev *dev,
> + enum rte_filter_type filter_type,
> + enum rte_filter_op filter_op,
> + void *arg)
> +{
> + int ret = 0;
> +
> + if (!dev)
> + return -EINVAL;
> +
> + switch (filter_type) {
> + case RTE_ETH_FILTER_GENERIC:
> + if (filter_op != RTE_ETH_FILTER_GET)
> + return -EINVAL;
> + *(const void **)arg = &ice_flow_ops;
> + break;
> + default:
> + PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
> + filter_type);
> + ret = -EINVAL;
> + break;
> + }
> +
> + return ret;
> +}
> +
> +static int
> ice_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
> struct rte_pci_device *pci_dev)
> {
> diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h
> index 50b966c..8a52239 100644
> --- a/drivers/net/ice/ice_ethdev.h
> +++ b/drivers/net/ice/ice_ethdev.h
> @@ -234,12 +234,16 @@ struct ice_vsi {
> bool offset_loaded;
> };
>
> +extern const struct rte_flow_ops ice_flow_ops;
> +
> /* Struct to store flow created. */
> struct rte_flow {
> TAILQ_ENTRY(rte_flow) node;
> void *rule;
> };
>
> +TAILQ_HEAD(ice_flow_list, rte_flow);
> +
> struct ice_pf {
> struct ice_adapter *adapter; /* The adapter this PF associate to */
> struct ice_vsi *main_vsi; /* pointer to main VSI structure */
> @@ -266,6 +270,7 @@ struct ice_pf {
> struct ice_eth_stats internal_stats;
> bool offset_loaded;
> bool adapter_stopped;
> + struct ice_flow_list flow_list;
> };
>
> /**
> diff --git a/drivers/net/ice/ice_generic_flow.c b/drivers/net/ice/ice_generic_flow.c
> new file mode 100644
> index 0000000..c6fce88
> --- /dev/null
> +++ b/drivers/net/ice/ice_generic_flow.c
> @@ -0,0 +1,682 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2019 Intel Corporation
> + */
> +
> +#include <sys/queue.h>
> +#include <stdio.h>
> +#include <errno.h>
> +#include <stdint.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdarg.h>
> +
> +#include <rte_ether.h>
> +#include <rte_ethdev_driver.h>
> +#include <rte_malloc.h>
> +
> +#include "ice_ethdev.h"
> +#include "ice_generic_flow.h"
> +#include "ice_switch_filter.h"
> +
> +static int ice_flow_validate(struct rte_eth_dev *dev,
> + const struct rte_flow_attr *attr,
> + const struct rte_flow_item pattern[],
> + const struct rte_flow_action actions[],
> + struct rte_flow_error *error);
> +static struct rte_flow *ice_flow_create(struct rte_eth_dev *dev,
> + const struct rte_flow_attr *attr,
> + const struct rte_flow_item pattern[],
> + const struct rte_flow_action actions[],
> + struct rte_flow_error *error);
> +static int ice_flow_destroy(struct rte_eth_dev *dev,
> + struct rte_flow *flow,
> + struct rte_flow_error *error);
> +static int ice_flow_flush(struct rte_eth_dev *dev,
> + struct rte_flow_error *error);
> +
> +const struct rte_flow_ops ice_flow_ops = {
> + .validate = ice_flow_validate,
> + .create = ice_flow_create,
> + .destroy = ice_flow_destroy,
> + .flush = ice_flow_flush,
> +};
> +
> +static int
> +ice_flow_valid_attr(const struct rte_flow_attr *attr,
> + struct rte_flow_error *error)
> +{
> + /* Must be input direction */
> + if (!attr->ingress) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
> + attr, "Only support ingress.");
> + return -rte_errno;
> + }
> +
> + /* Not supported */
> + if (attr->egress) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
> + attr, "Not support egress.");
> + return -rte_errno;
> + }
> +
> + /* Not supported */
> + if (attr->priority) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
> + attr, "Not support priority.");
> + return -rte_errno;
> + }
> +
> + /* Not supported */
> + if (attr->group) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
> + attr, "Not support group.");
> + return -rte_errno;
> + }
> +
> + return 0;
> +}
> +
> +/* Find the first VOID or non-VOID item pointer */
> +static const struct rte_flow_item *
> +ice_find_first_item(const struct rte_flow_item *item, bool is_void)
> +{
> + bool is_find;
> +
> + while (item->type != RTE_FLOW_ITEM_TYPE_END) {
> + if (is_void)
> + is_find = item->type == RTE_FLOW_ITEM_TYPE_VOID;
> + else
> + is_find = item->type != RTE_FLOW_ITEM_TYPE_VOID;
> + if (is_find)
> + break;
> + item++;
> + }
> + return item;
> +}
> +
> +/* Skip all VOID items of the pattern */
> +static void
> +ice_pattern_skip_void_item(struct rte_flow_item *items,
> + const struct rte_flow_item *pattern)
> +{
> + uint32_t cpy_count = 0;
> + const struct rte_flow_item *pb = pattern, *pe = pattern;
> +
> + for (;;) {
> + /* Find a non-void item first */
> + pb = ice_find_first_item(pb, false);
> + if (pb->type == RTE_FLOW_ITEM_TYPE_END) {
> + pe = pb;
> + break;
> + }
> +
> + /* Find a void item */
> + pe = ice_find_first_item(pb + 1, true);
> +
> + cpy_count = pe - pb;
> + rte_memcpy(items, pb, sizeof(struct rte_flow_item) * cpy_count);
> +
> + items += cpy_count;
> +
> + if (pe->type == RTE_FLOW_ITEM_TYPE_END) {
> + pb = pe;
> + break;
> + }
> +
> + pb = pe + 1;
> + }
> + /* Copy the END item. */
> + rte_memcpy(items, pe, sizeof(struct rte_flow_item));
> +}
> +
> +/* Check if the pattern matches a supported item type array */
> +static bool
> +ice_match_pattern(enum rte_flow_item_type *item_array,
> + const struct rte_flow_item *pattern)
> +{
> + const struct rte_flow_item *item = pattern;
> +
> + while ((*item_array == item->type) &&
> + (*item_array != RTE_FLOW_ITEM_TYPE_END)) {
> + item_array++;
> + item++;
> + }
> +
> + return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
> + item->type == RTE_FLOW_ITEM_TYPE_END);
> +}
> +
> +static uint64_t ice_flow_valid_pattern(const struct rte_flow_item pattern[],
> + struct rte_flow_error *error)
> +{
> + uint16_t i = 0;
> + uint64_t inset;
> + struct rte_flow_item *items; /* used for pattern without VOID items */
> + uint32_t item_num = 0; /* non-void item number */
> +
> + /* Get the non-void item number of pattern */
> + while ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_END) {
> + if ((pattern + i)->type != RTE_FLOW_ITEM_TYPE_VOID)
> + item_num++;
> + i++;
> + }
> + item_num++;
> +
> + items = rte_zmalloc("ice_pattern",
> + item_num * sizeof(struct rte_flow_item), 0);
> + if (!items) {
> + rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> + NULL, "No memory for PMD internal items.");
> + return -ENOMEM;
> + }
> +
> + ice_pattern_skip_void_item(items, pattern);
> +
> + for (i = 0; i < RTE_DIM(ice_supported_patterns); i++)
> + if (ice_match_pattern(ice_supported_patterns[i].items,
> + items)) {
> + inset = ice_supported_patterns[i].sw_fields;
> + rte_free(items);
> + return inset;
> + }
> + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
> + pattern, "Unsupported pattern");
> +
> + rte_free(items);
> + return 0;
> +}
> +
> +static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
> + struct rte_flow_error *error)
> +{
> + const struct rte_flow_item *item = pattern;
> + const struct rte_flow_item_eth *eth_spec, *eth_mask;
> + const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
> + const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
> + const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
> + const struct rte_flow_item_udp *udp_spec, *udp_mask;
> + const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
> + const struct rte_flow_item_icmp *icmp_mask;
> + const struct rte_flow_item_icmp6 *icmp6_mask;
> + const struct rte_flow_item_vxlan *vxlan_spec, *vxlan_mask;
> + const struct rte_flow_item_nvgre *nvgre_spec, *nvgre_mask;
> + enum rte_flow_item_type item_type;
> + uint8_t ipv6_addr_mask[16] = {
> + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
> + uint64_t input_set = ICE_INSET_NONE;
> + bool outer_ip = true;
> + bool outer_l4 = true;
> +
> + for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
> + if (item->last) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Not support range");
> + return 0;
> + }
> + item_type = item->type;
> + switch (item_type) {
> + case RTE_FLOW_ITEM_TYPE_ETH:
> + eth_spec = item->spec;
> + eth_mask = item->mask;
> +
> + if (eth_spec && eth_mask) {
> + if (rte_is_broadcast_ether_addr(ð_mask->src))
> + input_set |= ICE_INSET_SMAC;
> + if (rte_is_broadcast_ether_addr(ð_mask->dst))
> + input_set |= ICE_INSET_DMAC;
> + if (eth_mask->type == RTE_BE16(0xffff))
> + input_set |= ICE_INSET_ETHERTYPE;
> + }
> + break;
> + case RTE_FLOW_ITEM_TYPE_IPV4:
> + ipv4_spec = item->spec;
> + ipv4_mask = item->mask;
> +
> + if (!(ipv4_spec && ipv4_mask)) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid IPv4 spec or mask.");
> + return 0;
> + }
> +
> + /* Check IPv4 mask and update input set */
> + if (ipv4_mask->hdr.version_ihl ||
> + ipv4_mask->hdr.total_length ||
> + ipv4_mask->hdr.packet_id ||
> + ipv4_mask->hdr.hdr_checksum) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid IPv4 mask.");
> + return 0;
> + }
> +
> + if (outer_ip) {
> + if (ipv4_mask->hdr.src_addr == UINT32_MAX)
> + input_set |= ICE_INSET_IPV4_SRC;
> + if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
> + input_set |= ICE_INSET_IPV4_DST;
> + if (ipv4_mask->hdr.type_of_service == UINT8_MAX)
> + input_set |= ICE_INSET_IPV4_TOS;
> + if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
> + input_set |= ICE_INSET_IPV4_TTL;
> + if (ipv4_mask->hdr.fragment_offset == 0)
> + input_set |= ICE_INSET_IPV4_PROTO;
> + outer_ip = false;
> + } else {
> + if (ipv4_mask->hdr.src_addr == UINT32_MAX)
> + input_set |= ICE_INSET_TUN_IPV4_SRC;
> + if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
> + input_set |= ICE_INSET_TUN_IPV4_DST;
> + if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
> + input_set |= ICE_INSET_TUN_IPV4_TTL;
> + if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
> + input_set |= ICE_INSET_TUN_IPV4_PROTO;
> + }
> + break;
> + case RTE_FLOW_ITEM_TYPE_IPV6:
> + ipv6_spec = item->spec;
> + ipv6_mask = item->mask;
> +
> + if (!(ipv6_spec && ipv6_mask)) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item, "Invalid IPv6 spec or mask");
> + return 0;
> + }
> +
> + if (ipv6_mask->hdr.payload_len ||
> + ipv6_mask->hdr.vtc_flow) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid IPv6 mask");
> + return 0;
> + }
> +
> + if (outer_ip) {
> + if (!memcmp(ipv6_mask->hdr.src_addr,
> + ipv6_addr_mask,
> + RTE_DIM(ipv6_mask->hdr.src_addr)))
> + input_set |= ICE_INSET_IPV6_SRC;
> + if (!memcmp(ipv6_mask->hdr.dst_addr,
> + ipv6_addr_mask,
> + RTE_DIM(ipv6_mask->hdr.dst_addr)))
> + input_set |= ICE_INSET_IPV6_DST;
> + if (ipv6_mask->hdr.proto == UINT8_MAX)
> + input_set |= ICE_INSET_IPV6_NEXT_HDR;
> + if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
> + input_set |= ICE_INSET_IPV6_HOP_LIMIT;
> + outer_ip = false;
> + } else {
> + if (!memcmp(ipv6_mask->hdr.src_addr,
> + ipv6_addr_mask,
> + RTE_DIM(ipv6_mask->hdr.src_addr)))
> + input_set |= ICE_INSET_TUN_IPV6_SRC;
> + if (!memcmp(ipv6_mask->hdr.dst_addr,
> + ipv6_addr_mask,
> + RTE_DIM(ipv6_mask->hdr.dst_addr)))
> + input_set |= ICE_INSET_TUN_IPV6_DST;
> + if (ipv6_mask->hdr.proto == UINT8_MAX)
> + input_set |= ICE_INSET_TUN_IPV6_PROTO;
> + if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
> + input_set |= ICE_INSET_TUN_IPV6_TTL;
> + }
> +
> + break;
> + case RTE_FLOW_ITEM_TYPE_UDP:
> + udp_spec = item->spec;
> + udp_mask = item->mask;
> +
> + if (!(udp_spec && udp_mask)) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item, "Invalid UDP mask");
> + return 0;
> + }
> +
> + /* Check UDP mask and update input set*/
> + if (udp_mask->hdr.dgram_len ||
> + udp_mask->hdr.dgram_cksum) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid UDP mask");
> + return 0;
> + }
> +
> + if (outer_l4) {
> + if (udp_mask->hdr.src_port == UINT16_MAX)
> + input_set |= ICE_INSET_SRC_PORT;
> + if (udp_mask->hdr.dst_port == UINT16_MAX)
> + input_set |= ICE_INSET_DST_PORT;
> + outer_l4 = false;
> + } else {
> + if (udp_mask->hdr.src_port == UINT16_MAX)
> + input_set |= ICE_INSET_TUN_SRC_PORT;
> + if (udp_mask->hdr.dst_port == UINT16_MAX)
> + input_set |= ICE_INSET_TUN_DST_PORT;
> + }
> +
> + break;
> + case RTE_FLOW_ITEM_TYPE_TCP:
> + tcp_spec = item->spec;
> + tcp_mask = item->mask;
> +
> + if (!(tcp_spec && tcp_mask)) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item, "Invalid TCP mask");
> + return 0;
> + }
> +
> + /* Check TCP mask and update input set */
> + if (tcp_mask->hdr.sent_seq ||
> + tcp_mask->hdr.recv_ack ||
> + tcp_mask->hdr.data_off ||
> + tcp_mask->hdr.tcp_flags ||
> + tcp_mask->hdr.rx_win ||
> + tcp_mask->hdr.cksum ||
> + tcp_mask->hdr.tcp_urp) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid TCP mask");
> + return 0;
> + }
> +
> + if (outer_l4) {
> + if (tcp_mask->hdr.src_port == UINT16_MAX)
> + input_set |= ICE_INSET_SRC_PORT;
> + if (tcp_mask->hdr.dst_port == UINT16_MAX)
> + input_set |= ICE_INSET_DST_PORT;
> + outer_l4 = false;
> + } else {
> + if (tcp_mask->hdr.src_port == UINT16_MAX)
> + input_set |= ICE_INSET_TUN_SRC_PORT;
> + if (tcp_mask->hdr.dst_port == UINT16_MAX)
> + input_set |= ICE_INSET_TUN_DST_PORT;
> + }
> +
> + break;
> + case RTE_FLOW_ITEM_TYPE_SCTP:
> + sctp_spec = item->spec;
> + sctp_mask = item->mask;
> +
> + if (!(sctp_spec && sctp_mask)) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item, "Invalid SCTP mask");
> + return 0;
> + }
> +
> + /* Check SCTP mask and update input set */
> + if (sctp_mask->hdr.cksum) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid SCTP mask");
> + return 0;
> + }
> +
> + if (outer_l4) {
> + if (sctp_mask->hdr.src_port == UINT16_MAX)
> + input_set |= ICE_INSET_SRC_PORT;
> + if (sctp_mask->hdr.dst_port == UINT16_MAX)
> + input_set |= ICE_INSET_DST_PORT;
> + outer_l4 = false;
> + } else {
> + if (sctp_mask->hdr.src_port == UINT16_MAX)
> + input_set |= ICE_INSET_TUN_SRC_PORT;
> + if (sctp_mask->hdr.dst_port == UINT16_MAX)
> + input_set |= ICE_INSET_TUN_DST_PORT;
> + }
> +
> + break;
> + case RTE_FLOW_ITEM_TYPE_ICMP:
> + icmp_mask = item->mask;
> + if (icmp_mask->hdr.icmp_code ||
> + icmp_mask->hdr.icmp_cksum ||
> + icmp_mask->hdr.icmp_ident ||
> + icmp_mask->hdr.icmp_seq_nb) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid ICMP mask");
> + return 0;
> + }
> +
> + if (icmp_mask->hdr.icmp_type == UINT8_MAX)
> + input_set |= ICE_INSET_ICMP;
> + break;
> + case RTE_FLOW_ITEM_TYPE_ICMP6:
> + icmp6_mask = item->mask;
> + if (icmp6_mask->code ||
> + icmp6_mask->checksum) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid ICMP6 mask");
> + return 0;
> + }
> +
> + if (icmp6_mask->type == UINT8_MAX)
> + input_set |= ICE_INSET_ICMP6;
> + break;
> + case RTE_FLOW_ITEM_TYPE_VXLAN:
> + vxlan_spec = item->spec;
> + vxlan_mask = item->mask;
> + /* Check if VXLAN item is used to describe protocol.
> + * If yes, both spec and mask should be NULL.
> + * If no, both spec and mask shouldn't be NULL.
> + */
> + if ((!vxlan_spec && vxlan_mask) ||
> + (vxlan_spec && !vxlan_mask)) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid VXLAN item");
> + return -rte_errno;
> + }
> +
> + break;
> + case RTE_FLOW_ITEM_TYPE_NVGRE:
> + nvgre_spec = item->spec;
> + nvgre_mask = item->mask;
> + /* Check if VXLAN item is used to describe protocol.
> + * If yes, both spec and mask should be NULL.
> + * If no, both spec and mask shouldn't be NULL.
> + */
> + if ((!nvgre_spec && nvgre_mask) ||
> + (nvgre_spec && !nvgre_mask)) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid VXLAN item");
> + return -rte_errno;
> + }
> +
> + break;
> + default:
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM,
> + item,
> + "Invalid mask no exist");
> + break;
> + }
> + }
> + return input_set;
> +}
> +
> +static int ice_flow_valid_inset(const struct rte_flow_item pattern[],
> + uint64_t inset, struct rte_flow_error *error)
> +{
> + uint64_t fields;
> +
> + /* get valid field */
> + fields = ice_get_flow_field(pattern, error);
> + if ((!fields) || (fields && (!inset))) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
> + pattern,
> + "Invalid input set");
> + return -rte_errno;
> + }
> +
> + return 0;
> +}
> +
> +static int ice_flow_valid_action(const struct rte_flow_action *actions,
> + struct rte_flow_error *error)
> +{
> + switch (actions->type) {
> + case RTE_FLOW_ACTION_TYPE_QUEUE:
> + break;
> + case RTE_FLOW_ACTION_TYPE_DROP:
> + break;
> + default:
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ACTION, actions,
> + "Invalid action.");
> + return -rte_errno;
> + }
> +
> + return 0;
> +}
> +
> +static int
> +ice_flow_validate(__rte_unused struct rte_eth_dev *dev,
> + const struct rte_flow_attr *attr,
> + const struct rte_flow_item pattern[],
> + const struct rte_flow_action actions[],
> + struct rte_flow_error *error)
> +{
> + uint64_t inset = 0;
> + int ret = ICE_ERR_NOT_SUPPORTED;
> +
> + if (!pattern) {
> + rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> + NULL, "NULL pattern.");
> + return -rte_errno;
> + }
> +
> + if (!actions) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ACTION_NUM,
> + NULL, "NULL action.");
> + return -rte_errno;
> + }
> +
> + if (!attr) {
> + rte_flow_error_set(error, EINVAL,
> + RTE_FLOW_ERROR_TYPE_ATTR,
> + NULL, "NULL attribute.");
> + return -rte_errno;
> + }
> +
> + ret = ice_flow_valid_attr(attr, error);
> + if (!ret)
> + return ret;
> +
> + inset = ice_flow_valid_pattern(pattern, error);
> + if (!inset)
> + return -rte_errno;
> +
> + ret = ice_flow_valid_inset(pattern, inset, error);
> + if (ret)
> + return ret;
> +
> + ret = ice_flow_valid_action(actions, error);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static struct rte_flow *
> +ice_flow_create(struct rte_eth_dev *dev,
> + const struct rte_flow_attr *attr,
> + const struct rte_flow_item pattern[],
> + const struct rte_flow_action actions[],
> + struct rte_flow_error *error)
> +{
> + struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> + struct rte_flow *flow = NULL;
> + int ret;
> +
> + flow = rte_zmalloc("ice_flow", sizeof(struct rte_flow), 0);
> + if (!flow) {
> + rte_flow_error_set(error, ENOMEM,
> + RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> + "Failed to allocate memory");
> + return flow;
> + }
> +
> + ret = ice_flow_validate(dev, attr, pattern, actions, error);
> + if (ret < 0)
> + return NULL;
> +
> + ret = ice_create_switch_filter(pf, pattern, actions, flow, error);
> + if (ret)
> + goto free_flow;
> +
> + TAILQ_INSERT_TAIL(&pf->flow_list, flow, node);
> + return flow;
> +
> +free_flow:
> + rte_flow_error_set(error, -ret,
> + RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> + "Failed to create flow.");
> + rte_free(flow);
> + return NULL;
> +}
> +
> +static int
> +ice_flow_destroy(struct rte_eth_dev *dev,
> + struct rte_flow *flow,
> + struct rte_flow_error *error)
> +{
> + struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> + int ret = 0;
> +
> + ret = ice_destroy_switch_filter(pf, flow, error);
> +
> + if (!ret) {
> + TAILQ_REMOVE(&pf->flow_list, flow, node);
> + rte_free(flow);
> + } else
> + rte_flow_error_set(error, -ret,
> + RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> + "Failed to destroy flow.");
> +
> + return ret;
> +}
> +
> +static int
> +ice_flow_flush(struct rte_eth_dev *dev,
> + struct rte_flow_error *error)
> +{
> + struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> + struct rte_flow *p_flow;
> + int ret;
> +
> + TAILQ_FOREACH(p_flow, &pf->flow_list, node) {
> + ret = ice_flow_destroy(dev, p_flow, error);
> + if (ret) {
> + rte_flow_error_set(error, -ret,
> + RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
> + "Failed to flush SW flows.");
> + return -rte_errno;
> + }
> + }
> +
> + return ret;
> +}
> diff --git a/drivers/net/ice/ice_generic_flow.h b/drivers/net/ice/ice_generic_flow.h
> new file mode 100644
> index 0000000..ed7f3fe
> --- /dev/null
> +++ b/drivers/net/ice/ice_generic_flow.h
> @@ -0,0 +1,654 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2019 Intel Corporation
> + */
> +
> +#ifndef _ICE_GENERIC_FLOW_H_
> +#define _ICE_GENERIC_FLOW_H_
> +
> +#include <rte_flow_driver.h>
> +
> +struct ice_flow_pattern {
> + enum rte_flow_item_type *items;
> + uint64_t sw_fields;
> +};
> +
> +#define ICE_INSET_NONE 0x00000000000000000ULL
> +
> +/* bit0 ~ bit 7 */
> +#define ICE_INSET_SMAC 0x0000000000000001ULL
> +#define ICE_INSET_DMAC 0x0000000000000002ULL
> +#define ICE_INSET_ETHERTYPE 0x0000000000000020ULL
> +
> +/* bit 8 ~ bit 15 */
> +#define ICE_INSET_IPV4_SRC 0x0000000000000100ULL
> +#define ICE_INSET_IPV4_DST 0x0000000000000200ULL
> +#define ICE_INSET_IPV6_SRC 0x0000000000000400ULL
> +#define ICE_INSET_IPV6_DST 0x0000000000000800ULL
> +#define ICE_INSET_SRC_PORT 0x0000000000001000ULL
> +#define ICE_INSET_DST_PORT 0x0000000000002000ULL
> +#define ICE_INSET_ARP 0x0000000000004000ULL
> +
> +/* bit 16 ~ bit 31 */
> +#define ICE_INSET_IPV4_TOS 0x0000000000010000ULL
> +#define ICE_INSET_IPV4_PROTO 0x0000000000020000ULL
> +#define ICE_INSET_IPV4_TTL 0x0000000000040000ULL
> +#define ICE_INSET_IPV6_NEXT_HDR 0x0000000000200000ULL
> +#define ICE_INSET_IPV6_HOP_LIMIT 0x0000000000400000ULL
> +#define ICE_INSET_ICMP 0x0000000001000000ULL
> +#define ICE_INSET_ICMP6 0x0000000002000000ULL
> +
> +/* bit 32 ~ bit 47, tunnel fields */
> +#define ICE_INSET_TUN_SMAC 0x0000000100000000ULL
> +#define ICE_INSET_TUN_DMAC 0x0000000200000000ULL
> +#define ICE_INSET_TUN_IPV4_SRC 0x0000000400000000ULL
> +#define ICE_INSET_TUN_IPV4_DST 0x0000000800000000ULL
> +#define ICE_INSET_TUN_IPV4_TTL 0x0000001000000000ULL
> +#define ICE_INSET_TUN_IPV4_PROTO 0x0000002000000000ULL
> +#define ICE_INSET_TUN_IPV6_SRC 0x0000004000000000ULL
> +#define ICE_INSET_TUN_IPV6_DST 0x0000008000000000ULL
> +#define ICE_INSET_TUN_IPV6_TTL 0x0000010000000000ULL
> +#define ICE_INSET_TUN_IPV6_PROTO 0x0000020000000000ULL
> +#define ICE_INSET_TUN_SRC_PORT 0x0000040000000000ULL
> +#define ICE_INSET_TUN_DST_PORT 0x0000080000000000ULL
> +#define ICE_INSET_TUN_ID 0x0000100000000000ULL
> +
> +/* bit 48 ~ bit 55 */
> +#define ICE_INSET_LAST_ETHER_TYPE 0x0001000000000000ULL
> +
> +#define ICE_FLAG_VLAN_INNER 0x00000001ULL
> +#define ICE_FLAG_VLAN_OUTER 0x00000002ULL
> +
> +#define INSET_ETHER ( \
> + ICE_INSET_DMAC | ICE_INSET_SMAC | ICE_INSET_ETHERTYPE)
> +#define INSET_MAC_IPV4 ( \
> + ICE_INSET_IPV4_DST | ICE_INSET_IPV4_SRC | \
> + ICE_INSET_IPV4_PROTO | ICE_INSET_IPV4_TOS)
> +#define INSET_MAC_IPV4_L4 ( \
> + ICE_INSET_IPV4_DST | ICE_INSET_IPV4_SRC | \
> + ICE_INSET_IPV4_TOS | ICE_INSET_DST_PORT | \
> + ICE_INSET_SRC_PORT)
> +#define INSET_MAC_IPV4_ICMP ( \
> + ICE_INSET_IPV4_DST | ICE_INSET_IPV4_SRC | \
> + ICE_INSET_IPV4_TOS | ICE_INSET_ICMP)
> +#define INSET_MAC_IPV6 ( \
> + ICE_INSET_IPV6_DST | ICE_INSET_IPV6_SRC | \
> + ICE_INSET_IPV6_NEXT_HDR | ICE_INSET_IPV6_HOP_LIMIT)
> +#define INSET_MAC_IPV6_L4 ( \
> + ICE_INSET_IPV6_DST | ICE_INSET_IPV6_SRC | \
> + ICE_INSET_IPV6_HOP_LIMIT | ICE_INSET_DST_PORT | \
> + ICE_INSET_SRC_PORT)
> +#define INSET_MAC_IPV6_ICMP ( \
> + ICE_INSET_IPV6_DST | ICE_INSET_IPV6_SRC | \
> + ICE_INSET_IPV6_HOP_LIMIT | ICE_INSET_ICMP6)
> +#define INSET_TUNNEL_IPV4_TYPE1 ( \
> + ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST | \
> + ICE_INSET_TUN_IPV4_TTL | ICE_INSET_TUN_IPV4_PROTO)
> +#define INSET_TUNNEL_IPV4_TYPE2 ( \
> + ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST | \
> + ICE_INSET_TUN_IPV4_TTL | ICE_INSET_TUN_IPV4_PROTO | \
> + ICE_INSET_TUN_SRC_PORT | ICE_INSET_TUN_DST_PORT)
> +#define INSET_TUNNEL_IPV4_TYPE3 ( \
> + ICE_INSET_TUN_IPV4_SRC | ICE_INSET_TUN_IPV4_DST | \
> + ICE_INSET_TUN_IPV4_TTL | ICE_INSET_ICMP)
> +#define INSET_TUNNEL_IPV6_TYPE1 ( \
> + ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST | \
> + ICE_INSET_TUN_IPV6_TTL | ICE_INSET_TUN_IPV6_PROTO)
> +#define INSET_TUNNEL_IPV6_TYPE2 ( \
> + ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST | \
> + ICE_INSET_TUN_IPV6_TTL | ICE_INSET_TUN_IPV6_PROTO | \
> + ICE_INSET_TUN_SRC_PORT | ICE_INSET_TUN_DST_PORT)
> +#define INSET_TUNNEL_IPV6_TYPE3 ( \
> + ICE_INSET_TUN_IPV6_SRC | ICE_INSET_TUN_IPV6_DST | \
> + ICE_INSET_TUN_IPV6_TTL | ICE_INSET_ICMP6)
> +
> +/* L2 */
> +static enum rte_flow_item_type pattern_ethertype[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* non-tunnel IPv4 */
> +static enum rte_flow_item_type pattern_ipv4[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* non-tunnel IPv6 */
> +static enum rte_flow_item_type pattern_ipv6[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv6_icmp6[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_ICMP6,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN MAC IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv4_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 VXLAN MAC IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_vxlan_eth_ipv6_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv4_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE MAC IPv4 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv4_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_ipv6_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +/* IPv4 NVGRE MAC IPv6 */
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_udp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_tcp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_TCP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_sctp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_SCTP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static enum rte_flow_item_type pattern_ipv4_nvgre_eth_ipv6_icmp[] = {
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV4,
> + RTE_FLOW_ITEM_TYPE_UDP,
> + RTE_FLOW_ITEM_TYPE_VXLAN,
> + RTE_FLOW_ITEM_TYPE_ETH,
> + RTE_FLOW_ITEM_TYPE_IPV6,
> + RTE_FLOW_ITEM_TYPE_ICMP,
> + RTE_FLOW_ITEM_TYPE_END,
> +};
> +
> +static struct ice_flow_pattern ice_supported_patterns[] = {
> + {pattern_ethertype, INSET_ETHER},
> + {pattern_ipv4, INSET_MAC_IPV4},
> + {pattern_ipv4_udp, INSET_MAC_IPV4_L4},
> + {pattern_ipv4_sctp, INSET_MAC_IPV4_L4},
> + {pattern_ipv4_tcp, INSET_MAC_IPV4_L4},
> + {pattern_ipv4_icmp, INSET_MAC_IPV4_ICMP},
> + {pattern_ipv6, INSET_MAC_IPV6},
> + {pattern_ipv6_udp, INSET_MAC_IPV6_L4},
> + {pattern_ipv6_sctp, INSET_MAC_IPV6_L4},
> + {pattern_ipv6_tcp, INSET_MAC_IPV6_L4},
> + {pattern_ipv6_icmp6, INSET_MAC_IPV6_ICMP},
> + {pattern_ipv4_vxlan_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> + {pattern_ipv4_vxlan_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_vxlan_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_vxlan_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_vxlan_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> + {pattern_ipv4_vxlan_eth_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> + {pattern_ipv4_vxlan_eth_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_vxlan_eth_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_vxlan_eth_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_vxlan_eth_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> + {pattern_ipv4_vxlan_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> + {pattern_ipv4_vxlan_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_vxlan_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_vxlan_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_vxlan_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> + {pattern_ipv4_vxlan_eth_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> + {pattern_ipv4_vxlan_eth_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_vxlan_eth_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_vxlan_eth_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_vxlan_eth_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> + {pattern_ipv4_nvgre_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> + {pattern_ipv4_nvgre_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_nvgre_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_nvgre_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_nvgre_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> + {pattern_ipv4_nvgre_eth_ipv4, INSET_TUNNEL_IPV4_TYPE1},
> + {pattern_ipv4_nvgre_eth_ipv4_udp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_nvgre_eth_ipv4_tcp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_nvgre_eth_ipv4_sctp, INSET_TUNNEL_IPV4_TYPE2},
> + {pattern_ipv4_nvgre_eth_ipv4_icmp, INSET_TUNNEL_IPV4_TYPE3},
> + {pattern_ipv4_nvgre_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> + {pattern_ipv4_nvgre_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_nvgre_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_nvgre_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_nvgre_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> + {pattern_ipv4_nvgre_eth_ipv6, INSET_TUNNEL_IPV6_TYPE1},
> + {pattern_ipv4_nvgre_eth_ipv6_udp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_nvgre_eth_ipv6_tcp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_nvgre_eth_ipv6_sctp, INSET_TUNNEL_IPV6_TYPE2},
> + {pattern_ipv4_nvgre_eth_ipv6_icmp, INSET_TUNNEL_IPV6_TYPE3},
> +};
> +
> +#endif
> diff --git a/drivers/net/ice/meson.build b/drivers/net/ice/meson.build
> index 8697676..18180b9 100644
> --- a/drivers/net/ice/meson.build
> +++ b/drivers/net/ice/meson.build
> @@ -8,6 +8,7 @@ sources = files(
> 'ice_ethdev.c',
> 'ice_rxtx.c',
> 'ice_switch_filter.c'
Missing a comma here.
> + 'ice_generic_flow.c'
> )
>
> deps += ['hash']
^ permalink raw reply
* [PATCH v5 0/7] I2C IRQ Probe Improvements
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
This series attempts to align as much IRQ handling into the
probe path as possible. Note that I don't have a great setup
for testing these patches so they are mostly just build tested
and need careful review and testing before any of them are
merged.
The series brings the ACPI path inline with the way the device
tree path handles the IRQ entirely at probe time. However,
it still leaves any IRQ specified through the board_info as
being handled at device time. In that case we need to cache
something from the board_info until probe time, which leaves
any alternative solution with something basically the same as
the current handling although perhaps caching more stuff.
Thanks,
Charles
See previous discussions:
- https://lkml.org/lkml/2019/2/15/989
- https://www.spinics.net/lists/linux-i2c/msg39541.html
Charles Keepax (7):
i2c: core: Allow whole core to use i2c_dev_irq_from_resources
i2c: acpi: Use available IRQ helper functions
i2c: acpi: Factor out getting the IRQ from ACPI
i2c: core: Make i2c_acpi_get_irq available to the rest of the I2C core
i2c: core: Move ACPI IRQ handling to probe time
i2c: core: Move ACPI gpio IRQ handling into i2c_acpi_get_irq
i2c: core: Tidy up handling of init_irq
drivers/i2c/i2c-core-acpi.c | 57 +++++++++++++++++++++++++++++++--------------
drivers/i2c/i2c-core-base.c | 11 +++++----
drivers/i2c/i2c-core.h | 11 +++++++++
3 files changed, 57 insertions(+), 22 deletions(-)
--
2.11.0
^ permalink raw reply
* [PATCH v5 1/7] i2c: core: Allow whole core to use i2c_dev_irq_from_resources
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
Remove the static from i2c_dev_irq_from _resources so that other parts
of the core code can use this helper function.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-base.c | 4 ++--
drivers/i2c/i2c-core.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 2569e97f9bf35..8a303246d534b 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -679,8 +679,8 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
i2c_encode_flags_to_addr(client));
}
-static int i2c_dev_irq_from_resources(const struct resource *resources,
- unsigned int num_resources)
+int i2c_dev_irq_from_resources(const struct resource *resources,
+ unsigned int num_resources)
{
struct irq_data *irqd;
int i;
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index 851c11b4c0f3a..2a3b28bf826b1 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -19,6 +19,8 @@ extern struct list_head __i2c_board_list;
extern int __i2c_first_dynamic_bus_num;
int i2c_check_7bit_addr_validity_strict(unsigned short addr);
+int i2c_dev_irq_from_resources(const struct resource *resources,
+ unsigned int num_resources);
/*
* We only allow atomic transfers for very late communication, e.g. to send
--
2.11.0
^ permalink raw reply related
* [PATCH v5 2/7] i2c: acpi: Use available IRQ helper functions
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
Use the available IRQ helper functions, most of the functions have
additional helpful side affects like configuring the trigger type of the
IRQ.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-acpi.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index f1d648962b223..47d5b1c5ec9e0 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -133,14 +133,25 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
return 0;
}
+static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
+{
+ int *irq = data;
+ struct resource r;
+
+ if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r))
+ *irq = i2c_dev_irq_from_resources(&r, 1);
+
+ return 1; /* No need to add resource to the list */
+}
+
static int i2c_acpi_get_info(struct acpi_device *adev,
struct i2c_board_info *info,
struct i2c_adapter *adapter,
acpi_handle *adapter_handle)
{
struct list_head resource_list;
- struct resource_entry *entry;
struct i2c_acpi_lookup lookup;
+ int irq = -ENOENT;
int ret;
memset(&lookup, 0, sizeof(lookup));
@@ -172,16 +183,13 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
/* Then fill IRQ number if any */
INIT_LIST_HEAD(&resource_list);
- ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ i2c_acpi_add_resource, &irq);
if (ret < 0)
return -EINVAL;
- resource_list_for_each_entry(entry, &resource_list) {
- if (resource_type(entry->res) == IORESOURCE_IRQ) {
- info->irq = entry->res->start;
- break;
- }
- }
+ if (irq > 0)
+ info->irq = irq;
acpi_dev_free_resource_list(&resource_list);
--
2.11.0
^ permalink raw reply related
* [PATCH v5 3/7] i2c: acpi: Factor out getting the IRQ from ACPI
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
In preparation for future refactoring factor out the fetch of the IRQ
into its own helper function.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-acpi.c | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 47d5b1c5ec9e0..7d4d66ba752d4 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -144,14 +144,30 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
return 1; /* No need to add resource to the list */
}
+static int i2c_acpi_get_irq(struct acpi_device *adev)
+{
+ struct list_head resource_list;
+ int irq = -ENOENT;
+ int ret;
+
+ INIT_LIST_HEAD(&resource_list);
+
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ i2c_acpi_add_resource, &irq);
+ if (ret < 0)
+ return -EINVAL;
+
+ acpi_dev_free_resource_list(&resource_list);
+
+ return irq;
+}
+
static int i2c_acpi_get_info(struct acpi_device *adev,
struct i2c_board_info *info,
struct i2c_adapter *adapter,
acpi_handle *adapter_handle)
{
- struct list_head resource_list;
struct i2c_acpi_lookup lookup;
- int irq = -ENOENT;
int ret;
memset(&lookup, 0, sizeof(lookup));
@@ -182,16 +198,9 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
*adapter_handle = lookup.adapter_handle;
/* Then fill IRQ number if any */
- INIT_LIST_HEAD(&resource_list);
- ret = acpi_dev_get_resources(adev, &resource_list,
- i2c_acpi_add_resource, &irq);
- if (ret < 0)
- return -EINVAL;
-
- if (irq > 0)
- info->irq = irq;
-
- acpi_dev_free_resource_list(&resource_list);
+ ret = i2c_acpi_get_irq(adev);
+ if (ret > 0)
+ info->irq = ret;
acpi_set_modalias(adev, dev_name(&adev->dev), info->type,
sizeof(info->type));
--
2.11.0
^ permalink raw reply related
* [PATCH v5 4/7] i2c: core: Make i2c_acpi_get_irq available to the rest of the I2C core
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
In preparation for more refactoring make i2c_acpi_get_irq available
outside i2c-core-acpi.c.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
Changes since v4:
- Leave i2c_acpi_get_irq accepting an acpi_device, this should
avoid the NULL pointer issue we had with i2c_acpi_find_client_by_adev
Thanks,
Charles
drivers/i2c/i2c-core-acpi.c | 10 +++++++++-
drivers/i2c/i2c-core.h | 9 +++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 7d4d66ba752d4..0ddfcca6091e1 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -144,7 +144,15 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
return 1; /* No need to add resource to the list */
}
-static int i2c_acpi_get_irq(struct acpi_device *adev)
+/**
+ * i2c_acpi_get_irq - get device IRQ number from ACPI
+ * @client: Pointer to the I2C client device
+ *
+ * Find the IRQ number used by a specific client device.
+ *
+ * Return: The IRQ number or an error code.
+ */
+int i2c_acpi_get_irq(struct acpi_device *adev)
{
struct list_head resource_list;
int irq = -ENOENT;
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index 2a3b28bf826b1..4fbe0a0bcc4c4 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -58,11 +58,15 @@ static inline int __i2c_check_suspended(struct i2c_adapter *adap)
return 0;
}
+struct acpi_device;
+
#ifdef CONFIG_ACPI
const struct acpi_device_id *
i2c_acpi_match_device(const struct acpi_device_id *matches,
struct i2c_client *client);
void i2c_acpi_register_devices(struct i2c_adapter *adap);
+
+int i2c_acpi_get_irq(struct acpi_device *adev);
#else /* CONFIG_ACPI */
static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
static inline const struct acpi_device_id *
@@ -71,6 +75,11 @@ i2c_acpi_match_device(const struct acpi_device_id *matches,
{
return NULL;
}
+
+static inline int i2c_acpi_get_irq(struct acpi_device *adev)
+{
+ return 0;
+}
#endif /* CONFIG_ACPI */
extern struct notifier_block i2c_acpi_notifier;
--
2.11.0
^ permalink raw reply related
* [PATCH v5 5/7] i2c: core: Move ACPI IRQ handling to probe time
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
Bring the ACPI path in sync with the device tree path and handle all the
IRQ fetching at probe time. This leaves the only IRQ handling at device
registration time being that which is passed directly through the board
info as either a resource or an actual IRQ number.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
Changes since v4:
- Pass acpi_device to i2c_acpi_get_irq
- Pass the client acpi_device rather than the adaptor, I think (maybe
hope is more accurate) this should fix the issue seen by Benjamin.
Thanks,
Charles
drivers/i2c/i2c-core-acpi.c | 5 -----
drivers/i2c/i2c-core-base.c | 5 ++++-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 0ddfcca6091e1..f752879772f64 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -205,11 +205,6 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
if (adapter_handle)
*adapter_handle = lookup.adapter_handle;
- /* Then fill IRQ number if any */
- ret = i2c_acpi_get_irq(adev);
- if (ret > 0)
- info->irq = ret;
-
acpi_set_modalias(adev, dev_name(&adev->dev), info->type,
sizeof(info->type));
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 8a303246d534b..060d1a3a7ea4c 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -327,7 +327,10 @@ static int i2c_device_probe(struct device *dev)
if (irq == -EINVAL || irq == -ENODATA)
irq = of_irq_get(dev->of_node, 0);
} else if (ACPI_COMPANION(dev)) {
- irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
+ irq = i2c_acpi_get_irq(ACPI_COMPANION(dev));
+
+ if (irq == -ENOENT)
+ irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
}
if (irq == -EPROBE_DEFER)
return irq;
--
2.11.0
^ permalink raw reply related
* [PATCH v5 6/7] i2c: core: Move ACPI gpio IRQ handling into i2c_acpi_get_irq
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
It makes sense to contain all the ACPI IRQ handling in a single helper
function.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-acpi.c | 3 +++
drivers/i2c/i2c-core-base.c | 3 ---
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index f752879772f64..e21e31d661ba7 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -167,6 +167,9 @@ int i2c_acpi_get_irq(struct acpi_device *adev)
acpi_dev_free_resource_list(&resource_list);
+ if (irq == -ENOENT)
+ irq = acpi_dev_gpio_irq_get(adev, 0);
+
return irq;
}
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 060d1a3a7ea4c..95a0380286c1c 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -328,9 +328,6 @@ static int i2c_device_probe(struct device *dev)
irq = of_irq_get(dev->of_node, 0);
} else if (ACPI_COMPANION(dev)) {
irq = i2c_acpi_get_irq(ACPI_COMPANION(dev));
-
- if (irq == -ENOENT)
- irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
}
if (irq == -EPROBE_DEFER)
return irq;
--
2.11.0
^ permalink raw reply related
* [Cluster-devel] [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
To: cluster-devel.redhat.com
In-Reply-To: <20190612004258.GX1871505@magnolia>
On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
The patch looks good to me. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
> fs/btrfs/ioctl.c | 13 +++++--------
> fs/efivarfs/file.c | 18 +++++++++++++-----
> fs/ext2/ioctl.c | 16 ++++------------
> fs/ext4/ioctl.c | 13 +++----------
> fs/f2fs/file.c | 7 ++++---
> fs/gfs2/file.c | 42 +++++++++++++++++++++++++++++-------------
> fs/hfsplus/ioctl.c | 21 ++++++++++++---------
> fs/inode.c | 17 +++++++++++++++++
> fs/jfs/ioctl.c | 22 +++++++---------------
> fs/nilfs2/ioctl.c | 9 ++-------
> fs/ocfs2/ioctl.c | 13 +++----------
> fs/reiserfs/ioctl.c | 10 ++++------
> fs/ubifs/ioctl.c | 13 +++----------
> include/linux/fs.h | 2 ++
> 14 files changed, 108 insertions(+), 108 deletions(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> struct btrfs_inode *binode = BTRFS_I(inode);
> struct btrfs_root *root = binode->root;
> struct btrfs_trans_handle *trans;
> - unsigned int fsflags;
> + unsigned int fsflags, old_fsflags;
> int ret;
> const char *comp = NULL;
> u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> inode_lock(inode);
>
> fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> - if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> - (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - ret = -EPERM;
> - goto out_unlock;
> - }
> - }
> + old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> + ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> + if (ret)
> + goto out_unlock;
>
> if (fsflags & FS_SYNC_FL)
> binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
> return size;
> }
>
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
> {
> - struct inode *inode = file->f_mapping->host;
> unsigned int i_flags;
> unsigned int flags = 0;
>
> i_flags = inode->i_flags;
> if (i_flags & S_IMMUTABLE)
> flags |= FS_IMMUTABLE_FL;
> + return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> + struct inode *inode = file->f_mapping->host;
> + unsigned int flags = efivarfs_getflags(inode);
>
> if (copy_to_user(arg, &flags, sizeof(flags)))
> return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> struct inode *inode = file->f_mapping->host;
> unsigned int flags;
> unsigned int i_flags = 0;
> + unsigned int oldflags = efivarfs_getflags(inode);
> int error;
>
> if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> if (flags & ~FS_IMMUTABLE_FL)
> return -EOPNOTSUPP;
>
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + error = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (error)
> + return error;
>
> if (flags & FS_IMMUTABLE_FL)
> i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> }
> oldflags = ei->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - ret = -EPERM;
> - goto setflags_out;
> - }
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
> /* The JOURNAL_DATA flag is modifiable only by root */
> jflag = flags & EXT4_JOURNAL_DATA_FL;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto flags_out;
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto flags_out;
>
> /*
> * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
> {
> struct f2fs_inode_info *fi = F2FS_I(inode);
> unsigned int oldflags;
> + int err;
>
> /* Is it quota file? Do not allow user to mess with it */
> if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>
> oldflags = fi->i_flags;
>
> - if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + return err;
>
> flags = flags & F2FS_FL_USER_MODIFIABLE;
> flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
> {FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
> };
>
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> + int i;
> + u32 fsflags = 0;
> +
> + if (S_ISDIR(inode->i_mode))
> + gfsflags &= ~GFS2_DIF_JDATA;
> + else
> + gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> + for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> + if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> + fsflags |= fsflag_gfs2flag[i].fsflag;
> + return fsflags;
> +}
> +
> static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> struct gfs2_holder gh;
> - int i, error;
> - u32 gfsflags, fsflags = 0;
> + int error;
> + u32 fsflags;
>
> gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
> error = gfs2_glock_nq(&gh);
> if (error)
> goto out_uninit;
>
> - gfsflags = ip->i_diskflags;
> - if (S_ISDIR(inode->i_mode))
> - gfsflags &= ~GFS2_DIF_JDATA;
> - else
> - gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> - for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> - if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> - fsflags |= fsflag_gfs2flag[i].fsflag;
> + fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>
> if (put_user(fsflags, ptr))
> error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
> * @filp: file pointer
> * @reqflags: The flags to set
> * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
> *
> */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> + const u32 fsflags)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> struct buffer_head *bh;
> struct gfs2_holder gh;
> int error;
> - u32 new_flags, flags;
> + u32 new_flags, flags, oldflags;
>
> error = mnt_want_write_file(filp);
> if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> if (error)
> goto out_drop_write;
>
> + oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> + error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> + if (error)
> + goto out;
> +
> error = -EACCES;
> if (!inode_owner_or_capable(inode))
> goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
> mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
> }
>
> - return do_gfs2_set_flags(filp, gfsflags, mask);
> + return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
> }
>
> static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
> return 0;
> }
>
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
> {
> - struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags = 0;
>
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> flags |= FS_APPEND_FL;
> if (hip->userflags & HFSPLUS_FLG_NODUMP)
> flags |= FS_NODUMP_FL;
> + return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> + struct inode *inode = file_inode(file);
> + unsigned int flags = hfsplus_getflags(inode);
>
> return put_user(flags, user_flags);
> }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
> struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags, new_fl = 0;
> + unsigned int oldflags = hfsplus_getflags(inode);
> int err = 0;
>
> err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>
> inode_lock(inode);
>
> - if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> - inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock_inode;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock_inode;
>
> /* don't silently ignore unsupported ext2 flags */
> if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
> return timespec64_trunc(now, inode->i_sb->s_time_gran);
> }
> EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> + /*
> + * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> + * the relevant capability.
> + *
> + * This test looks nicer. Thanks to Pauline Middelink
> + */
> + if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> + !capable(CAP_LINUX_IMMUTABLE))
> + return -EPERM;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> /* Lock against other parallel changes of flags */
> inode_lock(inode);
>
> - oldflags = jfs_inode->mode2;
> -
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - if ((oldflags & JFS_IMMUTABLE_FL) ||
> - ((flags ^ oldflags) &
> - (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - err = -EPERM;
> - goto setflags_out;
> - }
> + oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> + 0);
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & JFS_FL_USER_MODIFIABLE;
> - flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> + flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
> jfs_inode->mode2 = flags;
>
> jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>
> oldflags = NILFS_I(inode)->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> - * relevant capability.
> - */
> - ret = -EPERM;
> - if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> - !capable(CAP_LINUX_IMMUTABLE))
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret)
> goto out;
>
> ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
> flags = flags & mask;
> flags |= oldflags & ~mask;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - status = -EPERM;
> - if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> - (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto bail_unlock;
> - }
> + status = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (status)
> + goto bail_unlock;
>
> handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
> if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> err = -EPERM;
> goto setflags_out;
> }
> - if (((flags ^ REISERFS_I(inode)->
> - i_attrs) & (REISERFS_IMMUTABLE_FL |
> - REISERFS_APPEND_FL))
> - && !capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> + err = vfs_ioc_setflags_check(inode,
> + REISERFS_I(inode)->i_attrs,
> + flags);
> + if (err)
> goto setflags_out;
> - }
> if ((flags & REISERFS_NOTAIL_FL) &&
> S_ISREG(inode->i_mode)) {
> int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
> if (err)
> return err;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> mutex_lock(&ui->ui_mutex);
> oldflags = ubifs2ioctl(ui->flags);
> - if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock;
>
> ui->flags = ioctl2ubifs(flags);
> ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
> }
> #endif
>
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
> #endif /* _LINUX_FS_H */
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* [PATCH v5 7/7] i2c: core: Tidy up handling of init_irq
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
Only set init_irq during i2c_device_new and only handle client->irq on
the probe/remove paths.
Suggested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-base.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 95a0380286c1c..a3dbaefe4ca66 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -314,6 +314,8 @@ static int i2c_device_probe(struct device *dev)
driver = to_i2c_driver(dev->driver);
+ client->irq = client->init_irq;
+
if (!client->irq && !driver->disable_i2c_core_irq_mapping) {
int irq = -ENOENT;
@@ -424,7 +426,7 @@ static int i2c_device_remove(struct device *dev)
dev_pm_clear_wake_irq(&client->dev);
device_init_wakeup(&client->dev, false);
- client->irq = client->init_irq;
+ client->irq = 0;
if (client->flags & I2C_CLIENT_HOST_NOTIFY)
pm_runtime_put(&client->adapter->dev);
@@ -741,7 +743,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
if (!client->init_irq)
client->init_irq = i2c_dev_irq_from_resources(info->resources,
info->num_resources);
- client->irq = client->init_irq;
strlcpy(client->name, info->type, sizeof(client->name));
--
2.11.0
^ permalink raw reply related
* [Ocfs2-devel] [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
To: Darrick J. Wong
Cc: matthew.garrett, yuchao0, tytso, shaggy, ard.biesheuvel, josef,
clm, adilger.kernel, jk, jack, dsterba, jaegeuk, viro,
cluster-devel, jfs-discussion, linux-efi, reiserfs-devel,
linux-kernel, linux-f2fs-devel, linux-xfs, linux-nilfs, linux-mtd,
ocfs2-devel, linux-fsdevel, linux-ext4, linux-btrfs
In-Reply-To: <20190612004258.GX1871505@magnolia>
On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
The patch looks good to me. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
> fs/btrfs/ioctl.c | 13 +++++--------
> fs/efivarfs/file.c | 18 +++++++++++++-----
> fs/ext2/ioctl.c | 16 ++++------------
> fs/ext4/ioctl.c | 13 +++----------
> fs/f2fs/file.c | 7 ++++---
> fs/gfs2/file.c | 42 +++++++++++++++++++++++++++++-------------
> fs/hfsplus/ioctl.c | 21 ++++++++++++---------
> fs/inode.c | 17 +++++++++++++++++
> fs/jfs/ioctl.c | 22 +++++++---------------
> fs/nilfs2/ioctl.c | 9 ++-------
> fs/ocfs2/ioctl.c | 13 +++----------
> fs/reiserfs/ioctl.c | 10 ++++------
> fs/ubifs/ioctl.c | 13 +++----------
> include/linux/fs.h | 2 ++
> 14 files changed, 108 insertions(+), 108 deletions(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> struct btrfs_inode *binode = BTRFS_I(inode);
> struct btrfs_root *root = binode->root;
> struct btrfs_trans_handle *trans;
> - unsigned int fsflags;
> + unsigned int fsflags, old_fsflags;
> int ret;
> const char *comp = NULL;
> u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> inode_lock(inode);
>
> fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> - if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> - (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - ret = -EPERM;
> - goto out_unlock;
> - }
> - }
> + old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> + ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> + if (ret)
> + goto out_unlock;
>
> if (fsflags & FS_SYNC_FL)
> binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
> return size;
> }
>
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
> {
> - struct inode *inode = file->f_mapping->host;
> unsigned int i_flags;
> unsigned int flags = 0;
>
> i_flags = inode->i_flags;
> if (i_flags & S_IMMUTABLE)
> flags |= FS_IMMUTABLE_FL;
> + return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> + struct inode *inode = file->f_mapping->host;
> + unsigned int flags = efivarfs_getflags(inode);
>
> if (copy_to_user(arg, &flags, sizeof(flags)))
> return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> struct inode *inode = file->f_mapping->host;
> unsigned int flags;
> unsigned int i_flags = 0;
> + unsigned int oldflags = efivarfs_getflags(inode);
> int error;
>
> if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> if (flags & ~FS_IMMUTABLE_FL)
> return -EOPNOTSUPP;
>
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + error = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (error)
> + return error;
>
> if (flags & FS_IMMUTABLE_FL)
> i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> }
> oldflags = ei->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - ret = -EPERM;
> - goto setflags_out;
> - }
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
> /* The JOURNAL_DATA flag is modifiable only by root */
> jflag = flags & EXT4_JOURNAL_DATA_FL;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto flags_out;
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto flags_out;
>
> /*
> * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
> {
> struct f2fs_inode_info *fi = F2FS_I(inode);
> unsigned int oldflags;
> + int err;
>
> /* Is it quota file? Do not allow user to mess with it */
> if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>
> oldflags = fi->i_flags;
>
> - if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + return err;
>
> flags = flags & F2FS_FL_USER_MODIFIABLE;
> flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
> {FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
> };
>
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> + int i;
> + u32 fsflags = 0;
> +
> + if (S_ISDIR(inode->i_mode))
> + gfsflags &= ~GFS2_DIF_JDATA;
> + else
> + gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> + for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> + if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> + fsflags |= fsflag_gfs2flag[i].fsflag;
> + return fsflags;
> +}
> +
> static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> struct gfs2_holder gh;
> - int i, error;
> - u32 gfsflags, fsflags = 0;
> + int error;
> + u32 fsflags;
>
> gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
> error = gfs2_glock_nq(&gh);
> if (error)
> goto out_uninit;
>
> - gfsflags = ip->i_diskflags;
> - if (S_ISDIR(inode->i_mode))
> - gfsflags &= ~GFS2_DIF_JDATA;
> - else
> - gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> - for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> - if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> - fsflags |= fsflag_gfs2flag[i].fsflag;
> + fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>
> if (put_user(fsflags, ptr))
> error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
> * @filp: file pointer
> * @reqflags: The flags to set
> * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
> *
> */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> + const u32 fsflags)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> struct buffer_head *bh;
> struct gfs2_holder gh;
> int error;
> - u32 new_flags, flags;
> + u32 new_flags, flags, oldflags;
>
> error = mnt_want_write_file(filp);
> if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> if (error)
> goto out_drop_write;
>
> + oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> + error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> + if (error)
> + goto out;
> +
> error = -EACCES;
> if (!inode_owner_or_capable(inode))
> goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
> mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
> }
>
> - return do_gfs2_set_flags(filp, gfsflags, mask);
> + return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
> }
>
> static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
> return 0;
> }
>
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
> {
> - struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags = 0;
>
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> flags |= FS_APPEND_FL;
> if (hip->userflags & HFSPLUS_FLG_NODUMP)
> flags |= FS_NODUMP_FL;
> + return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> + struct inode *inode = file_inode(file);
> + unsigned int flags = hfsplus_getflags(inode);
>
> return put_user(flags, user_flags);
> }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
> struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags, new_fl = 0;
> + unsigned int oldflags = hfsplus_getflags(inode);
> int err = 0;
>
> err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>
> inode_lock(inode);
>
> - if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> - inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock_inode;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock_inode;
>
> /* don't silently ignore unsupported ext2 flags */
> if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
> return timespec64_trunc(now, inode->i_sb->s_time_gran);
> }
> EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> + /*
> + * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> + * the relevant capability.
> + *
> + * This test looks nicer. Thanks to Pauline Middelink
> + */
> + if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> + !capable(CAP_LINUX_IMMUTABLE))
> + return -EPERM;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> /* Lock against other parallel changes of flags */
> inode_lock(inode);
>
> - oldflags = jfs_inode->mode2;
> -
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - if ((oldflags & JFS_IMMUTABLE_FL) ||
> - ((flags ^ oldflags) &
> - (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - err = -EPERM;
> - goto setflags_out;
> - }
> + oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> + 0);
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & JFS_FL_USER_MODIFIABLE;
> - flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> + flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
> jfs_inode->mode2 = flags;
>
> jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>
> oldflags = NILFS_I(inode)->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> - * relevant capability.
> - */
> - ret = -EPERM;
> - if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> - !capable(CAP_LINUX_IMMUTABLE))
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret)
> goto out;
>
> ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
> flags = flags & mask;
> flags |= oldflags & ~mask;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - status = -EPERM;
> - if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> - (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto bail_unlock;
> - }
> + status = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (status)
> + goto bail_unlock;
>
> handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
> if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> err = -EPERM;
> goto setflags_out;
> }
> - if (((flags ^ REISERFS_I(inode)->
> - i_attrs) & (REISERFS_IMMUTABLE_FL |
> - REISERFS_APPEND_FL))
> - && !capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> + err = vfs_ioc_setflags_check(inode,
> + REISERFS_I(inode)->i_attrs,
> + flags);
> + if (err)
> goto setflags_out;
> - }
> if ((flags & REISERFS_NOTAIL_FL) &&
> S_ISREG(inode->i_mode)) {
> int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
> if (err)
> return err;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> mutex_lock(&ui->ui_mutex);
> oldflags = ubifs2ioctl(ui->flags);
> - if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock;
>
> ui->flags = ioctl2ubifs(flags);
> ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
> }
> #endif
>
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
> #endif /* _LINUX_FS_H */
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP Platform Tap Delays Setup
From: Ulf Hansson @ 2019-06-20 13:33 UTC (permalink / raw)
To: Manish Narani
Cc: Mark Rutland, DTML, Nava kishore Manne, linux-mmc@vger.kernel.org,
Adrian Hunter, Linux Kernel Mailing List, Jolly Shah, Rajan Vaja,
Rob Herring, Michal Simek, Olof Johansson, Linux ARM
In-Reply-To: <MN2PR02MB602935234A2A779B5A05CD63C1E40@MN2PR02MB6029.namprd02.prod.outlook.com>
On Thu, 20 Jun 2019 at 10:14, Manish Narani <MNARANI@xilinx.com> wrote:
>
> Hi Uffe,
>
>
> > -----Original Message-----
> > From: Ulf Hansson <ulf.hansson@linaro.org>
> > Sent: Wednesday, June 19, 2019 7:09 PM
> > To: Manish Narani <MNARANI@xilinx.com>
> > Cc: Michal Simek <michals@xilinx.com>; Rob Herring <robh+dt@kernel.org>;
> > Mark Rutland <mark.rutland@arm.com>; Adrian Hunter
> > <adrian.hunter@intel.com>; Rajan Vaja <RAJANV@xilinx.com>; Jolly Shah
> > <JOLLYS@xilinx.com>; Nava kishore Manne <navam@xilinx.com>; Olof
> > Johansson <olof@lixom.net>; linux-mmc@vger.kernel.org; DTML
> > <devicetree@vger.kernel.org>; Linux Kernel Mailing List <linux-
> > kernel@vger.kernel.org>; Linux ARM <linux-arm-kernel@lists.infradead.org>
> > Subject: Re: [PATCH 3/3] mmc: sdhci-of-arasan: Add support for ZynqMP
> > Platform Tap Delays Setup
> >
> > On Wed, 19 Jun 2019 at 10:40, Manish Narani <MNARANI@xilinx.com> wrote:
> > >
> > > Hi Uffe,
> > >
> > >
> > > > -----Original Message-----
> > > > From: Ulf Hansson <ulf.hansson@linaro.org>
> > > > Sent: Monday, June 17, 2019 5:51 PM
> > > [...]
> > > >
> > > > The "const struct zynqmp_eemi_ops *eemi_ops; should then be moved into
> > > > a clock provider specific struct, which is assigned when calling
> > > > sdhci_arasan_register_sdclk. I understand that all the clock data is
> > > > folded into struct sdhci_arasan_data today, but I think that should be
> > > > moved into a "sub-struct" for the clock specifics.
> > > >
> > > > Moreover, when registering the clock, we should convert from using
> > > > devm_clk_register() into devm_clk_hw_register() as the first one is
> > > > now deprecated.
> > >
> > > Just a query here:
> > > When we switch to using devm_clk_hw_register() here, it will register the
> > clk_hw and return int.
> > > Is there a way we can get the clk (related to the clk_hw registered) from the
> > > clock framework?
> > > I am asking this because we will need that clk pointer while calling
> > clk_set_phase() function.
> >
> > I assume devm_clk_get() should work fine?
>
> This clock does not come through ZynqMP Clock framework. We are initializing it in this 'sdhci-of-arasan' driver and getting only the clock name from "clock_output_names" property. So I think devm_clk_get() will not work here for our case.
Well, I guess you need to register an OF clock provider to allow the
clock lookup to work. Apologize, but I don't have the time, currently
to point you in the exact direction.
However, in principle, my point is, there should be no difference
whether the clock is registered via the "ZynqMP Clock framework" or
via the mmc driver. The *clk_get() thing need to work, otherwise I
consider the clock registration in the mmc driver to be a hack. If you
see what I mean.
> I have gone through the clock framework and I found one function which may be used to create clock from clock hw, that is ' clk_hw_create_clk()' which can be used from our driver, however this needs change in the clock framework as below :
>
> ---
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index aa51756..4dc69ff 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -3420,6 +3420,7 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
>
> return clk;
> }
> +EXPORT_SYMBOL_GPL(clk_hw_create_clk);
>
> static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
> {
> diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
> index d8400d6..2319899 100644
> --- a/drivers/clk/clk.h
> +++ b/drivers/clk/clk.h
> @@ -22,17 +22,9 @@ static inline struct clk_hw *of_clk_get_hw(struct device_node *np,
> struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id);
>
> #ifdef CONFIG_COMMON_CLK
> -struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> - const char *dev_id, const char *con_id);
> void __clk_put(struct clk *clk);
> #else
> /* All these casts to avoid ifdefs in clkdev... */
> -static inline struct clk *
> -clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> - const char *con_id)
> -{
> - return (struct clk *)hw;
> -}
> static struct clk_hw *__clk_get_hw(struct clk *clk)
> {
> return (struct clk_hw *)clk;
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index f689fc5..d3f60fe 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -18,6 +18,7 @@
>
> struct device;
> struct clk;
> +struct clk_hw;
> struct device_node;
> struct of_phandle_args;
>
> @@ -934,4 +935,15 @@ static inline struct clk *of_clk_get_from_provider(struct of_phandle_args *clksp
> }
> #endif
>
> +#ifdef CONFIG_COMMON_CLK
> +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
> + const char *dev_id, const char *con_id);
> +#else
> +static inline struct clk *
> +clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
> + const char *con_id)
> +{
> + return (struct clk *)hw;
> +}
> +#endif
> #endif
> ---
>
> This change should help other drivers (outside 'drivers/clk/') as well for getting the clock created from clk_hw.
> Is this fine to do?
I think this is the wrong approach, see why further above.
Kind regards
Uffe
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
To: Darrick J. Wong
Cc: matthew.garrett, yuchao0, tytso, shaggy, ard.biesheuvel, josef,
clm, adilger.kernel, jk, jack, dsterba, jaegeuk, viro,
cluster-devel, jfs-discussion, linux-efi, reiserfs-devel,
linux-kernel, linux-f2fs-devel, linux-xfs, linux-nilfs, linux-mtd,
ocfs2-devel, linux-fsdevel, linux-ext4, linux-btrfs
In-Reply-To: <20190612004258.GX1871505@magnolia>
On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
The patch looks good to me. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
> fs/btrfs/ioctl.c | 13 +++++--------
> fs/efivarfs/file.c | 18 +++++++++++++-----
> fs/ext2/ioctl.c | 16 ++++------------
> fs/ext4/ioctl.c | 13 +++----------
> fs/f2fs/file.c | 7 ++++---
> fs/gfs2/file.c | 42 +++++++++++++++++++++++++++++-------------
> fs/hfsplus/ioctl.c | 21 ++++++++++++---------
> fs/inode.c | 17 +++++++++++++++++
> fs/jfs/ioctl.c | 22 +++++++---------------
> fs/nilfs2/ioctl.c | 9 ++-------
> fs/ocfs2/ioctl.c | 13 +++----------
> fs/reiserfs/ioctl.c | 10 ++++------
> fs/ubifs/ioctl.c | 13 +++----------
> include/linux/fs.h | 2 ++
> 14 files changed, 108 insertions(+), 108 deletions(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> struct btrfs_inode *binode = BTRFS_I(inode);
> struct btrfs_root *root = binode->root;
> struct btrfs_trans_handle *trans;
> - unsigned int fsflags;
> + unsigned int fsflags, old_fsflags;
> int ret;
> const char *comp = NULL;
> u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> inode_lock(inode);
>
> fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> - if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> - (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - ret = -EPERM;
> - goto out_unlock;
> - }
> - }
> + old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> + ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> + if (ret)
> + goto out_unlock;
>
> if (fsflags & FS_SYNC_FL)
> binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
> return size;
> }
>
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
> {
> - struct inode *inode = file->f_mapping->host;
> unsigned int i_flags;
> unsigned int flags = 0;
>
> i_flags = inode->i_flags;
> if (i_flags & S_IMMUTABLE)
> flags |= FS_IMMUTABLE_FL;
> + return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> + struct inode *inode = file->f_mapping->host;
> + unsigned int flags = efivarfs_getflags(inode);
>
> if (copy_to_user(arg, &flags, sizeof(flags)))
> return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> struct inode *inode = file->f_mapping->host;
> unsigned int flags;
> unsigned int i_flags = 0;
> + unsigned int oldflags = efivarfs_getflags(inode);
> int error;
>
> if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> if (flags & ~FS_IMMUTABLE_FL)
> return -EOPNOTSUPP;
>
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + error = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (error)
> + return error;
>
> if (flags & FS_IMMUTABLE_FL)
> i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> }
> oldflags = ei->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - ret = -EPERM;
> - goto setflags_out;
> - }
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
> /* The JOURNAL_DATA flag is modifiable only by root */
> jflag = flags & EXT4_JOURNAL_DATA_FL;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto flags_out;
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto flags_out;
>
> /*
> * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
> {
> struct f2fs_inode_info *fi = F2FS_I(inode);
> unsigned int oldflags;
> + int err;
>
> /* Is it quota file? Do not allow user to mess with it */
> if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>
> oldflags = fi->i_flags;
>
> - if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + return err;
>
> flags = flags & F2FS_FL_USER_MODIFIABLE;
> flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
> {FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
> };
>
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> + int i;
> + u32 fsflags = 0;
> +
> + if (S_ISDIR(inode->i_mode))
> + gfsflags &= ~GFS2_DIF_JDATA;
> + else
> + gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> + for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> + if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> + fsflags |= fsflag_gfs2flag[i].fsflag;
> + return fsflags;
> +}
> +
> static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> struct gfs2_holder gh;
> - int i, error;
> - u32 gfsflags, fsflags = 0;
> + int error;
> + u32 fsflags;
>
> gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
> error = gfs2_glock_nq(&gh);
> if (error)
> goto out_uninit;
>
> - gfsflags = ip->i_diskflags;
> - if (S_ISDIR(inode->i_mode))
> - gfsflags &= ~GFS2_DIF_JDATA;
> - else
> - gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> - for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> - if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> - fsflags |= fsflag_gfs2flag[i].fsflag;
> + fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>
> if (put_user(fsflags, ptr))
> error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
> * @filp: file pointer
> * @reqflags: The flags to set
> * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
> *
> */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> + const u32 fsflags)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> struct buffer_head *bh;
> struct gfs2_holder gh;
> int error;
> - u32 new_flags, flags;
> + u32 new_flags, flags, oldflags;
>
> error = mnt_want_write_file(filp);
> if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> if (error)
> goto out_drop_write;
>
> + oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> + error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> + if (error)
> + goto out;
> +
> error = -EACCES;
> if (!inode_owner_or_capable(inode))
> goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
> mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
> }
>
> - return do_gfs2_set_flags(filp, gfsflags, mask);
> + return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
> }
>
> static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
> return 0;
> }
>
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
> {
> - struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags = 0;
>
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> flags |= FS_APPEND_FL;
> if (hip->userflags & HFSPLUS_FLG_NODUMP)
> flags |= FS_NODUMP_FL;
> + return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> + struct inode *inode = file_inode(file);
> + unsigned int flags = hfsplus_getflags(inode);
>
> return put_user(flags, user_flags);
> }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
> struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags, new_fl = 0;
> + unsigned int oldflags = hfsplus_getflags(inode);
> int err = 0;
>
> err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>
> inode_lock(inode);
>
> - if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> - inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock_inode;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock_inode;
>
> /* don't silently ignore unsupported ext2 flags */
> if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
> return timespec64_trunc(now, inode->i_sb->s_time_gran);
> }
> EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> + /*
> + * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> + * the relevant capability.
> + *
> + * This test looks nicer. Thanks to Pauline Middelink
> + */
> + if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> + !capable(CAP_LINUX_IMMUTABLE))
> + return -EPERM;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> /* Lock against other parallel changes of flags */
> inode_lock(inode);
>
> - oldflags = jfs_inode->mode2;
> -
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - if ((oldflags & JFS_IMMUTABLE_FL) ||
> - ((flags ^ oldflags) &
> - (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - err = -EPERM;
> - goto setflags_out;
> - }
> + oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> + 0);
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & JFS_FL_USER_MODIFIABLE;
> - flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> + flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
> jfs_inode->mode2 = flags;
>
> jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>
> oldflags = NILFS_I(inode)->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> - * relevant capability.
> - */
> - ret = -EPERM;
> - if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> - !capable(CAP_LINUX_IMMUTABLE))
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret)
> goto out;
>
> ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
> flags = flags & mask;
> flags |= oldflags & ~mask;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - status = -EPERM;
> - if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> - (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto bail_unlock;
> - }
> + status = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (status)
> + goto bail_unlock;
>
> handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
> if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> err = -EPERM;
> goto setflags_out;
> }
> - if (((flags ^ REISERFS_I(inode)->
> - i_attrs) & (REISERFS_IMMUTABLE_FL |
> - REISERFS_APPEND_FL))
> - && !capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> + err = vfs_ioc_setflags_check(inode,
> + REISERFS_I(inode)->i_attrs,
> + flags);
> + if (err)
> goto setflags_out;
> - }
> if ((flags & REISERFS_NOTAIL_FL) &&
> S_ISREG(inode->i_mode)) {
> int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
> if (err)
> return err;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> mutex_lock(&ui->ui_mutex);
> oldflags = ubifs2ioctl(ui->flags);
> - if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock;
>
> ui->flags = ioctl2ubifs(flags);
> ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
> }
> #endif
>
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
> #endif /* _LINUX_FS_H */
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [f2fs-dev] [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
To: Darrick J. Wong
Cc: shaggy, jfs-discussion, linux-efi, linux-btrfs, clm,
adilger.kernel, matthew.garrett, linux-nilfs, cluster-devel,
linux-ext4, josef, reiserfs-devel, viro, dsterba, jaegeuk, tytso,
ard.biesheuvel, linux-kernel, linux-f2fs-devel, linux-xfs, jk,
jack, linux-fsdevel, linux-mtd, ocfs2-devel
In-Reply-To: <20190612004258.GX1871505@magnolia>
On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
The patch looks good to me. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
> fs/btrfs/ioctl.c | 13 +++++--------
> fs/efivarfs/file.c | 18 +++++++++++++-----
> fs/ext2/ioctl.c | 16 ++++------------
> fs/ext4/ioctl.c | 13 +++----------
> fs/f2fs/file.c | 7 ++++---
> fs/gfs2/file.c | 42 +++++++++++++++++++++++++++++-------------
> fs/hfsplus/ioctl.c | 21 ++++++++++++---------
> fs/inode.c | 17 +++++++++++++++++
> fs/jfs/ioctl.c | 22 +++++++---------------
> fs/nilfs2/ioctl.c | 9 ++-------
> fs/ocfs2/ioctl.c | 13 +++----------
> fs/reiserfs/ioctl.c | 10 ++++------
> fs/ubifs/ioctl.c | 13 +++----------
> include/linux/fs.h | 2 ++
> 14 files changed, 108 insertions(+), 108 deletions(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> struct btrfs_inode *binode = BTRFS_I(inode);
> struct btrfs_root *root = binode->root;
> struct btrfs_trans_handle *trans;
> - unsigned int fsflags;
> + unsigned int fsflags, old_fsflags;
> int ret;
> const char *comp = NULL;
> u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> inode_lock(inode);
>
> fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> - if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> - (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - ret = -EPERM;
> - goto out_unlock;
> - }
> - }
> + old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> + ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> + if (ret)
> + goto out_unlock;
>
> if (fsflags & FS_SYNC_FL)
> binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
> return size;
> }
>
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
> {
> - struct inode *inode = file->f_mapping->host;
> unsigned int i_flags;
> unsigned int flags = 0;
>
> i_flags = inode->i_flags;
> if (i_flags & S_IMMUTABLE)
> flags |= FS_IMMUTABLE_FL;
> + return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> + struct inode *inode = file->f_mapping->host;
> + unsigned int flags = efivarfs_getflags(inode);
>
> if (copy_to_user(arg, &flags, sizeof(flags)))
> return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> struct inode *inode = file->f_mapping->host;
> unsigned int flags;
> unsigned int i_flags = 0;
> + unsigned int oldflags = efivarfs_getflags(inode);
> int error;
>
> if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> if (flags & ~FS_IMMUTABLE_FL)
> return -EOPNOTSUPP;
>
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + error = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (error)
> + return error;
>
> if (flags & FS_IMMUTABLE_FL)
> i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> }
> oldflags = ei->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - ret = -EPERM;
> - goto setflags_out;
> - }
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
> /* The JOURNAL_DATA flag is modifiable only by root */
> jflag = flags & EXT4_JOURNAL_DATA_FL;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto flags_out;
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto flags_out;
>
> /*
> * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
> {
> struct f2fs_inode_info *fi = F2FS_I(inode);
> unsigned int oldflags;
> + int err;
>
> /* Is it quota file? Do not allow user to mess with it */
> if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>
> oldflags = fi->i_flags;
>
> - if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + return err;
>
> flags = flags & F2FS_FL_USER_MODIFIABLE;
> flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
> {FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
> };
>
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> + int i;
> + u32 fsflags = 0;
> +
> + if (S_ISDIR(inode->i_mode))
> + gfsflags &= ~GFS2_DIF_JDATA;
> + else
> + gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> + for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> + if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> + fsflags |= fsflag_gfs2flag[i].fsflag;
> + return fsflags;
> +}
> +
> static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> struct gfs2_holder gh;
> - int i, error;
> - u32 gfsflags, fsflags = 0;
> + int error;
> + u32 fsflags;
>
> gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
> error = gfs2_glock_nq(&gh);
> if (error)
> goto out_uninit;
>
> - gfsflags = ip->i_diskflags;
> - if (S_ISDIR(inode->i_mode))
> - gfsflags &= ~GFS2_DIF_JDATA;
> - else
> - gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> - for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> - if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> - fsflags |= fsflag_gfs2flag[i].fsflag;
> + fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>
> if (put_user(fsflags, ptr))
> error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
> * @filp: file pointer
> * @reqflags: The flags to set
> * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
> *
> */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> + const u32 fsflags)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> struct buffer_head *bh;
> struct gfs2_holder gh;
> int error;
> - u32 new_flags, flags;
> + u32 new_flags, flags, oldflags;
>
> error = mnt_want_write_file(filp);
> if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> if (error)
> goto out_drop_write;
>
> + oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> + error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> + if (error)
> + goto out;
> +
> error = -EACCES;
> if (!inode_owner_or_capable(inode))
> goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
> mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
> }
>
> - return do_gfs2_set_flags(filp, gfsflags, mask);
> + return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
> }
>
> static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
> return 0;
> }
>
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
> {
> - struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags = 0;
>
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> flags |= FS_APPEND_FL;
> if (hip->userflags & HFSPLUS_FLG_NODUMP)
> flags |= FS_NODUMP_FL;
> + return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> + struct inode *inode = file_inode(file);
> + unsigned int flags = hfsplus_getflags(inode);
>
> return put_user(flags, user_flags);
> }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
> struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags, new_fl = 0;
> + unsigned int oldflags = hfsplus_getflags(inode);
> int err = 0;
>
> err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>
> inode_lock(inode);
>
> - if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> - inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock_inode;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock_inode;
>
> /* don't silently ignore unsupported ext2 flags */
> if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
> return timespec64_trunc(now, inode->i_sb->s_time_gran);
> }
> EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> + /*
> + * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> + * the relevant capability.
> + *
> + * This test looks nicer. Thanks to Pauline Middelink
> + */
> + if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> + !capable(CAP_LINUX_IMMUTABLE))
> + return -EPERM;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> /* Lock against other parallel changes of flags */
> inode_lock(inode);
>
> - oldflags = jfs_inode->mode2;
> -
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - if ((oldflags & JFS_IMMUTABLE_FL) ||
> - ((flags ^ oldflags) &
> - (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - err = -EPERM;
> - goto setflags_out;
> - }
> + oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> + 0);
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & JFS_FL_USER_MODIFIABLE;
> - flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> + flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
> jfs_inode->mode2 = flags;
>
> jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>
> oldflags = NILFS_I(inode)->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> - * relevant capability.
> - */
> - ret = -EPERM;
> - if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> - !capable(CAP_LINUX_IMMUTABLE))
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret)
> goto out;
>
> ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
> flags = flags & mask;
> flags |= oldflags & ~mask;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - status = -EPERM;
> - if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> - (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto bail_unlock;
> - }
> + status = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (status)
> + goto bail_unlock;
>
> handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
> if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> err = -EPERM;
> goto setflags_out;
> }
> - if (((flags ^ REISERFS_I(inode)->
> - i_attrs) & (REISERFS_IMMUTABLE_FL |
> - REISERFS_APPEND_FL))
> - && !capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> + err = vfs_ioc_setflags_check(inode,
> + REISERFS_I(inode)->i_attrs,
> + flags);
> + if (err)
> goto setflags_out;
> - }
> if ((flags & REISERFS_NOTAIL_FL) &&
> S_ISREG(inode->i_mode)) {
> int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
> if (err)
> return err;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> mutex_lock(&ui->ui_mutex);
> oldflags = ubifs2ioctl(ui->flags);
> - if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock;
>
> ui->flags = ioctl2ubifs(flags);
> ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
> }
> #endif
>
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
> #endif /* _LINUX_FS_H */
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply
* Re: [PATCH v2 1/4] vfs: create a generic checking function for FS_IOC_SETFLAGS
From: Jan Kara @ 2019-06-20 13:34 UTC (permalink / raw)
To: Darrick J. Wong
Cc: shaggy, jfs-discussion, linux-efi, linux-btrfs, yuchao0, clm,
adilger.kernel, matthew.garrett, linux-nilfs, cluster-devel,
linux-ext4, josef, reiserfs-devel, viro, dsterba, jaegeuk, tytso,
ard.biesheuvel, linux-kernel, linux-f2fs-devel, linux-xfs, jk,
jack, linux-fsdevel, linux-mtd, ocfs2-devel
In-Reply-To: <20190612004258.GX1871505@magnolia>
On Tue 11-06-19 17:42:58, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> Create a generic checking function for the incoming FS_IOC_SETFLAGS flag
> values so that we can standardize the implementations that follow ext4's
> flag values.
>
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
The patch looks good to me. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> v2: fix jfs locking and remove its opencoded flags check
> ---
> fs/btrfs/ioctl.c | 13 +++++--------
> fs/efivarfs/file.c | 18 +++++++++++++-----
> fs/ext2/ioctl.c | 16 ++++------------
> fs/ext4/ioctl.c | 13 +++----------
> fs/f2fs/file.c | 7 ++++---
> fs/gfs2/file.c | 42 +++++++++++++++++++++++++++++-------------
> fs/hfsplus/ioctl.c | 21 ++++++++++++---------
> fs/inode.c | 17 +++++++++++++++++
> fs/jfs/ioctl.c | 22 +++++++---------------
> fs/nilfs2/ioctl.c | 9 ++-------
> fs/ocfs2/ioctl.c | 13 +++----------
> fs/reiserfs/ioctl.c | 10 ++++------
> fs/ubifs/ioctl.c | 13 +++----------
> include/linux/fs.h | 2 ++
> 14 files changed, 108 insertions(+), 108 deletions(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 6dafa857bbb9..f408aa93b0cf 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -187,7 +187,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> struct btrfs_inode *binode = BTRFS_I(inode);
> struct btrfs_root *root = binode->root;
> struct btrfs_trans_handle *trans;
> - unsigned int fsflags;
> + unsigned int fsflags, old_fsflags;
> int ret;
> const char *comp = NULL;
> u32 binode_flags = binode->flags;
> @@ -212,13 +212,10 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
> inode_lock(inode);
>
> fsflags = btrfs_mask_fsflags_for_type(inode, fsflags);
> - if ((fsflags ^ btrfs_inode_flags_to_fsflags(binode->flags)) &
> - (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - ret = -EPERM;
> - goto out_unlock;
> - }
> - }
> + old_fsflags = btrfs_inode_flags_to_fsflags(binode->flags);
> + ret = vfs_ioc_setflags_check(inode, old_fsflags, fsflags);
> + if (ret)
> + goto out_unlock;
>
> if (fsflags & FS_SYNC_FL)
> binode_flags |= BTRFS_INODE_SYNC;
> diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
> index 8e568428c88b..f4f6c1bec132 100644
> --- a/fs/efivarfs/file.c
> +++ b/fs/efivarfs/file.c
> @@ -110,16 +110,22 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
> return size;
> }
>
> -static int
> -efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +static inline unsigned int efivarfs_getflags(struct inode *inode)
> {
> - struct inode *inode = file->f_mapping->host;
> unsigned int i_flags;
> unsigned int flags = 0;
>
> i_flags = inode->i_flags;
> if (i_flags & S_IMMUTABLE)
> flags |= FS_IMMUTABLE_FL;
> + return flags;
> +}
> +
> +static int
> +efivarfs_ioc_getxflags(struct file *file, void __user *arg)
> +{
> + struct inode *inode = file->f_mapping->host;
> + unsigned int flags = efivarfs_getflags(inode);
>
> if (copy_to_user(arg, &flags, sizeof(flags)))
> return -EFAULT;
> @@ -132,6 +138,7 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> struct inode *inode = file->f_mapping->host;
> unsigned int flags;
> unsigned int i_flags = 0;
> + unsigned int oldflags = efivarfs_getflags(inode);
> int error;
>
> if (!inode_owner_or_capable(inode))
> @@ -143,8 +150,9 @@ efivarfs_ioc_setxflags(struct file *file, void __user *arg)
> if (flags & ~FS_IMMUTABLE_FL)
> return -EOPNOTSUPP;
>
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + error = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (error)
> + return error;
>
> if (flags & FS_IMMUTABLE_FL)
> i_flags |= S_IMMUTABLE;
> diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
> index 0367c0039e68..88b3b9720023 100644
> --- a/fs/ext2/ioctl.c
> +++ b/fs/ext2/ioctl.c
> @@ -60,18 +60,10 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> }
> oldflags = ei->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - ret = -EPERM;
> - goto setflags_out;
> - }
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & EXT2_FL_USER_MODIFIABLE;
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index e486e49b31ed..5126ee351a84 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -289,16 +289,9 @@ static int ext4_ioctl_setflags(struct inode *inode,
> /* The JOURNAL_DATA flag is modifiable only by root */
> jflag = flags & EXT4_JOURNAL_DATA_FL;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - *
> - * This test looks nicer. Thanks to Pauline Middelink
> - */
> - if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto flags_out;
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto flags_out;
>
> /*
> * The JOURNAL_DATA flag can only be changed by
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 45b45f37d347..a969d5497e03 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1670,6 +1670,7 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
> {
> struct f2fs_inode_info *fi = F2FS_I(inode);
> unsigned int oldflags;
> + int err;
>
> /* Is it quota file? Do not allow user to mess with it */
> if (IS_NOQUOTA(inode))
> @@ -1679,9 +1680,9 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
>
> oldflags = fi->i_flags;
>
> - if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - return -EPERM;
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + return err;
>
> flags = flags & F2FS_FL_USER_MODIFIABLE;
> flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
> diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
> index d174b1f8fd08..99f53cf699c6 100644
> --- a/fs/gfs2/file.c
> +++ b/fs/gfs2/file.c
> @@ -136,27 +136,36 @@ static struct {
> {FS_JOURNAL_DATA_FL, GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA},
> };
>
> +static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags)
> +{
> + int i;
> + u32 fsflags = 0;
> +
> + if (S_ISDIR(inode->i_mode))
> + gfsflags &= ~GFS2_DIF_JDATA;
> + else
> + gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> +
> + for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> + if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> + fsflags |= fsflag_gfs2flag[i].fsflag;
> + return fsflags;
> +}
> +
> static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> struct gfs2_holder gh;
> - int i, error;
> - u32 gfsflags, fsflags = 0;
> + int error;
> + u32 fsflags;
>
> gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
> error = gfs2_glock_nq(&gh);
> if (error)
> goto out_uninit;
>
> - gfsflags = ip->i_diskflags;
> - if (S_ISDIR(inode->i_mode))
> - gfsflags &= ~GFS2_DIF_JDATA;
> - else
> - gfsflags &= ~GFS2_DIF_INHERIT_JDATA;
> - for (i = 0; i < ARRAY_SIZE(fsflag_gfs2flag); i++)
> - if (gfsflags & fsflag_gfs2flag[i].gfsflag)
> - fsflags |= fsflag_gfs2flag[i].fsflag;
> + fsflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
>
> if (put_user(fsflags, ptr))
> error = -EFAULT;
> @@ -200,9 +209,11 @@ void gfs2_set_inode_flags(struct inode *inode)
> * @filp: file pointer
> * @reqflags: The flags to set
> * @mask: Indicates which flags are valid
> + * @fsflags: The FS_* inode flags passed in
> *
> */
> -static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> +static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask,
> + const u32 fsflags)
> {
> struct inode *inode = file_inode(filp);
> struct gfs2_inode *ip = GFS2_I(inode);
> @@ -210,7 +221,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> struct buffer_head *bh;
> struct gfs2_holder gh;
> int error;
> - u32 new_flags, flags;
> + u32 new_flags, flags, oldflags;
>
> error = mnt_want_write_file(filp);
> if (error)
> @@ -220,6 +231,11 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
> if (error)
> goto out_drop_write;
>
> + oldflags = gfs2_gfsflags_to_fsflags(inode, ip->i_diskflags);
> + error = vfs_ioc_setflags_check(inode, oldflags, fsflags);
> + if (error)
> + goto out;
> +
> error = -EACCES;
> if (!inode_owner_or_capable(inode))
> goto out;
> @@ -308,7 +324,7 @@ static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
> mask &= ~(GFS2_DIF_TOPDIR | GFS2_DIF_INHERIT_JDATA);
> }
>
> - return do_gfs2_set_flags(filp, gfsflags, mask);
> + return do_gfs2_set_flags(filp, gfsflags, mask, fsflags);
> }
>
> static int gfs2_getlabel(struct file *filp, char __user *label)
> diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c
> index 5e6502ef7415..862a3c9481d7 100644
> --- a/fs/hfsplus/ioctl.c
> +++ b/fs/hfsplus/ioctl.c
> @@ -57,9 +57,8 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
> return 0;
> }
>
> -static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +static inline unsigned int hfsplus_getflags(struct inode *inode)
> {
> - struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags = 0;
>
> @@ -69,6 +68,13 @@ static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> flags |= FS_APPEND_FL;
> if (hip->userflags & HFSPLUS_FLG_NODUMP)
> flags |= FS_NODUMP_FL;
> + return flags;
> +}
> +
> +static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
> +{
> + struct inode *inode = file_inode(file);
> + unsigned int flags = hfsplus_getflags(inode);
>
> return put_user(flags, user_flags);
> }
> @@ -78,6 +84,7 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
> struct inode *inode = file_inode(file);
> struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
> unsigned int flags, new_fl = 0;
> + unsigned int oldflags = hfsplus_getflags(inode);
> int err = 0;
>
> err = mnt_want_write_file(file);
> @@ -96,13 +103,9 @@ static int hfsplus_ioctl_setflags(struct file *file, int __user *user_flags)
>
> inode_lock(inode);
>
> - if ((flags & (FS_IMMUTABLE_FL|FS_APPEND_FL)) ||
> - inode->i_flags & (S_IMMUTABLE|S_APPEND)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock_inode;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock_inode;
>
> /* don't silently ignore unsupported ext2 flags */
> if (flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL)) {
> diff --git a/fs/inode.c b/fs/inode.c
> index df6542ec3b88..0ce60b720608 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2170,3 +2170,20 @@ struct timespec64 current_time(struct inode *inode)
> return timespec64_trunc(now, inode->i_sb->s_time_gran);
> }
> EXPORT_SYMBOL(current_time);
> +
> +/* Generic function to check FS_IOC_SETFLAGS values. */
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags)
> +{
> + /*
> + * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> + * the relevant capability.
> + *
> + * This test looks nicer. Thanks to Pauline Middelink
> + */
> + if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL) &&
> + !capable(CAP_LINUX_IMMUTABLE))
> + return -EPERM;
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(vfs_ioc_setflags_check);
> diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c
> index ba34dae8bd9f..b485c2d7620f 100644
> --- a/fs/jfs/ioctl.c
> +++ b/fs/jfs/ioctl.c
> @@ -98,24 +98,16 @@ long jfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> /* Lock against other parallel changes of flags */
> inode_lock(inode);
>
> - oldflags = jfs_inode->mode2;
> -
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - if ((oldflags & JFS_IMMUTABLE_FL) ||
> - ((flags ^ oldflags) &
> - (JFS_APPEND_FL | JFS_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - inode_unlock(inode);
> - err = -EPERM;
> - goto setflags_out;
> - }
> + oldflags = jfs_map_ext2(jfs_inode->mode2 & JFS_FL_USER_VISIBLE,
> + 0);
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err) {
> + inode_unlock(inode);
> + goto setflags_out;
> }
>
> flags = flags & JFS_FL_USER_MODIFIABLE;
> - flags |= oldflags & ~JFS_FL_USER_MODIFIABLE;
> + flags |= jfs_inode->mode2 & ~JFS_FL_USER_MODIFIABLE;
> jfs_inode->mode2 = flags;
>
> jfs_set_inode_flags(inode);
> diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
> index 9b96d79eea6c..0632336d2515 100644
> --- a/fs/nilfs2/ioctl.c
> +++ b/fs/nilfs2/ioctl.c
> @@ -148,13 +148,8 @@ static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
>
> oldflags = NILFS_I(inode)->i_flags;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
> - * relevant capability.
> - */
> - ret = -EPERM;
> - if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
> - !capable(CAP_LINUX_IMMUTABLE))
> + ret = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (ret)
> goto out;
>
> ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
> diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c
> index 994726ada857..467a2faf0305 100644
> --- a/fs/ocfs2/ioctl.c
> +++ b/fs/ocfs2/ioctl.c
> @@ -106,16 +106,9 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
> flags = flags & mask;
> flags |= oldflags & ~mask;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> - status = -EPERM;
> - if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
> - (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
> - if (!capable(CAP_LINUX_IMMUTABLE))
> - goto bail_unlock;
> - }
> + status = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (status)
> + goto bail_unlock;
>
> handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
> if (IS_ERR(handle)) {
> diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
> index acbbaf7a0bb2..92bcb1ecd994 100644
> --- a/fs/reiserfs/ioctl.c
> +++ b/fs/reiserfs/ioctl.c
> @@ -74,13 +74,11 @@ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> err = -EPERM;
> goto setflags_out;
> }
> - if (((flags ^ REISERFS_I(inode)->
> - i_attrs) & (REISERFS_IMMUTABLE_FL |
> - REISERFS_APPEND_FL))
> - && !capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> + err = vfs_ioc_setflags_check(inode,
> + REISERFS_I(inode)->i_attrs,
> + flags);
> + if (err)
> goto setflags_out;
> - }
> if ((flags & REISERFS_NOTAIL_FL) &&
> S_ISREG(inode->i_mode)) {
> int result;
> diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
> index 4f1a397fda69..bdea836fc38b 100644
> --- a/fs/ubifs/ioctl.c
> +++ b/fs/ubifs/ioctl.c
> @@ -107,18 +107,11 @@ static int setflags(struct inode *inode, int flags)
> if (err)
> return err;
>
> - /*
> - * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> - * the relevant capability.
> - */
> mutex_lock(&ui->ui_mutex);
> oldflags = ubifs2ioctl(ui->flags);
> - if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
> - if (!capable(CAP_LINUX_IMMUTABLE)) {
> - err = -EPERM;
> - goto out_unlock;
> - }
> - }
> + err = vfs_ioc_setflags_check(inode, oldflags, flags);
> + if (err)
> + goto out_unlock;
>
> ui->flags = ioctl2ubifs(flags);
> ubifs_set_inode_flags(inode);
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index f7fdfe93e25d..1825d055808c 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -3546,4 +3546,6 @@ static inline struct sock *io_uring_get_socket(struct file *file)
> }
> #endif
>
> +int vfs_ioc_setflags_check(struct inode *inode, int oldflags, int flags);
> +
> #endif /* _LINUX_FS_H */
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply
* [PATCH v5 1/7] i2c: core: Allow whole core to use i2c_dev_irq_from_resources
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
Remove the static from i2c_dev_irq_from _resources so that other parts
of the core code can use this helper function.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-base.c | 4 ++--
drivers/i2c/i2c-core.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 2569e97f9bf35..8a303246d534b 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -679,8 +679,8 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
i2c_encode_flags_to_addr(client));
}
-static int i2c_dev_irq_from_resources(const struct resource *resources,
- unsigned int num_resources)
+int i2c_dev_irq_from_resources(const struct resource *resources,
+ unsigned int num_resources)
{
struct irq_data *irqd;
int i;
diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h
index 851c11b4c0f3a..2a3b28bf826b1 100644
--- a/drivers/i2c/i2c-core.h
+++ b/drivers/i2c/i2c-core.h
@@ -19,6 +19,8 @@ extern struct list_head __i2c_board_list;
extern int __i2c_first_dynamic_bus_num;
int i2c_check_7bit_addr_validity_strict(unsigned short addr);
+int i2c_dev_irq_from_resources(const struct resource *resources,
+ unsigned int num_resources);
/*
* We only allow atomic transfers for very late communication, e.g. to send
--
2.11.0
^ permalink raw reply related
* [PATCH v5 3/7] i2c: acpi: Factor out getting the IRQ from ACPI
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
In preparation for future refactoring factor out the fetch of the IRQ
into its own helper function.
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-acpi.c | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 47d5b1c5ec9e0..7d4d66ba752d4 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -144,14 +144,30 @@ static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
return 1; /* No need to add resource to the list */
}
+static int i2c_acpi_get_irq(struct acpi_device *adev)
+{
+ struct list_head resource_list;
+ int irq = -ENOENT;
+ int ret;
+
+ INIT_LIST_HEAD(&resource_list);
+
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ i2c_acpi_add_resource, &irq);
+ if (ret < 0)
+ return -EINVAL;
+
+ acpi_dev_free_resource_list(&resource_list);
+
+ return irq;
+}
+
static int i2c_acpi_get_info(struct acpi_device *adev,
struct i2c_board_info *info,
struct i2c_adapter *adapter,
acpi_handle *adapter_handle)
{
- struct list_head resource_list;
struct i2c_acpi_lookup lookup;
- int irq = -ENOENT;
int ret;
memset(&lookup, 0, sizeof(lookup));
@@ -182,16 +198,9 @@ static int i2c_acpi_get_info(struct acpi_device *adev,
*adapter_handle = lookup.adapter_handle;
/* Then fill IRQ number if any */
- INIT_LIST_HEAD(&resource_list);
- ret = acpi_dev_get_resources(adev, &resource_list,
- i2c_acpi_add_resource, &irq);
- if (ret < 0)
- return -EINVAL;
-
- if (irq > 0)
- info->irq = irq;
-
- acpi_dev_free_resource_list(&resource_list);
+ ret = i2c_acpi_get_irq(adev);
+ if (ret > 0)
+ info->irq = ret;
acpi_set_modalias(adev, dev_name(&adev->dev), info->type,
sizeof(info->type));
--
2.11.0
^ permalink raw reply related
* [PATCH v5 7/7] i2c: core: Tidy up handling of init_irq
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
In-Reply-To: <20190620133420.4632-1-ckeepax@opensource.cirrus.com>
Only set init_irq during i2c_device_new and only handle client->irq on
the probe/remove paths.
Suggested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
No changes since v4.
Thanks,
Charles
drivers/i2c/i2c-core-base.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 95a0380286c1c..a3dbaefe4ca66 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -314,6 +314,8 @@ static int i2c_device_probe(struct device *dev)
driver = to_i2c_driver(dev->driver);
+ client->irq = client->init_irq;
+
if (!client->irq && !driver->disable_i2c_core_irq_mapping) {
int irq = -ENOENT;
@@ -424,7 +426,7 @@ static int i2c_device_remove(struct device *dev)
dev_pm_clear_wake_irq(&client->dev);
device_init_wakeup(&client->dev, false);
- client->irq = client->init_irq;
+ client->irq = 0;
if (client->flags & I2C_CLIENT_HOST_NOTIFY)
pm_runtime_put(&client->adapter->dev);
@@ -741,7 +743,6 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
if (!client->init_irq)
client->init_irq = i2c_dev_irq_from_resources(info->resources,
info->num_resources);
- client->irq = client->init_irq;
strlcpy(client->name, info->type, sizeof(client->name));
--
2.11.0
^ permalink raw reply related
* [PATCH v5 0/7] I2C IRQ Probe Improvements
From: Charles Keepax @ 2019-06-20 13:34 UTC (permalink / raw)
To: wsa, mika.westerberg
Cc: jarkko.nikula, andriy.shevchenko, linux-i2c, linux-acpi,
linux-kernel, benjamin.tissoires, jbroadus, patches
This series attempts to align as much IRQ handling into the
probe path as possible. Note that I don't have a great setup
for testing these patches so they are mostly just build tested
and need careful review and testing before any of them are
merged.
The series brings the ACPI path inline with the way the device
tree path handles the IRQ entirely at probe time. However,
it still leaves any IRQ specified through the board_info as
being handled at device time. In that case we need to cache
something from the board_info until probe time, which leaves
any alternative solution with something basically the same as
the current handling although perhaps caching more stuff.
Thanks,
Charles
See previous discussions:
- https://lkml.org/lkml/2019/2/15/989
- https://www.spinics.net/lists/linux-i2c/msg39541.html
Charles Keepax (7):
i2c: core: Allow whole core to use i2c_dev_irq_from_resources
i2c: acpi: Use available IRQ helper functions
i2c: acpi: Factor out getting the IRQ from ACPI
i2c: core: Make i2c_acpi_get_irq available to the rest of the I2C core
i2c: core: Move ACPI IRQ handling to probe time
i2c: core: Move ACPI gpio IRQ handling into i2c_acpi_get_irq
i2c: core: Tidy up handling of init_irq
drivers/i2c/i2c-core-acpi.c | 57 +++++++++++++++++++++++++++++++--------------
drivers/i2c/i2c-core-base.c | 11 +++++----
drivers/i2c/i2c-core.h | 11 +++++++++
3 files changed, 57 insertions(+), 22 deletions(-)
--
2.11.0
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
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.