Re: [PATCH] PCI: qcom: Ensure that PERST is asserted for at least 100 ms
On Thu 23 May 12:44 PDT 2019, Niklas Cassel wrote: > Currently, there is only a 1 ms sleep after asserting PERST. > > Reading the datasheets for different endpoints, some require PERST to be > asserted for 10 ms in order for the endpoint to perform a reset, others > require it to be asserted for 50 ms. > > Several SoCs using this driver uses PCIe Mini Card, where we don't know > what endpoint will be plugged in. > > The PCI Express Card Electromechanical Specification specifies: > "On power up, the deassertion of PERST# is delayed 100 ms (TPVPERL) from > the power rails achieving specified operating limits." > > Add a sleep of 100 ms before deasserting PERST, in order to ensure that > we are compliant with the spec. > > Signed-off-by: Niklas Cassel Reviewed-by: Bjorn Andersson > --- > drivers/pci/controller/dwc/pcie-qcom.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/pci/controller/dwc/pcie-qcom.c > b/drivers/pci/controller/dwc/pcie-qcom.c > index 0ed235d560e3..cae24376237c 100644 > --- a/drivers/pci/controller/dwc/pcie-qcom.c > +++ b/drivers/pci/controller/dwc/pcie-qcom.c > @@ -1110,6 +1110,8 @@ static int qcom_pcie_host_init(struct pcie_port *pp) > if (IS_ENABLED(CONFIG_PCI_MSI)) > dw_pcie_msi_init(pp); > > + /* Ensure that PERST has been asserted for at least 100 ms */ > + msleep(100); > qcom_ep_reset_deassert(pcie); > > ret = qcom_pcie_establish_link(pcie); > -- > 2.21.0 >
Re: [PATCH v7 5/5] namei: resolveat(2) syscall
On 2019-05-25, Linus Torvalds wrote: > In fact, I think resolveat() as a model is fundamentally wrong for yet > another reason: O_CREAT. If you want to _create_ a new file, and you > want to still have the path resolution modifiers in place, the > resolveat() model is broken, because it only gives you path resolution > for the lookup, and then when you do openat(O_CREAT) for the final > component, you now don't have any way to limit that last component. > > Sure, you can probably effectively hack around it with resolveat() on > everything but the last component, and then > openat(O_CREAT|O_EXCL|O_NOFOLLOW) on the last component, because the > O_EXCL|O_NOFOLLOW should mean that it won't do any of the unsafe > things. And then (if you didn't actually want the O_EXCL), you handle > the race between "somebody else got there first" by re-trying etc. So > I suspect the O_CREAT thing could be worked around with extra > complexity, but it's an example of how the O_PATH model really screws > you over. > > End result: I really think resolveat() is broken. It absolutely > *needs* to be a full-fledged "openat()" system call, just with added > path resolution flags. That's a very good point. I was starting to work on O_CREAT via resolveat(2) and it definitely was much harder than most people would be happy to deal with -- I'm not even sure that I handled all the cases. I'll go for an openat2(2) then. Thinking about it some more -- since it's a new syscall, I could actually implement the O_PATH link-mode as being just the regular mode argument (since openat(2) ignores the mode for non-O_CREAT anyway). The openat(2) wrapper might be more than one-line as a result but it should avoid polluting the resolution flags with mode flags (since openat(O_PATH) needs to have a g+rwx mode for backwards-compatibility). > > openat2(rootfd, "path/to/file", O_PATH, RESOLVE_IN_ROOT, ); > > Note that for O_CREAT, it either needs the 'mode' parameter too, or > the statbuf would need to be an in-out thing. I think the in-out model > might be nice (the varargs model with a conditional 'mode' parameter > is horrid, I think), but at some point it's just bike-shedding. > > Also, I'm not absolutely married to the statbuf, but I do think it > might be a useful extension. A *lot* of users need the size of the > file for subsequent mmap() calls (or for buffer management for > read/write interface) or for things like just headers (ie > "Content-length:" in html etc). > > I'm not sure people actually want a full 'struct stat', but people > historically also do st_ino/st_dev for indexing into existing > user-space caches (or to check permissions like that it's on the right > filesystem, but the resolve flags kind of make that less of an issue). > And st_mode to verify that it's a proper regular file etc etc. > > You can always just leave it as NULL if you don't care, there's almost > no downside to adding it, and I do think that people who want a "walk > pathname carefully" model almost always would want to also check the > end result anyway. Yeah, I agree -- most folks would want to double-check what they've opened or O_PATH'd. Though I'm still not clear what is the best way of doing the "stat" argument is -- especially given how much fun architecture-specific shenanigans are in fs/stat.c (should I only use cp_new_stat64 or have a separate 64-bit syscall). > > Is there a large amount of overhead or downside to the current > > open->fstat way of doing things, or is this more of a "if we're going to > > add more ways of opening we might as well add more useful things"? > > Right now, system calls are sadly very expensive on a lot of hardware. > We used to be very proud of the fact that Linux system calls were > fast, but with meltdown and retpoline etc, we're back to "system calls > can be several thousand cycles each, just in overhead, on commonly > available hardware". > > Is "several thousand cycles" fatal? Not necessarily. But I think that > if we do add a new system call, particularly a fancy one for special > security-conscious models, we should look at what people need and use, > and want. And performance should always be a concern. > > I realize that people who come at this from primarily just a security > issue background may think that security is the primary goal. But no. > Security always needs to realize that the _primary_ goal is to have > people _use_ it. Without users, security is entirely pointless. And > the users part is partly performance, but mostly "it's convenient". Yup, I agree. I was hoping to shunt most of the convenience to userspace to avoid ruffling feathers in VFS-land, but I'm more than happy to make the kernel ABI more convenient. > The whole "this is Linux-specific" is a big inconvenience point I hope that other OSes will take our lead and have a similar interface so that the particular inconvenience can go away eventually (this was one of the arguments for resolveat(2) -- it's a clear "this is a
Re: [PATCH] dt-bindings: pinctrl: fix spelling mistakes in pinctl documentation
On Sat 25 May 13:42 PDT 2019, Colin King wrote: > From: Colin Ian King > > The spelling of configured is incorrect in the documentation. Fix it. > > Signed-off-by: Colin Ian King Reviewed-by: Bjorn Andersson Thanks, Bjorn > --- > .../devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.txt| 6 +++--- > .../devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.txt | 6 +++--- > .../devicetree/bindings/pinctrl/qcom,sdm660-pinctrl.txt | 6 +++--- > .../devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.txt | 6 +++--- > 11 files changed, 33 insertions(+), 33 deletions(-) > > diff --git > a/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt > b/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt > index 68e93d5b7ede..c9782397ff14 100644 > --- a/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt > +++ b/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt > @@ -122,17 +122,17 @@ to specify in a pin configuration subnode: > - bias-disable: > Usage: optional > Value type: > - Definition: The specified pins should be configued as no pull. > + Definition: The specified pins should be configured as no pull. > > - bias-pull-down: > Usage: optional > Value type: > - Definition: The specified pins should be configued as pull down. > + Definition: The specified pins should be configured as pull down. > > - bias-pull-up: > Usage: optional > Value type: > - Definition: The specified pins should be configued as pull up. > + Definition: The specified pins should be configured as pull up. > > - output-high: > Usage: optional > diff --git > a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt > b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt > index 6dd72f8599e9..7b151894f5a0 100644 > --- a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt > +++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt > @@ -118,17 +118,17 @@ to specify in a pin configuration subnode: > - bias-disable: > Usage: optional > Value type: > - Definition: The specified pins should be configued as no pull. > + Definition: The specified pins should be configured as no pull. > > - bias-pull-down: > Usage: optional > Value type: > - Definition: The specified pins should be configued as pull down. > + Definition: The specified pins should be configured as pull down. > > - bias-pull-up: > Usage: optional > Value type: > - Definition: The specified pins should be configued as pull up. > + Definition: The specified pins should be configured as pull up. > > - output-high: > Usage: optional > diff --git > a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt > b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt > index 86ecdcfc4fb8..d46973968873 100644 > --- a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt > +++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt > @@ -97,17 +97,17 @@ to specify in a pin configuration subnode: > - bias-disable: > Usage: optional > Value type: > - Definition: The specified pins should be configued as no pull. > + Definition: The specified pins should be configured as no pull. > > - bias-pull-down: > Usage: optional > Value type: > - Definition: The specified pins should be configued as pull down. > + Definition: The specified pins should be configured as pull down. > > - bias-pull-up: > Usage: optional > Value type: > - Definition: The specified pins should be configued as pull up. > + Definition: The specified pins should be configured as pull up. > > - output-high: > Usage: optional > diff --git > a/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt > b/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt > index 195a7a0ef0cc..3354a63296d9 100644 > --- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt > +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt > @@ -130,17 +130,17 @@ to specify in a pin configuration subnode: > - bias-disable: > Usage: optional > Value type: > - Definition: The specified pins should be configued as no pull. > + Definition: The specified pins should be
[PATCH V8 15/15] arm64: Add Tegra194 PCIe driver to defconfig
Add PCIe host controller driver for DesignWare core based PCIe controller IP present in Tegra194. Signed-off-by: Vidya Sagar --- Changes since [v7]: * None Changes since [v6]: * None Changes since [v5]: * None Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * None Changes since [v1]: * Changed CONFIG_PCIE_TEGRA194 from 'y' to 'm' arch/arm64/configs/defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 8871cf7aaba9..52105b2c2418 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -195,6 +195,7 @@ CONFIG_PCIE_QCOM=y CONFIG_PCIE_ARMADA_8K=y CONFIG_PCIE_KIRIN=y CONFIG_PCIE_HISI_STB=y +CONFIG_PCIE_TEGRA194=m CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -- 2.17.1
[PATCH V8 14/15] PCI: tegra: Add Tegra194 PCIe support
Add support for Synopsys DesignWare core IP based PCIe host controller present in Tegra194 SoC. Signed-off-by: Vidya Sagar --- Changes since [v7]: * Addressed review comments from Thierry Changes since [v6]: * Removed code around "nvidia,disable-aspm-states" DT property * Refactored code to remove code duplication Changes since [v5]: * Addressed review comments from Thierry Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Changed 'nvidia,init-speed' to 'nvidia,init-link-speed' * Changed 'nvidia,pex-wake' to 'nvidia,wake-gpios' * Removed .runtime_suspend() & .runtime_resume() implementations Changes since [v1]: * Made CONFIG_PCIE_TEGRA194 as 'm' by default from its previous 'y' state * Modified code as per changes made to DT documentation * Refactored code to address Bjorn & Thierry's review comments * Added goto to avoid recursion in tegra_pcie_dw_host_init() API * Merged .scan_bus() of dw_pcie_host_ops implementation to tegra_pcie_dw_host_init() API drivers/pci/controller/dwc/Kconfig | 10 + drivers/pci/controller/dwc/Makefile|1 + drivers/pci/controller/dwc/pcie-tegra194.c | 1621 3 files changed, 1632 insertions(+) create mode 100644 drivers/pci/controller/dwc/pcie-tegra194.c diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index a6ce1ee51b4c..884112afc11b 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -220,6 +220,16 @@ config PCI_MESON and therefore the driver re-uses the DesignWare core functions to implement the driver. +config PCIE_TEGRA194 + tristate "NVIDIA Tegra194 (and later) PCIe controller" + depends on (TEGRA_BPMP && ARCH_TEGRA) || COMPILE_TEST + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_DW_HOST + select PHY_TEGRA194_P2U + help + Say Y here if you want support for DesignWare core based PCIe host + controller found in NVIDIA Tegra194 SoC. + config PCIE_UNIPHIER bool "Socionext UniPhier PCIe controllers" depends on ARCH_UNIPHIER || COMPILE_TEST diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile index b085dfd4fab7..b30336181d46 100644 --- a/drivers/pci/controller/dwc/Makefile +++ b/drivers/pci/controller/dwc/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o obj-$(CONFIG_PCIE_HISI_STB) += pcie-histb.o obj-$(CONFIG_PCI_MESON) += pci-meson.o +obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o # The following drivers are for devices that use the generic ACPI diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c new file mode 100644 index ..bb3b2d1ea78f --- /dev/null +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -0,0 +1,1621 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * PCIe host controller driver for Tegra194 SoC + * + * Copyright (C) 2019 NVIDIA Corporation. + * + * Author: Vidya Sagar + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pcie-designware.h" +#include +#include +#include "../../pci.h" + +#define APPL_PINMUX0x0 +#define APPL_PINMUX_PEX_RSTBIT(0) +#define APPL_PINMUX_CLKREQ_OVERRIDE_EN BIT(2) +#define APPL_PINMUX_CLKREQ_OVERRIDEBIT(3) +#define APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE_EN BIT(4) +#define APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE BIT(5) +#define APPL_PINMUX_CLKREQ_OUT_OVRD_EN BIT(9) +#define APPL_PINMUX_CLKREQ_OUT_OVRDBIT(10) + +#define APPL_CTRL 0x4 +#define APPL_CTRL_SYS_PRE_DET_STATEBIT(6) +#define APPL_CTRL_LTSSM_EN BIT(7) +#define APPL_CTRL_HW_HOT_RST_ENBIT(20) +#define APPL_CTRL_HW_HOT_RST_MODE_MASK GENMASK(1, 0) +#define APPL_CTRL_HW_HOT_RST_MODE_SHIFT22 +#define APPL_CTRL_HW_HOT_RST_MODE_IMDT_RST 0x1 + +#define APPL_INTR_EN_L0_0 0x8 +#define APPL_INTR_EN_L0_0_LINK_STATE_INT_ENBIT(0) +#define APPL_INTR_EN_L0_0_MSI_RCV_INT_EN BIT(4) +#define APPL_INTR_EN_L0_0_INT_INT_EN BIT(8) +#define APPL_INTR_EN_L0_0_CDM_REG_CHK_INT_EN BIT(19) +#define APPL_INTR_EN_L0_0_SYS_INTR_EN BIT(30) +#define APPL_INTR_EN_L0_0_SYS_MSI_INTR_EN BIT(31) + +#define APPL_INTR_STATUS_L00xC +#define APPL_INTR_STATUS_L0_LINK_STATE_INT BIT(0) +#define APPL_INTR_STATUS_L0_INT_INTBIT(8) +#define APPL_INTR_STATUS_L0_CDM_REG_CHK_INTBIT(18) + +#define APPL_INTR_EN_L1_0_00x1C +#define
[PATCH V8 08/15] dt-bindings: Add PCIe supports-clkreq property
Some host controllers need to know the existence of clkreq signal routing to downstream devices to be able to advertise low power features like ASPM L1 substates. Without clkreq signal routing being present, enabling ASPM L1 sub states might lead to downstream devices falling off the bus. Hence a new device tree property 'supports-clkreq' is added to make such host controllers aware of clkreq signal routing to downstream devices. Signed-off-by: Vidya Sagar Reviewed-by: Rob Herring Reviewed-by: Thierry Reding --- Changes since [v7]: * None Changes since [v6]: * None Changes since [v5]: * s/Documentation\/devicetree/dt-bindings/ in the subject Changes since [v4]: * None Changes since [v3]: * Rebased on top of linux-next top of the tree Changes since [v2]: * None Changes since [v1]: * This is a new patch in v2 series Documentation/devicetree/bindings/pci/pci.txt | 5 + 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/pci/pci.txt b/Documentation/devicetree/bindings/pci/pci.txt index 92c01db610df..d132f9efeb3e 100644 --- a/Documentation/devicetree/bindings/pci/pci.txt +++ b/Documentation/devicetree/bindings/pci/pci.txt @@ -24,6 +24,11 @@ driver implementation may support the following properties: unsupported link speed, for instance, trying to do training for unsupported link speed, etc. Must be '4' for gen4, '3' for gen3, '2' for gen2, and '1' for gen1. Any other values are invalid. +- supports-clkreq: + If present this property specifies that CLKREQ signal routing exists from + root port to downstream device and host bridge drivers can do programming + which depends on CLKREQ signal existence. For example, programming root port + not to advertise ASPM L1 Sub-States support if there is no CLKREQ signal. PCI-PCI Bridge properties - -- 2.17.1
[PATCH V8 13/15] phy: tegra: Add PCIe PIPE2UPHY support
Synopsys DesignWare core based PCIe controllers in Tegra 194 SoC interface with Universal PHY (UPHY) module through a PIPE2UPHY (P2U) module. For each PCIe lane of a controller, there is a P2U unit instantiated at hardware level. This driver provides support for the programming required for each P2U that is going to be used for a PCIe controller. Signed-off-by: Vidya Sagar --- Changes since [v7]: * Changed P2U driver file name from pcie-p2u-tegra194.c to phy-tegra194-p2u.c Changes since [v6]: * None Changes since [v5]: * Addressed review comments from Thierry Changes since [v4]: * None Changes since [v3]: * Rebased on top of linux-next top of the tree Changes since [v2]: * Replaced spaces with tabs in Kconfig file * Sorted header file inclusion alphabetically Changes since [v1]: * Added COMPILE_TEST in Kconfig * Removed empty phy_ops implementations * Modified code according to DT documentation file modifications drivers/phy/tegra/Kconfig| 7 ++ drivers/phy/tegra/Makefile | 1 + drivers/phy/tegra/phy-tegra194-p2u.c | 109 +++ 3 files changed, 117 insertions(+) create mode 100644 drivers/phy/tegra/phy-tegra194-p2u.c diff --git a/drivers/phy/tegra/Kconfig b/drivers/phy/tegra/Kconfig index a3b1de953fb7..c56fc8452e03 100644 --- a/drivers/phy/tegra/Kconfig +++ b/drivers/phy/tegra/Kconfig @@ -6,3 +6,10 @@ config PHY_TEGRA_XUSB To compile this driver as a module, choose M here: the module will be called phy-tegra-xusb. + +config PHY_TEGRA194_P2U + tristate "NVIDIA Tegra194 PIPE2UPHY PHY driver" + depends on ARCH_TEGRA || COMPILE_TEST + select GENERIC_PHY + help + Enable this to support the P2U (PIPE to UPHY) that is part of Tegra 19x SOCs. diff --git a/drivers/phy/tegra/Makefile b/drivers/phy/tegra/Makefile index a93cd9a499b2..ac43000dc4ce 100644 --- a/drivers/phy/tegra/Makefile +++ b/drivers/phy/tegra/Makefile @@ -5,3 +5,4 @@ phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_124_SOC) += xusb-tegra124.o phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_132_SOC) += xusb-tegra124.o phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_210_SOC) += xusb-tegra210.o phy-tegra-xusb-$(CONFIG_ARCH_TEGRA_186_SOC) += xusb-tegra186.o +obj-$(CONFIG_PHY_TEGRA194_P2U) += phy-tegra194-p2u.o diff --git a/drivers/phy/tegra/phy-tegra194-p2u.c b/drivers/phy/tegra/phy-tegra194-p2u.c new file mode 100644 index ..7b84b4c55e43 --- /dev/null +++ b/drivers/phy/tegra/phy-tegra194-p2u.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * P2U (PIPE to UPHY) driver for Tegra T194 SoC + * + * Copyright (C) 2019 NVIDIA Corporation. + * + * Author: Vidya Sagar + */ + +#include +#include +#include +#include +#include +#include + +#define P2U_PERIODIC_EQ_CTRL_GEN3 0xc0 +#define P2U_PERIODIC_EQ_CTRL_GEN3_PERIODIC_EQ_EN BIT(0) +#define P2U_PERIODIC_EQ_CTRL_GEN3_INIT_PRESET_EQ_TRAIN_EN BIT(1) +#define P2U_PERIODIC_EQ_CTRL_GEN4 0xc4 +#define P2U_PERIODIC_EQ_CTRL_GEN4_INIT_PRESET_EQ_TRAIN_EN BIT(1) + +#define P2U_RX_DEBOUNCE_TIME 0xa4 +#define P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_MASK 0x +#define P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_VAL160 + +struct tegra_p2u { + void __iomem *base; +}; + +static int tegra_p2u_power_on(struct phy *x) +{ + struct tegra_p2u *phy = phy_get_drvdata(x); + u32 val; + + val = readl(phy->base + P2U_PERIODIC_EQ_CTRL_GEN3); + val &= ~P2U_PERIODIC_EQ_CTRL_GEN3_PERIODIC_EQ_EN; + val |= P2U_PERIODIC_EQ_CTRL_GEN3_INIT_PRESET_EQ_TRAIN_EN; + writel(val, phy->base + P2U_PERIODIC_EQ_CTRL_GEN3); + + val = readl(phy->base + P2U_PERIODIC_EQ_CTRL_GEN4); + val |= P2U_PERIODIC_EQ_CTRL_GEN4_INIT_PRESET_EQ_TRAIN_EN; + writel(val, phy->base + P2U_PERIODIC_EQ_CTRL_GEN4); + + val = readl(phy->base + P2U_RX_DEBOUNCE_TIME); + val &= ~P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_MASK; + val |= P2U_RX_DEBOUNCE_TIME_DEBOUNCE_TIMER_VAL; + writel(val, phy->base + P2U_RX_DEBOUNCE_TIME); + + return 0; +} + +static const struct phy_ops ops = { + .power_on = tegra_p2u_power_on, + .owner = THIS_MODULE, +}; + +static int tegra_p2u_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct device *dev = >dev; + struct phy *generic_phy; + struct tegra_p2u *phy; + struct resource *res; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctl"); + phy->base = devm_ioremap_resource(dev, res); + if (IS_ERR(phy->base)) + return PTR_ERR_OR_ZERO(phy->base); + + platform_set_drvdata(pdev, phy); + + generic_phy = devm_phy_create(dev, NULL, ); + if (IS_ERR(generic_phy)) + return PTR_ERR_OR_ZERO(generic_phy); + + phy_set_drvdata(generic_phy, phy); + +
[PATCH V8 10/15] dt-bindings: PHY: P2U: Add Tegra194 P2U block
Add support for Tegra194 P2U (PIPE to UPHY) module block which is a glue module instantiated one for each PCIe lane between Synopsys DesignWare core based PCIe IP and Universal PHY block. Signed-off-by: Vidya Sagar Reviewed-by: Rob Herring Acked-by: Thierry Reding --- Changes since [v7]: * None Changes since [v6]: * None Changes since [v5]: * Added Sob * Changed node name from "p2u@" to "phy@" Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Changed node label to reflect new format that includes either 'hsio' or 'nvhs' in its name to reflect which UPHY brick they belong to Changes since [v1]: * This is a new patch in v2 series .../bindings/phy/phy-tegra194-p2u.txt | 28 +++ 1 file changed, 28 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/phy-tegra194-p2u.txt diff --git a/Documentation/devicetree/bindings/phy/phy-tegra194-p2u.txt b/Documentation/devicetree/bindings/phy/phy-tegra194-p2u.txt new file mode 100644 index ..d23ff90baad5 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-tegra194-p2u.txt @@ -0,0 +1,28 @@ +NVIDIA Tegra194 P2U binding + +Tegra194 has two PHY bricks namely HSIO (High Speed IO) and NVHS (NVIDIA High +Speed) each interfacing with 12 and 8 P2U instances respectively. +A P2U instance is a glue logic between Synopsys DesignWare Core PCIe IP's PIPE +interface and PHY of HSIO/NVHS bricks. Each P2U instance represents one PCIe +lane. + +Required properties: +- compatible: For Tegra19x, must contain "nvidia,tegra194-p2u". +- reg: Should be the physical address space and length of respective each P2U + instance. +- reg-names: Must include the entry "ctl". + +Required properties for PHY port node: +- #phy-cells: Defined by generic PHY bindings. Must be 0. + +Refer to phy/phy-bindings.txt for the generic PHY binding properties. + +Example: + +p2u_hsio_0: phy@3e1 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e1 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; +}; -- 2.17.1
[PATCH V8 12/15] arm64: tegra: Enable PCIe slots in P2972-0000 board
Enable PCIe controller nodes to enable respective PCIe slots on P2972- board. Following is the ownership of slots by different PCIe controllers. Controller-0 : M.2 Key-M slot Controller-1 : On-board Marvell eSATA controller Controller-3 : M.2 Key-E slot Signed-off-by: Vidya Sagar --- Changes since [v7]: * None Changes since [v6]: * None Changes since [v5]: * Arranged PCIe nodes in the order of their addresses Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Changed P2U label names to reflect new format that includes 'hsio'/'nvhs' strings to reflect UPHY brick they belong to Changes since [v1]: * Dropped 'pcie-' from phy-names property strings .../arm64/boot/dts/nvidia/tegra194-p2888.dtsi | 2 +- .../boot/dts/nvidia/tegra194-p2972-.dts | 41 +++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi index 0fd5bd29fbf9..30a83d4c5b69 100644 --- a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi @@ -191,7 +191,7 @@ regulator-boot-on; }; - sd3 { + vdd_1v8ao: sd3 { regulator-name = "VDD_1V8AO"; regulator-min-microvolt = <180>; regulator-max-microvolt = <180>; diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2972-.dts b/arch/arm64/boot/dts/nvidia/tegra194-p2972-.dts index 73801b48d1d8..a22704e76a84 100644 --- a/arch/arm64/boot/dts/nvidia/tegra194-p2972-.dts +++ b/arch/arm64/boot/dts/nvidia/tegra194-p2972-.dts @@ -167,4 +167,45 @@ }; }; }; + + pcie@1410 { + status = "okay"; + + vddio-pex-ctl-supply = <_1v8ao>; + + phys = <_hsio_0>; + phy-names = "p2u-0"; + }; + + pcie@1414 { + status = "okay"; + + vddio-pex-ctl-supply = <_1v8ao>; + + phys = <_hsio_7>; + phy-names = "p2u-0"; + }; + + pcie@1418 { + status = "okay"; + + vddio-pex-ctl-supply = <_1v8ao>; + + phys = <_hsio_2>, <_hsio_3>, <_hsio_4>, + <_hsio_5>; + phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3"; + }; + + pcie@141a { + status = "disabled"; + + vddio-pex-ctl-supply = <_1v8ao>; + + phys = <_nvhs_0>, <_nvhs_1>, <_nvhs_2>, + <_nvhs_3>, <_nvhs_4>, <_nvhs_5>, + <_nvhs_6>, <_nvhs_7>; + + phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4", + "p2u-5", "p2u-6", "p2u-7"; + }; }; -- 2.17.1
[PATCH V8 11/15] arm64: tegra: Add P2U and PCIe controller nodes to Tegra194 DT
Add P2U (PIPE to UPHY) and PCIe controller nodes to device tree. The Tegra194 SoC contains six PCIe controllers and twenty P2U instances grouped into two different PHY bricks namely High-Speed IO (HSIO-12 P2Us) and NVIDIA High Speed (NVHS-8 P2Us) respectively. Signed-off-by: Vidya Sagar --- Changes since [v7]: * Replaced 'core_apb' with 'apb' in reset names * Used macros instead of hardcoded numbers in 'interrupt-map' property * Aligned 'ranges' entries Changes since [v6]: * Removed properties "nvidia,disable-aspm-states" & "nvidia,controller-id". * Modified property "nvidia,bpmp" to include controller-id as well. Changes since [v5]: * Changes 'p2u@' to 'phy@' * Arranged all PCIe nodes in the order of their addresses Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Included 'hsio' or 'nvhs' in P2U node's label names to reflect which brick they belong to * Removed leading zeros in unit address Changes since [v1]: * Flattened all P2U nodes by removing 'hsio-p2u' and 'nvhs-p2u' super nodes * Changed P2U nodes compatible string from 'nvidia,tegra194-phy-p2u' to 'nvidia,tegra194-p2u' * Changed reg-name from 'base' to 'ctl' * Updated all PCIe nodes according to the changes made to DT documentation file arch/arm64/boot/dts/nvidia/tegra194.dtsi | 437 +++ 1 file changed, 437 insertions(+) diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi index c77ca211fa8f..feba034f26f0 100644 --- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi @@ -884,6 +884,166 @@ nvidia,interface = <3>; }; }; + + p2u_hsio_0: phy@3e1 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e1 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_1: phy@3e2 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e2 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_2: phy@3e3 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e3 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_3: phy@3e4 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e4 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_4: phy@3e5 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e5 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_5: phy@3e6 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e6 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_6: phy@3e7 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e7 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_7: phy@3e8 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e8 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_8: phy@3e9 { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03e9 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_hsio_9: phy@3ea { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03ea 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_nvhs_0: phy@3eb { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03eb 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_nvhs_1: phy@3ec { + compatible = "nvidia,tegra194-p2u"; + reg = <0x03ec 0x1>; + reg-names = "ctl"; + + #phy-cells = <0>; + }; + + p2u_nvhs_2: phy@3ed { + compatible = "nvidia,tegra194-p2u"; +
[PATCH V8 09/15] dt-bindings: PCI: tegra: Add device tree support for Tegra194
Add support for Tegra194 PCIe controllers. These controllers are based on Synopsys DesignWare core IP. Signed-off-by: Vidya Sagar Reviewed-by: Rob Herring --- Changes since [v7]: * Addressed review comments from Thierry * Modified DT example to reflect new changes Changes since [v6]: * Changed description of the property "nvidia,bpmp". * Removed property "nvidia,disable-aspm-states". Changes since [v5]: * Removed 'max-link-speed' as it is going to be a common sub-system property * Removed 'nvidia,init-link-speed' as there isn't much value addition * Removed 'nvidia,wake-gpios' for now * Addressed review comments from Thierry and Rob in general Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Using only 'Cx' (x-being controller number) format to represent a controller * Changed to 'value: description' format where applicable * Changed 'nvidia,init-speed' to 'nvidia,init-link-speed' * Provided more documentation for 'nvidia,init-link-speed' property * Changed 'nvidia,pex-wake' to 'nvidia,wake-gpios' Changes since [v1]: * Added documentation for 'power-domains' property * Removed 'window1' and 'window2' properties * Removed '_clk' and '_rst' from clock and reset names * Dropped 'pcie' from phy-names * Added entry for BPMP-FW handle * Removed offsets for some of the registers and added them in code and would be pickedup based on controller ID * Changed 'nvidia,max-speed' to 'max-link-speed' and is made as an optional * Changed 'nvidia,disable-clock-request' to 'supports-clkreq' with inverted operation * Added more documentation for 'nvidia,update-fc-fixup' property * Removed 'nvidia,enable-power-down' and 'nvidia,plat-gpios' properties * Added '-us' to all properties that represent time in microseconds * Moved P2U documentation to a separate file .../bindings/pci/nvidia,tegra194-pcie.txt | 155 ++ 1 file changed, 155 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt new file mode 100644 index ..674e5adb2895 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt @@ -0,0 +1,155 @@ +NVIDIA Tegra PCIe controller (Synopsys DesignWare Core based) + +This PCIe host controller is based on the Synopsis Designware PCIe IP +and thus inherits all the common properties defined in designware-pcie.txt. + +Required properties: +- compatible: For Tegra19x, must contain "nvidia,tegra194-pcie". +- device_type: Must be "pci" +- power-domains: A phandle to the node that controls power to the respective + PCIe controller and a specifier name for the PCIe controller. Following are + the specifiers for the different PCIe controllers +TEGRA194_POWER_DOMAIN_PCIEX8B: C0 +TEGRA194_POWER_DOMAIN_PCIEX1A: C1 +TEGRA194_POWER_DOMAIN_PCIEX1A: C2 +TEGRA194_POWER_DOMAIN_PCIEX1A: C3 +TEGRA194_POWER_DOMAIN_PCIEX4A: C4 +TEGRA194_POWER_DOMAIN_PCIEX8A: C5 + these specifiers are defined in + "include/dt-bindings/power/tegra194-powergate.h" file. +- reg: A list of physical base address and length pairs for each set of + controller registers. Must contain an entry for each entry in the reg-names + property. +- reg-names: Must include the following entries: + "appl": Controller's application logic registers + "config": As per the definition in designware-pcie.txt + "atu_dma": iATU and DMA registers. This is where the iATU (internal Address + Translation Unit) registers of the PCIe core are made available + for SW access. + "dbi": The aperture where root port's own configuration registers are + available +- interrupts: A list of interrupt outputs of the controller. Must contain an + entry for each entry in the interrupt-names property. +- interrupt-names: Must include the following entries: + "intr": The Tegra interrupt that is asserted for controller interrupts + "msi": The Tegra interrupt that is asserted when an MSI is received +- bus-range: Range of bus numbers associated with this controller +- #address-cells: Address representation for root ports (must be 3) + - cell 0 specifies the bus and device numbers of the root port: +[23:16]: bus number +[15:11]: device number + - cell 1 denotes the upper 32 address bits and should be 0 + - cell 2 contains the lower 32 address bits and is used to translate to the +CPU address space +- #size-cells: Size representation for root ports (must be 2) +- ranges: Describes the translation of addresses for root ports and standard + PCI regions. The entries must be 7 cells each, where the first three cells + correspond to the address as described for the #address-cells property + above, the fourth and fifth cells are for the physical CPU address to + translate to and the sixth and seventh cells are as described for the + #size-cells property
[PATCH V8 04/15] PCI: dwc: Move config space capability search API
Move PCIe config space capability search API to common DesignWare file as this can be used by both host and ep mode codes. Signed-off-by: Vidya Sagar Acked-by: Gustavo Pimentel Reviewed-by: Thierry Reding --- Changes since [v7]: * Changed comment to explicitly state their mere resemblance to standard APIs but not their operation and place of use. Changes since [v6]: * Exported dw_pcie_find_capability() API Changes since [v5]: * None Changes since [v4]: * Removed redundant APIs in pcie-designware-ep.c file after moving them to pcie-designware.c file based on Bjorn's comments. Changes since [v3]: * Rebased to linux-next top of the tree Changes since [v2]: * None Changes since [v1]: * Removed dw_pcie_find_next_ext_capability() API from here and made a separate patch for that .../pci/controller/dwc/pcie-designware-ep.c | 37 +- drivers/pci/controller/dwc/pcie-designware.c | 39 +++ drivers/pci/controller/dwc/pcie-designware.h | 2 + 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 2bf5a35c0570..65f479250087 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -40,39 +40,6 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) __dw_pcie_ep_reset_bar(pci, bar, 0); } -static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie *pci, u8 cap_ptr, - u8 cap) -{ - u8 cap_id, next_cap_ptr; - u16 reg; - - if (!cap_ptr) - return 0; - - reg = dw_pcie_readw_dbi(pci, cap_ptr); - cap_id = (reg & 0x00ff); - - if (cap_id > PCI_CAP_ID_MAX) - return 0; - - if (cap_id == cap) - return cap_ptr; - - next_cap_ptr = (reg & 0xff00) >> 8; - return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); -} - -static u8 dw_pcie_ep_find_capability(struct dw_pcie *pci, u8 cap) -{ - u8 next_cap_ptr; - u16 reg; - - reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); - next_cap_ptr = (reg & 0x00ff); - - return __dw_pcie_ep_find_next_cap(pci, next_cap_ptr, cap); -} - static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, struct pci_epf_header *hdr) { @@ -612,9 +579,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n"); return -ENOMEM; } - ep->msi_cap = dw_pcie_ep_find_capability(pci, PCI_CAP_ID_MSI); + ep->msi_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); - ep->msix_cap = dw_pcie_ep_find_capability(pci, PCI_CAP_ID_MSIX); + ep->msix_cap = dw_pcie_find_capability(pci, PCI_CAP_ID_MSIX); offset = dw_pcie_ep_find_ext_capability(pci, PCI_EXT_CAP_ID_REBAR); if (offset) { diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 83cdd2ce2486..38d76bd63b8f 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -14,6 +14,45 @@ #include "pcie-designware.h" +/* + * These interfaces resemble the pci_find_*capability() interfaces, but these + * are for configuring host controllers, which are bridges *to* PCI devices but + * are not PCI devices themselves. + */ +static u8 __dw_pcie_find_next_cap(struct dw_pcie *pci, u8 cap_ptr, + u8 cap) +{ + u8 cap_id, next_cap_ptr; + u16 reg; + + if (!cap_ptr) + return 0; + + reg = dw_pcie_readw_dbi(pci, cap_ptr); + cap_id = (reg & 0x00ff); + + if (cap_id > PCI_CAP_ID_MAX) + return 0; + + if (cap_id == cap) + return cap_ptr; + + next_cap_ptr = (reg & 0xff00) >> 8; + return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap); +} + +u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap) +{ + u8 next_cap_ptr; + u16 reg; + + reg = dw_pcie_readw_dbi(pci, PCI_CAPABILITY_LIST); + next_cap_ptr = (reg & 0x00ff); + + return __dw_pcie_find_next_cap(pci, next_cap_ptr, cap); +} +EXPORT_SYMBOL_GPL(dw_pcie_find_capability); + int dw_pcie_read(void __iomem *addr, int size, u32 *val) { if (!IS_ALIGNED((uintptr_t)addr, size)) { diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 14762e262758..6cb978132469 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -251,6 +251,8 @@ struct dw_pcie { #define to_dw_pcie_from_ep(endpoint) \ container_of((endpoint), struct dw_pcie, ep) +u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap); + int dw_pcie_read(void __iomem *addr, int size, u32 *val); int dw_pcie_write(void __iomem *addr, int size,
[PATCH V8 00/15] Add Tegra194 PCIe support
Tegra194 has six PCIe controllers based on Synopsys DesignWare core. There are two Universal PHY (UPHY) blocks with each supporting 12(HSIO: Hisg Speed IO) and 8(NVHS: NVIDIA High Speed) lanes respectively. Controllers:0~4 use UPHY lanes from HSIO brick whereas Controller:5 uses UPHY lanes from NVHS brick. Lane mapping in HSIO UPHY brick to each PCIe controller (0~4) is controlled in XBAR module by BPMP-FW. Since PCIe core has PIPE interface, a glue module called PIPE-to-UPHY (P2U) is used to connect each UPHY lane (applicable to both HSIO and NVHS UPHY bricks) to PCIe controller This patch series - Adds support for P2U PHY driver - Adds support for PCIe host controller - Adds device tree nodes each PCIe controllers - Enables nodes applicable to p2972- platform - Adds helper APIs in Designware core driver to get capability regs offset - Adds defines for new feature registers of PCIe spec revision 4 - Makes changes in DesignWare core driver to get Tegra194 PCIe working Testing done on P2972- platform - Able to get PCIe link up with on-board Marvel eSATA controller - Able to get PCIe link up with NVMe cards connected to M.2 Key-M slot - Able to do data transfers with both SATA drives and NVMe cards Note - Enabling x8 slot on P2972- platform requires pinmux driver for Tegra194. It is being worked on currently and hence Controller:5 (i.e. x8 slot) is disabled in this patch series. A future patch series would enable this. - This series is based on top of the following series Jisheng's patches to add support to .remove() in Designware sub-system https://patchwork.kernel.org/project/linux-pci/list/?series=98559 (Jisheng's patches are now accepted and applied for v5.2) My patches made on top of Jisheng's patches to export various symbols https://patchwork.kernel.org/project/linux-pci/list/?series=101259 Changes since [v7]: * Changed P2U driver file name from pcie-p2u-tegra194.c to phy-tegra194-p2u.c * Addressed review comments from Thierry and Rob Changes since [v6]: * Took care of review comments from Rob * Added a quirk to disable MSI for root ports * Removed using pcie_pme_disable_msi() API in host controller driver Changes since [v5]: * Removed patch that exports pcie_bus_config symbol * Took care of review comments from Thierry and Rob Changes since [v4]: * Removed redundant APIs in pcie-designware-ep.c file after moving them to pcie-designware.c file based on Bjorn's review comments Changes since [v3]: * Rebased on top of linux-next top of the tree * Addressed Gustavo's comments and added his Ack for some of the changes. Changes since [v2]: * Addressed review comments from Thierry Changes since [v1]: * Addressed review comments from Bjorn, Thierry, Jonathan, Rob & Kishon * Added more patches in v2 series Vidya Sagar (15): PCI: Add #defines for some of PCIe spec r4.0 features PCI: Disable MSI for Tegra194 root port PCI: dwc: Perform dbi regs write lock towards the end PCI: dwc: Move config space capability search API PCI: dwc: Add ext config space capability search API dt-bindings: PCI: designware: Add binding for CDM register check PCI: dwc: Add support to enable CDM register check dt-bindings: Add PCIe supports-clkreq property dt-bindings: PCI: tegra: Add device tree support for Tegra194 dt-bindings: PHY: P2U: Add Tegra194 P2U block arm64: tegra: Add P2U and PCIe controller nodes to Tegra194 DT arm64: tegra: Enable PCIe slots in P2972- board phy: tegra: Add PCIe PIPE2UPHY support PCI: tegra: Add Tegra194 PCIe support arm64: Add Tegra194 PCIe driver to defconfig .../bindings/pci/designware-pcie.txt |5 + .../bindings/pci/nvidia,tegra194-pcie.txt | 155 ++ Documentation/devicetree/bindings/pci/pci.txt |5 + .../bindings/phy/phy-tegra194-p2u.txt | 28 + .../arm64/boot/dts/nvidia/tegra194-p2888.dtsi |2 +- .../boot/dts/nvidia/tegra194-p2972-.dts | 41 + arch/arm64/boot/dts/nvidia/tegra194.dtsi | 437 + arch/arm64/configs/defconfig |1 + drivers/pci/controller/dwc/Kconfig| 10 + drivers/pci/controller/dwc/Makefile |1 + .../pci/controller/dwc/pcie-designware-ep.c | 37 +- .../pci/controller/dwc/pcie-designware-host.c | 14 +- drivers/pci/controller/dwc/pcie-designware.c | 87 + drivers/pci/controller/dwc/pcie-designware.h | 12 + drivers/pci/controller/dwc/pcie-tegra194.c| 1621 + drivers/pci/quirks.c | 23 + drivers/phy/tegra/Kconfig |7 + drivers/phy/tegra/Makefile|1 + drivers/phy/tegra/phy-tegra194-p2u.c | 109 ++ include/uapi/linux/pci_regs.h | 22 +- 20 files changed, 2575 insertions(+), 43 deletions(-) create mode 100644 Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt create mode 100644 Documentation/devicetree/bindings/phy/phy-tegra194-p2u.txt create mode 100644
[PATCH V8 01/15] PCI: Add #defines for some of PCIe spec r4.0 features
Add #defines only for the Data Link Feature and Physical Layer 16.0 GT/s features. Signed-off-by: Vidya Sagar Reviewed-by: Thierry Reding --- Changes since [v7]: * None Changes since [v6]: * None Changes since [v5]: * None Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Updated commit message and description to explicitly mention that defines are added only for some of the features and not all. Changes since [v1]: * None include/uapi/linux/pci_regs.h | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 27164769d184..95a1eeb22f49 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -709,7 +709,9 @@ #define PCI_EXT_CAP_ID_DPC 0x1D/* Downstream Port Containment */ #define PCI_EXT_CAP_ID_L1SS0x1E/* L1 PM Substates */ #define PCI_EXT_CAP_ID_PTM 0x1F/* Precision Time Measurement */ -#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM +#define PCI_EXT_CAP_ID_DLF 0x25/* Data Link Feature */ +#define PCI_EXT_CAP_ID_PL 0x26/* Physical Layer 16.0 GT/s */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL #define PCI_EXT_CAP_DSN_SIZEOF 12 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 @@ -1049,4 +1051,22 @@ #define PCI_L1SS_CTL1_LTR_L12_TH_SCALE0xe000 /* LTR_L1.2_THRESHOLD_Scale */ #define PCI_L1SS_CTL2 0x0c/* Control 2 Register */ +/* Data Link Feature */ +#define PCI_DLF_CAP0x04/* Capabilities Register */ +#define PCI_DLF_LOCAL_DLF_SUP_MASK0x007f /* Local Data Link Feature Supported */ +#define PCI_DLF_EXCHANGE_ENABLE 0x8000 /* Data Link Feature Exchange Enable */ +#define PCI_DLF_STS0x08/* Status Register */ +#define PCI_DLF_REMOTE_DLF_SUP_MASK 0x007f /* Remote Data Link Feature Supported */ +#define PCI_DLF_REMOTE_DLF_SUP_VALID 0x8000 /* Remote Data Link Feature Support Valid */ + +/* Physical Layer 16.0 GT/s */ +#define PCI_PL_16GT_CAP0x04/* Capabilities Register */ +#define PCI_PL_16GT_CTRL 0x08/* Control Register */ +#define PCI_PL_16GT_STS0x0c/* Status Register */ +#define PCI_PL_16GT_LDPM_STS 0x10/* Local Data Parity Mismatch Status Register */ +#define PCI_PL_16GT_FRDPM_STS 0x14/* First Retimer Data Parity Mismatch Status Register */ +#define PCI_PL_16GT_SRDPM_STS 0x18/* Second Retimer Data Parity Mismatch Status Register */ +#define PCI_PL_16GT_RSVD 0x1C/* Reserved */ +#define PCI_PL_16GT_LE_CTRL0x20/* Lane Equalization Control Register */ + #endif /* LINUX_PCI_REGS_H */ -- 2.17.1
[PATCH V8 07/15] PCI: dwc: Add support to enable CDM register check
Add support to enable CDM (Configuration Dependent Module) register check for any data corruption based on the device-tree flag 'snps,enable-cdm-check'. Signed-off-by: Vidya Sagar Acked-by: Gustavo Pimentel Reviewed-by: Thierry Reding --- Changes since [v7]: * None Changes since [v6]: * Changed "enable-cdm-check" to "snps,enable-cdm-check" Changes since [v5]: * None Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Changed code and commit description to reflect change in flag from 'cdm-check' to 'enable-cdm-check' Changes since [v1]: * This is a new patch in v2 series drivers/pci/controller/dwc/pcie-designware.c | 7 +++ drivers/pci/controller/dwc/pcie-designware.h | 9 + 2 files changed, 16 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index d8be6c3339fa..e9a059163034 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -521,4 +521,11 @@ void dw_pcie_setup(struct dw_pcie *pci) break; } dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); + + if (of_property_read_bool(np, "snps,enable-cdm-check")) { + val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS); + val |= PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS | + PCIE_PL_CHK_REG_CHK_REG_START; + dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val); + } } diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 45cd7c88d28a..6f555025caf9 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -86,6 +86,15 @@ #define PCIE_MISC_CONTROL_1_OFF0x8BC #define PCIE_DBI_RO_WR_EN BIT(0) +#define PCIE_PL_CHK_REG_CONTROL_STATUS 0xB20 +#define PCIE_PL_CHK_REG_CHK_REG_START BIT(0) +#define PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS BIT(1) +#define PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR BIT(16) +#define PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERRORBIT(17) +#define PCIE_PL_CHK_REG_CHK_REG_COMPLETE BIT(18) + +#define PCIE_PL_CHK_REG_ERR_ADDR 0xB28 + /* * iATU Unroll-specific register definitions * From 4.80 core version the address translation will be made by unroll -- 2.17.1
[PATCH V8 02/15] PCI: Disable MSI for Tegra194 root port
Tegra194 rootports don't generate MSI interrupts for PME and AER events. Since PCIe spec (Ref: r4.0 sec 7.7.1.2 and 7.7.2.2) doesn't support using a mix of INTx and MSI/MSI-X, MSI needs to be disabled to avoid root ports service drivers registering their respective ISRs with MSI interrupt and to let only INTx be used for all events. Signed-off-by: Vidya Sagar Reviewed-by: Thierry Reding --- Changes since [v7]: * Changed quirk macro to consider class code as well to avoid this quirk getting applied to Tegra194 when it is operating in endpoint mode. Also quoted relevant sections from PCIe spec in comments. Changes since [v6]: * This is a new patch drivers/pci/quirks.c | 23 +++ 1 file changed, 23 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0f16acc323c6..69c061e0ca7d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2592,6 +2592,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15, nvenet_msi_disable); +/* + * PCIe spec r4.0 sec 7.7.1.2 and sec 7.7.2.2 say that if MSI/MSI-X is enabled, + * then the device can't use INTx interrupts. Tegra194's PCIe root ports don't + * generate MSI interrupts for PME and AER events instead only INTx interrupts + * are generated. Though Tegra194 can generate MSI interrupts for other events, + * since PCIe specificiation doesn't support using a mix of INTx and MSI/MSI-X, + * it is required to disable MSI interrupts to avoid port service drivers + * registering their respective ISRs for MSIs. + */ +static void pci_quirk_nvidia_tegra194_disable_rp_msi(struct pci_dev *dev) +{ + dev->no_msi = 1; +} +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_NVIDIA, 0x1ad0, + PCI_CLASS_BRIDGE_PCI, 8, + pci_quirk_nvidia_tegra194_disable_rp_msi); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_NVIDIA, 0x1ad1, + PCI_CLASS_BRIDGE_PCI, 8, + pci_quirk_nvidia_tegra194_disable_rp_msi); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_NVIDIA, 0x1ad2, + PCI_CLASS_BRIDGE_PCI, 8, + pci_quirk_nvidia_tegra194_disable_rp_msi); + /* * Some versions of the MCP55 bridge from Nvidia have a legacy IRQ routing * config register. This register controls the routing of legacy -- 2.17.1
[PATCH V8 05/15] PCI: dwc: Add ext config space capability search API
Add extended configuration space capability search API using struct dw_pcie * pointer Signed-off-by: Vidya Sagar Acked-by: Gustavo Pimentel --- Changes since [v7]: * Changed data types of return and arguments to be inline with data being returned and passed. Changes since [v6]: * None Changes since [v5]: * None Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * None Changes since [v1]: * This is a new patch in v2 series drivers/pci/controller/dwc/pcie-designware.c | 41 drivers/pci/controller/dwc/pcie-designware.h | 1 + 2 files changed, 42 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 38d76bd63b8f..d8be6c3339fa 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -53,6 +53,47 @@ u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap) } EXPORT_SYMBOL_GPL(dw_pcie_find_capability); +static u16 dw_pcie_find_next_ext_capability(struct dw_pcie *pci, u16 start, + u8 cap) +{ + u32 header; + int ttl; + int pos = PCI_CFG_SPACE_SIZE; + + /* minimum 8 bytes per capability */ + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8; + + if (start) + pos = start; + + header = dw_pcie_readl_dbi(pci, pos); + /* +* If we have no capabilities, this is indicated by cap ID, +* cap version and next pointer all being 0. +*/ + if (header == 0) + return 0; + + while (ttl-- > 0) { + if (PCI_EXT_CAP_ID(header) == cap && pos != start) + return pos; + + pos = PCI_EXT_CAP_NEXT(header); + if (pos < PCI_CFG_SPACE_SIZE) + break; + + header = dw_pcie_readl_dbi(pci, pos); + } + + return 0; +} + +u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap) +{ + return dw_pcie_find_next_ext_capability(pci, 0, cap); +} +EXPORT_SYMBOL_GPL(dw_pcie_find_ext_capability); + int dw_pcie_read(void __iomem *addr, int size, u32 *val) { if (!IS_ALIGNED((uintptr_t)addr, size)) { diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 6cb978132469..45cd7c88d28a 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -252,6 +252,7 @@ struct dw_pcie { container_of((endpoint), struct dw_pcie, ep) u8 dw_pcie_find_capability(struct dw_pcie *pci, u8 cap); +u16 dw_pcie_find_ext_capability(struct dw_pcie *pci, u8 cap); int dw_pcie_read(void __iomem *addr, int size, u32 *val); int dw_pcie_write(void __iomem *addr, int size, u32 val); -- 2.17.1
[PATCH V8 06/15] dt-bindings: PCI: designware: Add binding for CDM register check
Add support to enable CDM (Configuration Dependent Module) registers check for any data corruption. CDM registers include standard PCIe configuration space registers, Port Logic registers and iATU and DMA registers. Refer Section S.4 of Synopsys DesignWare Cores PCI Express Controller Databook Version 4.90a Signed-off-by: Vidya Sagar Reviewed-by: Thierry Reding Reviewed-by: Rob Herring --- Changes since [v7]: * None Changes since [v6]: * Changed "enable-cdm-check" to "snps,enable-cdm-check" Changes since [v5]: * None Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * Changed flag name from 'cdm-check' to 'enable-cdm-check' * Added info about Port Logic and DMA registers being part of CDM Changes since [v1]: * This is a new patch in v2 series Documentation/devicetree/bindings/pci/designware-pcie.txt | 5 + 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt index 5561a1c060d0..3fba04da6a59 100644 --- a/Documentation/devicetree/bindings/pci/designware-pcie.txt +++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt @@ -34,6 +34,11 @@ Optional properties: - clock-names: Must include the following entries: - "pcie" - "pcie_bus" +- snps,enable-cdm-check: This is a boolean property and if present enables + automatic checking of CDM (Configuration Dependent Module) registers + for data corruption. CDM registers include standard PCIe configuration + space registers, Port Logic registers, DMA and iATU (internal Address + Translation Unit) registers. RC mode: - num-viewport: number of view ports configured in hardware. If a platform does not specify it, the driver assumes 2. -- 2.17.1
[PATCH V8 03/15] PCI: dwc: Perform dbi regs write lock towards the end
Remove multiple write enable and disable sequences of dbi registers as Tegra194 implements writes to BAR-0 register (offset: 0x10) controlled by DBI write-lock enable bit thereby not allowing any further writes to BAR-0 register in config space to take place. Hence enabling write permission at the start of function and disabling the same only towards the end. Signed-off-by: Vidya Sagar Reviewed-by: Thierry Reding --- Changes since [v7]: * None Changes since [v6]: * None Changes since [v5]: * Moved write enable to the beginning of the API and write disable to the end Changes since [v4]: * None Changes since [v3]: * None Changes since [v2]: * None Changes since [v1]: * None drivers/pci/controller/dwc/pcie-designware-host.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index f93252d0da5b..d3156446ff27 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -628,6 +628,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp) u32 val, ctrl, num_ctrls; struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + /* +* Enable DBI read-only registers for writing/updating configuration. +* Write permission gets disabled towards the end of this function. +*/ + dw_pcie_dbi_ro_wr_en(pci); + dw_pcie_setup(pci); if (!pp->ops->msi_host_init) { @@ -650,12 +656,10 @@ void dw_pcie_setup_rc(struct pcie_port *pp) dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x); /* Setup interrupt pins */ - dw_pcie_dbi_ro_wr_en(pci); val = dw_pcie_readl_dbi(pci, PCI_INTERRUPT_LINE); val &= 0x00ff; val |= 0x0100; dw_pcie_writel_dbi(pci, PCI_INTERRUPT_LINE, val); - dw_pcie_dbi_ro_wr_dis(pci); /* Setup bus numbers */ val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS); @@ -687,15 +691,13 @@ void dw_pcie_setup_rc(struct pcie_port *pp) dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); - /* Enable write permission for the DBI read-only register */ - dw_pcie_dbi_ro_wr_en(pci); /* Program correct class for RC */ dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI); - /* Better disable write permission right after the update */ - dw_pcie_dbi_ro_wr_dis(pci); dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, ); val |= PORT_LOGIC_SPEED_CHANGE; dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); + + dw_pcie_dbi_ro_wr_dis(pci); } EXPORT_SYMBOL_GPL(dw_pcie_setup_rc); -- 2.17.1
Re: Linux 5.1.5
Thanks, a bunch Greg! On 18:58 Sat 25 May , Greg KH wrote: I'm announcing the release of the 5.1.5 kernel. All users of the 5.1 kernel series must upgrade. The updated 5.1.y git tree can be found at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-5.1.y and can be browsed at the normal kernel.org git web browser: https://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git;a=summary thanks, greg k-h Documentation/filesystems/porting |5 Makefile|2 arch/Kconfig|2 arch/arm/boot/dts/imx6-logicpd-baseboard.dtsi |2 arch/mips/kernel/perf_event_mipsxx.c| 21 - arch/parisc/boot/compressed/head.S |6 arch/parisc/include/asm/assembly.h |6 arch/parisc/include/asm/cache.h | 10 arch/parisc/kernel/head.S |4 arch/parisc/kernel/process.c|1 arch/parisc/kernel/syscall.S|2 arch/parisc/mm/init.c |2 arch/powerpc/include/asm/mmu_context.h |1 arch/um/include/asm/mmu_context.h |1 arch/unicore32/include/asm/mmu_context.h|1 arch/x86/entry/entry_64.S | 18 + arch/x86/include/asm/mmu_context.h |6 arch/x86/include/asm/mpx.h | 15 arch/x86/include/asm/text-patching.h| 28 + arch/x86/kernel/ftrace.c| 32 +- arch/x86/mm/mpx.c | 10 block/blk-core.c|2 block/blk-mq-sysfs.c|6 block/blk-mq.c |8 block/blk-mq.h |2 drivers/base/dd.c |5 drivers/block/brd.c |7 drivers/clk/hisilicon/clk-hi3660.c |6 drivers/clk/mediatek/clk-pll.c | 48 ++- drivers/clk/rockchip/clk-rk3328.c | 18 - drivers/clk/tegra/clk-pll.c |4 drivers/dma/imx-sdma.c | 15 drivers/hwtracing/intel_th/msu.c| 35 ++ drivers/hwtracing/stm/core.c|9 drivers/infiniband/hw/mlx5/main.c |5 drivers/infiniband/ulp/ipoib/ipoib_main.c | 13 drivers/iommu/tegra-smmu.c | 25 + drivers/md/dm-cache-metadata.c |9 drivers/md/dm-crypt.c |9 drivers/md/dm-delay.c |3 drivers/md/dm-init.c|8 drivers/md/dm-integrity.c |4 drivers/md/dm-ioctl.c |6 drivers/md/dm-mpath.c |2 drivers/md/dm-zoned-metadata.c |5 drivers/md/dm.c |4 drivers/md/md.c | 180 +-- drivers/md/md.h | 25 - drivers/md/raid5.c | 29 + drivers/media/i2c/ov6650.c |2 drivers/media/platform/Kconfig |2 drivers/memory/tegra/mc.c |2 drivers/net/Makefile|2 drivers/net/ethernet/mellanox/mlx4/mcg.c|2 drivers/net/ethernet/mellanox/mlx5/core/Kconfig |1 drivers/net/ethernet/mellanox/mlx5/core/ecpf.c |2 drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c| 18 + drivers/net/ethernet/mellanox/mlx5/core/en_rep.c| 19 + drivers/net/ethernet/mellanox/mlx5/core/en_tc.c |2 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c |2 drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c | 30 - drivers/net/ethernet/mellanox/mlxsw/core.c |6 drivers/net/ethernet/mellanox/mlxsw/core.h |2 drivers/net/ethernet/mellanox/mlxsw/core_env.c | 18 + drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c|3 drivers/net/ethernet/mellanox/mlxsw/core_thermal.c |6 drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c | 17 - drivers/net/ppp/ppp_deflate.c | 20 - drivers/net/usb/qmi_wwan.c |2 drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c | 26 + drivers/net/wireless/intersil/p54/p54pci.c |
[PATCH] dlpar: Fix a missing-check bug in dlpar_parse_cc_property()
In dlpar_parse_cc_property(), 'prop->name' is allocated by kstrdup(). kstrdup() may return NULL, so it should be checked and handle error. And prop should be freed if 'prop->name' is NULL. Signed-off-by: Gen Zhang --- diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 1795804..c852024 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -61,6 +61,10 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) name = (char *)ccwa + be32_to_cpu(ccwa->name_offset); prop->name = kstrdup(name, GFP_KERNEL); + if (!prop->name) { + dlpar_free_cc_property(prop); + return NULL; + } prop->length = be32_to_cpu(ccwa->prop_length); value = (char *)ccwa + be32_to_cpu(ccwa->prop_offset); ---
Re: [A General Question] What should I do after getting Reviewed-by from a maintainer?
On Sat, May 25, 2019 at 07:06:48AM +0200, Willy Tarreau wrote: > On Sat, May 25, 2019 at 10:12:41AM +0800, Gen Zhang wrote: > > On Fri, May 24, 2019 at 04:21:36PM -0700, Randy Dunlap wrote: > > > On 5/22/19 6:17 PM, Gen Zhang wrote: > > > > Hi Andrew, > > > > I am starting submitting patches these days and got some patches > > > > "Reviewed-by" from maintainers. After checking the > > > > submitting-patches.html, I figured out what "Reviewed-by" means. But I > > > > didn't get the guidance on what to do after getting "Reviewed-by". > > > > Am I supposed to send this patch to more maintainers? Or something else? > > > > Thanks > > > > Gen > > > > > > > > > > [Yes, I am not Andrew. ;] > > > > > > Patches should be sent to a maintainer who is responsible for merging > > > changes for the driver or $arch or subsystem. > > > And they should also be Cc-ed to the appropriate mailing list(s) and > > > source code author(s), usually [unless they are no longer active]. > > > > > > Some source files have author email addresses in them. > > > Or in a kernel git tree, you can use "git log path/to/source/file.c" to > > > see > > > who has been making & merging patches to that file.c. > > > Probably the easiest thing to do is run ./scripts/get_maintainer.pl and > > > it will try to tell you who to send the patch to. > > > > > > HTH. > > > -- > > > ~Randy > > Thanks for your patient instructions, Randy! I alrady figured it out. > > Then if your question is what to do with these "Reviewed-by", you should > edit your patches and place these fields next to your Signed-off-by line > to indicate that these persons have reviewed this code (and didn't have > anything particular to say about it). From this point you should not > modify the patches with this tag. > > When you'll resend your final series to the maintainer, it will include > all these reviewed-by tags and will generally save the maintainer some > review time by skipping some of them. > > Willy Thanks for your instructions, Willy! I already figured out what to do now. Thanks Gen
Re: [PATCH 2/3] thermal: sun50i: add thermal driver for h6
Hello Yangtao, On Sun, May 26, 2019 at 02:48:13AM +0800, Frank Lee wrote: > On Sun, May 19, 2019 at 10:22 PM Ondřej Jirman wrote: > > > > I know, I don't think it needs to be per-soc. These actions are all shared > > by > > all SoCs. Maybe with an exception that some SoCs may need one more clock, > > but > > that can be made optionally-required by some flag in struct > > sunxi_thermal_chip. > > > > Only highly SoC specific thing is configuring the THS registers for sampling > > frequency/averaging/enabling interrupts. The reset/clock enable is generic, > > and > > already abstracted by the clock/reset framework. > > > > So what I suggest is having: > > > > sunxi_ths_enable() > > reset deassert > > bus clock prepare enable > > optionally module clock prepare enable (in the future) > > call per-soc calibration > > call per-soc setup callback > > > > sunxi_ths_disable() > > reset assert > > bus clock unprepare disable > > optionally module clock unprepare disable > > > > And if you could move devm_nvmem_cell_get to probe that should make per-SoC > > calibration callback also less repetitive and could avoid undoing the enable > > in case it returns EPROBE_DEFER (which is possible). > > > > All this should make it easier to support PM in the future and add less > > cumbersome to add support for A83T and H3/H5. > > > > BTW, what are your plans for more SoC support? I'd like to add support for > > A83T and H3/H5, maybe even during the 5.3 cycle if this driver happens to > > land > > early enough. If you don't have any plans I'll take it on. > > > > I plan to support h3 and a33 later. > Can you support other platforms? Yes, I can do A83T. H5 is similar (the same?) as H3. thank you and regards, o. > Cheers, > Yangtao > > > thank you and regards, > > o. > > > > > > > > > > thank you and regards, > > > > o. > > > > > > > > > Regards, > > > > > Yangtao > > > > > > ___ > > > linux-arm-kernel mailing list > > > linux-arm-ker...@lists.infradead.org > > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > > ___ > linux-arm-kernel mailing list > linux-arm-ker...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
[PATCH 4/8] staging: kpc2000: kpc_i2c: Remove unnecessary consecutive newlines
The kpc2000_i2c.c file contains instances of unnecessary consecutive newlines which impact the readability of the file. Remove these unnecessary newlines. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 5 - 1 file changed, 5 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 1d100bb7c548..1767f351a116 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -115,7 +115,6 @@ struct i2c_device { #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 - #define FEATURE_SMBUS_PEC BIT(0) #define FEATURE_BLOCK_BUFFERBIT(1) #define FEATURE_BLOCK_PROC BIT(2) @@ -521,8 +520,6 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, return 0; } - - static u32 i801_func(struct i2c_adapter *adapter) { struct i2c_device *priv = i2c_get_adapdata(adapter); @@ -571,8 +568,6 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = i801_func, }; - - / *** Part 2 - Driver Handlers *** / -- 2.21.0
[PATCH 7/8] staging: kpc2000: kpc_i2c: fail probe if unable to map I/O space
The kpc2000 driver does not verify whether or not mapping the I/O space succeeded during probe time. Make the driver verify that the mapping operation was successful before potentially using that area in the future. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 452052bf9476..51e91653e183 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -591,6 +591,8 @@ static int pi2c_probe(struct platform_device *pldev) return -ENXIO; priv->smba = (unsigned long)ioremap_nocache(res->start, resource_size(res)); + if (!priv->smba) + return -ENOMEM; platform_set_drvdata(pldev, priv); -- 2.21.0
[PATCH 5/8] staging: kpc2000: kpc_i2c: Use drvdata instead of platform_data
The kpc_i2c driver stashes private state data in the platform_data member of its device structure. In general, the platform_data structure is used for passing data to the driver during probe() rather than as a storage area for runtime state data. Instead, use the drvdata member for all state info meant to be accessible in driver callbacks. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 1767f351a116..e4bbb91af972 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -589,7 +589,7 @@ static int pi2c_probe(struct platform_device *pldev) res = platform_get_resource(pldev, IORESOURCE_MEM, 0); priv->smba = (unsigned long)ioremap_nocache(res->start, resource_size(res)); - pldev->dev.platform_data = priv; + platform_set_drvdata(pldev, priv); priv->features |= FEATURE_IDF; priv->features |= FEATURE_I2C_BLOCK_READ; @@ -620,7 +620,7 @@ static int pi2c_remove(struct platform_device *pldev) { struct i2c_device *lddev; - lddev = (struct i2c_device *)pldev->dev.platform_data; + lddev = (struct i2c_device *)platform_get_drvdata(pldev); i2c_del_adapter(>adapter); -- 2.21.0
[PATCH 3/8] staging: kpc2000: kpc_i2c: Use BIT macro rather than manual bit shifting
The FEATURES_* symbols use bit shifting of the style (1 << k) in order to assign a certain meaning to the value of inividual bits being set in the value of a given variable. Instead, use the BIT() macro in order to improve readability and maintain consistency with the rest of the kernel. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index b2a9cda05f1b..1d100bb7c548 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -116,12 +116,12 @@ struct i2c_device { #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 -#define FEATURE_SMBUS_PEC (1 << 0) -#define FEATURE_BLOCK_BUFFER(1 << 1) -#define FEATURE_BLOCK_PROC (1 << 2) -#define FEATURE_I2C_BLOCK_READ (1 << 3) +#define FEATURE_SMBUS_PEC BIT(0) +#define FEATURE_BLOCK_BUFFERBIT(1) +#define FEATURE_BLOCK_PROC BIT(2) +#define FEATURE_I2C_BLOCK_READ BIT(3) /* Not really a feature, but it's convenient to handle it as such */ -#define FEATURE_IDF (1 << 15) +#define FEATURE_IDF BIT(15) // FIXME! #undef inb_p -- 2.21.0
[PATCH 8/8] staging: kpc2000: kpc_i2c: Use devm_* API to manage mapped I/O space
The kpc_i2c driver does not unmap its I/O space upon error cases in the probe() function or upon remove(). Make the driver clean up after itself more maintainably by using the managed resource API. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 51e91653e183..a434dd0b78c4 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -590,7 +590,9 @@ static int pi2c_probe(struct platform_device *pldev) if (!res) return -ENXIO; - priv->smba = (unsigned long)ioremap_nocache(res->start, resource_size(res)); + priv->smba = (unsigned long)devm_ioremap_nocache(>dev, +res->start, +resource_size(res)); if (!priv->smba) return -ENOMEM; -- 2.21.0
[PATCH 6/8] staging: kpc2000: kpc_i2c: fail probe if unable to get I/O resource
The kpc_i2c driver attempts to map its I/O space without verifying whether or not the result of platform_get_resource() is NULL. Make the driver check that platform_get_resource did not return NULL before attempting to use the value returned to map an I/O space. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index e4bbb91af972..452052bf9476 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -587,6 +587,9 @@ static int pi2c_probe(struct platform_device *pldev) priv->adapter.algo = _algorithm; res = platform_get_resource(pldev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + priv->smba = (unsigned long)ioremap_nocache(res->start, resource_size(res)); platform_set_drvdata(pldev, priv); -- 2.21.0
[PATCH 0/8] staging: kpc2000: kpc_i2c: assorted driver cleanup
This series contains some patches aimed toward: - cleaning up unused/unneeded parts of driver state - a couple of small style fixups - a couple of API changes - better error handling in probe() in the kpc2000 i2c driver. Geordan Neukum (8): staging: kpc2000: kpc_i2c: Remove unused rw_sem staging: kpc2000: kpc_i2c: Remove pldev from i2c_device structure staging: kpc2000: kpc_i2c: Use BIT macro rather than manual bit shifting staging: kpc2000: kpc_i2c: Remove unnecessary consecutive newlines staging: kpc2000: kpc_i2c: Use drvdata instead of platform_data staging: kpc2000: kpc_i2c: fail probe if unable to get I/O resource staging: kpc2000: kpc_i2c: fail probe if unable to map I/O space staging: kpc2000: kpc_i2c: Use devm_* API to manage mapped I/O space drivers/staging/kpc2000/kpc2000_i2c.c | 33 --- 1 file changed, 15 insertions(+), 18 deletions(-) -- 2.21.0
[PATCH 1/8] staging: kpc2000: kpc_i2c: Remove unused rw_sem
In pi2c_probe, a rw_sem is initialized and stashed off in the i2c_device private runtime state struct. This rw_sem is never used after initialization. Remove the rw_sem and cleanup unneeded header inclusion. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index fb9a8386bcce..2c272ad8eca6 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include "kpc.h" @@ -38,7 +37,6 @@ struct i2c_device { unsigned long smba; struct i2c_adapter adapter; struct platform_device *pldev; - struct rw_semaphore rw_sem; unsigned intfeatures; }; @@ -606,7 +604,6 @@ static int pi2c_probe(struct platform_device *pldev) priv->features |= FEATURE_BLOCK_BUFFER; //init_MUTEX(>sem); - init_rwsem(>rw_sem); /* set up the sysfs linkage to our parent device */ priv->adapter.dev.parent = >dev; -- 2.21.0
[PATCH 2/8] staging: kpc2000: kpc_i2c: Remove pldev from i2c_device structure
The i2c_device structure contains a member used to stash a pointer to a platform_device. The driver contains no cases of this member being used after initialization. Remove the unnecessary struct member and the initialization of this member in the sole instance where the driver creates a variable of type: struct i2c_device. Signed-off-by: Geordan Neukum --- drivers/staging/kpc2000/kpc2000_i2c.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/kpc2000/kpc2000_i2c.c b/drivers/staging/kpc2000/kpc2000_i2c.c index 2c272ad8eca6..b2a9cda05f1b 100644 --- a/drivers/staging/kpc2000/kpc2000_i2c.c +++ b/drivers/staging/kpc2000/kpc2000_i2c.c @@ -36,7 +36,6 @@ MODULE_SOFTDEP("pre: i2c-dev"); struct i2c_device { unsigned long smba; struct i2c_adapter adapter; - struct platform_device *pldev; unsigned intfeatures; }; @@ -595,7 +594,6 @@ static int pi2c_probe(struct platform_device *pldev) res = platform_get_resource(pldev, IORESOURCE_MEM, 0); priv->smba = (unsigned long)ioremap_nocache(res->start, resource_size(res)); - priv->pldev = pldev; pldev->dev.platform_data = priv; priv->features |= FEATURE_IDF; -- 2.21.0
Re: Linux 5.1.5 (a regression: kernel BUG at lib/list_debug.c:29!)
On 5/25/19 1:37 PM, rwar...@gmx.de wrote: > hallo > > I today I got a regression > > see the attached dmesg > > -- > > Ronald [adding netdev + TIPC maintainers] [4.953673] [ cut here ] [4.953674] kernel BUG at lib/list_debug.c:29! [4.953678] invalid opcode: [#1] PREEMPT SMP PTI [4.953680] CPU: 3 PID: 1437 Comm: (t-daemon) Not tainted 5.1.5_MY #1 [4.953681] Hardware name: MSI MS-7A72/B250 PC MATE (MS-7A72), BIOS 3.90 07/05/2018 [4.953685] RIP: 0010:__list_add_valid.cold+0x26/0x3f [4.953686] Code: 00 00 00 c3 4c 89 c1 48 c7 c7 28 dc 5e ab e8 0e 80 b4 ff 0f 0b 48 89 f2 4c 89 c1 48 89 fe 48 c7 c7 d8 dc 5e ab e8 f7 7f b4 ff <0f> 0b 48 89 d1 4c 89 c6 4c 89 ca 48 c7 c7 80 dc 5e ab e8 e0 7f b4 [4.953687] RSP: 0018:b18ec22ffd88 EFLAGS: 00010246 [4.953689] RAX: 0058 RBX: ab8f5f00 RCX: [4.953690] RDX: RSI: 96b11eed5548 RDI: [4.953690] RBP: ab8f6090 R08: 0366 R09: 0003 [4.953691] R10: R11: 0001 R12: ab8f6090 [4.953692] R13: 0036 R14: 96b119564c00 R15: [4.953693] FS: 7f4f879bc980() GS:96b11eec() knlGS: [4.953694] CS: 0010 DS: ES: CR0: 80050033 [4.953695] CR2: 55ed16dfe800 CR3: 000459802005 CR4: 003606e0 [4.953696] DR0: DR1: DR2: [4.953697] DR3: DR6: fffe0ff0 DR7: 0400 [4.953697] Call Trace: [4.953701] proto_register+0x13b/0x1f0 [4.953704] tipc_socket_init+0x13/0x40 [4.953707] tipc_init_net+0xa5/0x130 [4.953709] ops_init+0x35/0x100 [4.953711] setup_net+0xc4/0x1e0 [4.953712] copy_net_ns+0xbd/0x180 [4.953715] create_new_namespaces+0x113/0x1e0 [4.953716] unshare_nsproxy_namespaces+0x50/0xa0 [4.953719] ksys_unshare+0x186/0x350 [4.953721] __x64_sys_unshare+0x9/0x10 [4.953722] do_syscall_64+0x50/0x160 [4.953725] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [4.953726] RIP: 0033:0x7f4f88a04e4b [4.953728] Code: 73 01 c3 48 8b 0d 3d 40 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 10 01 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 0d 40 0c 00 f7 d8 64 89 01 48 [4.953729] RSP: 002b:7ffc7f4d2088 EFLAGS: 0246 ORIG_RAX: 0110 [4.953730] RAX: ffda RBX: 55ed16eeab10 RCX: 7f4f88a04e4b [4.953731] RDX: RSI: 7ffc7f4d1ff0 RDI: 4000 [4.953732] RBP: 7ffc7f4d2270 R08: 7ffc7f4d2074 R09: 0001 [4.953732] R10: R11: 0246 R12: fff5 [4.953733] R13: R14: 55ed16fcf2f0 R15: [4.953735] Modules linked in: kvm_intel kvm irqbypass iTCO_wdt iTCO_vendor_support i915 video intel_gtt [4.953739] ---[ end trace 40639449ef1b96be ]--- Full log is at https://lore.kernel.org/lkml/f3c89197-90dc-240b-d96b-aa1286af7...@gmx.de/T/#u -- ~Randy
Re: SGX vs LSM (Re: [PATCH v20 00/28] Intel SGX1 support)
On Sat, May 25, 2019 at 3:40 PM Xing, Cedric wrote: > > > From: Andy Lutomirski [mailto:l...@amacapital.net] > > Sent: Friday, May 24, 2019 4:42 PM > > > > > On May 24, 2019, at 3:41 PM, Sean Christopherson > > > wrote: > > > > > >> On Fri, May 24, 2019 at 02:27:34PM -0700, Andy Lutomirski wrote: > > >> On Fri, May 24, 2019 at 1:03 PM Sean Christopherson > > >> wrote: > > >>> > > On Fri, May 24, 2019 at 12:37:44PM -0700, Andy Lutomirski wrote: > > > On Fri, May 24, 2019 at 11:34 AM Xing, Cedric > > > wrote: > > > > > > If "initial permissions" for enclaves are less restrictive than > > > shared objects, then it'd become a backdoor for circumventing LSM > > > when enclave whitelisting is *not* in place. For example, an > > > adversary may load a page, which would otherwise never be executable, > > > as an executable > > page in EPC. > > > > > > In the case a RWX page is needed, the calling process has to have > > > a RWX page serving as the source for EADD so PROCESS__EXECMEM will > > > have been checked. For SGX2, changing an EPC page to RWX is > > > subject to FILE__EXECMEM on /dev/sgx/enclave, which I see as a > > > security benefit because it only affects the enclave but not the > > > whole process hosting > > it. > > > > So the permission would be like FILE__EXECMOD on the source enclave > > page, because it would be mapped MAP_ANONYMOUS, PROT_WRITE? > > MAP_SHARED, PROT_WRITE isn't going to work because that means you > > can modify the file. > > >>> > > >>> Was this in response to Cedric's comment, or to my comment? > > >> > > >> Yours. I think that requiring source pages to be actually mapped W > > >> is not such a great idea. > > > > > > I wasn't requiring source pages to be mapped W. At least I didn't > > > intend to require W. What I was trying to say is that SGX could > > > trigger an EXECMEM check if userspace attempted to EADD or EAUG an > > > enclave page with RWX permissions, e.g.: > > > > > > if ((SECINFO.PERMS & RWX) == RWX) { > > > ret = security_mmap_file(NULL, RWX, ???); > > > if (ret) > > > return ret; > > > } > > > > > > But that's a moot point if we add security_enclave_load() or whatever. > > > > > >> > > >>> > > I'm starting to think that looking at the source VMA permission > > bits or source PTE permission bits is putting a bit too much policy > > into the driver as opposed to the LSM. How about delegating the > > whole thing to an LSM hook? The EADD operation would invoke a new > > hook, something like: > > > > int security_enclave_load_bytes(void *source_addr, struct > > vm_area_struct *source_vma, loff_t source_offset, unsigned int > > maxperm); > > > > Then you don't have to muck with mapping anything PROT_EXEC. > > Instead you load from a mapping of a file and the LSM applies > > whatever policy it feels appropriate. If the first pass gets > > something wrong, the application or library authors can take it up > > with the SELinux folks without breaking the whole ABI :) > > > > (I'm proposing passing in the source_vma because this hook would be > > called with mmap_sem held for read to avoid a TOCTOU race.) > > > > If we go this route, the only substantial change to the existing > > driver that's needed for an initial upstream merge is the maxperm > > mechanism and whatever hopefully minimal API changes are needed to > > allow users to conveniently set up the mappings. And we don't need > > to worry about how to hack around mprotect() calling into the LSM, > > because the LSM will actually be aware of SGX and can just do the > > right thing. > > >>> > > >>> This doesn't address restricting which processes can run which > > >>> enclaves, it only allows restricting the build flow. Or are you > > >>> suggesting this be done in addition to whitelisting sigstructs? > > >> > > >> In addition. > > >> > > >> But I named the function badly and gave it a bad signature, which > > >> confused you. Let's try again: > > >> > > >> int security_enclave_load_from_memory(const struct vm_area_struct > > >> *source, unsigned int maxperm); > > > > > > I prefer security_enclave_load(), "from_memory" seems redundant at best. > > > > Fine with me. > > If we think of EADD as a way of mmap()'ing an enclave file into memory, would > this security_enclave_load() be the same as > security_mmap_file(source_vma->vm_file, maxperm, MAP_PRIVATE), except that > the target is now EPC instead of regular pages? Hmm, that's clever. Although it seems plausible that an LSM would want to allow RX or RWX of a given file page but only in the context of an approved enclave, so I think it should still be its own hook. > > > > > > > > >> Maybe some really fancy future LSM would also want loff_t > > >> source_offset, but it's probably not terribly useful. This
Re: [PATCH net-next 0/5] net: mvpp2: Classifier updates, RSS
From: Maxime Chevallier Date: Fri, 24 May 2019 12:05:49 +0200 > Here is a set of updates for the PPv2 classifier, the main feature being > the support for steering to RSS contexts, to leverage all the available > RSS tables in the controller. > > The first two patches are non-critical fixes for the classifier, the > first one prevents us from allocating too much room to store the > classification rules, the second one configuring the C2 engine as > suggested by the PPv2 functionnal specs. > > Patches 3 to 5 introduce support for RSS contexts in mvpp2, allowing us > to steer traffic to dedicated RSS tables. Series applied, thanks.
Re: [PATCH net-next] net: ethtool: Document get_rxfh_context and set_rxfh_context ethtool ops
From: Maxime Chevallier Date: Fri, 24 May 2019 12:05:30 +0200 > ethtool ops get_rxfh_context and set_rxfh_context are used to create, > remove and access parameters associated to RSS contexts, in a similar > fashion to get_rxfh and set_rxfh. > > Add a small descritopn of these callbacks in the struct ethtool_ops doc. > > Signed-off-by: Maxime Chevallier As a doc fix, I'll put this into 'net'. Thank you.
Re: [PATCH 23/23] NFS: Add fs_context support.
On Thu, May 23, 2019 at 05:19:05PM +0100, David Howells wrote: > out_no_data: > - dfprintk(MOUNT, "NFS: mount program didn't pass any mount data\n"); > - return -EINVAL; > + if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) { > + ctx->skip_reconfig_option_check = true; > + return 0; > + } That really ought to be if (fc->root) { /* remount */ ctx->skip_reconfig_option_check = true; return 0; } and similar in the v4 counterpart. fc->purpose is a bad idea; it is possible to get rid of it. Frankly, I'm tempted to add static inline bool is_remount_fc(struct fs_context *fc) { return fc->root != NULL; } and just use that in such places...
Please Respond Urgently.
With due respect, I am inviting you for a business deal of Eleven Million Three hundred thousand united states dollars where this money can be shared between us. By indicating your interest I will send you the full details on how the business will be executed. Please send your reply to my private email --- ouedraogoah...@outlook.com
Re: [GIT PULL] ext4 fixes for 5.2-rc2
The pull request you sent on Sat, 25 May 2019 17:07:14 -0400: > git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git > tags/ext4_for_linus_stable has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/35efb51eee2241a970dcf70ed950f9db7e5351f7 Thank you! -- Deet-doot-dot, I am a bot. https://korg.wiki.kernel.org/userdoc/prtracker
Re: [GIT PULL] tracing: Small fixes to histogram code and header cleanup
On Sat, May 25, 2019 at 3:39 PM Steven Rostedt wrote: > You mean this one: Yes. > I have it in my queue for the next merge window, but I can cherry pick > it and send it to you directly now. Oh, "next merge window" is *way* too late. This is a serious problem that causes tens of lines of warnings, and may be hiding other warnings as a result simply because developers stop looking at them. Warnings are bad. Linus
RE: SGX vs LSM (Re: [PATCH v20 00/28] Intel SGX1 support)
> From: Andy Lutomirski [mailto:l...@amacapital.net] > Sent: Friday, May 24, 2019 4:42 PM > > > On May 24, 2019, at 3:41 PM, Sean Christopherson > > wrote: > > > >> On Fri, May 24, 2019 at 02:27:34PM -0700, Andy Lutomirski wrote: > >> On Fri, May 24, 2019 at 1:03 PM Sean Christopherson > >> wrote: > >>> > On Fri, May 24, 2019 at 12:37:44PM -0700, Andy Lutomirski wrote: > > On Fri, May 24, 2019 at 11:34 AM Xing, Cedric > > wrote: > > > > If "initial permissions" for enclaves are less restrictive than > > shared objects, then it'd become a backdoor for circumventing LSM > > when enclave whitelisting is *not* in place. For example, an > > adversary may load a page, which would otherwise never be executable, > > as an executable > page in EPC. > > > > In the case a RWX page is needed, the calling process has to have > > a RWX page serving as the source for EADD so PROCESS__EXECMEM will > > have been checked. For SGX2, changing an EPC page to RWX is > > subject to FILE__EXECMEM on /dev/sgx/enclave, which I see as a > > security benefit because it only affects the enclave but not the whole > > process hosting > it. > > So the permission would be like FILE__EXECMOD on the source enclave > page, because it would be mapped MAP_ANONYMOUS, PROT_WRITE? > MAP_SHARED, PROT_WRITE isn't going to work because that means you > can modify the file. > >>> > >>> Was this in response to Cedric's comment, or to my comment? > >> > >> Yours. I think that requiring source pages to be actually mapped W > >> is not such a great idea. > > > > I wasn't requiring source pages to be mapped W. At least I didn't > > intend to require W. What I was trying to say is that SGX could > > trigger an EXECMEM check if userspace attempted to EADD or EAUG an > > enclave page with RWX permissions, e.g.: > > > > if ((SECINFO.PERMS & RWX) == RWX) { > > ret = security_mmap_file(NULL, RWX, ???); > > if (ret) > > return ret; > > } > > > > But that's a moot point if we add security_enclave_load() or whatever. > > > >> > >>> > I'm starting to think that looking at the source VMA permission > bits or source PTE permission bits is putting a bit too much policy > into the driver as opposed to the LSM. How about delegating the > whole thing to an LSM hook? The EADD operation would invoke a new > hook, something like: > > int security_enclave_load_bytes(void *source_addr, struct > vm_area_struct *source_vma, loff_t source_offset, unsigned int > maxperm); > > Then you don't have to muck with mapping anything PROT_EXEC. > Instead you load from a mapping of a file and the LSM applies > whatever policy it feels appropriate. If the first pass gets > something wrong, the application or library authors can take it up > with the SELinux folks without breaking the whole ABI :) > > (I'm proposing passing in the source_vma because this hook would be > called with mmap_sem held for read to avoid a TOCTOU race.) > > If we go this route, the only substantial change to the existing > driver that's needed for an initial upstream merge is the maxperm > mechanism and whatever hopefully minimal API changes are needed to > allow users to conveniently set up the mappings. And we don't need > to worry about how to hack around mprotect() calling into the LSM, > because the LSM will actually be aware of SGX and can just do the > right thing. > >>> > >>> This doesn't address restricting which processes can run which > >>> enclaves, it only allows restricting the build flow. Or are you > >>> suggesting this be done in addition to whitelisting sigstructs? > >> > >> In addition. > >> > >> But I named the function badly and gave it a bad signature, which > >> confused you. Let's try again: > >> > >> int security_enclave_load_from_memory(const struct vm_area_struct > >> *source, unsigned int maxperm); > > > > I prefer security_enclave_load(), "from_memory" seems redundant at best. > > Fine with me. If we think of EADD as a way of mmap()'ing an enclave file into memory, would this security_enclave_load() be the same as security_mmap_file(source_vma->vm_file, maxperm, MAP_PRIVATE), except that the target is now EPC instead of regular pages? > > > > >> Maybe some really fancy future LSM would also want loff_t > >> source_offset, but it's probably not terribly useful. This same > >> callback would be used for EAUG. EAUG always zeroes the EPC page before making it available to an enclave. So I don't think there's anything needed to done here. > >> > >> Following up on your discussion with Cedric about sigstruct, the > >> other callback would be something like: > >> > >> int security_enclave_init(struct file *sigstruct_file); I'd still insist in using a pointer rather than a file, for reasons that we've discussed before. For
Re: [GIT PULL] tracing: Small fixes to histogram code and header cleanup
On Sat, 25 May 2019 10:09:19 -0700 Linus Torvalds wrote: > On Fri, May 24, 2019 at 8:11 PM Steven Rostedt wrote: > > > > Tom Zanussi sent me some small fixes and cleanups to the histogram > > code and I forgot to incorporate them. > > > > I also added a small clean up patch that was sent to me a while ago > > and I just noticed it. > > Why not the warning avoidance patch? It changes no actual code, and > avoids two 20-line build warnings for me that are very annoying.. > You mean this one: http://lkml.kernel.org/r/20190523124535.ga12...@gmail.com ? I have it in my queue for the next merge window, but I can cherry pick it and send it to you directly now. It's already been through my test suite. -- Steve
Re: [PATCH 0/4] trace: introduce trace event injection
On Sat, 25 May 2019 09:57:58 -0700 Cong Wang wrote: > This patchset introduces trace event injection, the first 3 patches > are some trivial prerequisites, the last one implements the trace > event injection. Please check each patch for details. > > I have tested them with both valid and invalid input on different > tracepoints, it works as expected. Hi Cong, Thanks for sending these patches, but I just want to let you know that it's currently a US holiday, and then afterward I'll be doing quite a bit of traveling for the next two weeks. If you don't hear from me in after two weeks, please send me a reminder. Thanks! -- Steve > > Cc: Steven Rostedt > Cc: Ingo Molnar > Signed-off-by: Cong Wang > > --- > > Cong Wang (4): > trace: fold type initialization into tracing_generic_entry_update() > trace: let filter_assign_type() detect FILTER_PTR_STRING > trace: make trace_get_fields() global > trace: introduce trace event injection > > include/linux/trace_events.h | 9 + > kernel/trace/Makefile | 1 + > kernel/trace/trace.c | 8 +- > kernel/trace/trace.h | 1 + > kernel/trace/trace_event_perf.c| 3 +- > kernel/trace/trace_events.c| 12 +- > kernel/trace/trace_events_filter.c | 3 + > kernel/trace/trace_events_inject.c | 330 + > 8 files changed, 353 insertions(+), 14 deletions(-) > create mode 100644 kernel/trace/trace_events_inject.c >
Re: [PATCH] z3fold: add inter-page compaction
On Fri, 24 May 2019 17:49:18 +0200 Vitaly Wool wrote: > For each page scheduled for compaction (e. g. by z3fold_free()), > try to apply inter-page compaction before running the traditional/ > existing intra-page compaction. That means, if the page has only one > buddy, we treat that buddy as a new object that we aim to place into > an existing z3fold page. If such a page is found, that object is > transferred and the old page is freed completely. The transferred > object is named "foreign" and treated slightly differently thereafter. > > Namely, we increase "foreign handle" counter for the new page. Pages > with non-zero "foreign handle" count become unmovable. This patch > implements "foreign handle" detection when a handle is freed to > decrement the foreign handle counter accordingly, so a page may as > well become movable again as the time goes by. > > As a result, we almost always have exactly 3 objects per page and > significantly better average compression ratio. > > ... > > +static inline struct z3fold_header *handle_to_z3fold_header(unsigned long); > +static inline struct z3fold_pool *zhdr_to_pool(struct z3fold_header *); Forward-declaring inline functions is peculiar, but it does appear to work. z3fold is quite inline-happy. Fortunately the compiler will ignore the inline hint if it seems a bad idea. Even then, the below shrinks z3fold.o text from 30k to 27k. Which might even make it faster --- a/mm/z3fold.c~a +++ a/mm/z3fold.c @@ -185,8 +185,8 @@ enum z3fold_handle_flags { HANDLES_ORPHANED = 0, }; -static inline struct z3fold_header *handle_to_z3fold_header(unsigned long); -static inline struct z3fold_pool *zhdr_to_pool(struct z3fold_header *); +static struct z3fold_header *handle_to_z3fold_header(unsigned long); +static struct z3fold_pool *zhdr_to_pool(struct z3fold_header *); static struct z3fold_header *__z3fold_alloc(struct z3fold_pool *, size_t, bool); static void add_to_unbuddied(struct z3fold_pool *, struct z3fold_header *); @@ -205,7 +205,7 @@ static int size_to_chunks(size_t size) static void compact_page_work(struct work_struct *w); -static inline struct z3fold_buddy_slots *alloc_slots(struct z3fold_pool *pool, +static struct z3fold_buddy_slots *alloc_slots(struct z3fold_pool *pool, gfp_t gfp) { struct z3fold_buddy_slots *slots = kmem_cache_alloc(pool->c_handle, @@ -220,17 +220,17 @@ static inline struct z3fold_buddy_slots return slots; } -static inline struct z3fold_pool *slots_to_pool(struct z3fold_buddy_slots *s) +static struct z3fold_pool *slots_to_pool(struct z3fold_buddy_slots *s) { return (struct z3fold_pool *)(s->pool & ~HANDLE_FLAG_MASK); } -static inline struct z3fold_buddy_slots *handle_to_slots(unsigned long handle) +static struct z3fold_buddy_slots *handle_to_slots(unsigned long handle) { return (struct z3fold_buddy_slots *)(handle & ~(SLOTS_ALIGN - 1)); } -static inline void free_handle(unsigned long handle) +static void free_handle(unsigned long handle) { struct z3fold_buddy_slots *slots; struct z3fold_header *zhdr; @@ -423,7 +423,7 @@ static unsigned long encode_handle(struc return (unsigned long)>slot[idx]; } -static inline struct z3fold_header *__get_z3fold_header(unsigned long handle, +static struct z3fold_header *__get_z3fold_header(unsigned long handle, bool lock) { struct z3fold_buddy_slots *slots; @@ -648,7 +648,7 @@ static int num_free_chunks(struct z3fold } /* Add to the appropriate unbuddied list */ -static inline void add_to_unbuddied(struct z3fold_pool *pool, +static void add_to_unbuddied(struct z3fold_pool *pool, struct z3fold_header *zhdr) { if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0 || @@ -664,7 +664,7 @@ static inline void add_to_unbuddied(stru } } -static inline void *mchunk_memmove(struct z3fold_header *zhdr, +static void *mchunk_memmove(struct z3fold_header *zhdr, unsigned short dst_chunk) { void *beg = zhdr; @@ -673,7 +673,7 @@ static inline void *mchunk_memmove(struc zhdr->middle_chunks << CHUNK_SHIFT); } -static inline bool buddy_single(struct z3fold_header *zhdr) +static bool buddy_single(struct z3fold_header *zhdr) { return !((zhdr->first_chunks && zhdr->middle_chunks) || (zhdr->first_chunks && zhdr->last_chunks) || @@ -884,7 +884,7 @@ static void compact_page_work(struct wor } /* returns _locked_ z3fold page header or NULL */ -static inline struct z3fold_header *__z3fold_alloc(struct z3fold_pool *pool, +static struct z3fold_header *__z3fold_alloc(struct z3fold_pool *pool, size_t size, bool can_sleep) { struct z3fold_header *zhdr = NULL; _ > > ... > > +static inline struct z3fold_header
Re: [PATCH v2] mm: add account_locked_vm utility function
On Fri, 24 May 2019 13:50:45 -0400 Daniel Jordan wrote: > locked_vm accounting is done roughly the same way in five places, so > unify them in a helper. Standardize the debug prints, which vary > slightly, but include the helper's caller to disambiguate between > callsites. > > Error codes stay the same, so user-visible behavior does too. The one > exception is that the -EPERM case in tce_account_locked_vm is removed > because Alexey has never seen it triggered. > > ... > > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -1564,6 +1564,25 @@ long get_user_pages_unlocked(unsigned long start, > unsigned long nr_pages, > int get_user_pages_fast(unsigned long start, int nr_pages, > unsigned int gup_flags, struct page **pages); > > +int __account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc, > + struct task_struct *task, bool bypass_rlim); > + > +static inline int account_locked_vm(struct mm_struct *mm, unsigned long > pages, > + bool inc) > +{ > + int ret; > + > + if (pages == 0 || !mm) > + return 0; > + > + down_write(>mmap_sem); > + ret = __account_locked_vm(mm, pages, inc, current, > + capable(CAP_IPC_LOCK)); > + up_write(>mmap_sem); > + > + return ret; > +} That's quite a mouthful for an inlined function. How about uninlining the whole thing and fiddling drivers/vfio/vfio_iommu_type1.c to suit. I wonder why it does down_write_killable and whether it really needs to...
Re: [PATCH] binfmt_flat: make load_flat_shared_library() work
On Fri, 24 May 2019 22:18:17 +0200 Jann Horn wrote: > load_flat_shared_library() is broken: It only calls load_flat_file() if > prepare_binprm() returns zero, but prepare_binprm() returns the number of > bytes read - so this only happens if the file is empty. ouch. > Instead, call into load_flat_file() if the number of bytes read is > non-negative. (Even if the number of bytes is zero - in that case, > load_flat_file() will see nullbytes and return a nice -ENOEXEC.) > > In addition, remove the code related to bprm creds and stop using > prepare_binprm() - this code is loading a library, not a main executable, > and it only actually uses the members "buf", "file" and "filename" of the > linux_binprm struct. Instead, call kernel_read() directly. > > Cc: sta...@vger.kernel.org > Fixes: 287980e49ffc ("remove lots of IS_ERR_VALUE abuses") > Signed-off-by: Jann Horn > --- > I only found the bug by looking at the code, I have not verified its > existence at runtime. > Also, this patch is compile-tested only. > It would be nice if someone who works with nommu Linux could have a > look at this patch. 287980e49ffc was three years ago! Has it really been broken for all that time? If so, it seems a good source of freed disk space...
[GIT PULL] ext4 fixes for 5.2-rc2
The following changes since commit 2c1d0e3631e5732dba98ef49ac0bec1388776793: ext4: avoid panic during forced reboot due to aborted journal (2019-05-17 17:37:18 -0400) are available in the Git repository at: git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git tags/ext4_for_linus_stable for you to fetch changes up to 66883da1eee8ad4b38eeff7fa1c86a097d9670fc: ext4: fix dcache lookup of !casefolded directories (2019-05-24 23:48:23 -0400) Bug fixes (including a regression fix) for ext4. Gabriel Krisman Bertazi (1): ext4: fix dcache lookup of !casefolded directories Jan Kara (2): ext4: wait for outstanding dio during truncate in nojournal mode ext4: do not delete unlinked inode from orphan list on failed truncate Theodore Ts'o (1): ext4: don't perform block validity checks on the journal inode fs/ext4/dir.c | 2 +- fs/ext4/extents.c | 12 fs/ext4/inode.c | 23 ++- 3 files changed, 19 insertions(+), 18 deletions(-)
Re: [PATCH 05/12] dma-buf: add explicit buffer pinning
On Tue, 16 Apr 2019 20:38:34 +0200 Christian König wrote: > + /** > + * @unpin_dma_buf: > + * > + * This is called by dma_buf_unpin and lets the exporter know that an > + * importer doesn't need to the DMA-buf to stay were it is any more. > + * s/need to/need/ s/were/where/ > + * This is called with the dmabuf->resv object locked. > + * > + * This callback is optional. > + */ > + void (*unpin)(struct dma_buf *); > + BR Hillf ___ amd-gfx mailing list amd-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 06/12] drm: remove prime sg_table caching
On Tue, 16 Apr 2019 20:38:35 +0200 Christian König wrote: > @ -331,14 +282,19 @@ EXPORT_SYMBOL(drm_gem_map_dma_buf); > * @sgt: scatterlist info of the buffer to unmap > * @dir: direction of DMA transfer > * > - * Not implemented. The unmap is done at drm_gem_map_detach(). This can be > - * used as the _buf_ops.unmap_dma_buf callback. > + * This can be used as the _buf_ops.unmap_dma_buf callback. > */ > void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, > struct sg_table *sgt, > enum dma_data_direction dir) > { > - /* nothing to be done here */ > + if (!sgt) if (WARN_ON(!sgt)) ? > + return; > + > + dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, > +DMA_ATTR_SKIP_CPU_SYNC); > + sg_free_table(sgt); > + kfree(sgt); > } > EXPORT_SYMBOL(drm_gem_unmap_dma_buf); > > -- > 2.17.1 > BR Hillf ___ amd-gfx mailing list amd-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 03/12] dma-buf: lock the reservation object during (un)map_dma_buf v3
On Tue, 16 Apr 2019 20:38:32 +0200 Christian König wrote: > @@ -688,9 +689,9 @@ struct sg_table *dma_buf_map_attachment(struct > dma_buf_attachment *attach, > if (attach->sgt) > return attach->sgt; > > - sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); > - if (!sg_table) > - sg_table = ERR_PTR(-ENOMEM); > + reservation_object_lock(attach->dmabuf->resv, NULL); > + sg_table = dma_buf_map_attachment_locked(attach, direction); > + reservation_object_unlock(attach->dmabuf->resv); > Looks better if sg_table is checked after mapping, and feed error info back in case there is anything unusual. > return sg_table; > } Best Regards Hillf ___ amd-gfx mailing list amd-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 04/12] dma-buf: add optional invalidate_mappings callback v5
On Tue, 16 Apr 2019 20:38:33 +0200 Christian König wrote: > Each importer can now provide an invalidate_mappings callback. > > This allows the exporter to provide the mappings without the need to pin > the backing store. > > v2: don't try to invalidate mappings when the callback is NULL, > lock the reservation obj while using the attachments, > add helper to set the callback > v3: move flag for invalidation support into the DMA-buf, > use new attach_info structure to set the callback > v4: use importer_priv field instead of mangling exporter priv. > v5: drop invalidation_supported flag > > Signed-off-by: Christian König > --- > drivers/dma-buf/dma-buf.c | 37 + > include/linux/dma-buf.h | 33 +++-- > 2 files changed, 68 insertions(+), 2 deletions(-) > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > index 83c92bfd964c..a3738fab3927 100644 > --- a/drivers/dma-buf/dma-buf.c > +++ b/drivers/dma-buf/dma-buf.c > @@ -563,6 +563,8 @@ struct dma_buf_attachment *dma_buf_attach(const struct > dma_buf_attach_info *info > > attach->dev = info->dev; > attach->dmabuf = dmabuf; > + attach->importer_priv = info->importer_priv; > + attach->invalidate = info->invalidate; > > mutex_lock(>lock); > > @@ -571,7 +573,9 @@ struct dma_buf_attachment *dma_buf_attach(const struct > dma_buf_attach_info *info > if (ret) > goto err_attach; > } > + reservation_object_lock(dmabuf->resv, NULL); > list_add(>node, >attachments); > + reservation_object_unlock(dmabuf->resv); > OK, protection from resv lock is needed for attach. > mutex_unlock(>lock); > The snippet in [PATCH 01/12] dma-buf: add dynamic caching of sg_table is copied and pasted below: @@ -573,6 +573,20 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, list_add(>node, >attachments); mutex_unlock(>lock); + + if (!dmabuf->ops->dynamic_sgt_mapping) { + struct sg_table *sgt; + + sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL); + if (!sgt) + sgt = ERR_PTR(-ENOMEM); + if (IS_ERR(sgt)) { + dma_buf_detach(dmabuf, attach); + return ERR_CAST(sgt); + } + attach->sgt = sgt; Looks like the protection mentioned is also needed in this case. + } + [...] > +/** > + * dma_buf_invalidate_mappings - invalidate all mappings of this dma_buf > + * > + * @dmabuf: [in]buffer which mappings should be invalidated > + * > + * Informs all attachmenst that they need to destroy and recreated all their s/Informs/Inform/ s/attachmenst/attachments/ s/recreated/recreate/ > + * mappings. > + */ > +void dma_buf_invalidate_mappings(struct dma_buf *dmabuf) > +{ > + struct dma_buf_attachment *attach; > + > + reservation_object_assert_held(dmabuf->resv); > + > + list_for_each_entry(attach, >attachments, node) > + if (attach->invalidate) > + attach->invalidate(attach); > +} > +EXPORT_SYMBOL_GPL(dma_buf_invalidate_mappings); > + > BR Hillf ___ amd-gfx mailing list amd-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 02/12] dma-buf: add dma_buf_(un)map_attachment_locked variants v3
On Tue, 16 Apr 2019 20:38:31 +0200 Christian König wrote: > Add function variants which can be called with the reservation lock > already held. > > v2: reordered, add lockdep asserts, fix kerneldoc > v3: rebased on sgt caching > > Signed-off-by: Christian König > --- > drivers/dma-buf/dma-buf.c | 63 +++ > include/linux/dma-buf.h | 5 > 2 files changed, 68 insertions(+) > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > index 65161a82d4d5..ef480e5fb239 100644 > --- a/drivers/dma-buf/dma-buf.c > +++ b/drivers/dma-buf/dma-buf.c > @@ -623,6 +623,43 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct > dma_buf_attachment *attach) > } > EXPORT_SYMBOL_GPL(dma_buf_detach); > > +/** > + * dma_buf_map_attachment_locked - Maps the buffer into _device_ address > space > + * with the reservation lock held. Is a wrapper for map_dma_buf() of the Something is missing; seems to be s/of the/of the dma_buf_ops./ > + * > + * Returns the scatterlist table of the attachment; > + * dma_buf_ops. Oh it is sitting here! > + * @attach: [in]attachment whose scatterlist is to be returned > + * @direction: [in]direction of DMA transfer > + * > + * Returns sg_table containing the scatterlist to be returned; returns > ERR_PTR > + * on error. May return -EINTR if it is interrupted by a signal. > + * EINTR looks impossible in the code. > + * A mapping must be unmapped by using dma_buf_unmap_attachment_locked(). > Note > + * that the underlying backing storage is pinned for as long as a mapping > + * exists, therefore users/importers should not hold onto a mapping for undue > + * amounts of time. > + */ > +struct sg_table * > +dma_buf_map_attachment_locked(struct dma_buf_attachment *attach, > + enum dma_data_direction direction) > +{ > + struct sg_table *sg_table; > + > + might_sleep(); > + reservation_object_assert_held(attach->dmabuf->resv); > + > + if (attach->sgt) > + return attach->sgt; > + > + sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); > + if (!sg_table) > + sg_table = ERR_PTR(-ENOMEM); > + > + return sg_table; > +} > +EXPORT_SYMBOL_GPL(dma_buf_map_attachment_locked); > + Best Regards Hillf ___ amd-gfx mailing list amd-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH net 1/4] net/udp_gso: Allow TX timestamp with UDP GSO
> On May 23, 2019, at 2:59 PM, Willem de Bruijn > wrote:what exactly is the issue with IP_TOS? > > If I understand correctly, the issue here is that the new 'P' option > that polls on the error queue times out. This is unrelated to > specifying TOS bits? Without zerocopy or timestamps, no message is > expected on the error queue. Please disregard last message. I think I was chasing a non-issue with TOS bits. I will remove all references to TOS.
Re: [PATCH net 1/4] net/udp_gso: Allow TX timestamp with UDP GSO
> On May 23, 2019, at 2:39 PM, Willem de Bruijn > wrote: > Zerocopy notification reference count is managed in skb_segment. That > should work. > I’m trying to understand the context of reference counting in skb_segment. I assume that there is an opportunity to optimize the count of outstanding zerocopy buffers, but I can’t see it. Please clarify.
[PATCH] dt-bindings: pinctrl: fix spelling mistakes in pinctl documentation
From: Colin Ian King The spelling of configured is incorrect in the documentation. Fix it. Signed-off-by: Colin Ian King --- .../devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.txt| 6 +++--- .../devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.txt | 6 +++--- .../devicetree/bindings/pinctrl/qcom,sdm660-pinctrl.txt | 6 +++--- .../devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.txt | 6 +++--- 11 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt index 68e93d5b7ede..c9782397ff14 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,apq8084-pinctrl.txt @@ -122,17 +122,17 @@ to specify in a pin configuration subnode: - bias-disable: Usage: optional Value type: - Definition: The specified pins should be configued as no pull. + Definition: The specified pins should be configured as no pull. - bias-pull-down: Usage: optional Value type: - Definition: The specified pins should be configued as pull down. + Definition: The specified pins should be configured as pull down. - bias-pull-up: Usage: optional Value type: - Definition: The specified pins should be configued as pull up. + Definition: The specified pins should be configured as pull up. - output-high: Usage: optional diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt index 6dd72f8599e9..7b151894f5a0 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt @@ -118,17 +118,17 @@ to specify in a pin configuration subnode: - bias-disable: Usage: optional Value type: - Definition: The specified pins should be configued as no pull. + Definition: The specified pins should be configured as no pull. - bias-pull-down: Usage: optional Value type: - Definition: The specified pins should be configued as pull down. + Definition: The specified pins should be configured as pull down. - bias-pull-up: Usage: optional Value type: - Definition: The specified pins should be configued as pull up. + Definition: The specified pins should be configured as pull up. - output-high: Usage: optional diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt index 86ecdcfc4fb8..d46973968873 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt @@ -97,17 +97,17 @@ to specify in a pin configuration subnode: - bias-disable: Usage: optional Value type: - Definition: The specified pins should be configued as no pull. + Definition: The specified pins should be configured as no pull. - bias-pull-down: Usage: optional Value type: - Definition: The specified pins should be configued as pull down. + Definition: The specified pins should be configured as pull down. - bias-pull-up: Usage: optional Value type: - Definition: The specified pins should be configued as pull up. + Definition: The specified pins should be configured as pull up. - output-high: Usage: optional diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt index 195a7a0ef0cc..3354a63296d9 100644 --- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt @@ -130,17 +130,17 @@ to specify in a pin configuration subnode: - bias-disable: Usage: optional Value type: - Definition: The specified pins should be configued as no pull. + Definition: The specified pins should be configured as no pull. - bias-pull-down: Usage: optional Value type: - Definition: The specified pins should be configued as pull down. + Definition: The specified pins should be configured as pull down.
Re: [PATCH V1 10/12] gpio: tegra: implement wake event support for Tegra210 and prior GPIO
On 5/22/19 6:24 AM, Thierry Reding wrote: On Tue, May 21, 2019 at 04:31:21PM -0700, Sowjanya Komatineni wrote: The GPIO controller doesn't have any controls to enable the system to wake up from low power states based on activity on GPIO pins. An extra hardware block that is part of the power management controller (PMC) contains these controls. In order for the GPIO controller to be able to cooperate with the PMC, obtain a reference to the PMC's IRQ domain and make it a parent to the GPIO controller's IRQ domain. This way the PMC gets an opportunity to program the additional registers required to enable wakeup sources on suspend. Signed-off-by: Sowjanya Komatineni --- drivers/gpio/gpio-tegra.c | 109 +++--- 1 file changed, 103 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 6d9b6906b9d0..d57e33050d0c 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -32,6 +32,8 @@ #include #include +#include + #define GPIO_BANK(x) ((x) >> 5) #define GPIO_PORT(x) (((x) >> 3) & 0x3) #define GPIO_BIT(x) ((x) & 0x7) @@ -275,8 +277,22 @@ static int tegra_gpio_set_config(struct gpio_chip *chip, unsigned int offset, static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) { struct tegra_gpio_info *tgi = gpiochip_get_data(chip); + struct irq_domain *domain = tgi->irq_domain; + + if (!gpiochip_irqchip_irq_valid(chip, offset)) + return -ENXIO; + + if (irq_domain_is_hierarchy(domain)) { + struct irq_fwspec spec; + + spec.fwnode = domain->fwnode; + spec.param_count = 2; + spec.param[0] = offset; + spec.param[1] = IRQ_TYPE_NONE; + return irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, ); + } - return irq_find_mapping(tgi->irq_domain, offset); + return irq_find_mapping(domain, offset); } static void tegra_gpio_irq_ack(struct irq_data *d) @@ -365,7 +381,10 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) irq_set_handler_locked(d, handle_edge_irq); - return 0; + if (d->parent_data) + return irq_chip_set_type_parent(d, type); + else + return 0; Why is this needed? Invoking GPIO irq_domain parent's set_type to configure PMC wake level based on the type for those GPIO's that are wake-able thru specified PMC wake events. } static void tegra_gpio_irq_shutdown(struct irq_data *d) @@ -566,10 +585,79 @@ static const struct dev_pm_ops tegra_gpio_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume) }; +static int tegra_gpio_irq_domain_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + if (WARN_ON(fwspec->param_count < 2)) + return -EINVAL; + + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + *hwirq = fwspec->param[0]; + + return 0; +} + +static int tegra_gpio_irq_domain_alloc(struct irq_domain *domain, + unsigned int virq, + unsigned int num_irqs, void *data) +{ + struct tegra_gpio_info *tgi = gpiochip_get_data(domain->host_data); + struct irq_fwspec *fwspec = data; + struct irq_fwspec spec; You can put the above two lines onto a single line. Will fix in next version + struct tegra_gpio_bank *bank; + unsigned long hwirq; + unsigned int type; + int err = 0; + + if (WARN_ON(fwspec->param_count < 2)) + return -EINVAL; + + if (!irq_domain_get_of_node(domain->parent)) + return -EINVAL; Can this ever fail? Will remove in next version of updated series.. + + err = tegra_gpio_irq_domain_translate(domain, fwspec, , ); + if (err) + return err; + + bank = >bank_info[GPIO_BANK(hwirq)]; + err = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, + >ic, bank); + + if (err < 0) + return err; + + spec.fwnode = domain->parent->fwnode; + spec.param_count = 3; + spec.param[0] = GIC_SPI; + spec.param[1] = fwspec->param[0]; + spec.param[2] = fwspec->param[1]; + + return irq_domain_alloc_irqs_parent(domain, virq, 1, ); What if num_irqs is different from 1? I'm not exactly sure what to pass as , but likely we'd have to create an array of struct irq_fwspec and pass that along. It seems like some drivers catch that case and refuse to work rather than pass potentially rubbish information along. See for
Re: Linux 5.1.5 (a regression: kernel BUG at lib/list_debug.c:29!)
hallo I today I got a regression see the attached dmesg -- Ronald [0.00] microcode: microcode updated early to revision 0xcc, date = 2019-04-01 [0.00] Linux version 5.1.5_MY (r...@obelix.fritz.box) (gcc version 9.1.1 20190503 (Red Hat 9.1.1-1) (GCC)) #1 SMP PREEMPT Sat May 25 22:02:41 CEST 2019 [0.00] Command line: BOOT_IMAGE=(hd0,gpt4)/boot/vmlinuz-5.1.5_MY root=UUID=7193b3bc-9bd6-4fb7-aeef-00ea9eeb53bb ro resume=UUID=1fa013bc-d3e2-4382-8e92-df1e5c4d52dc zswap.enabled=1 zswap.compressor=lz4 i915.enable_guc=3 i915.enable_fbc=1 rhgb quiet plymouth.splash_delay=0 [0.00] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers' [0.00] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers' [0.00] x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers' [0.00] x86/fpu: Supporting XSAVE feature 0x008: 'MPX bounds registers' [0.00] x86/fpu: Supporting XSAVE feature 0x010: 'MPX CSR' [0.00] x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256 [0.00] x86/fpu: xstate_offset[3]: 832, xstate_sizes[3]: 64 [0.00] x86/fpu: xstate_offset[4]: 896, xstate_sizes[4]: 64 [0.00] x86/fpu: Enabled xstate features 0x1f, context size is 960 bytes, using 'compacted' format. [0.00] BIOS-provided physical RAM map: [0.00] BIOS-e820: [mem 0x-0x0009c3ff] usable [0.00] BIOS-e820: [mem 0x0009c400-0x0009] reserved [0.00] BIOS-e820: [mem 0x000e-0x000f] reserved [0.00] BIOS-e820: [mem 0x0010-0x73638fff] usable [0.00] BIOS-e820: [mem 0x73639000-0x73639fff] ACPI NVS [0.00] BIOS-e820: [mem 0x7363a000-0x7363afff] reserved [0.00] BIOS-e820: [mem 0x7363b000-0x7dedcfff] usable [0.00] BIOS-e820: [mem 0x7dedd000-0x7e3a1fff] reserved [0.00] BIOS-e820: [mem 0x7e3a2000-0x7e44bfff] usable [0.00] BIOS-e820: [mem 0x7e44c000-0x7e7f2fff] ACPI NVS [0.00] BIOS-e820: [mem 0x7e7f3000-0x7f3fefff] reserved [0.00] BIOS-e820: [mem 0x7f3ff000-0x7f3f] usable [0.00] BIOS-e820: [mem 0x7f40-0x8fff] reserved [0.00] BIOS-e820: [mem 0xe000-0xefff] reserved [0.00] BIOS-e820: [mem 0xfe00-0xfe010fff] reserved [0.00] BIOS-e820: [mem 0xfec0-0xfec00fff] reserved [0.00] BIOS-e820: [mem 0xfed0-0xfed00fff] reserved [0.00] BIOS-e820: [mem 0xfee0-0xfee00fff] reserved [0.00] BIOS-e820: [mem 0xff00-0x] reserved [0.00] BIOS-e820: [mem 0x0001-0x00046eff] usable [0.00] NX (Execute Disable) protection: active [0.00] SMBIOS 3.0 present. [0.00] DMI: MSI MS-7A72/B250 PC MATE (MS-7A72), BIOS 3.90 07/05/2018 [0.00] tsc: Detected 3400.000 MHz processor [0.001220] tsc: Detected 3408.000 MHz TSC [0.001220] e820: update [mem 0x-0x0fff] usable ==> reserved [0.001221] e820: remove [mem 0x000a-0x000f] usable [0.001225] last_pfn = 0x46f000 max_arch_pfn = 0x4 [0.001228] MTRR default type: write-back [0.001228] MTRR fixed ranges enabled: [0.001229] 0-9 write-back [0.001229] A-B uncachable [0.001230] C-F write-protect [0.001230] MTRR variable ranges enabled: [0.001231] 0 base 008000 mask 7F8000 uncachable [0.001232] 1 base 007F80 mask 7FFF80 uncachable [0.001232] 2 disabled [0.001233] 3 disabled [0.001233] 4 disabled [0.001233] 5 disabled [0.001233] 6 disabled [0.001234] 7 disabled [0.001234] 8 disabled [0.001234] 9 disabled [0.002122] x86/PAT: Configuration [0-7]: WB WC UC- UC WB WP UC- WT [0.002268] last_pfn = 0x7f400 max_arch_pfn = 0x4 [0.007059] found SMP MP-table at [mem 0x000fcc80-0x000fcc8f] [0.007069] Using GB pages for direct mapping [0.007071] BRK [0x373201000, 0x373201fff] PGTABLE [0.007072] BRK [0x373202000, 0x373202fff] PGTABLE [0.007072] BRK [0x373203000, 0x373203fff] PGTABLE [0.007095] BRK [0x373204000, 0x373204fff] PGTABLE [0.007096] BRK [0x373205000, 0x373205fff] PGTABLE [0.007181] BRK [0x373206000, 0x373206fff] PGTABLE [0.007200] BRK [0x373207000, 0x373207fff] PGTABLE [0.007246] BRK [0x373208000, 0x373208fff] PGTABLE [0.007271] BRK [0x373209000, 0x373209fff] PGTABLE [0.007271] BRK [0x37320a000, 0x37320afff] PGTABLE [0.007300] BRK [0x37320b000, 0x37320bfff] PGTABLE [0.007329] RAMDISK: [mem 0x35869000-0x36c2cfff] [0.007334] ACPI: Early table checksum verification disabled [0.007358] ACPI: RSDP 0x000F05B0 24
[PATCH][next] ASoC: cx2072x: fix spelling mistake "configued" -> "configured"
From: Colin Ian King There is a spelling mistake in a dev_err error message. Fit it. Signed-off-by: Colin Ian King --- sound/soc/codecs/cx2072x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index e8e6fd2e97b6..f25376789c5c 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -933,7 +933,7 @@ static int cx2072x_hw_params(struct snd_pcm_substream *substream, return frame_size; if (cx2072x->mclk_rate == 0) { - dev_err(dev, "Master clock rate is not configued\n"); + dev_err(dev, "Master clock rate is not configured\n"); return -EINVAL; } -- 2.20.1
Re: [PATCH net 1/4] net/udp_gso: Allow TX timestamp with UDP GSO
> On May 23, 2019, at 2:59 PM, Willem de Bruijn > wrote: > what exactly is the issue with IP_TOS? > > If I understand correctly, the issue here is that the new 'P' option > that polls on the error queue times out. This is unrelated to > specifying TOS bits? Without zerocopy or timestamps, no message is > expected on the error queue. I was not able to get to the root cause, but I noticed that IP_TOS CMSG was lost until I applied this fix. I also found it confusing as to why that may be the case.
Re: [PATCH 2/3] thermal: sun50i: add thermal driver for h6
On Sat, May 25, 2019 at 11:48 AM Frank Lee wrote: > > HI Ondřej, > > On Sun, May 19, 2019 at 10:22 PM Ondřej Jirman wrote: > > > > Hello Yangtao, > > > > On Sat, May 18, 2019 at 12:34:57AM +0800, Frank Lee wrote: > > > HI, > > > > > > On Fri, May 17, 2019 at 2:29 AM Ondřej Jirman wrote: > > > > > > > > Hi Yangtao, > > > > > > > > thank you for work on this driver. > > > > > > > > On Fri, May 17, 2019 at 02:06:53AM +0800, Frank Lee wrote: > > > > > HI Ondřej, > > > > > > > > > > On Mon, May 13, 2019 at 6:16 AM Ondřej Jirman > > > > > wrote: > > > > > > > + > > > > > > > +/* Temp Unit: millidegree Celsius */ > > > > > > > +static int tsens_reg2temp(struct tsens_device *tmdev, > > > > > > > + int reg) > > > > > > > > > > > > Please name all functions so that they are more clearly identifiable > > > > > > in stack traces as belonging to this driver. For example: > > > > > > > > > > > > sun8i_ths_reg2temp > > > > > > > > > > > > The same applies for all tsens_* functions below. tsens_* is too > > > > > > generic. > > > > > > > > > > Done but no sun8i_ths_reg2temp. > > > > > > > > > > ths_reg2tem() should be a generic func. > > > > > I think it should be suitable for all platforms, so no platform > > > > > prefix. > > > > > > > > You've missed my point. The driver name is sun8i_thermal and if you get > > > > and oops from the kernel you'll get a stack trace where there are just > > > > function > > > > names. If you use too generic function names, it will not be clear which > > > > driver is oopsing. > > > > > > > > - sun8i_ths_reg2temp will tell you much more clearly where to search > > > > than > > > > - ths_reg2temp > > > > > > > > Of course you can always grep, but most thermal drivers are thermal > > > > sensor (ths) > > > > drivers, and if multiple of them used this too-generic naming scheme > > > > you'd > > > > have hard time debugging. > > > > > > > > Look at other thermal drivers. They usually encode driver name in the > > > > function > > > > names to help with identification (even if these are static driver-local > > > > functions). > > > > > > > > > > Can we change to sunxi_ths_ prefix? > > > > It should probably match the driver name, but yes, that's better. > > > > > > > > > +static int tsens_probe(struct platform_device *pdev) > > > > > > > +{ > > > > > > > + struct tsens_device *tmdev; > > > > > > > + struct device *dev = >dev; > > > > > > > + int ret; > > > > > > > + > > > > > > > + tmdev = devm_kzalloc(dev, sizeof(*tmdev), GFP_KERNEL); > > > > > > > + if (!tmdev) > > > > > > > + return -ENOMEM; > > > > > > > + > > > > > > > + tmdev->dev = dev; > > > > > > > + tmdev->chip = of_device_get_match_data(>dev); > > > > > > > + if (!tmdev->chip) > > > > > > > + return -EINVAL; > > > > > > > + > > > > > > > + ret = tsens_init(tmdev); > > > > > > > + if (ret) > > > > > > > + return ret; > > > > > > > + > > > > > > > + ret = tsens_register(tmdev); > > > > > > > + if (ret) > > > > > > > + return ret; > > > > > > > > > > > > Why split this out of probe into separate functions? > > > > > > > > > > > > > + ret = tmdev->chip->enable(tmdev); > > > > > > > + if (ret) > > > > > > > + return ret; > > > > > > > + > > > > > > > + platform_set_drvdata(pdev, tmdev); > > > > > > > + > > > > > > > + return ret; > > > > > > > +} > > > > > > > + > > > > > > > +static int tsens_remove(struct platform_device *pdev) > > > > > > > +{ > > > > > > > + struct tsens_device *tmdev = platform_get_drvdata(pdev); > > > > > > > + > > > > > > > + tmdev->chip->disable(tmdev); > > > > > > > + > > > > > > > + return 0; > > > > > > > +} > > > > > > > + > > > > > > > +static int sun50i_thermal_enable(struct tsens_device *tmdev) > > > > > > > +{ > > > > > > > + int ret, val; > > > > > > > + > > > > > > > + ret = reset_control_deassert(tmdev->reset); > > > > > > > + if (ret) > > > > > > > + return ret; > > > > > > > + > > > > > > > + ret = clk_prepare_enable(tmdev->bus_clk); > > > > > > > + if (ret) > > > > > > > + goto assert_reset; > > > > > > > + > > > > > > > + ret = tsens_calibrate(tmdev); > > > > > > > + if (ret) > > > > > > > + return ret; > > > > > > > > > > > > If this fails (it may likely fail with EPROBE_DEFER) you are > > > > > > leaving reset > > > > > > deasserted, and clock enabled. > > > > > > > > > > > > Overall, I think, reset/clock management and nvmem reading will be > > > > > > common > > > > > > to all the HW variants, so it doesn't make much sense splitting it > > > > > > out > > > > > > of probe into separate functions, and makes it more error prone. > > > > > > > > > > Our long-term goal is to support all platforms. > > > > > Bacicallt there is a differencr between each generation. > > > > > So I feel it necessary to isolate these differences. > > > > > > > > > > Maybe: > >
Re: [PATCH] libbpf: fix warning PTR_ERR_OR_ZERO can be used
On 5/25/19 2:02 AM, Hariprasad Kelam wrote: > fix below warning reported by coccicheck > > /tools/lib/bpf/libbpf.c:3461:1-3: WARNING: PTR_ERR_OR_ZERO can be used > > Signed-off-by: Hariprasad Kelam Acked-by: Yonghong Song > --- > tools/lib/bpf/libbpf.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index 197b574..33c25b6 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -3458,9 +3458,7 @@ bpf_object__find_map_by_offset(struct bpf_object *obj, > size_t offset) > > long libbpf_get_error(const void *ptr) > { > - if (IS_ERR(ptr)) > - return PTR_ERR(ptr); > - return 0; > + return PTR_ERR_OR_ZERO(ptr); > } > > int bpf_prog_load(const char *file, enum bpf_prog_type type, >
[PATCH 4/4] ARM: dts: meson8b: mxq: add the VDDEE regulator
The VDDEE regulator is basically a copy of the VCCK regulator. VDDEE supplies for example the Mali GPU and is controlled by PWM_D instead of PWM_C. Add the VDDEE PWM regulator and make it the supply of the Mali GPU. Signed-off-by: Martin Blumenstingl --- arch/arm/boot/dts/meson8b-mxq.dts | 26 +++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/meson8b-mxq.dts b/arch/arm/boot/dts/meson8b-mxq.dts index 07f1cc513f8a..8f7a02c1e27b 100644 --- a/arch/arm/boot/dts/meson8b-mxq.dts +++ b/arch/arm/boot/dts/meson8b-mxq.dts @@ -116,6 +116,22 @@ regulator-boot-on; regulator-always-on; }; + + vddee: regulator-vddee { + compatible = "pwm-regulator"; + + regulator-name = "VDDEE"; + regulator-min-microvolt = <86>; + regulator-max-microvolt = <114>; + + vin-supply = <_5v>; + + pwms = <_cd 1 1148 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; }; { @@ -151,6 +167,10 @@ }; }; + { + mali-supply = <>; +}; + { status = "okay"; vref-supply = <_1v8>; @@ -182,10 +202,10 @@ _cd { status = "okay"; - pinctrl-0 = <_c1_pins>; + pinctrl-0 = <_c1_pins>, <_d_pins>; pinctrl-names = "default"; - clocks = < CLKID_XTAL>; - clock-names = "clkin0"; + clocks = < CLKID_XTAL>, < CLKID_XTAL>; + clock-names = "clkin0", "clkin1"; }; _AO { -- 2.21.0
[PATCH 2/4] ARM: dts: meson8b: ec100: add the VDDEE regulator
The VDDEE regulator is basically a copy of the VCCK regulator. VDDEE supplies for example the Mali GPU and is controlled by PWM_D instead of PWM_C. Add the VDDEE PWM regulator and make it the supply of the Mali GPU. Signed-off-by: Martin Blumenstingl --- arch/arm/boot/dts/meson8b-ec100.dts | 31 ++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/meson8b-ec100.dts b/arch/arm/boot/dts/meson8b-ec100.dts index 9bf4249cb60d..61a1265064dc 100644 --- a/arch/arm/boot/dts/meson8b-ec100.dts +++ b/arch/arm/boot/dts/meson8b-ec100.dts @@ -219,6 +219,27 @@ */ vin-supply = <_3v3>; }; + + vddee: regulator-vddee { + /* +* Silergy SY8089AAC-GP 2A continuous, 3A peak, 1MHz +* Synchronous Step Down Regulator. Also called VDDAO +* in a part of the schematics. +*/ + compatible = "pwm-regulator"; + + regulator-name = "VDDEE"; + regulator-min-microvolt = <86>; + regulator-max-microvolt = <114>; + + vin-supply = <_5v>; + + pwms = <_cd 1 1148 0>; + pwm-dutycycle-range = <100 0>; + + regulator-boot-on; + regulator-always-on; + }; }; { @@ -268,6 +289,10 @@ }; }; + { + mali-supply = <>; +}; + { status = "okay"; vref-supply = <_1v8>; @@ -349,10 +374,10 @@ _cd { status = "okay"; - pinctrl-0 = <_c1_pins>; + pinctrl-0 = <_c1_pins>, <_d_pins>; pinctrl-names = "default"; - clocks = < CLKID_XTAL>; - clock-names = "clkin0"; + clocks = < CLKID_XTAL>, < CLKID_XTAL>; + clock-names = "clkin0", "clkin1"; }; { -- 2.21.0
[PATCH 0/4] ARM: dts: meson8b: add VDDEE / mali-supply
EC-100 and Odroid-C1 use a "copy" of the VCCK regulator as "VDDEE" regulator. VDDEE supplies the Mali GPU and various other bits within the SoC. The VDDEE regulator is not exclusive to the Mali GPU so it must not change it's voltage. The GPU OPP table has a fixed voltage for all frequencies of 1.10V. This matches with what u-boot sets on my EC-100 and Odroid-C1. Dependencies: - compile time: patch #4 depends on my other patch "ARM: meson8b-mxq: better support for the TRONFY MXQ" from [0] - runtime: we don't want the kernel to change the output of the VDDEE regulator to the maximum value. Thus the PWM driver has to be able to read the PWM period and duty cycle from u-boot. This is supported with my series called "pwm-meson: cleanups and improvements" from [1] [0] https://patchwork.kernel.org/patch/10960283/ [1] https://patchwork.kernel.org/cover/10961073/ Martin Blumenstingl (4): ARM: dts: meson8b: add the PWM_D output pin ARM: dts: meson8b: ec100: add the VDDEE regulator ARM: dts: meson8b: odroidc1: add the VDDEE regulator ARM: dts: meson8b: mxq: add the VDDEE regulator arch/arm/boot/dts/meson8b-ec100.dts| 31 +++--- arch/arm/boot/dts/meson8b-mxq.dts | 26 ++--- arch/arm/boot/dts/meson8b-odroidc1.dts | 27 +++--- arch/arm/boot/dts/meson8b.dtsi | 8 +++ 4 files changed, 83 insertions(+), 9 deletions(-) -- 2.21.0
[PATCH 3/4] ARM: dts: meson8b: odroidc1: add the VDDEE regulator
The VDDEE regulator is basically a copy of the VCCK regulator. VDDEE supplies for example the Mali GPU and is controlled by PWM_D instead of PWM_C. Add the VDDEE PWM regulator and make it the supply of the Mali GPU. Signed-off-by: Martin Blumenstingl --- arch/arm/boot/dts/meson8b-odroidc1.dts | 27 +++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts index f3ad9397f670..893a3aa5ec36 100644 --- a/arch/arm/boot/dts/meson8b-odroidc1.dts +++ b/arch/arm/boot/dts/meson8b-odroidc1.dts @@ -194,6 +194,23 @@ vin-supply = <>; }; + vddee: regulator-vcck { + /* Monolithic Power Systems MP2161 */ + compatible = "pwm-regulator"; + + regulator-name = "VDDEE"; + regulator-min-microvolt = <86>; + regulator-max-microvolt = <114>; + + vin-supply = <>; + + pwms = <_cd 1 12218 0>; + pwm-dutycycle-range = <91 0>; + + regulator-boot-on; + regulator-always-on; + }; + vdd_rtc: regulator-vdd-rtc { /* * Torex Semiconductor XC6215 configured for a fixed output of @@ -315,6 +332,10 @@ pinctrl-names = "default"; }; + { + mali-supply = <>; +}; + { status = "okay"; vref-supply = <_1v8>; @@ -347,10 +368,10 @@ _cd { status = "okay"; - pinctrl-0 = <_c1_pins>; + pinctrl-0 = <_c1_pins>, <_d_pins>; pinctrl-names = "default"; - clocks = < CLKID_XTAL>; - clock-names = "clkin0"; + clocks = < CLKID_XTAL>, < CLKID_XTAL>; + clock-names = "clkin0", "clkin1"; }; { -- 2.21.0
[PATCH 1/4] ARM: dts: meson8b: add the PWM_D output pin
The PWM_D output is used for the VDDEE PWM regulator which supplies for example the Mali GPU on the EC-100 and Odroid-C1 boards. Add the output pin the VDDEE regulators can be added. Signed-off-by: Martin Blumenstingl --- arch/arm/boot/dts/meson8b.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi index e4134c63a48c..1b0106fbb0ac 100644 --- a/arch/arm/boot/dts/meson8b.dtsi +++ b/arch/arm/boot/dts/meson8b.dtsi @@ -401,6 +401,14 @@ }; }; + pwm_d_pins: pwm-d { + mux { + groups = "pwm_d"; + function = "pwm_d"; + bias-disable; + }; + }; + uart_b0_pins: uart-b0 { mux { groups = "uart_tx_b0", -- 2.21.0
Re: [PATCH 2/3] thermal: sun50i: add thermal driver for h6
HI, Following the discussion above, I made some changes. I think it's time to consider V3 and see what else needs to be modified. Thx, Yangtao
mainline/master boot bisection: v5.2-rc1-369-g2409207a73cc on meson-g12a-x96-max
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This automated bisection report was sent to you on the basis * * that you may be involved with the breaking commit it has * * found. No manual investigation has been done to verify it, * * and the root cause of the problem may be somewhere else. * * Hope this helps! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * mainline/master boot bisection: v5.2-rc1-369-g2409207a73cc on meson-g12a-x96-max Summary: Start: 2409207a73cc Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Details:https://kernelci.org/boot/id/5ce8b16e59b514388a7a362a Plain log: https://storage.kernelci.org//mainline/master/v5.2-rc1-369-g2409207a73cc/arm64/defconfig+CONFIG_RANDOMIZE_BASE=y/gcc-8/lab-baylibre/boot-meson-g12a-x96-max.txt HTML log: https://storage.kernelci.org//mainline/master/v5.2-rc1-369-g2409207a73cc/arm64/defconfig+CONFIG_RANDOMIZE_BASE=y/gcc-8/lab-baylibre/boot-meson-g12a-x96-max.html Result: 11a7bea17c9e arm64: dts: meson: g12a: add pinctrl support controllers Checks: revert: PASS verify: PASS Parameters: Tree: mainline URL:git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Branch: master Target: meson-g12a-x96-max CPU arch: arm64 Lab:lab-baylibre Compiler: gcc-8 Config: defconfig+CONFIG_RANDOMIZE_BASE=y Test suite: boot Breaking commit found: --- commit 11a7bea17c9e0a36daab934d83e15a760f402147 Author: Jerome Brunet Date: Mon Mar 18 10:58:45 2019 +0100 arm64: dts: meson: g12a: add pinctrl support controllers Add the peripheral and always-on pinctrl controllers to the g12a soc. Signed-off-by: Jerome Brunet Signed-off-by: Neil Armstrong Signed-off-by: Kevin Hilman diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi index abfa167751af..5e07e4ca3f4b 100644 --- a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi +++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi @@ -104,6 +104,29 @@ #address-cells = <2>; #size-cells = <2>; ranges = <0x0 0x0 0x0 0x34400 0x0 0x400>; + + periphs_pinctrl: pinctrl@40 { + compatible = "amlogic,meson-g12a-periphs-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio: bank@40 { + reg = <0x0 0x40 0x0 0x4c>, + <0x0 0xe8 0x0 0x18>, + <0x0 0x120 0x0 0x18>, + <0x0 0x2c0 0x0 0x40>, + <0x0 0x340 0x0 0x1c>; + reg-names = "gpio", + "pull", + "pull-enable", + "mux", + "ds"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <_pinctrl 0 0 86>; + }; + }; }; hiu: bus@3c000 { @@ -150,6 +173,25 @@ clocks = <>, < CLKID_CLK81>; clock-names = "xtal", "mpeg-clk"; }; + + ao_pinctrl: pinctrl@14 { + compatible = "amlogic,meson-g12a-aobus-pinctrl"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gpio_ao: bank@14 { + reg = <0x0 0x14 0x0 0x8>, + <0x0 0x1c 0x0 0x8>, + <0x0 0x24 0x0 0x14>; + reg-names = "mux", + "ds", + "gpio"; + gpio-controller; +
Re: [PATCH 2/3] thermal: sun50i: add thermal driver for h6
HI Ondřej, On Sun, May 19, 2019 at 10:22 PM Ondřej Jirman wrote: > > Hello Yangtao, > > On Sat, May 18, 2019 at 12:34:57AM +0800, Frank Lee wrote: > > HI, > > > > On Fri, May 17, 2019 at 2:29 AM Ondřej Jirman wrote: > > > > > > Hi Yangtao, > > > > > > thank you for work on this driver. > > > > > > On Fri, May 17, 2019 at 02:06:53AM +0800, Frank Lee wrote: > > > > HI Ondřej, > > > > > > > > On Mon, May 13, 2019 at 6:16 AM Ondřej Jirman wrote: > > > > > > + > > > > > > +/* Temp Unit: millidegree Celsius */ > > > > > > +static int tsens_reg2temp(struct tsens_device *tmdev, > > > > > > + int reg) > > > > > > > > > > Please name all functions so that they are more clearly identifiable > > > > > in stack traces as belonging to this driver. For example: > > > > > > > > > > sun8i_ths_reg2temp > > > > > > > > > > The same applies for all tsens_* functions below. tsens_* is too > > > > > generic. > > > > > > > > Done but no sun8i_ths_reg2temp. > > > > > > > > ths_reg2tem() should be a generic func. > > > > I think it should be suitable for all platforms, so no platform prefix. > > > > > > You've missed my point. The driver name is sun8i_thermal and if you get > > > and oops from the kernel you'll get a stack trace where there are just > > > function > > > names. If you use too generic function names, it will not be clear which > > > driver is oopsing. > > > > > > - sun8i_ths_reg2temp will tell you much more clearly where to search > > > than > > > - ths_reg2temp > > > > > > Of course you can always grep, but most thermal drivers are thermal > > > sensor (ths) > > > drivers, and if multiple of them used this too-generic naming scheme you'd > > > have hard time debugging. > > > > > > Look at other thermal drivers. They usually encode driver name in the > > > function > > > names to help with identification (even if these are static driver-local > > > functions). > > > > > > > Can we change to sunxi_ths_ prefix? > > It should probably match the driver name, but yes, that's better. > > > > > > > +static int tsens_probe(struct platform_device *pdev) > > > > > > +{ > > > > > > + struct tsens_device *tmdev; > > > > > > + struct device *dev = >dev; > > > > > > + int ret; > > > > > > + > > > > > > + tmdev = devm_kzalloc(dev, sizeof(*tmdev), GFP_KERNEL); > > > > > > + if (!tmdev) > > > > > > + return -ENOMEM; > > > > > > + > > > > > > + tmdev->dev = dev; > > > > > > + tmdev->chip = of_device_get_match_data(>dev); > > > > > > + if (!tmdev->chip) > > > > > > + return -EINVAL; > > > > > > + > > > > > > + ret = tsens_init(tmdev); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + ret = tsens_register(tmdev); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > > > > > Why split this out of probe into separate functions? > > > > > > > > > > > + ret = tmdev->chip->enable(tmdev); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + platform_set_drvdata(pdev, tmdev); > > > > > > + > > > > > > + return ret; > > > > > > +} > > > > > > + > > > > > > +static int tsens_remove(struct platform_device *pdev) > > > > > > +{ > > > > > > + struct tsens_device *tmdev = platform_get_drvdata(pdev); > > > > > > + > > > > > > + tmdev->chip->disable(tmdev); > > > > > > + > > > > > > + return 0; > > > > > > +} > > > > > > + > > > > > > +static int sun50i_thermal_enable(struct tsens_device *tmdev) > > > > > > +{ > > > > > > + int ret, val; > > > > > > + > > > > > > + ret = reset_control_deassert(tmdev->reset); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > + > > > > > > + ret = clk_prepare_enable(tmdev->bus_clk); > > > > > > + if (ret) > > > > > > + goto assert_reset; > > > > > > + > > > > > > + ret = tsens_calibrate(tmdev); > > > > > > + if (ret) > > > > > > + return ret; > > > > > > > > > > If this fails (it may likely fail with EPROBE_DEFER) you are leaving > > > > > reset > > > > > deasserted, and clock enabled. > > > > > > > > > > Overall, I think, reset/clock management and nvmem reading will be > > > > > common > > > > > to all the HW variants, so it doesn't make much sense splitting it out > > > > > of probe into separate functions, and makes it more error prone. > > > > > > > > Our long-term goal is to support all platforms. > > > > Bacicallt there is a differencr between each generation. > > > > So I feel it necessary to isolate these differences. > > > > > > > > Maybe: > > > > At some point, we can draw a part of the public part and platform > > > > difference into different > > > > files. something like qcom thermal driver. > > > > > > I understand, but I wrote ths drivers for H3/H5/A83T and it so far it > > > looks like > > > all of them would share these 3 calls. > > > > > > You'll be enabling clock/reset and callibrating
Re: [PATCH net 1/4] net/udp_gso: Allow TX timestamp with UDP GSO
> On May 25, 2019, at 8:20 AM, Willem de Bruijn > wrote: > > On Fri, May 24, 2019 at 6:01 PM Fred Klassen wrote: >> >> >> >>> On May 24, 2019, at 12:29 PM, Willem de Bruijn >>> wrote: >>> >>> It is the last moment that a timestamp can be generated for the last >>> byte, I don't see how that is "neither the start nor the end of a GSO >>> packet”. >> >> My misunderstanding. I thought TCP did last segment timestamping, not >> last byte. In that case, your statements make sense. >> It would be interesting if a practical case can be made for timestamping the last segment. In my mind, I don’t see how that would be valuable. >>> >>> It depends whether you are interested in measuring network latency or >>> host transmit path latency. >>> >>> For the latter, knowing the time from the start of the sendmsg call to >>> the moment the last byte hits the wire is most relevant. Or in absence >>> of (well defined) hardware support, the last byte being queued to the >>> device is the next best thing. > > Sounds to me like both cases have a legitimate use case, and we want > to support both. > > Implementation constraints are that storage for this timestamp > information is scarce and we cannot add new cold cacheline accesses in > the datapath. > > The simplest approach would be to unconditionally timestamp both the > first and last segment. With the same ID. Not terribly elegant. But it > works. > > If conditional, tx_flags has only one bit left. I think we can harvest > some, as not all defined bits are in use at the same stages in the > datapath, but that is not a trivial change. Some might also better be > set in the skb, instead of skb_shinfo. Which would also avoids > touching that cacheline. We could possibly repurpose bits from u32 > tskey. > > All that can come later. Initially, unless we can come up with > something more elegant, I would suggest that UDP follows the rule > established by TCP and timestamps the last byte. And we add an > explicit SOF_TIMESTAMPING_OPT_FIRSTBYTE that is initially only > supported for UDP, sets a new SKBTX_TX_FB_TSTAMP bit in > __sock_tx_timestamp and is interpreted in __udp_gso_segment. > I don’t see how to practically TX timestamp the last byte of any packet (UDP GSO or otherwise). The best we could do is timestamp the last segment, or rather the time that the last segment is queued. Let me attempt to explain. First let’s look at software TX timestamps which are for are generated by skb_tx_timestamp() in nearly every network driver’s xmit routine. It states: —— cut * Ethernet MAC Drivers should call this function in their hard_xmit() * function immediately before giving the sk_buff to the MAC hardware. —— cut That means that the sk_buff will get timestamped just before rather than just after it is sent. To truly capture the timestamp of the last byte, this routine routine would have to be called a second time, right after sending to MAC hardware. Then the user program would have sort out the 2 timestamps. My guess is that this isn’t something that NIC vendors would be willing to implement in their drivers. So, the best we can do is timestamp is just before the last segment. Suppose UDP GSO sends 3000 bytes to a 1500 byte MTU adapter. If we set SKBTX_HW_TSTAMP flag on the last segment, the timestamp occurs half way through the burst. But it may not be exactly half way because the segments may get queued much faster than wire rate. Therefore the time between segment 1 and segment 2 may be much much smaller than their spacing on the wire. I would not find this useful. I propose that we stick with the method used for IP fragments, which is timestamping just before the first byte is sent. Put another way, I propose that we start the clock in an automobile race just before the front of the first car crosses the start line rather than when the front of the last car crosses the start line. TX timestamping in hardware has even more limitations. For the most part, we can only do one timestamp per packet or burst. If we requested a timestamp of only the last segment of a packet, we would have work backwards to calculate the start time of the packet, but that would only be be a best guess. For extremely time sensitive applications (such as the one we develop), this would not be practical. We could still consider setting a flag that would allow the timestamping the last segment rather than the first. However since we cannot truly measure the timestamp of the last byte, I would question the value in doing so.
[PATCH 1/1] clk: pwm: implement the .get_duty_cycle callback
Commit 9fba738a53dda2 ("clk: add duty cycle support") added support for getting and setting the duty cycle of a clock. This implements the get_duty_cycle callback for PWM based clocks so the duty cycle is shown in the debugfs output (/sys/kernel/debug/clk/clk_summary). Signed-off-by: Martin Blumenstingl --- drivers/clk/clk-pwm.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/clk/clk-pwm.c b/drivers/clk/clk-pwm.c index 02b472a1f9b0..c0cd6a0ff7f8 100644 --- a/drivers/clk/clk-pwm.c +++ b/drivers/clk/clk-pwm.c @@ -47,10 +47,24 @@ static unsigned long clk_pwm_recalc_rate(struct clk_hw *hw, return clk_pwm->fixed_rate; } +static int clk_pwm_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_pwm *clk_pwm = to_clk_pwm(hw); + struct pwm_state state; + + pwm_get_state(clk_pwm->pwm, ); + + duty->num = state.duty_cycle; + duty->den = state.period; + + return 0; +} + static const struct clk_ops clk_pwm_ops = { .prepare = clk_pwm_prepare, .unprepare = clk_pwm_unprepare, .recalc_rate = clk_pwm_recalc_rate, + .get_duty_cycle = clk_pwm_get_duty_cycle, }; static int clk_pwm_probe(struct platform_device *pdev) -- 2.21.0
[PATCH 0/1] clk-pwm: show duty cycle in debugfs
This is a patch that I had lying around in my tree for a while. I was planning to use it back when I was debugging CPU clock issues on Meson8b a while ago but it turned out that PWM was not related to that. Feel free to apply or drop this patch, depending on whether it might or might not be useful for anyone. I have successfully tested it with the 32.768kHz LPO clock for the SDIO wifi chipset on my Khadas VIM (Amlogic Meson GXL SoC): wifi32k [...] 32768 [...] 5 Martin Blumenstingl (1): clk: pwm: implement the .get_duty_cycle callback drivers/clk/clk-pwm.c | 14 ++ 1 file changed, 14 insertions(+) -- 2.21.0
[PATCH] alarmtimer: fix kerneldoc comment for alarmtimer_suspend
This brings the kernel doc in line with the function signature. Signed-off-by: Yangtao Li --- kernel/time/alarmtimer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 0519a8805aab..57518efc3810 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -233,7 +233,6 @@ EXPORT_SYMBOL_GPL(alarm_expires_remaining); /** * alarmtimer_suspend - Suspend time callback * @dev: unused - * @state: unused * * When we are going into suspend, we look through the bases * to see which is the soonest timer to expire. We then -- 2.17.0
Re: [PATCH] mm/mempolicy: Fix an incorrect rebind node in mpol_rebind_nodemask
(Cc Vlastimil) On Sat, 25 May 2019 15:07:23 +0800 zhong jiang wrote: > We bind an different node to different vma, Unluckily, > it will bind different vma to same node by checking the /proc/pid/numa_maps. > > Commit 213980c0f23b ("mm, mempolicy: simplify rebinding mempolicies when > updating cpusets") > has introduced the issue. when we change memory policy by seting cpuset.mems, > A process will rebind the specified policy more than one times. > if the cpuset_mems_allowed is not equal to user specified nodes. hence the > issue will trigger. > Maybe result in the out of memory which allocating memory from same node. > > --- a/mm/mempolicy.c > +++ b/mm/mempolicy.c > @@ -345,7 +345,7 @@ static void mpol_rebind_nodemask(struct mempolicy *pol, > const nodemask_t *nodes) > else { > nodes_remap(tmp, pol->v.nodes,pol->w.cpuset_mems_allowed, > *nodes); > - pol->w.cpuset_mems_allowed = tmp; > + pol->w.cpuset_mems_allowed = *nodes; > } > > if (nodes_empty(tmp)) hm, I'm not surprised the code broke. What the heck is going on in there? It used to have a perfunctory comment, but Vlastimil deleted it. Could someone please propose a comment for the above code block explaining why we're doing what we do?
Re: [PATCH v7 2/4] soc: qcom: Add AOSS QMP driver
On Sat 25 May 10:53 PDT 2019, Sai Prakash Ranjan wrote: > On 5/1/2019 10:07 AM, Bjorn Andersson wrote: > > The Always On Subsystem (AOSS) Qualcomm Messaging Protocol (QMP) driver > > is used to communicate with the AOSS for certain side-channel requests, > > that are not available through the RPMh interface. > > > > The communication is a very simple synchronous mechanism of messages > > being written in message RAM and a doorbell in the AOSS is rung. As the > > AOSS has processed the message length is cleared and an interrupt is > > fired by the AOSS as acknowledgment. > > > > The driver exposes the QDSS clock as a clock and the low-power state > > associated with the remoteprocs in the system as a set of power-domains. > > > > Signed-off-by: Bjorn Andersson > > --- > > > > Changes since v6: > > - Squash the pd into the same driver as the communication, to simplify > >the interaction. > > - Representing the QDSS clocks as a clock/power domain turns out to > >cascade into a request to make all Coresight drivers have a secondary > >compatible to replace the required bus clock with a required power > >domain. So in v7 this is exposed as a clock instead. > > - Some error checking updates, as reported by Doug. > > > > Thanks for the patch Bjorn. > Tested the QDSS functionality on SDM845 based Cheza board with this > change and it works just fine. > > Tested-by: Sai Prakash Ranjan Thanks for the confirmation Sai! Regards, Bjorn
[PATCH v3 1/3] thermal: sun8i: add thermal driver for h6
This patch adds the support for allwinner thermal sensor, within allwinner SoC. It will register sensors for thermal framework and use device tree to bind cooling device. Signed-off-by: Yangtao Li --- MAINTAINERS | 7 + drivers/thermal/Kconfig | 14 + drivers/thermal/Makefile| 1 + drivers/thermal/sun8i_thermal.c | 437 4 files changed, 459 insertions(+) create mode 100644 drivers/thermal/sun8i_thermal.c diff --git a/MAINTAINERS b/MAINTAINERS index 2336dd26ece4..d312f9eecf0d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -674,6 +674,13 @@ L: linux-cry...@vger.kernel.org S: Maintained F: drivers/crypto/sunxi-ss/ +ALLWINNER THERMAL DRIVER +M: Yangtao Li +L: linux...@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml +F: drivers/thermal/sun8i_thermal.c + ALLWINNER VPU DRIVER M: Maxime Ripard M: Paul Kocialkowski diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 9966364a6deb..e5465053d66f 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -262,6 +262,20 @@ config SPEAR_THERMAL Enable this to plug the SPEAr thermal sensor driver into the Linux thermal framework. +config SUN8I_THERMAL + tristate "Allwinner sun8i thermal driver" + depends on ARCH_SUNXI || COMPILE_TEST + depends on HAS_IOMEM + depends on NVMEM_SUNXI_SID + depends on OF + depends on RESET_CONTROLLER + help + Support for the sun8i thermal sensor driver into the Linux thermal + framework. + + To compile this driver as a module, choose M here: the + module will be called sun8i-thermal. + config ROCKCHIP_THERMAL tristate "Rockchip thermal driver" depends on ARCH_ROCKCHIP || COMPILE_TEST diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 74a37c7f847a..fa6f8b206281 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o obj-y += broadcom/ obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o +obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o obj-$(CONFIG_RCAR_GEN3_THERMAL)+= rcar_gen3_thermal.o diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c new file mode 100644 index ..a9cc2197f4cb --- /dev/null +++ b/drivers/thermal/sun8i_thermal.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Thermal sensor driver for Allwinner SOC + * Copyright (C) 2019 Yangtao Li + * + * Based on the work of Icenowy Zheng + * Based on the work of Ondrej Jirman + * Based on the work of Josef Gajdusek + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SENSOR_NUM 4 + +#define FT_TEMP_MASK GENMASK(11, 0) +#define TEMP_CALIB_MASKGENMASK(11, 0) +#define TEMP_TO_REG672 +#define CALIBRATE_DEFAULT 0x800 + +#define SUN50I_THS_CTRL0 0x00 +#define SUN50I_H6_THS_ENABLE 0x04 +#define SUN50I_H6_THS_PC 0x08 +#define SUN50I_H6_THS_DIC 0x10 +#define SUN50I_H6_THS_DIS 0x20 +#define SUN50I_H6_THS_MFC 0x30 +#define SUN50I_H6_THS_TEMP_CALIB 0xa0 +#define SUN50I_H6_THS_TEMP_DATA0xc0 + +#define SUN50I_THS_CTRL0_T_ACQ(x) ((GENMASK(15, 0) & (x)) << 16) +#define SUN50I_THS_FILTER_EN BIT(2) +#define SUN50I_THS_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) +#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)((GENMASK(19, 0) & (x)) << 12) +#define SUN50I_H6_THS_DATA_IRQ_STS(x) BIT(x) + +/* millidegree celsius */ +#define SUN50I_H6_FT_DEVIATION 7000 + +struct ths_device; + +struct tsensor { + struct ths_device *tmdev; + struct thermal_zone_device *tzd; + int id; + wait_queue_head_t wait_queue; +}; + +struct ths_thermal_chip { + int sensor_num; + int offset; + int scale; + int ft_deviation; + int temp_calib_base; + int temp_data_base; + int (*calibrate)(struct ths_device *tmdev); + int (*init)(struct ths_device *tmdev); + irqreturn_t (*irq_thread)(int irq, void *data); +}; + +struct ths_device { + const struct ths_thermal_chip *chip; + struct device
[PATCH v3 2/3] dt-bindings: thermal: add binding document for h6 thermal controller
This patch adds binding document for allwinner h6 thermal controller. Signed-off-by: Yangtao Li --- .../bindings/thermal/sun8i-thermal.yaml | 71 +++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml new file mode 100644 index ..54cf1277870e --- /dev/null +++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner SUN8I Thermal Controller Device Tree Bindings + +maintainers: + - Yangtao Li + +description: |- + This describes the device tree binding for the Allwinner thermal + controller which measures the on-SoC temperatures. + +properties: + compatible: +enum: + - allwinner,sun50i-h6-ths + + reg: +maxItems: 1 + + interrupts: +maxItems: 1 + + resets: +maxItems: 1 + + clocks: +items: + - description: ths bus clock + + clock-names: +items: + - const: bus + + "#thermal-sensor-cells": +enum: [ 0, 1 ] + + nvmem-cells: +items: + - description: ths calibrate data + + nvmem-cell-names: +items: + - const: calib + +required: + - compatible + - reg + - interrupts + - reset + - clocks + - clock-names + +examples: + - | +ths: ths@5070400 { + compatible = "allwinner,sun50i-h6-ths"; + reg = <0x05070400 0x100>; + clocks = < CLK_BUS_THS>; + clock-names = "bus"; + resets = < RST_BUS_THS>; + interrupts = ; + nvmem-cells = <_calib>; + nvmem-cell-names = "calib"; + #thermal-sensor-cells = <1>; +}; + +... -- 2.17.0
[PATCH v3 3/3] thermal: fix indentation in makefile
To unify code style. Signed-off-by: Yangtao Li --- drivers/thermal/Makefile | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index fa6f8b206281..d7eafb5ef8ef 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_THERMAL) += thermal_sys.o thermal_sys-y += thermal_core.o thermal_sysfs.o \ - thermal_helpers.o + thermal_helpers.o # interface to/from other layers providing sensors thermal_sys-$(CONFIG_THERMAL_HWMON)+= thermal_hwmon.o @@ -25,11 +25,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o thermal_sys-$(CONFIG_CLOCK_THERMAL)+= clock_cooling.o # devfreq cooling -thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o +thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o # platform thermal drivers obj-y += broadcom/ -obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o +obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o obj-$(CONFIG_SPEAR_THERMAL)+= spear_thermal.o obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o @@ -50,7 +50,7 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ obj-y += st/ obj-$(CONFIG_QCOM_TSENS) += qcom/ obj-y += tegra/ -obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o +obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o -- 2.17.0
[PATCH v3 0/3] add thermal driver for h6
This patchset add support for H6 thermal sensor. BWY, do a cleanup in thermal makfile. Yangtao Li (3): thermal: sun8i: add thermal driver for h6 dt-bindings: thermal: add binding document for h6 thermal controller thermal: fix indentation in makefile .../bindings/thermal/sun8i-thermal.yaml | 71 +++ MAINTAINERS | 7 + drivers/thermal/Kconfig | 14 + drivers/thermal/Makefile | 9 +- drivers/thermal/sun8i_thermal.c | 437 ++ 5 files changed, 534 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml create mode 100644 drivers/thermal/sun8i_thermal.c --- v3: -Add a sun8i prefix to some function -Remove disable callback and rename enable to init -Remove clock enable, calibration from init callback -Convert driver to interrupt based -Convert doc to yaml file --- 2.17.0
[PATCH 04/14] pwm: meson: change MISC_CLK_SEL_WIDTH to MISC_CLK_SEL_MASK
MISC_CLK_SEL_WIDTH is only used in one place where it's converted into a bit-mask. Rename and change the macro to be a bit-mask so that conversion is not needed anymore. No functional changes intended. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index c62a3ac924d0..84b28ba0f903 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -33,7 +33,7 @@ #define MISC_A_CLK_DIV_SHIFT 8 #define MISC_B_CLK_SEL_SHIFT 6 #define MISC_A_CLK_SEL_SHIFT 4 -#define MISC_CLK_SEL_WIDTH 2 +#define MISC_CLK_SEL_MASK 0x3 #define MISC_B_EN BIT(1) #define MISC_A_EN BIT(0) @@ -463,7 +463,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson, channel->mux.reg = meson->base + REG_MISC_AB; channel->mux.shift = mux_reg_shifts[i]; - channel->mux.mask = BIT(MISC_CLK_SEL_WIDTH) - 1; + channel->mux.mask = MISC_CLK_SEL_MASK; channel->mux.flags = 0; channel->mux.lock = >lock; channel->mux.table = NULL; -- 2.21.0
[PATCH 10/14] pwm: meson: simplify the calculation of the pre-divider and count
Replace the loop to calculate the pre-divider and count with two separate div64_u64() calculations. This makes the code easier to read and improves the precision. Two example cases: 1) 32.768kHz LPO clock for the SDIO wifi chip on Khadas VIM clock input: 500MHz (FCLK_DIV4) period: 30518ns duty cycle: 15259ns old algorithm: pre_div=0, cnt=15259 new algorithm: pre_div=0, cnt=15259 (no difference in calculated values) 2) PWM LED on Khadas VIM clock input: 24MHz (XTAL) period: 7812500ns duty cycle: 7812500ns old algorithm: pre_div=2, cnt=62004 new algorithm: pre_div=2, cnt=62500 Using a scope (24MHz sampling rate) shows the actual difference: - old: 7753000ns, off by -59500ns (0.7616%) - new: 7815000ns, off by +2500ns (0.032%) Suggested-by: Uwe Kleine-König Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 27915d6475e3..9afa1e5aaebf 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -145,7 +146,6 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); unsigned int duty, period, pre_div, cnt, duty_cnt; unsigned long fin_freq = -1; - u64 fin_ps; duty = state->duty_cycle; period = state->period; @@ -164,24 +164,19 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, } dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq); - fin_ps = (u64)NSEC_PER_SEC * 1000; - do_div(fin_ps, fin_freq); - - /* Calc pre_div with the period */ - for (pre_div = 0; pre_div <= MISC_CLK_DIV_MASK; pre_div++) { - cnt = DIV_ROUND_CLOSEST_ULL((u64)period * 1000, - fin_ps * (pre_div + 1)); - dev_dbg(meson->chip.dev, "fin_ps=%llu pre_div=%u cnt=%u\n", - fin_ps, pre_div, cnt); - if (cnt <= 0x) - break; - } + pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xLL); if (pre_div > MISC_CLK_DIV_MASK) { dev_err(meson->chip.dev, "unable to get period pre_div\n"); return -EINVAL; } + cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1)); + if (cnt > 0x) { + dev_err(meson->chip.dev, "unable to get period cnt\n"); + return -EINVAL; + } + dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period, pre_div, cnt); @@ -195,8 +190,8 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, channel->lo = cnt; } else { /* Then check is we can have the duty with the same pre_div */ - duty_cnt = DIV_ROUND_CLOSEST_ULL((u64)duty * 1000, -fin_ps * (pre_div + 1)); + duty_cnt = div64_u64(fin_freq * (u64)duty, +NSEC_PER_SEC * (pre_div + 1)); if (duty_cnt > 0x) { dev_err(meson->chip.dev, "unable to get duty cycle\n"); return -EINVAL; -- 2.21.0
[PATCH 09/14] pwm: meson: move pwm_set_chip_data() to meson_pwm_request()
All existing PWM drivers (except pwm-meson and two other ones) call pwm_set_chip_data() from their pwm_ops.request() callback. Now that we can access the struct meson_pwm_channel from struct meson_pwm we can do the same. Move the call to pwm_set_chip_data() to meson_pwm_request() and drop the custom meson_pwm_add_channels(). This makes the implementation consistent with other drivers and makes it slightly more obvious thatpwm_get_chip_data() cannot be used from pwm_ops.get_state() (because that's called by the PWM core before pwm_ops.request()). No functional changes intended. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 22 -- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index ac7e188155fd..27915d6475e3 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -98,12 +98,16 @@ static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip) static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { - struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); + struct meson_pwm *meson = to_meson_pwm(chip); + struct meson_pwm_channel *channel; struct device *dev = chip->dev; int err; - if (!channel) - return -ENODEV; + channel = pwm_get_chip_data(pwm); + if (channel) + return 0; + + channel = >channels[pwm->hwpwm]; if (channel->clk_parent) { err = clk_set_parent(channel->clk, channel->clk_parent); @@ -124,7 +128,7 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) chip->ops->get_state(chip, pwm, >state); - return 0; + return pwm_set_chip_data(pwm, channel); } static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) @@ -460,14 +464,6 @@ static int meson_pwm_init_channels(struct meson_pwm *meson) return 0; } -static void meson_pwm_add_channels(struct meson_pwm *meson) -{ - unsigned int i; - - for (i = 0; i < meson->chip.npwm; i++) - pwm_set_chip_data(>chip.pwms[i], >channels[i]); -} - static int meson_pwm_probe(struct platform_device *pdev) { struct meson_pwm *meson; @@ -503,8 +499,6 @@ static int meson_pwm_probe(struct platform_device *pdev) return err; } - meson_pwm_add_channels(meson); - platform_set_drvdata(pdev, meson); return 0; -- 2.21.0
[PATCH 11/14] pwm: meson: read the full hardware state in meson_pwm_get_state()
Update the meson_pwm_get_state() implementation to take care of all information in the registers instead of only reading the "enabled" state. The PWM output is only enabled if two conditions are met: 1. the per-channel clock is enabled 2. the PWM output is enabled Calculate the PWM period and duty cycle using the reverse formula which we already have in meson_pwm_calc() and update struct pwm_state with the results. As result of this /sys/kernel/debug/pwm now shows the PWM state set by the bootloader (or firmware) after booting Linux. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 52 ++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 9afa1e5aaebf..010212166d5d 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -287,19 +287,65 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static unsigned int meson_pwm_cnt_to_ns(struct pwm_chip *chip, + struct pwm_device *pwm, u32 cnt) +{ + struct meson_pwm *meson = to_meson_pwm(chip); + struct meson_pwm_channel *channel; + unsigned long fin_freq; + u32 fin_ns; + + /* to_meson_pwm() can only be used after .get_state() is called */ + channel = >channels[pwm->hwpwm]; + + fin_freq = clk_get_rate(channel->clk); + if (fin_freq == 0) + return 0; + + fin_ns = div_u64(NSEC_PER_SEC, fin_freq); + + return cnt * fin_ns * (channel->pre_div + 1); +} + static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { struct meson_pwm *meson = to_meson_pwm(chip); - u32 value, mask; + struct meson_pwm_channel_data *channel_data; + struct meson_pwm_channel *channel; + u32 value, tmp; if (!state) return; - mask = meson_pwm_per_channel_data[pwm->hwpwm].pwm_en_mask; + channel = >channels[pwm->hwpwm]; + channel_data = _pwm_per_channel_data[pwm->hwpwm]; value = readl(meson->base + REG_MISC_AB); - state->enabled = (value & mask) != 0; + + tmp = channel_data->pwm_en_mask | channel_data->clk_en_mask; + state->enabled = (value & tmp) == tmp; + + tmp = value >> channel_data->clk_div_shift; + channel->pre_div = FIELD_GET(MISC_CLK_DIV_MASK, tmp); + + value = readl(meson->base + channel_data->reg_offset); + + channel->lo = FIELD_GET(PWM_LOW_MASK, value); + channel->hi = FIELD_GET(PWM_HIGH_MASK, value); + + if (channel->lo == 0) { + state->period = meson_pwm_cnt_to_ns(chip, pwm, channel->hi); + state->duty_cycle = state->period; + } else if (channel->lo >= channel->hi) { + state->period = meson_pwm_cnt_to_ns(chip, pwm, + channel->lo + channel->hi); + state->duty_cycle = meson_pwm_cnt_to_ns(chip, pwm, + channel->hi); + } else { + state->period = 0; + state->duty_cycle = 0; + } } static const struct pwm_ops meson_pwm_ops = { -- 2.21.0
[PATCH 06/14] pwm: meson: pass struct pwm_device to meson_pwm_calc()
meson_pwm_calc() is the last function that accepts a struct meson_pwm_channel. meson_pwm_enable(), meson_pwm_disable() and meson_pwm_apply() for example are all taking a struct pwm_device as parameter. When they need the struct meson_pwm_channel these functions simply call pwm_get_chip_data() internally. Make meson_pwm_calc() consistent with the other functions in the meson-pwm driver by passing struct pwm_device to it as well. The value of the "id" parameter is actually pwm->hwpwm, but the driver never read the "id" parameter, which is why there's no replacement for it in the new code. No functional changes. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 39ea119add7b..d6eb4d04d5c9 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -114,10 +114,10 @@ static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) clk_disable_unprepare(channel->clk); } -static int meson_pwm_calc(struct meson_pwm *meson, - struct meson_pwm_channel *channel, +static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, struct pwm_state *state) { + struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); unsigned int duty, period, pre_div, cnt, duty_cnt; unsigned long fin_freq = -1; u64 fin_ps; @@ -280,7 +280,7 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->period != channel->state.period || state->duty_cycle != channel->state.duty_cycle || state->polarity != channel->state.polarity) { - err = meson_pwm_calc(meson, channel, state); + err = meson_pwm_calc(meson, pwm, state); if (err < 0) return err; -- 2.21.0
[PATCH 01/14] pwm: meson: unify the parameter list of meson_pwm_{enable,disable}
This is a preparation for a future cleanup. Pass struct pwm_device instead of passing the individual values required by each function as these can be obtained for each struct pwm_device instance. As a nice side-effect the driver now uses "switch (pwm->hwpwm)" everywhere. Before some functions used "switch (id)" while others used "switch (pwm->hwpwm)". No functional changes. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 15 +++ 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 5fef7e925282..3fbbc4128ce8 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -183,15 +183,14 @@ static int meson_pwm_calc(struct meson_pwm *meson, return 0; } -static void meson_pwm_enable(struct meson_pwm *meson, -struct meson_pwm_channel *channel, -unsigned int id) +static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm) { + struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); u32 value, clk_shift, clk_enable, enable; unsigned int offset; unsigned long flags; - switch (id) { + switch (pwm->hwpwm) { case 0: clk_shift = MISC_A_CLK_DIV_SHIFT; clk_enable = MISC_A_CLK_EN; @@ -228,12 +227,12 @@ static void meson_pwm_enable(struct meson_pwm *meson, spin_unlock_irqrestore(>lock, flags); } -static void meson_pwm_disable(struct meson_pwm *meson, unsigned int id) +static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) { u32 value, enable; unsigned long flags; - switch (id) { + switch (pwm->hwpwm) { case 0: enable = MISC_A_EN; break; @@ -266,7 +265,7 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return -EINVAL; if (!state->enabled) { - meson_pwm_disable(meson, pwm->hwpwm); + meson_pwm_disable(meson, pwm); channel->state.enabled = false; return 0; @@ -293,7 +292,7 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, } if (state->enabled && !channel->state.enabled) { - meson_pwm_enable(meson, channel, pwm->hwpwm); + meson_pwm_enable(meson, pwm); channel->state.enabled = true; } -- 2.21.0
[PATCH 03/14] pwm: meson: use GENMASK and FIELD_PREP for the lo and hi values
meson_pwm_calc() ensures that "lo" is always less than 16 bits wide (otherwise it would overflow into the "hi" part of the REG_PWM_{A,B} register). Use GENMASK and FIELD_PREP for the lo and hi values to make it easier to spot how wide these are internally. Additionally this is a preparation step for the .get_state() implementation where the GENMASK() for lo and hi becomes handy because it can be used with FIELD_GET() to extract the values from the register REG_PWM_{A,B} register. No functional changes intended. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 35b38c7201c3..c62a3ac924d0 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -5,6 +5,8 @@ * Copyright (C) 2014 Amlogic, Inc. */ +#include +#include #include #include #include @@ -20,7 +22,8 @@ #define REG_PWM_A 0x0 #define REG_PWM_B 0x4 -#define PWM_HIGH_SHIFT 16 +#define PWM_LOW_MASK GENMASK(15, 0) +#define PWM_HIGH_MASK GENMASK(31, 16) #define REG_MISC_AB0x8 #define MISC_B_CLK_EN BIT(23) @@ -217,7 +220,8 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm) value |= clk_enable; writel(value, meson->base + REG_MISC_AB); - value = (channel->hi << PWM_HIGH_SHIFT) | channel->lo; + value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) | + FIELD_PREP(PWM_LOW_MASK, channel->lo); writel(value, meson->base + offset); value = readl(meson->base + REG_MISC_AB); -- 2.21.0
[PATCH 13/14] pwm: meson: add support PWM_POLARITY_INVERSED when disabling
meson_pwm_apply() has to consider the PWM polarity when disabling the output. With enabled=false and polarity=PWM_POLARITY_NORMAL the output needs to be LOW. The driver already supports this. With enabled=false and polarity=PWM_POLARITY_INVERSED the output needs to be HIGH. Implement this in the driver by internally enabling the output with the same settings that we already use for "period == duty". This fixes a PWM API violation which expects that the driver honors the polarity also for enabled=false. Due to the IP block not supporting this natively we only get "an as close as possible" to 100% HIGH signal (in my test setup with input clock of 24MHz and measuring the output with a logic analyzer at 24MHz sampling rate I got a duty cycle of 99.998475% on a Khadas VIM). Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 23 ++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 900d362ec3c9..bb48ba85f756 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -245,6 +245,7 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { + struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); struct meson_pwm *meson = to_meson_pwm(chip); int err = 0; @@ -252,7 +253,27 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return -EINVAL; if (!state->enabled) { - meson_pwm_disable(meson, pwm); + if (state->polarity == PWM_POLARITY_INVERSED) { + /* +* This IP block revision doesn't have an "always high" +* setting which we can use for "inverted disabled". +* Instead we achieve this using the same settings +* that we use a pre_div of 0 (to get the shortest +* possible duration for one "count") and +* "period == duty_cycle". This results in a signal +* which is LOW for one "count", while being HIGH for +* the rest of the (so the signal is HIGH for slightly +* less than 100% of the period, but this is the best +* we can achieve). +*/ + channel->pre_div = 0; + channel->hi = ~0; + channel->lo = 0; + + meson_pwm_enable(meson, pwm); + } else { + meson_pwm_disable(meson, pwm); + } } else { err = meson_pwm_calc(meson, pwm, state); if (err < 0) -- 2.21.0
[PATCH 14/14] pwm: meson: add documentation to the driver
Add a link to the datasheet and a short summary how the hardware works. The goal is to make it easier for other developers to understand why the pwm-meson driver is implemented the way it is. Suggested-by: Uwe Kleine-König Co-authored-by: Neil Armstrong Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index bb48ba85f756..6a978caba483 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -1,5 +1,23 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* + * PWM controller driver for Amlogic Meson SoCs. + * + * This PWM is only a set of Gates, Dividers and Counters: + * PWM output is achieved by calculating a clock that permits calculating + * two periods (low and high). The counter then has to be set to switch after + * N cycles for the first half period. + * The hardware has no "polarity" setting. This driver reverses the period + * cycles (the low length is inverted with the high length) for + * PWM_POLARITY_INVERSED. This means that .get_state cannot read the polarity + * from the hardware. + * Setting the duty cycle will disable and re-enable the PWM output. + * Disabling the PWM stops the output immediately (without waiting for the + * current period to complete first). + * + * The public S922X datasheet contains some documentation for this PWM + * controller starting on page 1084: + * https://dl.khadas.com/Hardware/VIM2/Datasheet/S912_Datasheet_V0.220170314publicversion-Wesion.pdf + * * Copyright (c) 2016 BayLibre, SAS. * Author: Neil Armstrong * Copyright (C) 2014 Amlogic, Inc. -- 2.21.0
[PATCH 08/14] pwm: meson: add the per-channel register offsets and bits in a struct
Introduce struct meson_pwm_channel_data which contains the per-channel offsets for the PWM register and REG_MISC_AB bits. Replace the existing switch (pwm->hwpwm) statements with an access to the new struct. This simplifies the code and will make it easier to implement pwm_ops.get_state() because the switch-case which all per-channel registers and offsets (as previously implemented in meson_pwm_enable()) doesn't have to be duplicated. No functional changes intended. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 92 - 1 file changed, 35 insertions(+), 57 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index d1718f54ecec..ac7e188155fd 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -39,9 +39,27 @@ #define MESON_NUM_PWMS 2 -static const unsigned int mux_reg_shifts[] = { - MISC_A_CLK_SEL_SHIFT, - MISC_B_CLK_SEL_SHIFT +static struct meson_pwm_channel_data { + u8 reg_offset; + u8 clk_sel_shift; + u8 clk_div_shift; + u32 clk_en_mask; + u32 pwm_en_mask; +} meson_pwm_per_channel_data[MESON_NUM_PWMS] = { + { + .reg_offset = REG_PWM_A, + .clk_sel_shift = MISC_A_CLK_SEL_SHIFT, + .clk_div_shift = MISC_A_CLK_DIV_SHIFT, + .clk_en_mask= MISC_A_CLK_EN, + .pwm_en_mask= MISC_A_EN, + }, + { + .reg_offset = REG_PWM_B, + .clk_sel_shift = MISC_B_CLK_SEL_SHIFT, + .clk_div_shift = MISC_B_CLK_DIV_SHIFT, + .clk_en_mask= MISC_B_CLK_EN, + .pwm_en_mask= MISC_B_EN, + } }; struct meson_pwm_channel { @@ -194,43 +212,26 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm) { struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); - u32 value, clk_shift, clk_enable, enable; - unsigned int offset; + struct meson_pwm_channel_data *channel_data; unsigned long flags; + u32 value; - switch (pwm->hwpwm) { - case 0: - clk_shift = MISC_A_CLK_DIV_SHIFT; - clk_enable = MISC_A_CLK_EN; - enable = MISC_A_EN; - offset = REG_PWM_A; - break; - - case 1: - clk_shift = MISC_B_CLK_DIV_SHIFT; - clk_enable = MISC_B_CLK_EN; - enable = MISC_B_EN; - offset = REG_PWM_B; - break; - - default: - return; - } + channel_data = _pwm_per_channel_data[pwm->hwpwm]; spin_lock_irqsave(>lock, flags); value = readl(meson->base + REG_MISC_AB); - value &= ~(MISC_CLK_DIV_MASK << clk_shift); - value |= channel->pre_div << clk_shift; - value |= clk_enable; + value &= ~(MISC_CLK_DIV_MASK << channel_data->clk_div_shift); + value |= channel->pre_div << channel_data->clk_div_shift; + value |= channel_data->clk_en_mask; writel(value, meson->base + REG_MISC_AB); value = FIELD_PREP(PWM_HIGH_MASK, channel->hi) | FIELD_PREP(PWM_LOW_MASK, channel->lo); - writel(value, meson->base + offset); + writel(value, meson->base + channel_data->reg_offset); value = readl(meson->base + REG_MISC_AB); - value |= enable; + value |= channel_data->pwm_en_mask; writel(value, meson->base + REG_MISC_AB); spin_unlock_irqrestore(>lock, flags); @@ -238,26 +239,13 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm) static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) { - u32 value, enable; unsigned long flags; - - switch (pwm->hwpwm) { - case 0: - enable = MISC_A_EN; - break; - - case 1: - enable = MISC_B_EN; - break; - - default: - return; - } + u32 value; spin_lock_irqsave(>lock, flags); value = readl(meson->base + REG_MISC_AB); - value &= ~enable; + value &= ~meson_pwm_per_channel_data[pwm->hwpwm].pwm_en_mask; writel(value, meson->base + REG_MISC_AB); spin_unlock_irqrestore(>lock, flags); @@ -309,18 +297,7 @@ static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, if (!state) return; - switch (pwm->hwpwm) { - case 0: - mask = MISC_A_EN; - break; - - case 1: - mask = MISC_B_EN; - break; - - default: - return; - } + mask = meson_pwm_per_channel_data[pwm->hwpwm].pwm_en_mask; value = readl(meson->base + REG_MISC_AB);
[PATCH 02/14] pwm: meson: use devm_clk_get_optional() to get the input clock
Simplify the code which fetches the input clock for a PWM channel by using devm_clk_get_optional(). This comes with a small functional change: previously all errors except EPROBE_DEFER were ignored. Now all other errors are also treated as errors. If no input clock is present devm_clk_get_optional() will return NULL instead of an error which matches the behavior of the old code. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 11 +++ 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 3fbbc4128ce8..35b38c7201c3 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -474,14 +474,9 @@ static int meson_pwm_init_channels(struct meson_pwm *meson, snprintf(name, sizeof(name), "clkin%u", i); - channel->clk_parent = devm_clk_get(dev, name); - if (IS_ERR(channel->clk_parent)) { - err = PTR_ERR(channel->clk_parent); - if (err == -EPROBE_DEFER) - return err; - - channel->clk_parent = NULL; - } + channel->clk_parent = devm_clk_get_optional(dev, name); + if (IS_ERR(channel->clk_parent)) + return PTR_ERR(channel->clk_parent); } return 0; -- 2.21.0
[PATCH 12/14] pwm: meson: don't cache struct pwm_state internally
The PWM core already caches the "current struct pwm_state" as the "current state of the hardware registers" inside struct pwm_device. Drop the struct pwm_state from struct meson_pwm_channel in favour of the struct pwm_state in struct pwm_device. While here also drop any checks based on the pwm_state because the PWM core already takes care of this. No functional changes intended. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 25 + 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 010212166d5d..900d362ec3c9 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -68,8 +68,6 @@ struct meson_pwm_channel { unsigned int lo; u8 pre_div; - struct pwm_state state; - struct clk *clk_parent; struct clk_mux mux; struct clk *clk; @@ -127,8 +125,6 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) return err; } - chip->ops->get_state(chip, pwm, >state); - return pwm_set_chip_data(pwm, channel); } @@ -153,10 +149,6 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm, if (state->polarity == PWM_POLARITY_INVERSED) duty = period - duty; - if (period == channel->state.period && - duty == channel->state.duty_cycle) - return 0; - fin_freq = clk_get_rate(channel->clk); if (fin_freq == 0) { dev_err(meson->chip.dev, "invalid source clock frequency\n"); @@ -253,7 +245,6 @@ static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm) static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) { - struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); struct meson_pwm *meson = to_meson_pwm(chip); int err = 0; @@ -262,26 +253,12 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (!state->enabled) { meson_pwm_disable(meson, pwm); - channel->state.enabled = false; - - return 0; - } - - if (state->period != channel->state.period || - state->duty_cycle != channel->state.duty_cycle || - state->polarity != channel->state.polarity) { + } else { err = meson_pwm_calc(meson, pwm, state); if (err < 0) return err; - channel->state.polarity = state->polarity; - channel->state.period = state->period; - channel->state.duty_cycle = state->duty_cycle; - } - - if (state->enabled && !channel->state.enabled) { meson_pwm_enable(meson, pwm); - channel->state.enabled = true; } return 0; -- 2.21.0
[PATCH 00/14] pwm-meson: cleanups and improvements
This series consists of various cleanups and improvements for the pwm-meson driver. Patches 1 to 6 are small code cleanups with the goal of making the code easier to read. Patches 7 to 9 are reworking the way the per-channel settings are accessed. This is a first preparation step for adding full support to meson_pwm_get_state() in the pwm-meson driver. Patch 7 makes struct meson_pwm_channel accessible from struct meson_pwm because meson_pwm_get_state() cannot use pwm_get_chip_data(). Patch 8 removes redundant switch/case statements and ensures that we don't have to add another redundant one for the upcoming full meson_pwm_get_state() implementation. Patch 9 gets rid of meson_pwm_add_channels() and moves the pwm_set_chip_data() call to meson_pwm_request() (like all other PWM drivers do - except two). Patch 10 is based on a suggestion by Uwe to simplify the calculation of the values which the PWM IP requires. The nice benefit of this is that we have an easier calculation which we can do "in reverse" for the meson_pwm_get_state() (which calculates nanoseconds from the hardware values). Patch 11 implements reading the period and duty cycle in the meson_pwm_get_state() callback. Patch 12 removes some internal caching which we don't need anymore now meson_pwm_get_state() is fully implemented. The PWM core now takes care of not calling pwm_ops.apply() if "nothing has changed". Patch 13 adds support for PWM_POLARITY_INVERSED when disabling the output as suggested by Uwe. Patch 14 completes this series by adding some documentation to the driver. Thanks to Neil for summarizing how the hardware works internally. Due to the changed PWM calculation in patch 10 I have verified that we don't break any existing boards. The patch itself contains two examples which show that the new calculation improves precision. I made screenshots of the measurements in pulseview [0] for the second case ("PWM LED on Khadas VIM"): - old algorithm: [1] - old algorithm: [2] Dependencies: This series applies on top of Neil's patch "pwm: pwm-meson: update with SPDX Licence identifier" [3] [0] https://sigrok.org/wiki/PulseView [1] https://abload.de/img/old-algormjs9.png [2] https://abload.de/img/new-algo4ckjo.png [3] https://patchwork.kernel.org/patch/10951319/ Martin Blumenstingl (14): pwm: meson: unify the parameter list of meson_pwm_{enable,disable} pwm: meson: use devm_clk_get_optional() to get the input clock pwm: meson: use GENMASK and FIELD_PREP for the lo and hi values pwm: meson: change MISC_CLK_SEL_WIDTH to MISC_CLK_SEL_MASK pwm: meson: don't duplicate the polarity internally pwm: meson: pass struct pwm_device to meson_pwm_calc() pwm: meson: add the meson_pwm_channel data to struct meson_pwm pwm: meson: add the per-channel register offsets and bits in a struct pwm: meson: move pwm_set_chip_data() to meson_pwm_request() pwm: meson: simplify the calculation of the pre-divider and count pwm: meson: read the full hardware state in meson_pwm_get_state() pwm: meson: don't cache struct pwm_state internally pwm: meson: add support PWM_POLARITY_INVERSED when disabling pwm: meson: add documentation to the driver drivers/pwm/pwm-meson.c | 323 +--- 1 file changed, 169 insertions(+), 154 deletions(-) -- 2.21.0
[PATCH 05/14] pwm: meson: don't duplicate the polarity internally
Let meson_pwm_calc() use the polarity from struct pwm_state directly. This removes a level of indirection where meson_pwm_apply() first had to set a driver-internal inverter mask which was then only used by meson_pwm_calc(). Instead of adding the polarity as parameter to meson_pwm_calc() switch to struct pwm_state directly to make it easier to see where the parameters are actually coming from. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 23 --- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 84b28ba0f903..39ea119add7b 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -63,7 +63,6 @@ struct meson_pwm { struct pwm_chip chip; const struct meson_pwm_data *data; void __iomem *base; - u8 inverter_mask; /* * Protects register (write) access to the REG_MISC_AB register * that is shared between the two PWMs. @@ -116,14 +115,17 @@ static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) } static int meson_pwm_calc(struct meson_pwm *meson, - struct meson_pwm_channel *channel, unsigned int id, - unsigned int duty, unsigned int period) + struct meson_pwm_channel *channel, + struct pwm_state *state) { - unsigned int pre_div, cnt, duty_cnt; + unsigned int duty, period, pre_div, cnt, duty_cnt; unsigned long fin_freq = -1; u64 fin_ps; - if (~(meson->inverter_mask >> id) & 0x1) + duty = state->duty_cycle; + period = state->period; + + if (state->polarity == PWM_POLARITY_INVERSED) duty = period - duty; if (period == channel->state.period && @@ -278,15 +280,7 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, if (state->period != channel->state.period || state->duty_cycle != channel->state.duty_cycle || state->polarity != channel->state.polarity) { - if (state->polarity != channel->state.polarity) { - if (state->polarity == PWM_POLARITY_NORMAL) - meson->inverter_mask |= BIT(pwm->hwpwm); - else - meson->inverter_mask &= ~BIT(pwm->hwpwm); - } - - err = meson_pwm_calc(meson, channel, pwm->hwpwm, -state->duty_cycle, state->period); + err = meson_pwm_calc(meson, channel, state); if (err < 0) return err; @@ -520,7 +514,6 @@ static int meson_pwm_probe(struct platform_device *pdev) meson->chip.of_pwm_n_cells = 3; meson->data = of_device_get_match_data(>dev); - meson->inverter_mask = BIT(meson->chip.npwm) - 1; channels = devm_kcalloc(>dev, meson->chip.npwm, sizeof(*channels), GFP_KERNEL); -- 2.21.0
[PATCH 07/14] pwm: meson: add the meson_pwm_channel data to struct meson_pwm
Make struct meson_pwm_channel accessible from struct meson_pwm. PWM core has a limitation: per-channel data can only be set after pwmchip_add() is called. However, pwmchip_add() internally calls pwm_ops.get_state(). If pwm_ops.get_state() needs access to the per-channel data it has to obtain it from struct pwm_chip and struct pwm_device's hwpwm information. Add a struct meson_pwm_channel for each PWM channel to struct meson_pwm so the pwm_ops.get_state() callback can be implemented as it needs access to the clock from struct meson_pwm_channel. Signed-off-by: Martin Blumenstingl --- drivers/pwm/pwm-meson.c | 25 ++--- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index d6eb4d04d5c9..d1718f54ecec 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -37,6 +37,8 @@ #define MISC_B_EN BIT(1) #define MISC_A_EN BIT(0) +#define MESON_NUM_PWMS 2 + static const unsigned int mux_reg_shifts[] = { MISC_A_CLK_SEL_SHIFT, MISC_B_CLK_SEL_SHIFT @@ -62,6 +64,7 @@ struct meson_pwm_data { struct meson_pwm { struct pwm_chip chip; const struct meson_pwm_data *data; + struct meson_pwm_channel channels[MESON_NUM_PWMS]; void __iomem *base; /* * Protects register (write) access to the REG_MISC_AB register @@ -435,8 +438,7 @@ static const struct of_device_id meson_pwm_matches[] = { }; MODULE_DEVICE_TABLE(of, meson_pwm_matches); -static int meson_pwm_init_channels(struct meson_pwm *meson, - struct meson_pwm_channel *channels) +static int meson_pwm_init_channels(struct meson_pwm *meson) { struct device *dev = meson->chip.dev; struct clk_init_data init; @@ -445,7 +447,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson, int err; for (i = 0; i < meson->chip.npwm; i++) { - struct meson_pwm_channel *channel = [i]; + struct meson_pwm_channel *channel = >channels[i]; snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i); @@ -480,18 +482,16 @@ static int meson_pwm_init_channels(struct meson_pwm *meson, return 0; } -static void meson_pwm_add_channels(struct meson_pwm *meson, - struct meson_pwm_channel *channels) +static void meson_pwm_add_channels(struct meson_pwm *meson) { unsigned int i; for (i = 0; i < meson->chip.npwm; i++) - pwm_set_chip_data(>chip.pwms[i], [i]); + pwm_set_chip_data(>chip.pwms[i], >channels[i]); } static int meson_pwm_probe(struct platform_device *pdev) { - struct meson_pwm_channel *channels; struct meson_pwm *meson; struct resource *regs; int err; @@ -509,18 +509,13 @@ static int meson_pwm_probe(struct platform_device *pdev) meson->chip.dev = >dev; meson->chip.ops = _pwm_ops; meson->chip.base = -1; - meson->chip.npwm = 2; + meson->chip.npwm = MESON_NUM_PWM; meson->chip.of_xlate = of_pwm_xlate_with_flags; meson->chip.of_pwm_n_cells = 3; meson->data = of_device_get_match_data(>dev); - channels = devm_kcalloc(>dev, meson->chip.npwm, - sizeof(*channels), GFP_KERNEL); - if (!channels) - return -ENOMEM; - - err = meson_pwm_init_channels(meson, channels); + err = meson_pwm_init_channels(meson); if (err < 0) return err; @@ -530,7 +525,7 @@ static int meson_pwm_probe(struct platform_device *pdev) return err; } - meson_pwm_add_channels(meson, channels); + meson_pwm_add_channels(meson); platform_set_drvdata(pdev, meson); -- 2.21.0
[PATCH 02/10] media: rc: sunxi: Add A31 compatible
A31 have a different memory mapping so add the compatible we will need it later. Signed-off-by: Clément Péron --- drivers/media/rc/sunxi-cir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index 307e44714ea0..29ac33b68596 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -319,6 +319,7 @@ static int sunxi_ir_remove(struct platform_device *pdev) static const struct of_device_id sunxi_ir_match[] = { { .compatible = "allwinner,sun4i-a10-ir", }, { .compatible = "allwinner,sun5i-a13-ir", }, + { .compatible = "allwinner,sun6i-a31-ir", }, {}, }; MODULE_DEVICE_TABLE(of, sunxi_ir_match); -- 2.20.1
[PATCH 03/10] ARM: dts: sunxi: prefer A31 instead of A13 for ir
Since A31 memory mapping of the IR driver has changed. Prefer the A31 bindings instead of A13. Signed-off-by: Clément Péron --- arch/arm/boot/dts/sun6i-a31.dtsi | 2 +- arch/arm/boot/dts/sun8i-a83t.dtsi | 2 +- arch/arm/boot/dts/sun9i-a80.dtsi | 2 +- arch/arm/boot/dts/sunxi-h3-h5.dtsi | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index c04efad81bbc..110622b30796 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -1351,7 +1351,7 @@ }; ir: ir@1f02000 { - compatible = "allwinner,sun5i-a13-ir"; + compatible = "allwinner,sun6i-a31-ir"; clocks = <_gates 1>, <_clk>; clock-names = "apb", "ir"; resets = <_rst 1>; diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi index 392b0cabbf0d..8d603f3309f2 100644 --- a/arch/arm/boot/dts/sun8i-a83t.dtsi +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi @@ -1067,7 +1067,7 @@ r_cir: ir@1f02000 { compatible = "allwinner,sun8i-a83t-ir", - "allwinner,sun5i-a13-ir"; + "allwinner,sun6i-a31-ir"; clocks = <_ccu CLK_APB0_IR>, <_ccu CLK_IR>; clock-names = "apb", "ir"; resets = <_ccu RST_APB0_IR>; diff --git a/arch/arm/boot/dts/sun9i-a80.dtsi b/arch/arm/boot/dts/sun9i-a80.dtsi index 0c1eec9000e3..310cd972ee5b 100644 --- a/arch/arm/boot/dts/sun9i-a80.dtsi +++ b/arch/arm/boot/dts/sun9i-a80.dtsi @@ -1167,7 +1167,7 @@ }; r_ir: ir@8002000 { - compatible = "allwinner,sun5i-a13-ir"; + compatible = "allwinner,sun6i-a31-ir"; interrupts = ; pinctrl-names = "default"; pinctrl-0 = <_ir_pins>; diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi index 84977d4eb97a..f0f5ba349c1b 100644 --- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi +++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi @@ -822,7 +822,7 @@ }; ir: ir@1f02000 { - compatible = "allwinner,sun5i-a13-ir"; + compatible = "allwinner,sun6i-a31-ir"; clocks = <_ccu CLK_APB0_IR>, <_ccu CLK_IR>; clock-names = "apb", "ir"; resets = <_ccu RST_APB0_IR>; -- 2.20.1
[PATCH 04/10] dt-bindings: media: sunxi-ir: Add A64 compatible
There is some minor differences between A31 and A64 driver. But A31 IR driver is compatible with A64. Signed-off-by: Clément Péron --- Documentation/devicetree/bindings/media/sunxi-ir.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt index 53e88ebb53fe..da5aeba843de 100644 --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt @@ -5,6 +5,7 @@ Required properties: "allwinner,sun4i-a10-ir" "allwinner,sun5i-a13-ir" "allwinner,sun6i-a31-ir" + "allwinner,sun50i-a64-ir", "allwinner,sun6i-a31-ir" - clocks : list of clock specifiers, corresponding to entries in clock-names property; - clock-names : should contain "apb" and "ir" entries; -- 2.20.1
[PATCH 06/10] arm64: dts: allwinner: a64: Enable IR on Orange Pi Win
From: Jernej Skrabec OrangePi Win board contains IR receiver. Enable it. Signed-off-by: Jernej Skrabec Signed-off-by: Clément Péron --- arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts index 510f661229dc..e05191b71adf 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts @@ -180,6 +180,10 @@ status = "okay"; }; +_ir { + status = "okay"; +}; + _rsb { status = "okay"; -- 2.20.1
[PATCH 08/10] arm64: dts: allwiner: h6: Add IR receiver node
Allwiner H6 IR is similar to A31 and can use same driver. Add support for it. Signed-off-by: Clément Péron --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 19 +++ 1 file changed, 19 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 16c5c3d0fd81..649cbdfe452e 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -647,6 +647,25 @@ pins = "PL0", "PL1"; function = "s_i2c"; }; + + r_ir_rx_pin: r-ir-rx-pin { + pins = "PL9"; + function = "s_cir_rx"; + }; + }; + + r_ir: ir@704 { + compatible = "allwinner,sun50i-h6-ir", +"allwinner,sun6i-a31-ir"; + reg = <0x0704 0x400>; + interrupts = ; + clocks = <_ccu CLK_R_APB1_IR>, +<_ccu CLK_IR>; + clock-names = "apb", "ir"; + resets = <_ccu RST_R_APB1_IR>; + pinctrl-names = "default"; + pinctrl-0 = <_ir_rx_pin>; + status = "disabled"; }; r_i2c: i2c@7081400 { -- 2.20.1
[PATCH 05/10] arm64: dts: allwinner: a64: Add IR node
From: Igors Makejevs IR peripheral is completely compatible with A31 one. Signed-off-by: Igors Makejevs Signed-off-by: Jernej Skrabec Signed-off-by: Clément Péron --- arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 18 ++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 8c5b521e6389..b22b0aa89515 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -1072,6 +1072,19 @@ #size-cells = <0>; }; + r_ir: ir@1f02000 { + compatible = "allwinner,sun50i-a64-ir", +"allwinner,sun6i-a31-ir"; + reg = <0x01f02000 0x400>; + clocks = <_ccu CLK_APB0_IR>, <_ccu CLK_IR>; + clock-names = "apb", "ir"; + resets = <_ccu RST_APB0_IR>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <_ir_rx_pin>; + status = "disabled"; + }; + r_pwm: pwm@1f03800 { compatible = "allwinner,sun50i-a64-pwm", "allwinner,sun5i-a13-pwm"; @@ -1099,6 +1112,11 @@ function = "s_i2c"; }; + r_ir_rx_pin: r-ir-rx-pin { + pins = "PL11"; + function = "s_cir_rx"; + }; + r_pwm_pin: r-pwm-pin { pins = "PL10"; function = "s_pwm"; -- 2.20.1