* [PATCH 2/6] dmaengine: xilinx_dma: fix completion callback is not invoked for each DMA operation
From: Andrea Merello @ 2018-06-20 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620083653.17010-1-andrea.merello@gmail.com>
API specification says: "On completion of each DMA operation, the next in
queue is started and a tasklet triggered. The tasklet will then call the
client driver completion callback routine for notification, if set."
Currently the driver keeps a "desc_pendingcount" counter of the total
descriptor pending, and it uses as IRQ coalesce threshold, as result it
only calls the CBs after ALL pending operations are completed, which is
wrong.
This patch uses disable IRQ coalesce and checks for the completion flag
for the descriptors (which is further divided in segments).
Possibly a better optimization could be using proper IRQ coalesce
threshold to get an IRQ after all segments of the descriptors are done.
But we don't do that yet..
NOTE: for now we do this only for AXI DMA, other DMA flavors are
untested/untouched.
This is loosely based on
commit 65df81a6dc74 ("xilinx_dma: IrqThreshold set incorrectly, unreliable.")
in my linux-4.6-zynq tree
From: Jeremy Trimble [original patch]
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
drivers/dma/xilinx/xilinx_dma.c | 39 +++++++++++++++++++++------------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index a516e7ffef21..cf12f7147f07 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -164,6 +164,7 @@
#define XILINX_DMA_CR_COALESCE_SHIFT 16
#define XILINX_DMA_BD_SOP BIT(27)
#define XILINX_DMA_BD_EOP BIT(26)
+#define XILINX_DMA_BD_CMPLT BIT(31)
#define XILINX_DMA_COALESCE_MAX 255
#define XILINX_DMA_NUM_DESCS 255
#define XILINX_DMA_NUM_APP_WORDS 5
@@ -1274,12 +1275,9 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
- if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
- reg &= ~XILINX_DMA_CR_COALESCE_MAX;
- reg |= chan->desc_pendingcount <<
- XILINX_DMA_CR_COALESCE_SHIFT;
- dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
- }
+ reg &= ~XILINX_DMA_CR_COALESCE_MAX;
+ reg |= 1 << XILINX_DMA_CR_COALESCE_SHIFT;
+ dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
if (chan->has_sg && !chan->xdev->mcdma)
xilinx_write(chan, XILINX_DMA_REG_CURDESC,
@@ -1378,6 +1376,20 @@ static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan)
return;
list_for_each_entry_safe(desc, next, &chan->active_list, node) {
+ if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+ /*
+ * Check whether the last segment in this descriptor
+ * has been completed.
+ */
+ const struct xilinx_axidma_tx_segment *const tail_seg =
+ list_last_entry(&desc->segments,
+ struct xilinx_axidma_tx_segment,
+ node);
+
+ /* we've processed all the completed descriptors */
+ if (!(tail_seg->hw.status & XILINX_DMA_BD_CMPLT))
+ break;
+ }
list_del(&desc->node);
if (!desc->cyclic)
dma_cookie_complete(&desc->async_tx);
@@ -1826,14 +1838,13 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
struct xilinx_axidma_tx_segment, node);
desc->async_tx.phys = segment->phys;
- /* For the last DMA_MEM_TO_DEV transfer, set EOP */
- if (chan->direction == DMA_MEM_TO_DEV) {
- segment->hw.control |= XILINX_DMA_BD_SOP;
- segment = list_last_entry(&desc->segments,
- struct xilinx_axidma_tx_segment,
- node);
- segment->hw.control |= XILINX_DMA_BD_EOP;
- }
+ /* For the first transfer, set SOP */
+ segment->hw.control |= XILINX_DMA_BD_SOP;
+ /* For the last transfer, set EOP */
+ segment = list_last_entry(&desc->segments,
+ struct xilinx_axidma_tx_segment,
+ node);
+ segment->hw.control |= XILINX_DMA_BD_EOP;
return &desc->async_tx;
--
2.17.1
^ permalink raw reply related
* [PATCH 3/6] dt-bindings: xilinx_dma: add required xlnx, lengthregwidth property
From: Andrea Merello @ 2018-06-20 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620083653.17010-1-andrea.merello@gmail.com>
The width of the "length register" cannot be autodetected, and it is now
specified with a DT property. Add DOC for it.
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
index a2b8bfaec43c..acecdc5d8d47 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
@@ -36,6 +36,8 @@ Required properties:
Required properties for VDMA:
- xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
+Required properties for AXI DMA:
+- xlnx,lengthregwidth: Should be the width of the length register as configured in h/w.
Optional properties:
- xlnx,include-sg: Tells configured for Scatter-mode in
--
2.17.1
^ permalink raw reply related
* [PATCH 4/6] dmaengine: xilinx_dma: fix hardcoded maximum transfer length may be wrong
From: Andrea Merello @ 2018-06-20 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620083653.17010-1-andrea.merello@gmail.com>
The maximum transfer length is currently hardcoded in the driver, but
it depends by how the soft-IP is actually configured.
This seems to affect also max possible length for SG transfers.
This patch introduce a new DT property in order to operate with proper
maximum transfer length.
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
drivers/dma/xilinx/xilinx_dma.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index cf12f7147f07..bdbc8ba9092a 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -439,6 +439,7 @@ struct xilinx_dma_device {
struct clk *rxs_clk;
u32 nr_channels;
u32 chan_id;
+ int max_transfer;
};
/* Macros */
@@ -1806,8 +1807,8 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
* the next chuck start address is aligned
*/
copy = sg_dma_len(sg) - sg_used;
- if (copy > XILINX_DMA_MAX_TRANS_LEN)
- copy = XILINX_DMA_MAX_TRANS_LEN &
+ if (copy > chan->xdev->max_transfer)
+ copy = chan->xdev->max_transfer &
chan->copy_mask;
hw = &segment->hw;
@@ -1914,8 +1915,8 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic(
* the next chuck start address is aligned
*/
copy = period_len - sg_used;
- if (copy > XILINX_DMA_MAX_TRANS_LEN)
- copy = XILINX_DMA_MAX_TRANS_LEN &
+ if (copy > chan->xdev->max_transfer)
+ copy = chan->xdev->max_transfer &
chan->copy_mask;
hw = &segment->hw;
@@ -2594,7 +2595,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
struct xilinx_dma_device *xdev;
struct device_node *child, *np = pdev->dev.of_node;
struct resource *io;
- u32 num_frames, addr_width;
+ u32 num_frames, addr_width, lenreg_width;
int i, err;
/* Allocate and initialize the DMA engine structure */
@@ -2625,9 +2626,18 @@ static int xilinx_dma_probe(struct platform_device *pdev)
return PTR_ERR(xdev->regs);
/* Retrieve the DMA engine properties from the device tree */
- xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
- if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+
+ if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
xdev->mcdma = of_property_read_bool(node, "xlnx,mcdma");
+ err = of_property_read_u32(node, "xlnx,lengthregwidth",
+ &lenreg_width);
+ if (err < 0) {
+ dev_err(xdev->dev,
+ "missing xlnx,lengthregwidth property\n");
+ return err;
+ }
+ xdev->max_transfer = GENMASK(lenreg_width - 1, 0);
+ }
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
err = of_property_read_u32(node, "xlnx,num-fstores",
--
2.17.1
^ permalink raw reply related
* [PATCH 5/6] dmaengine: xilinx_dma: autodetect whether the HW supports scatter-gather
From: Andrea Merello @ 2018-06-20 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620083653.17010-1-andrea.merello@gmail.com>
The HW can be either direct-access or scatter-gather version. These are
SW incompatible.
The driver can handle both version: a DT property was used to
tell the driver whether to assume the HW is is scatter-gather mode.
This patch makes the driver to autodetect this information. The DT
property is not required anymore.
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
drivers/dma/xilinx/xilinx_dma.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index bdbc8ba9092a..8c6e818e596f 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -86,6 +86,7 @@
#define XILINX_DMA_DMASR_DMA_DEC_ERR BIT(6)
#define XILINX_DMA_DMASR_DMA_SLAVE_ERR BIT(5)
#define XILINX_DMA_DMASR_DMA_INT_ERR BIT(4)
+#define XILINX_DMA_DMASR_SG_MASK BIT(3)
#define XILINX_DMA_DMASR_IDLE BIT(1)
#define XILINX_DMA_DMASR_HALTED BIT(0)
#define XILINX_DMA_DMASR_DELAY_MASK GENMASK(31, 24)
@@ -407,7 +408,6 @@ struct xilinx_dma_config {
* @dev: Device Structure
* @common: DMA device structure
* @chan: Driver specific DMA channel
- * @has_sg: Specifies whether Scatter-Gather is present or not
* @mcdma: Specifies whether Multi-Channel is present or not
* @flush_on_fsync: Flush on frame sync
* @ext_addr: Indicates 64 bit addressing is supported by dma device
@@ -426,7 +426,6 @@ struct xilinx_dma_device {
struct device *dev;
struct dma_device common;
struct xilinx_dma_chan *chan[XILINX_DMA_MAX_CHANS_PER_DEVICE];
- bool has_sg;
bool mcdma;
u32 flush_on_fsync;
bool ext_addr;
@@ -2391,7 +2390,6 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
chan->dev = xdev->dev;
chan->xdev = xdev;
- chan->has_sg = xdev->has_sg;
chan->desc_pendingcount = 0x0;
chan->ext_addr = xdev->ext_addr;
/* This variable ensures that descriptors are not
@@ -2488,6 +2486,13 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
chan->stop_transfer = xilinx_dma_stop_transfer;
}
+ /* check if SG is enabled */
+ if (dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
+ XILINX_DMA_DMASR_SG_MASK)
+ chan->has_sg = true;
+ dev_dbg(chan->dev, "ch %d: SG %s\n", chan->id,
+ chan->has_sg ? "enabled" : "disabled");
+
/* Initialize the tasklet */
tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,
(unsigned long)chan);
@@ -2626,7 +2631,6 @@ static int xilinx_dma_probe(struct platform_device *pdev)
return PTR_ERR(xdev->regs);
/* Retrieve the DMA engine properties from the device tree */
-
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
xdev->mcdma = of_property_read_bool(node, "xlnx,mcdma");
err = of_property_read_u32(node, "xlnx,lengthregwidth",
--
2.17.1
^ permalink raw reply related
* [PATCH 6/6] dt-bindings: xilinx_dma: drop has-sg property
From: Andrea Merello @ 2018-06-20 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620083653.17010-1-andrea.merello@gmail.com>
This property is not needed anymore, because the driver now autodetects it.
Delete references in documentation.
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
index acecdc5d8d47..53341314eeb8 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
@@ -39,9 +39,6 @@ Required properties for VDMA:
Required properties for AXI DMA:
- xlnx,lengthregwidth: Should be the width of the length register as configured in h/w.
-Optional properties:
-- xlnx,include-sg: Tells configured for Scatter-mode in
- the hardware.
Optional properties for AXI DMA:
- xlnx,mcdma: Tells whether configured for multi-channel mode in the hardware.
Optional properties for VDMA:
--
2.17.1
^ permalink raw reply related
* [PATCH] ARM: dts: imx6sll: declare src module to be compatible to imx51's src
From: Anson Huang @ 2018-06-20 8:38 UTC (permalink / raw)
To: linux-arm-kernel
i.MX6SLL uses same SRC module as i.MX51, add "fsl,imx51-src"
compatible string to enable SRC driver to support setting
CPU resume address for cpu-idle and suspend/resume.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
---
arch/arm/boot/dts/imx6sll.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
index c9b0ccc..000e613 100644
--- a/arch/arm/boot/dts/imx6sll.dtsi
+++ b/arch/arm/boot/dts/imx6sll.dtsi
@@ -548,7 +548,7 @@
};
src: reset-controller at 20d8000 {
- compatible = "fsl,imx6sll-src";
+ compatible = "fsl,imx6sll-src", "fsl,imx51-src";
reg = <0x020d8000 0x4000>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
--
2.7.4
^ permalink raw reply related
* [PATCH] arm64: dts: allwinner: h6: Add LED device nodes for Pine H64
From: Maxime Ripard @ 2018-06-20 8:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620071341.8143-1-wens@csie.org>
On Wed, Jun 20, 2018 at 03:13:41PM +0800, Chen-Yu Tsai wrote:
> The Pine H64 has 3 GPIO-controlled LEDs, which are labeled "heartbeat",
> "link", and "status".
>
> Add device nodes for them.
>
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Thanks!
Maxime
--
Maxime Ripard, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180620/3e704fb9/attachment-0001.sig>
^ permalink raw reply
* [PATCH] driver core: add a debugfs entry to show deferred devices
From: Javier Martinez Canillas @ 2018-06-20 8:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619225145.GA23389@kroah.com>
On 06/20/2018 12:51 AM, Greg Kroah-Hartman wrote:
[snip]
>> @@ -233,6 +252,9 @@ void device_unblock_probing(void)
>> */
>> static int deferred_probe_initcall(void)
>> {
>> + debugfs_create_file("deferred_devices", 0444, NULL, NULL,
>> + &deferred_devs_fops);
>
> In the root of debugfs?
>
I added in the root for lack of a better place. Any suggestion is welcomed.
> Anyway, what about "devices_deferred", to help keep things semi-sane if
> we have other driver core debugfs entries?
>
I don't have a strong opinion on the name really, so I'll change it.
> And you don't remove the file ever?
>
Yeah, I saw that it wasn't removed in other places for debugfs entries
created by the core since unlike drivers they can't be built as a module
or re-loaded. But you are right, I'll add an __exitcall to remove there.
> And what is the use of this file? What can you do with this
> information? Who is going to use it? Don't we have other deferred
This patch is the result of a discussion with Tomeu and Mark (cc'ed) to
allow https://kernelci.org to test if there was a regression that makes
drivers to defer their probe.
The problem with the probe deferral mechanism is that you don't have a
way to distinguish between a valid deferral due a dependency not being
available yet and a bug (i.e: wrong DTB, config symbol not enabled, etc)
that prevents the device to eventually being probed.
> probe debugging somewhere else?
>
There is some debug yes, but it isn't suitable for the use case I explained.
For start, it only tells you if a given driver for a device was deferred or
probed correctly while this patch attempts to tell what was left (if any)
in the queue after the last driver was registered.
Second, is only enabled until late_initcall so it will only print the probe
deferral for built-in drivers and not for modules. This patch registers the
debugfs entry after the probe debugging has been disabled.
> thanks,
>
> greg k-h
>
Best regards,
--
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat
^ permalink raw reply
* [PATCH v10 13/14] cpufreq: Add module to register cpufreq on Krait CPUs
From: sricharan at codeaurora.org @ 2018-06-20 8:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619152927.GA6139@arch>
On 2018-06-19 20:59, Craig Tatlor wrote:
> The pvs refuse check is incorrect... With downstream it says it isn't
> blown and that it is 11, which also happens on upstream if I import
> it's
> efuse reading code from an older revision, or comment out the check.
>
ok, atleast on my ipq8064, it works the same. let me check once.
> Also, I'm still getting my issue about clocks above 2,147,483,647hz
> however I think this may be related to the division in the hfpll driver
> so I'll have a debug around there.
>
hmm, atleast on ipq8064, it goes till the max frequency. As you said
it might be to do with the hfpll driver that runs on 8974. I will try
to test
on that hardware.
That said, just realized that i missed a minor comment from Bjorn.
Will anyway update it.
Regards,
Sricharan
> On Tue, Jun 19, 2018 at 07:15:24PM +0530, Sricharan R wrote:
>> From: Stephen Boyd <sboyd@codeaurora.org>
>>
>> Register a cpufreq-generic device whenever we detect that a
>> "qcom,krait" compatible CPU is present in DT.
>>
>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> [Sricharan: updated to use dev_pm_opp_set_prop_name and
>> nvmem apis]
>> Signed-off-by: Sricharan R <sricharan@codeaurora.org>
>> [Thierry Escande: update to add support for opp-supported-hw]
>> Signed-off-by: Thierry Escande <thierry.escande@linaro.org>
>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
>> ---
>> [v10] updated to add support for opp-supported-hw given by
>> Thierry Escande <thierry.escande@linaro.org>
>>
>> drivers/cpufreq/Kconfig.arm | 10 ++
>> drivers/cpufreq/Makefile | 1 +
>> drivers/cpufreq/cpufreq-dt-platdev.c | 5 +
>> drivers/cpufreq/qcom-cpufreq.c | 201
>> +++++++++++++++++++++++++++++++++++
>> 4 files changed, 217 insertions(+)
>> create mode 100644 drivers/cpufreq/qcom-cpufreq.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index 7f56fe5..87e5d8d 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -134,6 +134,16 @@ config ARM_OMAP2PLUS_CPUFREQ
>> depends on ARCH_OMAP2PLUS
>> default ARCH_OMAP2PLUS
>>
>> +config ARM_QCOM_CPUFREQ
>> + bool "CPUfreq driver for the QCOM SoCs with KRAIT processors"
>> + depends on ARCH_QCOM
>> + select PM_OPP
>> + help
>> + This enables the CPUFreq driver for Qualcomm SoCs with
>> + KRAIT processors.
>> +
>> + If in doubt, say N.
>> +
>> config ARM_S3C_CPUFREQ
>> bool
>> help
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 8d24ade..c591e1e 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
>> obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
>> obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o
>> obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
>> +obj-$(CONFIG_ARM_QCOM_CPUFREQ) += qcom-cpufreq.o
>> obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o
>> obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o
>> obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o
>> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c
>> b/drivers/cpufreq/cpufreq-dt-platdev.c
>> index 3b585e4..e2e9a99 100644
>> --- a/drivers/cpufreq/cpufreq-dt-platdev.c
>> +++ b/drivers/cpufreq/cpufreq-dt-platdev.c
>> @@ -127,6 +127,11 @@
>> { .compatible = "ti,am43", },
>> { .compatible = "ti,dra7", },
>>
>> + { .compatible = "qcom,ipq8064", },
>> + { .compatible = "qcom,apq8064", },
>> + { .compatible = "qcom,msm8974", },
>> + { .compatible = "qcom,msm8960", },
>> +
>> { }
>> };
>>
>> diff --git a/drivers/cpufreq/qcom-cpufreq.c
>> b/drivers/cpufreq/qcom-cpufreq.c
>> new file mode 100644
>> index 0000000..1d4ab54
>> --- /dev/null
>> +++ b/drivers/cpufreq/qcom-cpufreq.c
>> @@ -0,0 +1,201 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +// Copyright (c) 2018, The Linux Foundation. All rights reserved.
>> +
>> +#include <linux/cpu.h>
>> +#include <linux/module.h>
>> +#include <linux/nvmem-consumer.h>
>> +#include <linux/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm_opp.h>
>> +#include <linux/slab.h>
>> +
>> +static void __init get_krait_bin_format_a(int *speed, int *pvs, int
>> *pvs_ver,
>> + struct nvmem_cell *pvs_nvmem, u8 *buf)
>> +{
>> + u32 pte_efuse;
>> +
>> + pte_efuse = *((u32 *)buf);
>> +
>> + *speed = pte_efuse & 0xf;
>> + if (*speed == 0xf)
>> + *speed = (pte_efuse >> 4) & 0xf;
>> +
>> + if (*speed == 0xf) {
>> + *speed = 0;
>> + pr_warn("Speed bin: Defaulting to %d\n", *speed);
>> + } else {
>> + pr_info("Speed bin: %d\n", *speed);
>> + }
>> +
>> + *pvs = (pte_efuse >> 10) & 0x7;
>> + if (*pvs == 0x7)
>> + *pvs = (pte_efuse >> 13) & 0x7;
>> +
>> + if (*pvs == 0x7) {
>> + *pvs = 0;
>> + pr_warn("PVS bin: Defaulting to %d\n", *pvs);
>> + } else {
>> + pr_info("PVS bin: %d\n", *pvs);
>> + }
>> +
>> + kfree(buf);
>> +}
>> +
>> +static void __init get_krait_bin_format_b(int *speed, int *pvs, int
>> *pvs_ver,
>> + struct nvmem_cell *pvs_nvmem, u8 *buf)
>> +{
>> + u32 pte_efuse, redundant_sel;
>> +
>> + pte_efuse = *((u32 *)buf);
>> + redundant_sel = (pte_efuse >> 24) & 0x7;
>> + *speed = pte_efuse & 0x7;
>> +
>> + /* 4 bits of PVS are in efuse register bits 31, 8-6. */
>> + *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
>> + *pvs_ver = (pte_efuse >> 4) & 0x3;
>> +
>> + switch (redundant_sel) {
>> + case 1:
>> + *speed = (pte_efuse >> 27) & 0xf;
>> + break;
>> + case 2:
>> + *pvs = (pte_efuse >> 27) & 0xf;
>> + break;
>> + }
>> +
>> + /* Check SPEED_BIN_BLOW_STATUS */
>> + if (pte_efuse & BIT(3)) {
>> + pr_info("Speed bin: %d\n", *speed);
>> + } else {
>> + pr_warn("Speed bin not set. Defaulting to 0!\n");
>> + *speed = 0;
>> + }
>> +
>> + /* Check PVS_BLOW_STATUS */
>> + pte_efuse = *(((u32 *)buf) + 4);
>> + if (pte_efuse) {
>> + pr_info("PVS bin: %d\n", *pvs);
>> + } else {
>> + pr_warn("PVS bin not set. Defaulting to 0!\n");
>> + *pvs = 0;
>> + }
>> +
>> + pr_info("PVS version: %d\n", *pvs_ver);
>> + kfree(buf);
>> +}
>> +
>> +static int __init qcom_cpufreq_populate_opps(struct nvmem_cell
>> *pvs_nvmem,
>> + struct opp_table **tbl1,
>> + struct opp_table **tbl2)
>> +{
>> + int speed = 0, pvs = 0, pvs_ver = 0, cpu, ret;
>> + struct device *cpu_dev;
>> + u8 *buf;
>> + size_t len;
>> + char pvs_name[] = "speedXX-pvsXX-vXX";
>> + u32 hw_version;
>> +
>> + buf = nvmem_cell_read(pvs_nvmem, &len);
>> + if (len == 4)
>> + get_krait_bin_format_a(&speed, &pvs, &pvs_ver, pvs_nvmem, buf);
>> + else if (len == 8)
>> + get_krait_bin_format_b(&speed, &pvs, &pvs_ver, pvs_nvmem, buf);
>> + else
>> + pr_warn("Unable to read nvmem data. Defaulting to 0!\n");
>> +
>> + snprintf(pvs_name, sizeof(pvs_name), "speed%d-pvs%d-v%d",
>> + speed, pvs, pvs_ver);
>> +
>> + hw_version = (1 << speed);
>> +
>> + for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
>> + cpu_dev = get_cpu_device(cpu);
>> + if (!cpu_dev)
>> + return -ENODEV;
>> +
>> + tbl1[cpu] = dev_pm_opp_set_prop_name(cpu_dev, pvs_name);
>> + if (IS_ERR(tbl1[cpu])) {
>> + ret = PTR_ERR(tbl1[cpu]);
>> + tbl1[cpu] = 0;
>> + pr_warn("failed to add OPP name %s\n", pvs_name);
>> + return ret;
>> + }
>> +
>> + tbl2[cpu] = dev_pm_opp_set_supported_hw(cpu_dev, &hw_version,
>> + 1);
>> + if (IS_ERR(tbl2[cpu])) {
>> + ret = PTR_ERR(tbl2[cpu]);
>> + tbl2[cpu] = 0;
>> + pr_warn("failed to set supported hw version\n");
>> + return ret;
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int __init qcom_cpufreq_driver_init(void)
>> +{
>> + struct platform_device *pdev;
>> + struct device *cpu_dev;
>> + struct device_node *np;
>> + struct nvmem_cell *pvs_nvmem;
>> + struct opp_table *tbl1[NR_CPUS] = { NULL }, *tbl2[NR_CPUS] = { NULL
>> };
>> + int ret, cpu = 0;
>> +
>> + cpu_dev = get_cpu_device(0);
>> + if (!cpu_dev)
>> + return -ENODEV;
>> +
>> + np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
>> + if (!np)
>> + return -ENOENT;
>> +
>> + if (!of_device_is_compatible(np, "operating-points-v2-krait-cpu")) {
>> + ret = -ENOENT;
>> + goto free_np;
>> + }
>> +
>> + pvs_nvmem = of_nvmem_cell_get(np, NULL);
>> + if (IS_ERR(pvs_nvmem)) {
>> + dev_err(cpu_dev, "Could not get nvmem cell\n");
>> + ret = PTR_ERR(pvs_nvmem);
>> + goto free_np;
>> + }
>> +
>> + ret = qcom_cpufreq_populate_opps(pvs_nvmem, tbl1, tbl2);
>> + if (ret)
>> + goto free_opp_name;
>> +
>> + pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
>> + if (IS_ERR(pdev)) {
>> + ret = PTR_ERR(pdev);
>> + goto free_opp_name;
>> + }
>> +
>> + of_node_put(np);
>> +
>> + return 0;
>> +
>> +free_opp_name:
>> + while (tbl1[cpu]) {
>> + dev_pm_opp_put_prop_name(tbl1[cpu]);
>> + cpu++;
>> + }
>> +
>> + cpu = 0;
>> + while (tbl2[cpu]) {
>> + dev_pm_opp_put_supported_hw(tbl2[cpu]);
>> + cpu++;
>> + }
>> +
>> +free_np:
>> + of_node_put(np);
>> +
>> + return ret;
>> +}
>> +late_initcall(qcom_cpufreq_driver_init);
>> +
>> +MODULE_DESCRIPTION("Qualcomm CPUfreq driver");
>> +MODULE_AUTHOR("Stephen Boyd <sboyd@codeaurora.org>");
>> +MODULE_LICENSE("GPL v2");
>> --
>> 1.9.1
>>
> --
> To unsubscribe from this list: send the line "unsubscribe
> linux-arm-msm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH v2 1/2] arm64: dts: renesas: r8a77980: add PCIe support
From: Simon Horman @ 2018-06-20 8:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <7e8c70ae-5c85-1e73-1be9-a40901a345f0@cogentembedded.com>
On Thu, Jun 14, 2018 at 10:17:46PM +0300, Sergei Shtylyov wrote:
> Describe the PCIe PHY, PCIEC, and PCIe bus clock in the R8A77980 device
> tree.
>
> Based on the original (and large) patch by Vladimir Barinov.
>
> Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
This looks good to me.
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
I am marking it as deferred pending acceptance of the
renesas,r8a77980-pcie-phy binding. Please repost or otherwise
ping me once that has happened.
^ permalink raw reply
* [PATCH v2 0/2] Add R8A77980/Condor PCIe support
From: Simon Horman @ 2018-06-20 8:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cfa599bd-d244-0032-490b-553f7870d07c@cogentembedded.com>
On Mon, Jun 18, 2018 at 07:16:47PM +0300, Sergei Shtylyov wrote:
> On 06/18/2018 12:36 PM, Simon Horman wrote:
>
> >> Here's the set of 2 patches against Simon Horman's 'renesas.git' repo's
> >> 'renesas-devel-20180614v2-v4.17' tag. We're adding the R8A77980 PCIe related
> >> device nodes and then enable PCIe on the Condor board. These patches depend
> >> on the R8A77980 PCIe PHY driver support in order to work properly. Note that
> >> in case the PCIe PHY driver is not enabled, the kernel will BUG() due to I/O
> >> space page leak in the PCIe driver...
> >
> > Is that problem specific to the presence of PCIe nodes for
> > condor/r8a77980
>
> The nodes are safe unless they are enabled, so the Condor patch may be
> deferred untl I fix the PCI code.
Understood. I would expect that given this is a but a fix
would be backported to -stable in due course. But I agree its
best to be cautious here.
> > condor/r8a77980 or is it also true of other (R-Car) boards where
> > PCIe is enabled?
>
> The leak happens every time the driver fails to probe later than
> pci_remap_iospace() is called but the BUG_ON() is only triggered by rhe 2nd try
> with EPROBE_DEFER returned previously.
>
> > Regardless, it sounds like these patches expose a kernel bug.
> > Is it being fixed?
>
> I'm working on a fix (which embraces several PCI drivers)...
>
> >> [1/2] arm64: dts: renesas: r8a77980: add PCIe support
> >> [2/2] arm64: dts: renesas: condor: add PCIe support
>
> WBR, Sergei
>
^ permalink raw reply
* [PATCH v2 0/5] crypto: ccree: cleanup, fixes and R-Car enabling
From: Simon Horman @ 2018-06-20 8:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOtvUMc8D9DQFC6vZ+GnaVBg5uFVrQmOrnSQKz7ZPHGh4BCsZg@mail.gmail.com>
On Tue, Jun 19, 2018 at 04:57:15PM +0300, Gilad Ben-Yossef wrote:
> On Tue, Jun 19, 2018 at 3:58 PM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
> > Hi Gilad,
> >
> > On Thu, May 24, 2018 at 4:19 PM Gilad Ben-Yossef <gilad@benyossef.com> wrote:
> >> The patch set enables the use of CryptoCell found in some Renesas R-Car
> >> Salvator-X boards and fixes some driver issues uncovered that prevented
> >> to work properly.
> >
> > With DEBUG enabled on R-Car H3, I see lots of
> >
> > ccree e6601000.crypto: IRR includes unknown cause bits (0x00000098)
> > ccree e6601000.crypto: IRR includes unknown cause bits (0x000000C0)
> > ccree e6601000.crypto: IRR includes unknown cause bits (0x000000D0)
> > ccree e6601000.crypto: IRR includes unknown cause bits (0x000000D8)
> > ccree e6601000.crypto: IRR includes unknown cause bits (0x000000E0)
> > ccree e6601000.crypto: IRR includes unknown cause bits (0x000000F0)
> > ccree e6601000.crypto: IRR includes unknown cause bits (0x000000F8)
> >
> > during boot. Is that expected?
>
> Yes. The condition itself it is reporting is not necessarily bad. It
> means that driver
> did not act on certain HW notification during interrupts and that's
> OK, we don't act on all of them
> depending on configuration - e.g. if you have CONFIG_FIPS enabled and
> an active TEE module or not.
>
> I can rate_limit the message if it bothers you but other than that it
> is a harmless debug print.
Rate limiting sounds like an excellent idea to me.
^ permalink raw reply
* [PATCH] ARM: shmobile: rcar-gen2: Stop compiling headsmp-apmu on !SMP
From: Simon Horman @ 2018-06-20 8:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619172049.20089-1-geert+renesas@glider.be>
On Tue, Jun 19, 2018 at 07:20:49PM +0200, Geert Uytterhoeven wrote:
> As of commit cad160ed0a94927e ("ARM: shmobile: Convert file to use
> cntvoff"), there's no non-SMP code left in headsmp-apmu.S.
>
> Hence build the file for SMP only, and drop the no longer needed check
> for CONFIG_SMP inside the file.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Thanks Geert,
This looks fine to me but I will wait to see if there are other reviews
before applying.
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
^ permalink raw reply
* [PATCH 0/1] Move {idmap_pg_dir,tramp_pg_dir,swapper_pg_dir}
From: Jun Yao @ 2018-06-20 8:57 UTC (permalink / raw)
To: linux-arm-kernel
This patch moves {idmap_pg_dir,tramp_pg_dir,swapper_pg_dir} to .rodata
section, which makes KSMA more difficult. At the same time, it is more
concise than the previous patches[1][2]. As James Morse suggested[2],
this patch updates swapper_pg_dir through the fixmap entry.
[1] http://www.openwall.com/lists/kernel-hardening/2018/05/31/1
[2] https://patchwork.kernel.org/patch/10449589/
Jun Yao (1):
arm64/mm: move {idmap_pg_dir,tramp_pg_dir,swapper_pg_dir} to .rodata
section
arch/arm64/include/asm/pgalloc.h | 19 +++++++++++++++++++
arch/arm64/kernel/vmlinux.lds.S | 32 ++++++++++++++++++--------------
arch/arm64/mm/mmu.c | 23 +++++++++++++++++++----
3 files changed, 56 insertions(+), 18 deletions(-)
--
2.17.1
^ permalink raw reply
* [PATCH 1/1] arm64/mm: move {idmap_pg_dir, tramp_pg_dir, swapper_pg_dir} to .rodata section
From: Jun Yao @ 2018-06-20 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180620085755.20045-1-yaojun8558363@gmail.com>
Move {idmap_pg_dir,tramp_pg_dir,swapper_pg_dir} to .rodata
section. And update the swapper_pg_dir by fixmap.
Signed-off-by: Jun Yao <yaojun8558363@gmail.com>
---
arch/arm64/include/asm/pgalloc.h | 19 +++++++++++++++++++
arch/arm64/kernel/vmlinux.lds.S | 32 ++++++++++++++++++--------------
arch/arm64/mm/mmu.c | 23 +++++++++++++++++++----
3 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
index 2e05bcd944c8..cc96a7e6957d 100644
--- a/arch/arm64/include/asm/pgalloc.h
+++ b/arch/arm64/include/asm/pgalloc.h
@@ -29,6 +29,10 @@
#define PGALLOC_GFP (GFP_KERNEL | __GFP_ZERO)
#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
+#if CONFIG_STRICT_KERNEL_RWX
+extern spinlock_t pgdir_lock;
+#endif
+
#if CONFIG_PGTABLE_LEVELS > 2
static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
@@ -78,6 +82,21 @@ static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pudp, pgdval_t prot)
static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, pud_t *pudp)
{
+#if CONFIG_STRICT_KERNEL_RWX
+ if (mm == &init_mm) {
+ pgd_t *pgd;
+
+ spin_lock(&pgdir_lock);
+ pgd = pgd_set_fixmap(__pa_symbol(swapper_pg_dir));
+
+ pgd = (pgd_t *)((unsigned long)pgd + pgdp - swapper_pg_dir);
+ __pgd_populate(pgdp, __pa(pudp), PUD_TYPE_TABLE);
+
+ pgd_clear_fixmap();
+ spin_unlock(&pgdir_lock);
+ return;
+ }
+#endif
__pgd_populate(pgdp, __pa(pudp), PUD_TYPE_TABLE);
}
#else
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 605d1b60469c..86532c57206a 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -216,21 +216,25 @@ SECTIONS
BSS_SECTION(0, 0, 0)
. = ALIGN(PAGE_SIZE);
- idmap_pg_dir = .;
- . += IDMAP_DIR_SIZE;
-#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
- tramp_pg_dir = .;
- . += PAGE_SIZE;
-#endif
-
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
- reserved_ttbr0 = .;
- . += RESERVED_TTBR0_SIZE;
-#endif
- swapper_pg_dir = .;
- . += SWAPPER_DIR_SIZE;
- swapper_pg_end = .;
+ .rodata : {
+ . = ALIGN(PAGE_SIZE);
+ idmap_pg_dir = .;
+ . += IDMAP_DIR_SIZE;
+
+ #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+ tramp_pg_dir = .;
+ . += PAGE_SIZE;
+ #endif
+
+ #ifdef CONFIG_ARM64_SW_TTBR0_PAN
+ reserved_ttbr0 = .;
+ . += RESERVED_TTBR0_SIZE;
+ #endif
+ swapper_pg_dir = .;
+ . += SWAPPER_DIR_SIZE;
+ swapper_pg_end = .;
+ }
__pecoff_data_size = ABSOLUTE(. - __initdata_begin);
_end = .;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 2dbb2c9f1ec1..c1aa85a6ada5 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -66,6 +66,10 @@ static pte_t bm_pte[PTRS_PER_PTE] __page_aligned_bss;
static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused;
static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused;
+#ifdef CONFIG_STRICT_KERNEL_RWX
+DEFINE_SPINLOCK(pgdir_lock);
+#endif
+
pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot)
{
@@ -417,12 +421,22 @@ static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start,
void __init mark_linear_text_alias_ro(void)
{
+ unsigned long size;
+
/*
* Remove the write permissions from the linear alias of .text/.rodata
+ *
+ * We free some pages in .rodata at paging_init(), which generates a
+ * hole. And the hole splits .rodata into two pieces.
*/
+ size = (unsigned long)swapper_pg_dir + PAGE_SIZE - (unsigned long)_text;
update_mapping_prot(__pa_symbol(_text), (unsigned long)lm_alias(_text),
- (unsigned long)__init_begin - (unsigned long)_text,
- PAGE_KERNEL_RO);
+ size, PAGE_KERNEL_RO);
+
+ size = (unsigned long)__init_begin - (unsigned long)swapper_pg_end;
+ update_mapping_prot(__pa_symbol(swapper_pg_end),
+ (unsigned long)lm_alias(swapper_pg_end),
+ size, PAGE_KERNEL_RO);
}
static void __init map_mem(pgd_t *pgdp)
@@ -587,8 +601,9 @@ static void __init map_kernel(pgd_t *pgdp)
*/
map_kernel_segment(pgdp, _text, _etext, text_prot, &vmlinux_text, 0,
VM_NO_GUARD);
- map_kernel_segment(pgdp, __start_rodata, __inittext_begin, PAGE_KERNEL,
- &vmlinux_rodata, NO_CONT_MAPPINGS, VM_NO_GUARD);
+ map_kernel_segment(pgdp, __start_rodata, __inittext_begin,
+ PAGE_KERNEL, &vmlinux_rodata,
+ NO_CONT_MAPPINGS | NO_BLOCK_MAPPINGS, VM_NO_GUARD);
map_kernel_segment(pgdp, __inittext_begin, __inittext_end, text_prot,
&vmlinux_inittext, 0, VM_NO_GUARD);
map_kernel_segment(pgdp, __initdata_begin, __initdata_end, PAGE_KERNEL,
--
2.17.1
^ permalink raw reply related
* [PATCH v5 2/6] clocksource/drivers: Add a new driver for the Atmel ARM TC blocks
From: Thomas Gleixner @ 2018-06-20 9:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619211929.22908-3-alexandre.belloni@bootlin.com>
On Tue, 19 Jun 2018, Alexandre Belloni wrote:
> +
> +static struct atmel_tcb_clksrc {
> + struct clocksource clksrc;
> + struct clock_event_device clkevt;
> + struct regmap *regmap;
> + void __iomem *base;
> + struct clk *clk[2];
> + char name[20];
> + int channels[2];
> + int bits;
> + int irq;
> + struct {
> + u32 cmr;
> + u32 imr;
> + u32 rc;
> + bool clken;
> + } cache[2];
> + u32 bmr_cache;
> + bool registered;
> +} tc = {
> + .clksrc = {
> + .rating = 200,
> + .mask = CLOCKSOURCE_MASK(32),
> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
> + },
> + .clkevt = {
> + .features = CLOCK_EVT_FEAT_ONESHOT,
> + /* Should be lower than at91rm9200's system timer */
> + .rating = 125,
> + },
> +};
> +
> +static struct tc_clkevt_device {
> + struct clock_event_device clkevt;
> + struct regmap *regmap;
> + void __iomem *base;
> + struct clk *slow_clk;
> + struct clk *clk;
> + char name[20];
> + int channel;
> + int irq;
> + struct {
> + u32 cmr;
> + u32 imr;
> + u32 rc;
> + bool clken;
> + } cache;
> + bool registered;
> + bool clk_enabled;
> +} tce = {
> + .clkevt = {
> + .features = CLOCK_EVT_FEAT_PERIODIC |
> + CLOCK_EVT_FEAT_ONESHOT,
> + /*
> + * Should be lower than at91rm9200's system timer
> + * but higher than tc.clkevt.rating
> + */
> + .rating = 140,
> + },
> +};
To be honest: This stuff is horrible to read and the two structs are almost
identical. There is really no good reason to have all this duplicated
mess. I'm pretty sure you can consolidate stuff further when using _one_.
And please define the structs separate from the define and arrange the
struct members in tabluar fashion.
> +/*
> + * Clocksource and clockevent using the same channel(s)
> + */
> +static u64 tc_get_cycles(struct clocksource *cs)
> +{
> + u32 lower, upper;
> +
> + do {
> + upper = readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[1]));
> + lower = readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[0]));
> + } while (upper != readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[1])));
> +
> + return (upper << 16) | lower;
> +}
For timekeeping the win of this is dubious. With a 5Mhz clock the 32bit
part wraps around in ~859 seconds, which is plenty even for NOHZ.
So I really would avoid the double read/compare/eventually repeat magic and
just use the lower 32bits for performance sake. I assume the same is true
for sched_clock(), but I might be wrong.
> +static int tcb_clkevt_next_event(unsigned long delta,
> + struct clock_event_device *d)
> +{
> + u32 old, next, cur;
> +
> + old = readl(tc.base + ATMEL_TC_CV(tc.channels[0]));
> + next = old + delta;
> + writel(next, tc.base + ATMEL_TC_RC(tc.channels[0]));
> + cur = readl(tc.base + ATMEL_TC_CV(tc.channels[0]));
> +
> + /* check whether the delta elapsed while setting the register */
> + if ((next < old && cur < old && cur > next) ||
> + (next > old && (cur < old || cur > next))) {
> + /*
> + * Clear the CPCS bit in the status register to avoid
> + * generating a spurious interrupt next time a valid
> + * timer event is configured.
> + */
> + old = readl(tc.base + ATMEL_TC_SR(tc.channels[0]));
> + return -ETIME;
> + }
Aarg. Doesn;t that timer block have a simple count down and fire mode?
These compare equal timers suck.
Thanks,
tglx
^ permalink raw reply
* [PATCH] driver core: add a debugfs entry to show deferred devices
From: Javier Martinez Canillas @ 2018-06-20 9:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHp75VcOd5K+T6bkxyz3qgqNr4-=K9GGRh+DQ_qgW7dGKdzO5A@mail.gmail.com>
Hi Andy,
On 06/20/2018 01:43 AM, Andy Shevchenko wrote:
> On Wed, Jun 20, 2018 at 1:51 AM, Greg Kroah-Hartman
> <gregkh@linuxfoundation.org> wrote:
>> On Tue, Jun 19, 2018 at 10:59:14PM +0200, Javier Martinez Canillas wrote:
>>> For debugging purposes it may be useful to know what are the devices whose
>>> probe function was deferred. Add a debugfs entry showing that information.
>>>
>>> $ cat /sys/kernel/debug/deferred_devices
>>> 48070000.i2c:twl at 48:bci
>>> musb-hdrc.0.auto
>>> omapdrm.0
>
>
>> And what is the use of this file? What can you do with this
>> information? Who is going to use it? Don't we have other deferred
>> probe debugging somewhere else?
>
> Indeed.
>
> Javier, have you tried to add 'initcall_debug' to a kernel command
> line followed by 'dyndbg="file drivers/base/dd.c +p"'?
>
I already mentioned this to Greg, but I'll elaborate a little bit. Using these
kernel cmdline options will only tell us when a driver for a device was probed
or deferred but it doesn't tell us what's left in the queue after all drivers
have been registered.
Yes, we could parse the kernel log and do some computation to figure out if a
deferred driver finally got probed, but I don't understand why we can't just
expose the deferred queue if the kernel already has that info and is useful?
But even if we do that, the current debug printouts are only enabled until
late_initcall time. So it won't print deferred probes for drivers registered
by modules:
static void deferred_probe_work_func(struct work_struct *work)
{
...
if (initcall_debug && !initcalls_done)
deferred_probe_debug(dev);
else
bus_probe_device(dev);
...
}
static int deferred_probe_initcall(void)
{
...
initcalls_done = true;
...
}
late_initcall(deferred_probe_initcall);
Again, we could change that but in my opinion we should try to make debug more
easier and this patch is quite trivial. The kernelci folks said that this will
be useful for them and allows to detect regressions on drivers' probe as early
as possible, which I think is very important.
Best regards,
--
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat
^ permalink raw reply
* [PATCH v10 13/14] cpufreq: Add module to register cpufreq on Krait CPUs
From: sricharan at codeaurora.org @ 2018-06-20 9:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f195e30e-bef3-9352-9584-fec35631ec5e@arm.com>
Hi Sudeep,
>>
>> Register a cpufreq-generic device whenever we detect that a
>> "qcom,krait" compatible CPU is present in DT.
>>
>
> Just curious to know how different is this from qcom kryo driver
> that was added recently. IIRC even that gets the speedbin from nvmem.
> Can they be merged ? I don't see need to have different driver for
> Krait
> and Kryo CPUs when the code is not even remotely related to CPU type.
>
> Sorry if I have missed anything from previous versions, I just happen
> to open and looked at this series first time today.
Correct, having these two merged was pointed out earlier as well by
Viresh.
Now that kryo is merged, i will check once and see if they can be
nicely
merged.
Regards,
Sricharan
^ permalink raw reply
* [PATCH 1/1] arm64: dts: rockchip: correct voltage selector Firefly-RK3399
From: Heiko Stübner @ 2018-06-20 9:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <459cb125-a3e2-8f1e-b960-011020d41b3c@gmx.de>
Hi Heinrich,
Am Mittwoch, 20. Juni 2018, 07:59:34 CEST schrieb Heinrich Schuchardt:
> On 06/20/2018 01:21 AM, Heiko Stuebner wrote:
> > Am Donnerstag, 14. Juni 2018, 14:55:27 CEST schrieb Heiko Stuebner:
> >> Am Montag, 4. Juni 2018, 19:15:23 CEST schrieb Heinrich Schuchardt:
> >>> Without this patch the Firefly-RK3399 board boot process hangs after
> >>> these
> >>>
> >>> lines:
> >>> fan53555-regulator 0-0040: FAN53555 Option[8] Rev[1] Detected!
> >>> fan53555-reg: supplied by vcc_sys
> >>> vcc1v8_s3: supplied by vcc_1v8
> >>>
> >>> Blacklisting driver fan53555 allows booting.
> >>>
> >>> The device tree uses a value of fcs,suspend-voltage-selector different
> >>> to
> >>> any other board.
> >>>
> >>> Changing this setting to the usual value is sufficient to enable
> >>> booting.
> >>>
> >>> Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
> >>
> >> applied for 4.19.
> >
> > and dropped again.
> >
> > Sadly it looks like the patch causes conflicts with at least one firefly
> > board in a kernelci lab. My own is currently not ready to use, so I cannot
> > look myself right now.
> >
> > The issue kernelci people described sounded quite a lot like the one
> > in your commit message, so my current theory is that the
> > suspend-voltage-selector must in some form corespond to the
> > cpu_b_sleep_h gpio setting we're currently not handling at all, which
> > would therefore depend on how the bootloader sets this up.
>
> please, provide a link to the log displaying the issue and the contact
> who can provide the exact setup.
>
> I have been testing with U-Boot as boot loader.
failing boot can be found on
https://kernelci.org/boot/id/5b2a053d59b514569079a872/
As this board is sitting in the "lab-baylibre-seattle", I guess
Kevin Hilman (Cc'ed now) is the one that can say a bit more about the
board setup.
The more interesting question would be how to make sure we don't
die with possible different bootloader versions. As I don't really thing
"upgrade your bootloader" is an always valid option.
Heiko
^ permalink raw reply
* [PATCH V2 1/3] watchdog: stm32: add pclk feature for stm32mp1
From: Guenter Roeck @ 2018-06-20 9:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1529481238-15277-2-git-send-email-ludovic.Barre@st.com>
On 06/20/2018 12:53 AM, Ludovic Barre wrote:
> From: Ludovic Barre <ludovic.barre@st.com>
>
> This patch adds config data to manage specific properties by
> compatible. Adds stm32mp1 config which requires pclk clock.
>
> Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
> ---
> .../devicetree/bindings/watchdog/st,stm32-iwdg.txt | 21 +++-
> drivers/watchdog/stm32_iwdg.c | 132 ++++++++++++++-------
> 2 files changed, 104 insertions(+), 49 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
> index cc13b10a..f07f6d89 100644
> --- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
> +++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
> @@ -2,18 +2,31 @@ STM32 Independent WatchDoG (IWDG)
> ---------------------------------
>
> Required properties:
> -- compatible: "st,stm32-iwdg"
> -- reg: physical base address and length of the registers set for the device
> -- clocks: must contain a single entry describing the clock input
> +- compatible: Should be either "st,stm32-iwdg" or "st,stm32mp1-iwdg"
> +- reg: Physical base address and length of the registers set for the device
> +- clocks: Reference to the clock entry lsi. Additional pclk clock entry
> + is required only for st,stm32mp1-iwdg.
> +- clock-names: Name of the clocks used.
> + "lsi" for st,stm32-iwdg
> + "pclk", "lsi" for st,stm32mp1-iwdg
>
> Optional Properties:
> - timeout-sec: Watchdog timeout value in seconds.
>
> -Example:
> +Examples:
>
> iwdg: watchdog at 40003000 {
> compatible = "st,stm32-iwdg";
> reg = <0x40003000 0x400>;
> clocks = <&clk_lsi>;
> + clock-names = "lsi";
> + timeout-sec = <32>;
> +};
> +
> +iwdg: iwdg at 5a002000 {
> + compatible = "st,stm32mp1-iwdg";
> + reg = <0x5a002000 0x400>;
> + clocks = <&rcc IWDG2>, <&clk_lsi>;
> + clock-names = "pclk", "lsi";
> timeout-sec = <32>;
> };
> diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
> index c97ad56..fc96670 100644
> --- a/drivers/watchdog/stm32_iwdg.c
> +++ b/drivers/watchdog/stm32_iwdg.c
> @@ -11,12 +11,13 @@
>
> #include <linux/clk.h>
> #include <linux/delay.h>
> -#include <linux/kernel.h>
> -#include <linux/module.h>
> #include <linux/interrupt.h>
> #include <linux/io.h>
> #include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> #include <linux/of.h>
> +#include <linux/of_device.h>
> #include <linux/platform_device.h>
> #include <linux/watchdog.h>
>
> @@ -54,11 +55,17 @@
> #define TIMEOUT_US 100000
> #define SLEEP_US 1000
>
> +struct stm32_iwdg_config {
> + bool has_pclk;
> +};
> +
This data structure is unnecessary. Just assign the boolean directly to .data
and ...
> struct stm32_iwdg {
> - struct watchdog_device wdd;
> - void __iomem *regs;
> - struct clk *clk;
> - unsigned int rate;
> + struct watchdog_device wdd;
> + void __iomem *regs;
> + struct stm32_iwdg_config *config;
declare bool has_pclk here.
> + struct clk *clk_lsi;
> + struct clk *clk_pclk;
> + unsigned int rate;
> };
>
> static inline u32 reg_read(void __iomem *base, u32 reg)
> @@ -133,6 +140,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device *wdd,
> return 0;
> }
>
> +static int stm32_iwdg_clk_init(struct platform_device *pdev,
> + struct stm32_iwdg *wdt)
> +{
> + u32 ret;
> +
> + wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
> + if (IS_ERR(wdt->clk_lsi)) {
> + dev_err(&pdev->dev, "Unable to get lsi clock\n");
> + return PTR_ERR(wdt->clk_lsi);
> + }
> +
> + /* optional peripheral clock */
> + if (wdt->config->has_pclk) {
> + wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
> + if (IS_ERR(wdt->clk_pclk)) {
> + dev_err(&pdev->dev, "Unable to get pclk clock\n");
> + return PTR_ERR(wdt->clk_pclk);
> + }
> +
> + ret = clk_prepare_enable(wdt->clk_pclk);
> + if (ret) {
> + dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
> + return ret;
> + }
> + }
> +
> + ret = clk_prepare_enable(wdt->clk_lsi);
> + if (ret) {
> + dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
> + clk_disable_unprepare(wdt->clk_pclk);
> + return ret;
> + }
> +
> + wdt->rate = clk_get_rate(wdt->clk_lsi);
> +
> + return 0;
> +}
> +
> static const struct watchdog_info stm32_iwdg_info = {
> .options = WDIOF_SETTIMEOUT |
> WDIOF_MAGICCLOSE |
> @@ -147,49 +192,50 @@ static const struct watchdog_ops stm32_iwdg_ops = {
> .set_timeout = stm32_iwdg_set_timeout,
> };
>
> +static const struct stm32_iwdg_config stm32_iwdg_cfg = {
> + .has_pclk = false,
> +};
> +
> +static const struct stm32_iwdg_config stm32mp1_iwdg_cfg = {
> + .has_pclk = true,
> +};
> +
> +static const struct of_device_id stm32_iwdg_of_match[] = {
> + { .compatible = "st,stm32-iwdg", .data = &stm32_iwdg_cfg },
> + { .compatible = "st,stm32mp1-iwdg", .data = &stm32mp1_iwdg_cfg },
> + { /* end node */ }
> +};
> +MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
> +
> static int stm32_iwdg_probe(struct platform_device *pdev)
> {
> struct watchdog_device *wdd;
> + const struct of_device_id *match;
> struct stm32_iwdg *wdt;
> struct resource *res;
> - void __iomem *regs;
> - struct clk *clk;
> int ret;
>
> + match = of_match_device(stm32_iwdg_of_match, &pdev->dev);
> + if (!match || !match->data)
> + return -ENODEV;
> +
> + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> + if (!wdt)
> + return -ENOMEM;
> +
> + wdt->config = (struct stm32_iwdg_config *)match->data;
> +
> /* This is the timer base. */
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> - regs = devm_ioremap_resource(&pdev->dev, res);
> - if (IS_ERR(regs)) {
> + wdt->regs = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(wdt->regs)) {
> dev_err(&pdev->dev, "Could not get resource\n");
> - return PTR_ERR(regs);
> + return PTR_ERR(wdt->regs);
> }
>
> - clk = devm_clk_get(&pdev->dev, NULL);
> - if (IS_ERR(clk)) {
> - dev_err(&pdev->dev, "Unable to get clock\n");
> - return PTR_ERR(clk);
> - }
> -
> - ret = clk_prepare_enable(clk);
> - if (ret) {
> - dev_err(&pdev->dev, "Unable to prepare clock %p\n", clk);
> + ret = stm32_iwdg_clk_init(pdev, wdt);
> + if (ret)
> return ret;
> - }
> -
> - /*
> - * Allocate our watchdog driver data, which has the
> - * struct watchdog_device nested within it.
> - */
> - wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> - if (!wdt) {
> - ret = -ENOMEM;
> - goto err;
> - }
> -
> - /* Initialize struct stm32_iwdg. */
> - wdt->regs = regs;
> - wdt->clk = clk;
> - wdt->rate = clk_get_rate(clk);
>
> /* Initialize struct watchdog_device. */
> wdd = &wdt->wdd;
> @@ -217,7 +263,8 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
>
> return 0;
> err:
> - clk_disable_unprepare(clk);
> + clk_disable_unprepare(wdt->clk_lsi);
> + clk_disable_unprepare(wdt->clk_pclk);
>
> return ret;
> }
> @@ -227,23 +274,18 @@ static int stm32_iwdg_remove(struct platform_device *pdev)
> struct stm32_iwdg *wdt = platform_get_drvdata(pdev);
>
> watchdog_unregister_device(&wdt->wdd);
> - clk_disable_unprepare(wdt->clk);
> + clk_disable_unprepare(wdt->clk_lsi);
> + clk_disable_unprepare(wdt->clk_pclk);
>
> return 0;
> }
>
> -static const struct of_device_id stm32_iwdg_of_match[] = {
> - { .compatible = "st,stm32-iwdg" },
> - { /* end node */ }
> -};
> -MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
> -
> static struct platform_driver stm32_iwdg_driver = {
> .probe = stm32_iwdg_probe,
> .remove = stm32_iwdg_remove,
> .driver = {
> .name = "iwdg",
> - .of_match_table = stm32_iwdg_of_match,
> + .of_match_table = of_match_ptr(stm32_iwdg_of_match),
> },
> };
> module_platform_driver(stm32_iwdg_driver);
>
^ permalink raw reply
* [PATCHv3 10/19] arm64: convert native/compat syscall entry to C
From: Dave Martin @ 2018-06-20 9:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619130932.ww53s5rnragcodha@lakrids.cambridge.arm.com>
On Tue, Jun 19, 2018 at 02:15:24PM +0100, Mark Rutland wrote:
> On Tue, Jun 19, 2018 at 01:18:17PM +0100, Dave Martin wrote:
> > On Mon, Jun 18, 2018 at 01:03:01PM +0100, Mark Rutland wrote:
> > > +static inline void sve_user_reset(void)
> > > +{
> >
> > Can we call this "sve_user_discard" please?
> >
> > "Reset" is a reasonable name for the concept, but the "discard"
> > terminology has been used elsewhere.
>
> Sure; done.
>
> > > + if (!system_supports_sve())
> > > + return;
> > > +
> > > + /*
> > > + * task_fpsimd_load() won't be called to update CPACR_EL1 in
> > > + * ret_to_user unless TIF_FOREIGN_FPSTATE is still set, which only
> > > + * happens if a context switch or kernel_neon_begin() or context
> > > + * modification (sigreturn, ptrace) intervenes.
> > > + * So, ensure that CPACR_EL1 is already correct for the fast-path case.
> > > + */
> >
> > This comment should go after clear_thead_flag(), since it describes not
> > the purpose of this function but the presence of sve_user_disable().
> >
> > > + clear_thread_flag(TIF_SVE);
> > > + sve_user_disable();
> > > +}
>
> Good point. I've moved the clear_thread_flag(TIF_SVE) above the comment
> (with a blank line before the comment).
Thanks -- with those changes:
Reviewed-by: Dave Martin <Dave.Martin@arm.com> (for the SVE parts)
Cheers
---Dave
^ permalink raw reply
* [PATCH] arm64: allwinner: a64-sopine: Add cd-gpios to mmc0 node
From: Emmanuel Vadot @ 2018-06-20 9:30 UTC (permalink / raw)
To: linux-arm-kernel
The card detect GPIO for Sopine and Pine64-LTS is PF6.
Add this to the dts.
Signed-off-by: Emmanuel Vadot <manu@freebsd.org>
---
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi
index 43418bd881d8..3dfc0c55eb96 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi
@@ -45,6 +45,8 @@
#include "sun50i-a64.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
@@ -52,6 +54,7 @@
non-removable;
disable-wp;
bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
status = "okay";
};
--
2.17.0
^ permalink raw reply related
* [PATCH 18/20] dts: sama5d2: Update coresight bindings for hardware ports
From: Suzuki K Poulose @ 2018-06-20 9:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180619212417.GB3128@piout.net>
On 19/06/18 22:24, Alexandre Belloni wrote:
> On 05/06/2018 22:43:29+0100, Suzuki K Poulose wrote:
>> Switch to the new coresight bindings for hardware ports
>>
>> Cc: Nicolas Ferre <nicolas.ferre@microchip.com>
>> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
>> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>> arch/arm/boot/dts/sama5d2.dtsi | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
> Applied, thanks.
>
Alexandre,
Please hold off applying this change, as we are yet to come to an
agreement on this. Sorry for the trouble. See [0]
[0] http://lists.infradead.org/pipermail/linux-arm-kernel/2018-June/582269.html
Kind regards
Suzuki
^ permalink raw reply
* [PATCH v5 2/6] clocksource/drivers: Add a new driver for the Atmel ARM TC blocks
From: Alexandre Belloni @ 2018-06-20 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.21.1806201037240.10546@nanos.tec.linutronix.de>
On 20/06/2018 11:03:40+0200, Thomas Gleixner wrote:
> > +/*
> > + * Clocksource and clockevent using the same channel(s)
> > + */
> > +static u64 tc_get_cycles(struct clocksource *cs)
> > +{
> > + u32 lower, upper;
> > +
> > + do {
> > + upper = readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[1]));
> > + lower = readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[0]));
> > + } while (upper != readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[1])));
> > +
> > + return (upper << 16) | lower;
> > +}
>
> For timekeeping the win of this is dubious. With a 5Mhz clock the 32bit
> part wraps around in ~859 seconds, which is plenty even for NOHZ.
>
> So I really would avoid the double read/compare/eventually repeat magic and
> just use the lower 32bits for performance sake. I assume the same is true
> for sched_clock(), but I might be wrong.
>
Agreed, this is why this is only used with the 16 bit counters (the
register is 32 bit wide but the counter only have 16 bits. For the 32
bit counters, tc_get_cycles32 is used and only use one counter.
> > +static int tcb_clkevt_next_event(unsigned long delta,
> > + struct clock_event_device *d)
> > +{
> > + u32 old, next, cur;
> > +
> > + old = readl(tc.base + ATMEL_TC_CV(tc.channels[0]));
> > + next = old + delta;
> > + writel(next, tc.base + ATMEL_TC_RC(tc.channels[0]));
> > + cur = readl(tc.base + ATMEL_TC_CV(tc.channels[0]));
> > +
> > + /* check whether the delta elapsed while setting the register */
> > + if ((next < old && cur < old && cur > next) ||
> > + (next > old && (cur < old || cur > next))) {
> > + /*
> > + * Clear the CPCS bit in the status register to avoid
> > + * generating a spurious interrupt next time a valid
> > + * timer event is configured.
> > + */
> > + old = readl(tc.base + ATMEL_TC_SR(tc.channels[0]));
> > + return -ETIME;
> > + }
>
> Aarg. Doesn;t that timer block have a simple count down and fire mode?
> These compare equal timers suck.
It only counts up...
--
Alexandre Belloni, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply
* [PATCH] driver core: add a debugfs entry to show deferred devices
From: Javier Martinez Canillas @ 2018-06-20 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <ea628ded-3cb3-c426-da6d-bf7cb51f4ca8@redhat.com>
[adding Peter Robinson - Fedora IoT Architect to cc list]
On 06/20/2018 10:46 AM, Javier Martinez Canillas wrote:
> On 06/20/2018 12:51 AM, Greg Kroah-Hartman wrote:
>
> [snip]
>
>>> @@ -233,6 +252,9 @@ void device_unblock_probing(void)
>>> */
>>> static int deferred_probe_initcall(void)
>>> {
>>> + debugfs_create_file("deferred_devices", 0444, NULL, NULL,
>>> + &deferred_devs_fops);
>>
>> In the root of debugfs?
>>
>
> I added in the root for lack of a better place. Any suggestion is welcomed.
>
>> Anyway, what about "devices_deferred", to help keep things semi-sane if
>> we have other driver core debugfs entries?
>>
>
> I don't have a strong opinion on the name really, so I'll change it.
>
>> And you don't remove the file ever?
>>
>
> Yeah, I saw that it wasn't removed in other places for debugfs entries
> created by the core since unlike drivers they can't be built as a module
> or re-loaded. But you are right, I'll add an __exitcall to remove there.
>
>> And what is the use of this file? What can you do with this
>> information? Who is going to use it? Don't we have other deferred
>
> This patch is the result of a discussion with Tomeu and Mark (cc'ed) to
> allow https://kernelci.org to test if there was a regression that makes
> drivers to defer their probe.
>
> The problem with the probe deferral mechanism is that you don't have a
> way to distinguish between a valid deferral due a dependency not being
> available yet and a bug (i.e: wrong DTB, config symbol not enabled, etc)
> that prevents the device to eventually being probed.
>
This is not only useful for catching regressions though, Peter also told me
that having this information would save him a lot of time when doing hardware
bringup for ARM devices / IoT platforms.
As mentioned, debugging probe deferral issues caused by drivers not available
or wrong Device Trees is really a PITA. Not all architectures have the luxury
of ACPI / PnP / auto enumerable buses / etc, that hide all this complexity.
So the most information to troubleshoot we have, the better in my opinion.
>> probe debugging somewhere else?
>>
>
> There is some debug yes, but it isn't suitable for the use case I explained.
>
> For start, it only tells you if a given driver for a device was deferred or
> probed correctly while this patch attempts to tell what was left (if any)
> in the queue after the last driver was registered.
>
> Second, is only enabled until late_initcall so it will only print the probe
> deferral for built-in drivers and not for modules. This patch registers the
> debugfs entry after the probe debugging has been disabled.
>
>> thanks,
>>
>> greg k-h
>>
Best regards,
--
Javier Martinez Canillas
Software Engineer - Desktop Hardware Enablement
Red Hat
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox