* [PATCH v2] Documentation: dt: reset: Revise typos in TI syscon reset example
From: Philipp Zabel @ 2017-01-12 10:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170112012217.18115-1-s-anna@ti.com>
Am Mittwoch, den 11.01.2017, 19:22 -0600 schrieb Suman Anna:
> Fix couple of typos in the example given in the TI syscon reset
> binding. The ti,reset-bits used for DSP0 are corrected to match
> the values that will be used in the actual DT node.
>
> Signed-off-by: Suman Anna <s-anna@ti.com>
> ---
> v2: Address Rob Herring's comment to change the reset node name
> from "psc-reset" to "reset-controller"
I've applied the patch, thank you.
regards
Philipp
^ permalink raw reply
* [PATCH] ARM: dts: dra72-evm-revc: fix typo in ethernet-phy node
From: Sekhar Nori @ 2017-01-12 10:54 UTC (permalink / raw)
To: linux-arm-kernel
Fix a typo in impedance setting for ethernet-phy at 3
Fixes: b76db38cd8ae ("ARM: dts: dra72-evm-revc: add phy impedance settings")
Cc: Mugunthan V N <mugunthanvnm@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
---
arch/arm/boot/dts/dra72-evm-revc.dts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/dra72-evm-revc.dts b/arch/arm/boot/dts/dra72-evm-revc.dts
index c3d939c9666c..3f808a47df03 100644
--- a/arch/arm/boot/dts/dra72-evm-revc.dts
+++ b/arch/arm/boot/dts/dra72-evm-revc.dts
@@ -75,6 +75,6 @@
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
- ti,min-output-imepdance;
+ ti,min-output-impedance;
};
};
--
2.9.0
^ permalink raw reply related
* [RFC PATCH v4 0/5] ARM: Fix dma_alloc_coherent() and friends for NOMMU
From: Benjamin Gaignard @ 2017-01-12 10:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CA+M3ks5jTNSLLOetvOUZP=B=a2wPNjXadbw6Zcn475Okc4QEPw@mail.gmail.com>
2017-01-12 11:35 GMT+01:00 Benjamin Gaignard <benjamin.gaignard@linaro.org>:
> 2017-01-11 15:34 GMT+01:00 Vladimir Murzin <vladimir.murzin@arm.com>:
>> On 11/01/17 13:17, Benjamin Gaignard wrote:
>>> 2017-01-10 15:18 GMT+01:00 Vladimir Murzin <vladimir.murzin@arm.com>:
>>>> Hi,
>>>>
>>>> It seem that addition of cache support for M-class cpus uncovered
>>>> latent bug in DMA usage. NOMMU memory model has been treated as being
>>>> always consistent; however, for R/M classes of cpu memory can be
>>>> covered by MPU which in turn might configure RAM as Normal
>>>> i.e. bufferable and cacheable. It breaks dma_alloc_coherent() and
>>>> friends, since data can stuck in caches now or be buffered.
>>>>
>>>> This patch set is trying to address the issue by providing region of
>>>> memory suitable for consistent DMA operations. It is supposed that
>>>> such region is marked by MPU as non-cacheable. Robin suggested to
>>>> advertise such memory as reserved shared-dma-pool, rather then using
>>>> homebrew command line option, and extend dma-coherent to provide
>>>> default DMA area in the similar way as it is done for CMA (PATCH
>>>> 2/5). It allows us to offload all bookkeeping on generic coherent DMA
>>>> framework, and it is seems that it might be reused by other
>>>> architectures like c6x and blackfin.
>>>>
>>>> Dedicated DMA region is required for cases other than:
>>>> - MMU/MPU is off
>>>> - cpu is v7m w/o cache support
>>>> - device is coherent
>>>>
>>>> In case one of the above conditions is true dma operations are forced
>>>> to be coherent and wired with dma_noop_ops.
>>>>
>>>> To make life easier NOMMU dma operations are kept in separate
>>>> compilation unit.
>>>>
>>>> Since the issue was reported in the same time as Benjamin sent his
>>>> patch [1] to allow mmap for NOMMU, his case is also addressed in this
>>>> series (PATCH 1/5 and PATCH 3/5).
>>>>
>>>> Thanks!
>>>
>>> I have tested this v4 on my setup (stm32f4, no cache, no MPU) and unfortunately
>>> it doesn't work with my drm/kms driver.
>>
>> I guess the same is for fbmem, but would be better to have confirmation since
>> amba-clcd I use has not been ported to drm/kms (yet), so I can't test.
>>
>>> I haven't any errors but nothing is displayed unlike what I have when
>>> using current dma-mapping
>>> code.
>>> I guess the issue is coming from dma-noop where __get_free_pages() is
>>> used instead of alloc_pages()
>>> in dma-mapping.
>>
>> Unless I've missed something bellow is a call stack for both
>>
>> #1
>> __alloc_simple_buffer
>> __dma_alloc_buffer
>> alloc_pages
>> split_page
>> __dma_clear_buffer
>> memset
>> page_address
>>
>> #2
>> __get_free_pages
>> alloc_pages
>> page_address
>>
>> So the difference is that nommu case in dma-mapping.c memzeros memory, handles
>> DMA_ATTR_NO_KERNEL_MAPPING and does optimisation of memory usage.
>>
>> Is something from above critical for your driver?
>
> I have removed all the diff (split_page, __dma_clear_buffer, memset)
> from #1 and it is still working.
> DMA_ATTR_NO_KERNEL_MAPPING flag is not set when allocating the buffer.
>
> I have investigated more and found that dma-noop doesn't take care of
> "dma-ranges" property which is set in DT.
> I believed that is the root cause of my problem with your patches.
After testing changing virt_to_phys to virt_to_dma in dma-noop.c fix the issue
modetest and fbdemo are now still functional.
>
> Benjamin
>
>>
>>>
>>> Since my hardware doesn't have cache or MPU (and so use dma-noop) I
>>> haven't reserved specific memory region.
>>> Buffer addresses and vma parameters look correct... What could I have
>>> miss here ?
>>
>> No ideas, sorry...
>>
>> Cheers
>> Vladimir
>>
>>>
>>> Benjamin
>>>
>>>>
>>>> [1] http://www.armlinux.org.uk/developer/patches/viewpatch.php?id=8633/1
>>>>
>>>> Vladimir Murzin (5):
>>>> dma: Add simple dma_noop_mmap
>>>> drivers: dma-coherent: Introduce default DMA pool
>>>> ARM: NOMMU: Introduce dma operations for noMMU
>>>> ARM: NOMMU: Set ARM_DMA_MEM_BUFFERABLE for M-class cpus
>>>> ARM: dma-mapping: Remove traces of NOMMU code
>>>>
>>>> .../bindings/reserved-memory/reserved-memory.txt | 3 +
>>>> arch/arm/include/asm/dma-mapping.h | 3 +-
>>>> arch/arm/mm/Kconfig | 2 +-
>>>> arch/arm/mm/Makefile | 5 +-
>>>> arch/arm/mm/dma-mapping-nommu.c | 252 +++++++++++++++++++++
>>>> arch/arm/mm/dma-mapping.c | 26 +--
>>>> drivers/base/dma-coherent.c | 59 ++++-
>>>> lib/dma-noop.c | 21 ++
>>>> 8 files changed, 335 insertions(+), 36 deletions(-)
>>>> create mode 100644 arch/arm/mm/dma-mapping-nommu.c
>>>>
>>>> --
>>>> 2.0.0
>>>>
>>>
>>>
>>>
>>
>
>
>
> --
> Benjamin Gaignard
>
> Graphic Study Group
>
> Linaro.org ? Open source software for ARM SoCs
>
> Follow Linaro: Facebook | Twitter | Blog
--
Benjamin Gaignard
Graphic Study Group
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH] rtc: armada38x: avoid unused-function warning
From: Arnd Bergmann @ 2017-01-12 11:13 UTC (permalink / raw)
To: linux-arm-kernel
When CONFIG_PM_SLEEP is not set, rtc_update_mbus_timing_params becomes
unused, now that armada38x_rtc_probe() no longer calls
rtc_update_mbus_timing_params on startup:
drivers/rtc/rtc-armada38x.c:79:13: error: 'rtc_update_mbus_timing_params' defined but not used [-Werror=unused-function]
This addresses the warning by marking the PM functions as __maybe_unused,
so the unused functions get silently dropped. I could not tell from
the changelog if dropping the call to armada38x_rtc_probe() was
intended here, and if that is the correct thing to do without
CONFIG_PM_SLEEP, so we might need a different fix that brings it back.
Fixes: 4c492eb022c2 ("rtc: armada38x: make struct rtc_class_ops const")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/rtc/rtc-armada38x.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
index 4f75c619bbba..2e451acccd9c 100644
--- a/drivers/rtc/rtc-armada38x.c
+++ b/drivers/rtc/rtc-armada38x.c
@@ -338,8 +338,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static int armada38x_rtc_suspend(struct device *dev)
+static int __maybe_unused armada38x_rtc_suspend(struct device *dev)
{
if (device_may_wakeup(dev)) {
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
@@ -350,7 +349,7 @@ static int armada38x_rtc_suspend(struct device *dev)
return 0;
}
-static int armada38x_rtc_resume(struct device *dev)
+static int __maybe_unused armada38x_rtc_resume(struct device *dev)
{
if (device_may_wakeup(dev)) {
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
@@ -363,7 +362,6 @@ static int armada38x_rtc_resume(struct device *dev)
return 0;
}
-#endif
static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
armada38x_rtc_suspend, armada38x_rtc_resume);
--
2.9.0
^ permalink raw reply related
* [PATCH v2 2/2] arm64: dts: juno: Adds missing CoreSight STM component.
From: Sudeep Holla @ 2017-01-12 11:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484167449-14432-3-git-send-email-mike.leach@linaro.org>
On 11/01/17 20:44, Mike Leach wrote:
> Add missing CoreSight STM component definition to Juno CoreSight
> infrastructure juno-cs-rX.dtsi files.
>
> Component connected to different funnels depending on Juno platform variant.
>
> Signed-off-by: Mike Leach <mike.leach@linaro.org>
> ---
> arch/arm64/boot/dts/arm/juno-cs-r0.dtsi | 16 ++++++++++++++++
> arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi | 16 ++++++++++++++++
> 2 files changed, 32 insertions(+)
>
Can we avoid duplication with something like below ? I don't have strong
opinion but I just saw the opportunity. I can squash it in if you
agree(no need to repost).
Regards,
Sudeep
-->8
diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi
b/arch/arm64/boot/dts/arm/juno-base.dtsi
index 7c89000f954d..15fcd09d9d84 100644
--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
@@ -83,6 +83,21 @@
* The actual size is just 4K though 64K is reserved. Access to the
* unmapped reserved region results in a DECERR response.
*/
+ stm at 20100000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0 0x20100000 0 0x1000>,
+ <0 0x28000000 0 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ power-domains = <&scpi_devpd 0>;
+ port {
+ stm_out_port: endpoint {
+ };
+ };
+ };
+
etm0: etm at 22040000 {
compatible = "arm,coresight-etm4x", "arm,primecell";
reg = <0 0x22040000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts
b/arch/arm64/boot/dts/arm/juno-r1.dts
index 881339536e90..1c16a96ff677 100644
--- a/arch/arm64/boot/dts/arm/juno-r1.dts
+++ b/arch/arm64/boot/dts/arm/juno-r1.dts
@@ -228,3 +228,7 @@
&gpu1_thermal_zone {
status = "okay";
};
+
+&stm_out_port {
+ remote-endpoint = <&csys1_funnel_in_port0>;
+};
diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts
b/arch/arm64/boot/dts/arm/juno-r2.dts
index fca3a1705114..69890cc1edae 100644
--- a/arch/arm64/boot/dts/arm/juno-r2.dts
+++ b/arch/arm64/boot/dts/arm/juno-r2.dts
@@ -228,3 +228,7 @@
&gpu1_thermal_zone {
status = "okay";
};
+
+&stm_out_port {
+ remote-endpoint = <&csys1_funnel_in_port0>;
+};
diff --git a/arch/arm64/boot/dts/arm/juno.dts
b/arch/arm64/boot/dts/arm/juno.dts
index c90c37b66db5..ad270e090ba4 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -204,3 +204,7 @@
&etm5 {
cpu = <&A53_3>;
};
+
+&stm_out_port {
+ remote-endpoint = <&main_funnel_in_port2>;
+};
^ permalink raw reply related
* [PATCH v8 2/5] i2c: Add STM32F4 I2C driver
From: M'boumba Cedric Madianga @ 2017-01-12 11:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111153940.dtxzvtdici3r7l54@pengutronix.de>
2017-01-11 16:39 GMT+01:00 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> On Wed, Jan 11, 2017 at 02:58:44PM +0100, M'boumba Cedric Madianga wrote:
>> Hi Uwe,
>>
>> 2017-01-11 9:22 GMT+01:00 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
>> > Hello Cedric,
>> >
>> > On Thu, Jan 05, 2017 at 10:07:23AM +0100, M'boumba Cedric Madianga wrote:
>> >> +/*
>> >> + * In standard mode:
>> >> + * SCL period = SCL high period = SCL low period = CCR * I2C parent clk period
>> >> + *
>> >> + * In fast mode:
>> >> + * If Duty = 0; SCL high period = 1 * CCR * I2C parent clk period
> ^^
>> >> + * SCL low period = 2 * CCR * I2C parent clk period
> ^^
>> >> + * If Duty = 1; SCL high period = 9 * CCR * I2C parent clk period
> ^^
>> >> + * SCL low period = 16 * CCR * I2C parent clk period
>
>> > s/ \*/ */ several times
>>
>> Sorry but I don't see where is the issue as the style for multi-line
>> comments seems ok.
>> Could you please clarify that point if possible ? Thanks in advance
>
> There are several places with double spaces before * marked above.
Ok I see thanks.
>
>> >> + * In order to reach 400 kHz with lower I2C parent clk frequencies we always set
>> >> + * Duty = 1
>> >> + *
>> >> + * For both modes, we have CCR = SCL period * I2C parent clk frequency
>> >> + * with scl_period = 5 microseconds in Standard mode and scl_period = 1
>> > s/mode/Mode/
>>
>> ok thanks
>>
>> >
>> >> + * microsecond in Fast Mode in order to satisfy scl_high and scl_low periods
>> >> + * constraints defined by i2c bus specification
>> >
>> > I don't understand scl_period = 1 ?s for Fast Mode. For a bus freqency
>> > of 400 kHz we need low + high = 2.5 ?s. Is there a factor 10 missing
>> > somewhere?
>>
>> As CCR = SCL_period * I2C parent clk frequency with minimal freq =
>> 2Mhz and SCL_period = 1 we have:
>> CCR = 1 * 2Mhz = 2.
>> But to compute, scl_low and scl_high in Fast mode, we have to do the
>> following thing as Duty=1:
>> scl_high = 9 * CCR * I2C parent clk period
>> scl_low = 16 * CCR * I2C parent clk period
>> In our example:
>> scl_high = 9 * 2 * 0,0000005 = 0,000009 sec = 9 ?s
>> scl_low = 16 * 2 * 0.0000005 = 0,000016 sec = 16 ?s
>> So low + high = 27 ?s > 2,5 ?s
>
> For me 9 ?s + 16 ?s is 25 ?s, resulting in 40 kHz. That's why I wondered
> if there is a factor 10 missing somewhere.
Hum ok. I am going to double-check what is wrong because when I check
with the scope I always reach 400Khz for SCL.
I will let you know.
>
>> >> + */
>> >> +static struct stm32f4_i2c_timings i2c_timings[] = {
>> >> [...]
>> >> +
>> >> +/**
>> >> + * stm32f4_i2c_hw_config() - Prepare I2C block
>> >> + * @i2c_dev: Controller's private data
>> >> + */
>> >> +static int stm32f4_i2c_hw_config(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + int ret = 0;
>> >> +
>> >> + /* Disable I2C */
>> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_PE);
>> >> +
>> >> + ret = stm32f4_i2c_set_periph_clk_freq(i2c_dev);
>> >> + if (ret)
>> >> + return ret;
>> >> +
>> >> + stm32f4_i2c_set_rise_time(i2c_dev);
>> >> +
>> >> + stm32f4_i2c_set_speed_mode(i2c_dev);
>> >> +
>> >> + stm32f4_i2c_set_filter(i2c_dev);
>> >> +
>> >> + /* Enable I2C */
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_PE);
>> >
>> > This function is called after a hw reset, so there should be no need to
>> > use clr_bits and set_bits because the value read from hw should be
>> > known.
>>
>> ok thanks
>>
>> >
>> >> + return ret;
>> >
>> > return 0;
>>
>> ok thanks
>>
>> >
>> >> +}
>> >> +
>> >> +static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + u32 status;
>> >> + int ret;
>> >> +
>> >> + ret = readl_relaxed_poll_timeout(i2c_dev->base + STM32F4_I2C_SR2,
>> >> + status,
>> >> + !(status & STM32F4_I2C_SR2_BUSY),
>> >> + 10, 1000);
>> >> + if (ret) {
>> >> + dev_dbg(i2c_dev->dev, "bus not free\n");
>> >> + ret = -EBUSY;
>> >> + }
>> >> +
>> >> + return ret;
>> >> +}
>> >> +
>> >> +/**
>> >> + * stm32f4_i2c_write_ byte() - Write a byte in the data register
>> >> + * @i2c_dev: Controller's private data
>> >> + * @byte: Data to write in the register
>> >> + */
>> >> +static void stm32f4_i2c_write_byte(struct stm32f4_i2c_dev *i2c_dev, u8 byte)
>> >> +{
>> >> + writel_relaxed(byte, i2c_dev->base + STM32F4_I2C_DR);
>> >> +}
>> >> +
>> >> +/**
>> >> + * stm32f4_i2c_write_msg() - Fill the data register in write mode
>> >> + * @i2c_dev: Controller's private data
>> >> + *
>> >> + * This function fills the data register with I2C transfer buffer
>> >> + */
>> >> +static void stm32f4_i2c_write_msg(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
>> >> +
>> >> + stm32f4_i2c_write_byte(i2c_dev, *msg->buf++);
>> >> + msg->count--;
>> >> +}
>> >> +
>> >> +static void stm32f4_i2c_read_msg(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
>> >> + u32 rbuf;
>> >> +
>> >> + rbuf = readl_relaxed(i2c_dev->base + STM32F4_I2C_DR);
>> >> + *msg->buf++ = rbuf & 0xff;
>> >
>> > This is unnecessary. buf has an 8 bit wide type so
>> >
>> > *msg->buf++ = rbuf;
>> >
>> > has the same effect. (ISTR this is something I already pointed out
>> > earlier?)
>>
>> Yes you are right.
>>
>> >
>> >> + msg->count--;
>> >> +}
>> >> +
>> >> +static void stm32f4_i2c_terminate_xfer(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
>> >> + void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
>> >> +
>> >> + stm32f4_i2c_disable_irq(i2c_dev);
>> >> +
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + if (msg->stop)
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
>> >> + else
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
>> >> +
>> >> + complete(&i2c_dev->complete);
>> >> +}
>> >> +
>> >> +/**
>> >> + * stm32f4_i2c_handle_write() - Handle FIFO empty interrupt in case of write
>> >> + * @i2c_dev: Controller's private data
>> >> + */
>> >> +static void stm32f4_i2c_handle_write(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
>> >> + void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
>> >> +
>> >> + if (msg->count) {
>> >> + stm32f4_i2c_write_msg(i2c_dev);
>> >> + if (!msg->count) {
>> >> + /* Disable buffer interrupts for RXNE/TXE events */
>> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
>> >> + }
>> >> + } else {
>> >> + stm32f4_i2c_terminate_xfer(i2c_dev);
>> >
>> > Is stm32f4_i2c_terminate_xfer also called when arbitration is lost? If
>> > yes, is it then right to set STM32F4_I2C_CR1_STOP or
>> > STM32F4_I2C_CR1_START?
>>
>> If arbitration is lost, stm32f4_i2c_terminate_xfer() is not called.
>> In that case, we return -EAGAIN and i2c-core will retry by calling
>> stm32f4_i2c_xfer()
>>
>> >
>> >> + }
>> >> +}
>> >> +
>> >> +/**
>> >> + * stm32f4_i2c_handle_read() - Handle FIFO empty interrupt in case of read
>> >> + * @i2c_dev: Controller's private data
>> >> + */
>> >> +static void stm32f4_i2c_handle_read(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
>> >> + void __iomem *reg = i2c_dev->base + STM32F4_I2C_CR2;
>> >> +
>> >> + switch (msg->count) {
>> >> + case 1:
>> >> + stm32f4_i2c_disable_irq(i2c_dev);
>> >> + stm32f4_i2c_read_msg(i2c_dev);
>> >> + complete(&i2c_dev->complete);
>> >> + break;
>> >> + /*
>> >> + * For 2 or 3-byte reception, we do not have to read the data register
>> >> + * when RXNE occurs as we have to wait for byte transferred finished
>> >
>> > it's hard to understand because if you don't know the hardware the
>> > meaning of RXNE is unknown.
>>
>> Ok I will replace RXNE by RX not empty in that comment
>>
>> >
>> >> + * event before reading data. So, here we just disable buffer
>> >> + * interrupt in order to avoid another system preemption due to RXNE
>> >> + * event
>> >> + */
>> >> + case 2:
>> >> + case 3:
>> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR2_ITBUFEN);
>> >> + break;
>> >> + /* For N byte reception with N > 3 we directly read data register */
>> >> + default:
>> >> + stm32f4_i2c_read_msg(i2c_dev);
>> >> + }
>> >> +}
>> >> +
>> >> +/**
>> >> + * stm32f4_i2c_handle_rx_btf() - Handle byte transfer finished interrupt
>> >> + * in case of read
>> >> + * @i2c_dev: Controller's private data
>> >> + */
>> >> +static void stm32f4_i2c_handle_rx_btf(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >
>> > btf is a hw-related name. Maybe better use _done which is easier to
>> > understand?
>>
>> OK
>>
>> >
>> >> + struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
>> >> + void __iomem *reg;
>> >> + u32 mask;
>> >> + int i;
>> >> +
>> >> + switch (msg->count) {
>> >> + case 2:
>> >> + /*
>> >> + * In order to correctly send the Stop or Repeated Start
>> >> + * condition on the I2C bus, the STOP/START bit has to be set
>> >> + * before reading the last two bytes.
>> >> + * After that, we could read the last two bytes, disable
>> >> + * remaining interrupts and notify the end of xfer to the
>> >> + * client
>> >
>> > This is surprising. I didn't recheck the manual, but that looks very
>> > uncomfortable.
>>
>> I agree but this exactly the hardware way of working described in the
>> reference manual.
>
> IMHO that's a hw bug. This makes it for example impossible to implement
> SMBus block transfers (I think).
This is not correct.
Setting STOP/START bit does not mean the the pulse will be sent right now.
Here we have just to prepare the hardware for the 2 next pulse but the
STOP/START/ACK pulse will be generated at the right time as required
by I2C specification.
So SMBus block transfer will be possible.
>
>> > How does this work, when I only want to read a single
>> > byte? Same problem for ACK below.
>>
>> For a single reception, we enable NACK and STOP or Repeatead START
>> bits during address match.
>> The NACK and STOP/START pulses are sent as soon as the data is
>> received in the shift register.
>> Please note that in that case, we don't have to wait BTF event to read the data.
>> Data is read as soon as RXNE event occurs.
>>
>> >
>> >> + */
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + if (msg->stop)
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
>> >> + else
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
>> >> +
>> >> + for (i = 2; i > 0; i--)
>> >> + stm32f4_i2c_read_msg(i2c_dev);
>> >> +
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR2;
>> >> + mask = STM32F4_I2C_CR2_ITEVTEN | STM32F4_I2C_CR2_ITERREN;
>> >> + stm32f4_i2c_clr_bits(reg, mask);
>> >> +
>> >> + complete(&i2c_dev->complete);
>> >> + break;
>> >> + case 3:
>> >> + /*
>> >> + * In order to correctly send the ACK on the I2C bus for the
>> >> + * last two bytes, we have to set ACK bit before reading the
>> >> + * third last data byte
>> >> + */
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
>> >> + stm32f4_i2c_read_msg(i2c_dev);
>> >> + break;
>> >> + default:
>> >> + stm32f4_i2c_read_msg(i2c_dev);
>> >> + }
>> >> +}
>> >> +
>> >> +/**
>> >> + * stm32f4_i2c_handle_rx_addr() - Handle address matched interrupt in case of
>> >> + * master receiver
>> >> + * @i2c_dev: Controller's private data
>> >> + */
>> >> +static void stm32f4_i2c_handle_rx_addr(struct stm32f4_i2c_dev *i2c_dev)
>> >> +{
>> >> + struct stm32f4_i2c_msg *msg = &i2c_dev->msg;
>> >> + void __iomem *reg;
>> >> +
>> >> + switch (msg->count) {
>> >> + case 0:
>> >> + stm32f4_i2c_terminate_xfer(i2c_dev);
>> >> + /* Clear ADDR flag */
>> >> + readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
>> >> + break;
>> >> + case 1:
>> >> + /*
>> >> + * Single byte reception:
>> >
>> > This also happens for the last byte of a 5 byte transfer, right?
>>
>> For a 5 byte transfer the behavior is different:
>> We have to read data from DR (data register) as soon as the RXNE (RX
>> not empty) event occurs for data1, data2 and data3 (until N-2 data for
>> a more generic case)
>> The ACK is automatically sent as soon as the data is received in the
>> shift register as the I2C controller was configured to do that during
>> adress match phase.
>>
>> For data3 (N-2 data), we wait for BTF (Byte Transfer finished) event
>> in order to set NACK before reading DR.
>> This event occurs when a new data has been received in shift register
>> (in our case data4 or N-1 data) but the prevoius data in DR (in our
>> case data3 or N-2 data) has not been read yet.
>> In that way, the NACK pulse will be correctly generated after the last
>> received data byte.
>>
>> For data4 and data5, we wait for BTF event (data4 or N-1 data in DR
>> and data5 or N data in shift register), set STOP or repeated Start in
>> order to correctly sent the right pulse after the last received data
>> byte and run 2 consecutives read of DR.
>
> So "Single byte reception" above is wrong, as this case is also used for
> longer transfers and should be updated accordingly.
I don't think so.
stm32f4_i2c_handle_rx_addr() is called once during adress match phase.
It is used to configure the I2C controller according to the number of
data to be received as it has to be done in a different way according
to the number of data to received:
- single byte reception
- 2-byte reception
- N-byte reception
Then, as soon as, the controller is correctly configured, for each
byte to be received, we use stm32f4_i2c_handle_read() or
stm32f4_i2c_handle_rx_done().
stm32f4_i2c_handle_read() is used to read data for a single byte
reception or until N-2 data for N-byte reception
stm32f4_i2c_handle_rx_done() is used to read data for a 2-byte
reception, or data N-2, N-1 and N for a N-byte reception.
So, single-reception and longer transfer have been clearly managed in
a different way.
>
>> >> + * Enable NACK, clear ADDR flag and generate STOP or RepSTART
>> >> + */
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
>> >> + readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
>> >> + if (msg->stop)
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_STOP);
>> >> + else
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_START);
>> >> + break;
>> >> + case 2:
>> >> + /*
>> >> + * 2-byte reception:
>> >> + * Enable NACK and set POS
>> >
>> > What is POS?
>> POS is used to define the position of the (N)ACK pulse
>> 0: ACK is generated when the current is being received in the shift register
>> 1: ACK is generated when the next byte which will be received in the
>> shift register (used for 2-byte reception)
>
> Can you please put this into the comment. "POS" isn't much helpful
> there.
Ok I will add a comment for that.
>
>>
>> >
>> >> + */
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_POS);
>> >
>> > You could get rid of this, when caching the value of CR1. Would save two
>> > register reads here. This doesn't work for all registers, but it should
>> > be possible to apply for most of them, maybe enough to get rid of the
>> > clr_bits and set_bits function.
>> >
>> >> + readl_relaxed(i2c_dev->base + STM32F4_I2C_SR2);
>> >> + break;
>> >> +
>> >> + default:
>> >> + /* N-byte reception: Enable ACK */
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_ACK);
>> >
>> > Do you need to set ACK for each byte transferred?
>> I need to do that in order to be SMBus compatible and the ACK/NACK
>> seems to be used by default in Documentation/i2c/i2c-protocol file.
>
> Yeah, protocol wise you need to ack each byte. I just wondered if you
> need to set the hardware bit for each byte or if it is retained in
> hardware until unset by a register write.
ACK bit is set in stm32f4_i2c_handle_rx_addr().
As explained above, this function is called once during address match phase.
So, this bit is set only once just before receiving the first data byte.
>
> Best regards
> Uwe
>
> --
> Pengutronix e.K. | Uwe Kleine-K?nig |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
Best regards,
Cedric
^ permalink raw reply
* [PATCH 56/62] watchdog: tangox_wdt: Convert to use device managed functions
From: Måns Rullgård @ 2017-01-12 11:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0f68aa11-161b-0435-ea0f-851432464bc1@sigmadesigns.com>
Marc Gonzalez <marc_gonzalez@sigmadesigns.com> writes:
>> So far we have a claim that a cast to a void * may somehow be different
>> to a cast to a different pointer, if used as function argument, and that
>> the behavior with such a cast may be undefined. In other words, you claim
>> that a function implemented as, say,
>>
>> void func(int *var) {}
>>
>> might result in undefined behavior if some header file declares it as
>>
>> void func(void *);
>>
>> and it is called as
>>
>> int var;
>>
>> func(&var);
>>
>> That seems really far fetched to me.
>
> Thanks for giving me an opportunity to play the language lawyer :-)
>
> C99 6.3.2.3 sub-clause 8 states:
>
> "A pointer to a function of one type may be converted to a pointer to
> a function of another type and back again; the result shall compare
> equal to the original pointer. If a converted pointer is used to call
> a function whose type is not compatible with the pointed-to type, the
> behavior is undefined."
>
> So, the behavior is undefined, not when you cast clk_disable_unprepare,
> but when clk_disable_unprepare is later called through the devres->action
> function pointer.
Only if the function types are incompatible. C99 6.7.5.3 subclause 15:
For two function types to be compatible, both shall specify compatible
return types. Moreover, the parameter type lists, if both are
present, shall agree in the number of parameters and in use of the
ellipsis terminator; corresponding parameters shall have compatible
types.
The question then is whether pointer to void and pointer to struct clk
are compatible types. 6.7.5.1 subclause 2:
For two pointer types to be compatible, both shall be identically
qualified and both shall be pointers to compatible types.
6.2.5 subclause 27:
A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type. 39)
39) The same representation and alignment requirements are meant to
imply interchangeability as arguments to functions, return values
from functions, and members of unions.
6.3.2.3 subclause 1:
A pointer to void may be converted to or from a pointer to any
incomplete or object type.
>From what I can tell, the standard stops just short of declaring pointer
to void compatible with other pointer types.
> However, I agree that it will work as expected on typical platforms
> (where all pointers are the same size, and the calling convention
> treats all pointers the same).
Yes, I don't see how it could possibly go wrong.
--
M?ns Rullg?rd
^ permalink raw reply
* [PATCH v2 2/2] arm64: dts: juno: Adds missing CoreSight STM component.
From: Mike Leach @ 2017-01-12 11:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0120ef9b-2e01-e00a-2de8-c540ab70af85@arm.com>
Hi Sudeep,
I'm fine with that - less duplication the better.
I've not played with .dts files much to I hadn't realised that type of construction was possible.
Regards
Mike
----------------------------------------------------------------
Mike Leach +44 (0)1254 893911 (Direct)
Principal Engineer +44 (0)1254 893900 (Main)
Arm Blackburn Design Centre +44 (0)1254 893901 (Fax)
Belthorn House
Walker Rd mailto:mike.leach at arm.com
Guide
Blackburn
BB1 2QE
----------------------------------------------------------------
> -----Original Message-----
> From: CoreSight [mailto:coresight-bounces at lists.linaro.org] On Behalf Of
> Sudeep Holla
> Sent: 12 January 2017 11:15
> To: Mike Leach; Liviu Dudau; Lorenzo Pieralisi
> Cc: coresight at lists.linaro.org; Suzuki Poulose; linux-arm-
> kernel at lists.infradead.org; Sudeep Holla
> Subject: Re: [PATCH v2 2/2] arm64: dts: juno: Adds missing CoreSight STM
> component.
>
>
>
> On 11/01/17 20:44, Mike Leach wrote:
> > Add missing CoreSight STM component definition to Juno CoreSight
> > infrastructure juno-cs-rX.dtsi files.
> >
> > Component connected to different funnels depending on Juno platform
> variant.
> >
> > Signed-off-by: Mike Leach <mike.leach@linaro.org>
> > ---
> > arch/arm64/boot/dts/arm/juno-cs-r0.dtsi | 16 ++++++++++++++++
> > arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi | 16 ++++++++++++++++
> > 2 files changed, 32 insertions(+)
> >
>
> Can we avoid duplication with something like below ? I don't have strong
> opinion but I just saw the opportunity. I can squash it in if you
> agree(no need to repost).
>
> Regards,
> Sudeep
>
> -->8
>
> diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi
> b/arch/arm64/boot/dts/arm/juno-base.dtsi
> index 7c89000f954d..15fcd09d9d84 100644
> --- a/arch/arm64/boot/dts/arm/juno-base.dtsi
> +++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
> @@ -83,6 +83,21 @@
> * The actual size is just 4K though 64K is reserved. Access to the
> * unmapped reserved region results in a DECERR response.
> */
> +stm at 20100000 {
> +compatible = "arm,coresight-stm", "arm,primecell";
> +reg = <0 0x20100000 0 0x1000>,
> + <0 0x28000000 0 0x180000>;
> +reg-names = "stm-base", "stm-stimulus-base";
> +
> +clocks = <&soc_smc50mhz>;
> +clock-names = "apb_pclk";
> +power-domains = <&scpi_devpd 0>;
> +port {
> +stm_out_port: endpoint {
> +};
> +};
> +};
> +
> etm0: etm at 22040000 {
> compatible = "arm,coresight-etm4x", "arm,primecell";
> reg = <0 0x22040000 0 0x1000>;
> diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts
> b/arch/arm64/boot/dts/arm/juno-r1.dts
> index 881339536e90..1c16a96ff677 100644
> --- a/arch/arm64/boot/dts/arm/juno-r1.dts
> +++ b/arch/arm64/boot/dts/arm/juno-r1.dts
> @@ -228,3 +228,7 @@
> &gpu1_thermal_zone {
> status = "okay";
> };
> +
> +&stm_out_port {
> +remote-endpoint = <&csys1_funnel_in_port0>;
> +};
> diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts
> b/arch/arm64/boot/dts/arm/juno-r2.dts
> index fca3a1705114..69890cc1edae 100644
> --- a/arch/arm64/boot/dts/arm/juno-r2.dts
> +++ b/arch/arm64/boot/dts/arm/juno-r2.dts
> @@ -228,3 +228,7 @@
> &gpu1_thermal_zone {
> status = "okay";
> };
> +
> +&stm_out_port {
> +remote-endpoint = <&csys1_funnel_in_port0>;
> +};
> diff --git a/arch/arm64/boot/dts/arm/juno.dts
> b/arch/arm64/boot/dts/arm/juno.dts
> index c90c37b66db5..ad270e090ba4 100644
> --- a/arch/arm64/boot/dts/arm/juno.dts
> +++ b/arch/arm64/boot/dts/arm/juno.dts
> @@ -204,3 +204,7 @@
> &etm5 {
> cpu = <&A53_3>;
> };
> +
> +&stm_out_port {
> +remote-endpoint = <&main_funnel_in_port2>;
> +};
>
> _______________________________________________
> CoreSight mailing list
> CoreSight at lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/coresight
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
^ permalink raw reply
* [PATCH v8 2/5] i2c: Add STM32F4 I2C driver
From: M'boumba Cedric Madianga @ 2017-01-12 11:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111154200.xcxdlnnakyttumzw@pengutronix.de>
Hi Uwe,
2017-01-11 16:42 GMT+01:00 Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>:
> Hello Cedric,
>
> On Wed, Jan 11, 2017 at 03:20:41PM +0100, M'boumba Cedric Madianga wrote:
>> >
>> >> + */
>> >> + reg = i2c_dev->base + STM32F4_I2C_CR1;
>> >> + stm32f4_i2c_clr_bits(reg, STM32F4_I2C_CR1_ACK);
>> >> + stm32f4_i2c_set_bits(reg, STM32F4_I2C_CR1_POS);
>> >
>> > You could get rid of this, when caching the value of CR1. Would save two
>> > register reads here. This doesn't work for all registers, but it should
>> > be possible to apply for most of them, maybe enough to get rid of the
>> > clr_bits and set_bits function.
>>
>> I agree at many places I could save registers read by not using
>> clr_bits and set_bits function when the registers in question has been
>> already read.
>> But it is not enough to get rid of the clr_bits and set_bits function.
>> For example when calling stm32f4_i2c_terminate_xfer(), the CR1
>> register is never read before so set_bits function is useful.
>
> I didn't double check the manual, but I would expect that CR1 isn't
> modified by hardware. So you can cache the result in the driver data
> structure and do the necessary modifications with that one.
CR1 is modified by hardware to clear some bits set by software during
the communication.
>
> Best regards
> Uwe
>
> --
> Pengutronix e.K. | Uwe Kleine-K?nig |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
Best regards,
Cedric
^ permalink raw reply
* [RFC PATCH 00/10] arm64/sve: Add userspace vector length control API
From: Dave Martin @ 2017-01-12 11:25 UTC (permalink / raw)
To: linux-arm-kernel
This is an add-on series for the Scalable Vector Extension (SVE) core
patches [1], adding an interface to allow userspace tasks to control
what vector length they use for SVE instructions.
(For an architectural overview of SVE, and an explanation of what a
"vector length" is, see [2].)
The amount of SVE register state depends on the vector length, so using
large vector lengths with SVE can requre the userspace signal frame to
grow. This leads to some ABI impacts in common with other arches that
may have to grow their signal frame.
In this series I do not dictate any particular policy for the SVE vector
length: the kernel provides a default, but userspace can set the vector
length as it likes, provided the hardware supports the chosen length.
For example, userspace may pick a length that the images being loaded
have been validated against or optimised for.
Overview
========
The API proposed here consists of prctl() calls to allow a task to
set/query its vector length and related control flags, and corresponding
ptrace extensions to allow a debugger to do the same for a traced task:
prctl():
* PR_SVE_SET_VL
* PR_SVE_GET_VL
ptrace() NT_ARM_SVE regset:
* user_sve_header.flags & SVE_PT_VL_*
* user_sve_header.vl
(I follow the existing convention of not including the arch name in
prctl names).
The context switch logic is also extended to set the correct vector
length when scheduling a task in, since the vector length may now differ
between tasks.
The expected users of this API are libc startup, dynamic linker and
runtime environment plumbing code. I don't expect ordinary user code to
change its own vector length on-the-fly, partly because it is generally
The Wrong Thing To Do with respect to the SVE programming model, and
partly because of ABI subtleties which make it difficult to do this
correctly.
ABI Impact
==========
The current arm64 signal frame size is not sufficient to save all SVE
state for larger vector lengths.
This won't affect existing binary distros, since the signal frame is not
extended unless some SVE instructions are executed by the user task.
However, non-SVE code executing in the same processes as SVE-aware code
may start to see the kernel using more than MINSIGSTKSZ bytes of stack
to deliver a signal, which may lead to stack overruns. Other ABI
breakages are also possible if we were to simply increase the
MINSIGSTKSZ #define. SVE aware code will need to move to a new
mechanism to discover the signal frame size: perhaps a new prctl() (not
implemented in this series).
As a temporary workaround, I added a Kconfig option in [1] to clamp the
vector length to a safe maximum that hides this effect, but this was
only intended as a short-term kludge.
This series removes the Kconfig kludge and introduces a new runtime
mechanism:
# echo <vector length in bytes> >/proc/cpu/sve_default_vector_length
will now set the default vector length for newly-exec'd processes. This
is initialised to the ABI-safe value 512 at boot (or the maximum value
supported by the hardware, if smaller). Administrators / distro
maintainers / developers can set this to something different in boot
scripts if they are comfortable doing so, or to see what happens.
We _could_ increase the kernel default in the future when and if we are
satisfied that the change is sufficiently low-impact.
User tasks can always override the default via prctl(): the logic is
that non-SVE-aware code doesn't know how to change the vector length,
and so won't do that anyway. SVE-aware code is presumed to understand
the consequences.
The vector length can be made inheritable (allowing implementation of
taskset-like tools, or running a testsuite with a particular vector
length) or not (for general-purpose processes; in which case the vector
length is reset to the default across exec).
[1] arm64: Scalable Vector Extension core support
http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/470507.html
[2] Technology Update: The Scalable Vector Extension (SVE) for the ARMv8-A architecture
https://www.community.arm.com/processors/b/blog/posts/technology-update-the-scalable-vector-extension-sve-for-the-armv8-a-architecture
Note: The size of an SVE vector register (the "vector length") is
choosable per hardware implementation, and the ISA allows software to be
coded independently of the actual vector length in use. The vector
length can also be selected explicitly by software within the limits
supported by the hardware -- this is expected to be useful in some
situations. This series exposes this control to userspace.
Dave Martin (10):
prctl: Add skeleton for PR_SVE_{SET,GET}_VL controls
arm64/sve: Track vector length for each task
arm64/sve: Set CPU vector length to match current task
arm64/sve: Factor out clearing of tasks' SVE regs
arm64/sve: Wire up vector length control prctl() calls
arm64/sve: Disallow VL setting for individual threads by default
arm64/sve: Add vector length inheritance control
arm64/sve: ptrace: Wire up vector length control and reporting
arm64/sve: Enable default vector length control via procfs
Revert "arm64/sve: Limit vector length to 512 bits by default"
arch/arm64/Kconfig | 35 ----
arch/arm64/include/asm/fpsimd.h | 25 ++-
arch/arm64/include/asm/fpsimdmacros.h | 7 +-
arch/arm64/include/asm/processor.h | 12 ++
arch/arm64/include/uapi/asm/ptrace.h | 5 +
arch/arm64/kernel/entry-fpsimd.S | 2 +-
arch/arm64/kernel/fpsimd.c | 334 +++++++++++++++++++++++++++++++---
arch/arm64/kernel/ptrace.c | 27 +--
arch/arm64/kernel/signal.c | 15 +-
arch/arm64/mm/proc.S | 5 -
include/uapi/linux/prctl.h | 10 +
kernel/sys.c | 12 ++
12 files changed, 407 insertions(+), 82 deletions(-)
--
2.1.4
^ permalink raw reply
* [RFC PATCH 01/10] prctl: Add skeleton for PR_SVE_{SET, GET}_VL controls
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
This patch adds a do-nothing skeleton for the arm64 Scalable Vector
Extension control prctls.
These prctls are only avilable with
CONFIG_ARM64=y
CONFIG_ARM64_SVE=y
Otherwise they will compile out and return -EINVAL if attempted
from userspace.
The backend functions sve_{set,get}_task_vl() will be fleshed out
with actual functionality in subsequent patches.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
There will probably also be a call to discover the signal frame size
(MINSIGSTKSZ equivalent) for the current configuration, something like
* PR_GET_MINSIGSTKSZ
This series doesn't add this yet: only the PR_SVE_{SET,GET}_VL prctls
are provided.
arch/arm64/include/asm/fpsimd.h | 19 +++++++++++++++++++
arch/arm64/include/asm/processor.h | 4 ++++
arch/arm64/kernel/fpsimd.c | 13 +++++++++++++
include/uapi/linux/prctl.h | 4 ++++
kernel/sys.c | 12 ++++++++++++
5 files changed, 52 insertions(+)
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 88bcf69..e13259e 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -17,6 +17,7 @@
#define __ASM_FP_H
#include <asm/ptrace.h>
+#include <asm/errno.h>
#ifndef __ASSEMBLY__
@@ -110,12 +111,30 @@ extern unsigned int sve_get_vl(void);
extern void fpsimd_sync_to_sve(struct task_struct *task);
#ifdef CONFIG_ARM64_SVE
+
extern void fpsimd_sync_to_fpsimd(struct task_struct *task);
extern void fpsimd_sync_from_fpsimd_zeropad(struct task_struct *task);
+extern int sve_set_task_vl(struct task_struct *task,
+ unsigned long vector_length, unsigned long flags);
+extern int sve_get_task_vl(struct task_struct *task);
+
#else /* !CONFIG_ARM64_SVE */
+
static void __maybe_unused fpsimd_sync_to_fpsimd(struct task_struct *task) { }
static void __maybe_unused fpsimd_sync_from_fpsimd_zeropad(
struct task_struct *task) { }
+
+static int __maybe_unused sve_set_task_vl(struct task_struct *task,
+ unsigned long vector_length, unsigned long flags)
+{
+ return -EINVAL;
+}
+
+static int __maybe_unused sve_get_task_vl(struct task_struct *task)
+{
+ return -EINVAL;
+}
+
#endif /* !CONFIG_ARM64_SVE */
#endif
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 747c65a..6f0f300 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -190,4 +190,8 @@ int cpu_enable_pan(void *__unused);
int cpu_enable_uao(void *__unused);
int cpu_enable_cache_maint_trap(void *__unused);
+#define SVE_SET_VL(task, vector_length, flags) \
+ sve_set_task_vl(task, vector_length, flags)
+#define SVE_GET_VL(task) sve_get_task_vl(task)
+
#endif /* __ASM_PROCESSOR_H */
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 2c113e4..bdacfcd 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -468,6 +468,19 @@ void fpsimd_sync_from_fpsimd_zeropad(struct task_struct *task)
__fpsimd_sync_from_fpsimd_zeropad(task, sve_vq_from_vl(vl));
}
+/* PR_SVE_SET_VL */
+int sve_set_task_vl(struct task_struct *task,
+ unsigned long vector_length, unsigned long flags)
+{
+ return -EINVAL;
+}
+
+/* PR_SVE_GET_VL */
+int sve_get_task_vl(struct task_struct *task)
+{
+ return -EINVAL;
+}
+
#endif /* CONFIG_ARM64_SVE */
#ifdef CONFIG_KERNEL_MODE_NEON
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index a8d0759..e32e2da 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -197,4 +197,8 @@ struct prctl_mm_map {
# define PR_CAP_AMBIENT_LOWER 3
# define PR_CAP_AMBIENT_CLEAR_ALL 4
+/* arm64 Scalable Vector Extension controls */
+#define PR_SVE_SET_VL 48 /* set task vector length */
+#define PR_SVE_GET_VL 49 /* get task vector length */
+
#endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index 842914e..5f50385 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -103,6 +103,12 @@
#ifndef SET_FP_MODE
# define SET_FP_MODE(a,b) (-EINVAL)
#endif
+#ifndef SVE_SET_VL
+# define SVE_SET_VL(a,b,c) (-EINVAL)
+#endif
+#ifndef SVE_GET_VL
+# define SVE_GET_VL(a) (-EINVAL)
+#endif
/*
* this is where the system-wide overflow UID and GID are defined, for
@@ -2261,6 +2267,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
case PR_GET_FP_MODE:
error = GET_FP_MODE(me);
break;
+ case PR_SVE_SET_VL:
+ error = SVE_SET_VL(me, arg2, arg3);
+ break;
+ case PR_SVE_GET_VL:
+ error = SVE_GET_VL(me);
+ break;
default:
error = -EINVAL;
break;
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 02/10] arm64/sve: Track vector length for each task
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
In preparation for allowing each task to have its own independent
vector length, this patch adds a sve_vl field to thread_struct to
track it, and interrogates this instead of interrogating the
hardware when knowledge of the task's vector length is needed.
The hardware supported vector length is not known straight out of
boot, so init_task and other kernel tasks forked early may lack
this knowledge.
We only need this knowledge when in the context of a user task that
has SVE state (or that has just trapped while attempting to have
SVE state). So, we can hook into exec() to set task vector length
if it wasn't known at boot/fork time, before the task enters
userspace.
There is no way to change sve_vl for a task yet, so all tasks still
execute with the hardware vector length. Subsequent patches will
enable changing the vector length for tasks.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/include/asm/processor.h | 1 +
arch/arm64/kernel/fpsimd.c | 44 ++++++++++++++++++++++++++------------
arch/arm64/kernel/ptrace.c | 4 ++--
arch/arm64/kernel/signal.c | 15 +++++++++----
4 files changed, 44 insertions(+), 20 deletions(-)
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 6f0f300..96eada9 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -83,6 +83,7 @@ struct thread_struct {
unsigned long tp2_value;
#endif
struct fpsimd_state fpsimd_state;
+ u16 sve_vl; /* SVE vector length */
unsigned long fault_address; /* fault info */
unsigned long fault_code; /* ESR_EL1 value */
struct debug_info debug; /* debugging */
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index bdacfcd..6065707 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -99,6 +99,9 @@ void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
WARN_ON(1);
}
+/* Maximum supported vector length across all CPUs (initially poisoned) */
+int sve_max_vl = -1;
+
#ifdef CONFIG_ARM64_SVE
static void task_fpsimd_to_sve(struct task_struct *task);
@@ -156,9 +159,9 @@ void *__task_sve_state(struct task_struct *task)
static void *__task_pffr(struct task_struct *task)
{
- unsigned int vl = sve_get_vl();
+ unsigned int vl = task->thread.sve_vl;
- BUG_ON(vl % 16);
+ BUG_ON(!sve_vl_valid(vl));
return (char *)__task_sve_state(task) + 34 * vl;
}
@@ -272,6 +275,18 @@ void fpsimd_flush_thread(void)
memset(__task_sve_state(current), 0,
arch_task_struct_size -
((char *)__task_sve_state(current) - (char *)current));
+
+ /*
+ * User tasks must have a valid vector length set, but tasks
+ * forked early (e.g., init) may not have one yet.
+ * By now, we will know what the hardware supports, so set the
+ * task vector length if it doesn't have one:
+ */
+ if (!current->thread.sve_vl) {
+ BUG_ON(!sve_vl_valid(sve_max_vl));
+
+ current->thread.sve_vl = sve_max_vl;
+ }
}
set_thread_flag(TIF_FOREIGN_FPSTATE);
@@ -310,16 +325,15 @@ static void __task_sve_to_fpsimd(struct task_struct *task, unsigned int vq)
static void task_sve_to_fpsimd(struct task_struct *task)
{
- unsigned int vl = sve_get_vl();
+ unsigned int vl = task->thread.sve_vl;
unsigned int vq;
if (!(elf_hwcap & HWCAP_SVE))
return;
- BUG_ON(vl % 16);
- vq = vl / 16;
- BUG_ON(vq < 1 || vq > 16);
+ BUG_ON(!sve_vl_valid(vl));
+ vq = sve_vq_from_vl(vl);
__task_sve_to_fpsimd(task, vq);
}
@@ -373,16 +387,15 @@ static void __task_fpsimd_to_sve(struct task_struct *task, unsigned int vq)
static void task_fpsimd_to_sve(struct task_struct *task)
{
- unsigned int vl = sve_get_vl();
+ unsigned int vl = task->thread.sve_vl;
unsigned int vq;
if (!(elf_hwcap & HWCAP_SVE))
return;
- BUG_ON(vl % 16);
- vq = vl / 16;
- BUG_ON(vq < 1 || vq > 16);
+ BUG_ON(!sve_vl_valid(vl));
+ vq = sve_vq_from_vl(vl);
__task_fpsimd_to_sve(task, vq);
}
@@ -463,8 +476,9 @@ static void __fpsimd_sync_from_fpsimd_zeropad(struct task_struct *task,
void fpsimd_sync_from_fpsimd_zeropad(struct task_struct *task)
{
- unsigned int vl = sve_get_vl();
+ unsigned int vl = task->thread.sve_vl;
+ BUG_ON(!sve_vl_valid(vl));
__fpsimd_sync_from_fpsimd_zeropad(task, sve_vq_from_vl(vl));
}
@@ -606,11 +620,13 @@ void __init fpsimd_init_task_struct_size(void)
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
((read_cpuid(ID_AA64PFR0_EL1) >> ID_AA64PFR0_SVE_SHIFT)
& 0xf) == 1) {
- arch_task_struct_size = sizeof(struct task_struct) +
- 35 * sve_get_vl();
+ /* FIXME: This should be the minimum across all CPUs */
+ sve_max_vl = sve_get_vl();
+ arch_task_struct_size = sizeof(struct task_struct) +
+ 35 * sve_max_vl;
pr_info("SVE: enabled with maximum %u bits per vector\n",
- sve_get_vl() * 8);
+ sve_max_vl * 8);
}
}
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index fb8cef63..32debb8 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -736,7 +736,7 @@ static int sve_get(struct task_struct *target,
/* Header */
memset(&header, 0, sizeof(header));
- header.vl = sve_get_vl();
+ header.vl = target->thread.sve_vl;
BUG_ON(!sve_vl_valid(header.vl));
vq = sve_vq_from_vl(header.vl);
@@ -830,7 +830,7 @@ static int sve_set(struct task_struct *target,
if (ret)
goto out;
- if (header.vl != sve_get_vl())
+ if (header.vl != target->thread.sve_vl)
return -EINVAL;
BUG_ON(!sve_vl_valid(header.vl));
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 9ef9953..7615c7d 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -222,8 +222,11 @@ static int preserve_sve_context(struct sve_context __user *ctx)
{
int err = 0;
u16 reserved[ARRAY_SIZE(ctx->__reserved)];
- unsigned int vl = sve_get_vl();
- unsigned int vq = sve_vq_from_vl(vl);
+ unsigned int vl = current->thread.sve_vl;
+ unsigned int vq;
+
+ BUG_ON(!sve_vl_valid(vl));
+ vq = sve_vq_from_vl(vl);
memset(reserved, 0, sizeof(reserved));
@@ -253,7 +256,7 @@ static int __restore_sve_fpsimd_context(struct user_ctxs *user,
__task_sve_state(current);
struct fpsimd_state fpsimd;
- if (vl != sve_get_vl())
+ if (vl != current->thread.sve_vl)
return -EINVAL;
set_thread_flag(TIF_FOREIGN_FPSTATE);
@@ -543,7 +546,11 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user)
}
if (IS_ENABLED(CONFIG_ARM64_SVE) && test_thread_flag(TIF_SVE)) {
- unsigned int vq = sve_vq_from_vl(sve_get_vl());
+ unsigned int vl = current->thread.sve_vl;
+ unsigned int vq;
+
+ BUG_ON(!sve_vl_valid(vl));
+ vq = sve_vq_from_vl(vl);
BUG_ON(!(elf_hwcap & HWCAP_SVE));
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 03/10] arm64/sve: Set CPU vector length to match current task
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
This patch adds the necessary code to configure the CPU for the
task's vector length, whenever SVE state is loaded for a task.
No special action is needed on sched-out: only user tasks with SVE
state care what the CPU's VL is set to.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/include/asm/fpsimd.h | 3 ++-
arch/arm64/include/asm/fpsimdmacros.h | 7 ++++++-
arch/arm64/kernel/entry-fpsimd.S | 2 +-
arch/arm64/kernel/fpsimd.c | 10 +++++++---
4 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index e13259e..22d09c0 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -100,7 +100,8 @@ extern void __init fpsimd_init_task_struct_size(void);
extern void *__task_sve_state(struct task_struct *task);
extern void sve_save_state(void *state, u32 *pfpsr);
-extern void sve_load_state(void const *state, u32 const *pfpsr);
+extern void sve_load_state(void const *state, u32 const *pfpsr,
+ unsigned long vq_minus_1);
extern unsigned int sve_get_vl(void);
/*
diff --git a/arch/arm64/include/asm/fpsimdmacros.h b/arch/arm64/include/asm/fpsimdmacros.h
index e2bb032..7b53bc1 100644
--- a/arch/arm64/include/asm/fpsimdmacros.h
+++ b/arch/arm64/include/asm/fpsimdmacros.h
@@ -254,7 +254,12 @@
.purgem savep
.endm
-.macro sve_load nb, xpfpsr, ntmp
+.macro sve_load nb, xpfpsr, xvqminus1 ntmp
+ mrs_s x\ntmp, ZCR_EL1
+ bic x\ntmp, x\ntmp, ZCR_EL1_LEN_MASK
+ orr x\ntmp, x\ntmp, \xvqminus1
+ msr_s ZCR_EL1, x\ntmp // self-synchronising
+
.macro loadz n
_zldrv \n, \nb, (\n) - 34
.endm
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
index 5dcec55..0a3fdcb 100644
--- a/arch/arm64/kernel/entry-fpsimd.S
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -73,7 +73,7 @@ ENTRY(sve_save_state)
ENDPROC(sve_save_state)
ENTRY(sve_load_state)
- sve_load 0, x1, 2
+ sve_load 0, x1, x2, 3
ret
ENDPROC(sve_load_state)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 6065707..ab2bb62 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -175,10 +175,14 @@ extern void *__task_pffr(struct task_struct *task);
static void task_fpsimd_load(struct task_struct *task)
{
if (IS_ENABLED(CONFIG_ARM64_SVE) &&
- test_tsk_thread_flag(task, TIF_SVE))
+ test_tsk_thread_flag(task, TIF_SVE)) {
+ unsigned int vl = task->thread.sve_vl;
+
+ BUG_ON(!sve_vl_valid(vl));
sve_load_state(__task_pffr(task),
- &task->thread.fpsimd_state.fpsr);
- else
+ &task->thread.fpsimd_state.fpsr,
+ sve_vq_from_vl(vl) - 1);
+ } else
fpsimd_load_state(&task->thread.fpsimd_state);
/*
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 04/10] arm64/sve: Factor out clearing of tasks' SVE regs
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
The patch factors out the code that clears a task's SVE regs on
exec(), so that we can reuse it in subsequent patches.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/kernel/fpsimd.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index ab2bb62..54d7ed0 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -260,6 +260,19 @@ void fpsimd_thread_switch(struct task_struct *next)
}
}
+static void clear_sve_regs(struct task_struct *task)
+{
+ BUG_ON(task == current && preemptible());
+
+ BUG_ON((char *)__task_sve_state(task) < (char *)task);
+ BUG_ON(arch_task_struct_size <
+ ((char *)__task_sve_state(task) - (char *)task));
+
+ memset(__task_sve_state(task), 0,
+ arch_task_struct_size -
+ ((char *)__task_sve_state(task) - (char *)task));
+}
+
void fpsimd_flush_thread(void)
{
if (!system_supports_fpsimd())
@@ -272,13 +285,7 @@ void fpsimd_flush_thread(void)
memset(¤t->thread.fpsimd_state, 0, sizeof(struct fpsimd_state));
if (IS_ENABLED(CONFIG_ARM64_SVE) && (elf_hwcap & HWCAP_SVE)) {
- BUG_ON((char *)__task_sve_state(current) < (char *)current);
- BUG_ON(arch_task_struct_size <
- ((char *)__task_sve_state(current) - (char *)current));
-
- memset(__task_sve_state(current), 0,
- arch_task_struct_size -
- ((char *)__task_sve_state(current) - (char *)current));
+ clear_sve_regs(current);
/*
* User tasks must have a valid vector length set, but tasks
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 05/10] arm64/sve: Wire up vector length control prctl() calls
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
This patch provides implementation for the PR_SVE_SET_VL and
PR_SVE_GET_VL prctls, which allow a task to set and query its
vector length and associated control flags (although no flags are
defined in this patch).
Currently any thread can set its VL, allowing a mix of VLs within
a single process -- this behaviour will be refined in susequent
patches.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/include/asm/fpsimd.h | 2 ++
arch/arm64/kernel/fpsimd.c | 65 +++++++++++++++++++++++++++++++++++++++--
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 22d09c0..1ec2363 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -103,6 +103,8 @@ extern void sve_save_state(void *state, u32 *pfpsr);
extern void sve_load_state(void const *state, u32 const *pfpsr,
unsigned long vq_minus_1);
extern unsigned int sve_get_vl(void);
+extern int sve_set_vector_length(struct task_struct *task,
+ unsigned long vl, unsigned long flags);
/*
* FPSIMD/SVE synchronisation helpers for ptrace:
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 54d7ed0..5f2c24a 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -493,17 +493,78 @@ void fpsimd_sync_from_fpsimd_zeropad(struct task_struct *task)
__fpsimd_sync_from_fpsimd_zeropad(task, sve_vq_from_vl(vl));
}
+int sve_set_vector_length(struct task_struct *task,
+ unsigned long vl, unsigned long flags)
+{
+ BUG_ON(task == current && preemptible());
+
+ if (flags)
+ return -EINVAL; /* No flags defined yet */
+
+ if (!sve_vl_valid(vl))
+ return -EINVAL;
+
+ if (vl > sve_max_vl) {
+ BUG_ON(!sve_vl_valid(sve_max_vl));
+ vl = sve_max_vl;
+ }
+
+ /*
+ * To ensure the FPSIMD bits of the SVE vector registers are preserved,
+ * write any live register state back to task_struct, and convert to a
+ * non-SVE thread.
+ */
+ if (vl != task->thread.sve_vl) {
+ if (task == current &&
+ !test_and_set_thread_flag(TIF_FOREIGN_FPSTATE))
+ task_fpsimd_save(current);
+
+ if (test_and_clear_tsk_thread_flag(task, TIF_SVE))
+ task_sve_to_fpsimd(task);
+
+ /*
+ * To avoid surprises, also zero out the SVE regs storage.
+ * This means that the P-regs, FFR and high bits of Z-regs
+ * will read as zero on next access:
+ */
+ clear_sve_regs(task);
+ }
+
+ task->thread.sve_vl = vl;
+
+ fpsimd_flush_task_state(task);
+
+ return 0;
+}
+
/* PR_SVE_SET_VL */
int sve_set_task_vl(struct task_struct *task,
unsigned long vector_length, unsigned long flags)
{
- return -EINVAL;
+ int ret;
+
+ if (!(elf_hwcap & HWCAP_SVE))
+ return -EINVAL;
+
+ BUG_ON(task != current);
+
+ preempt_disable();
+ ret = sve_set_vector_length(current, vector_length, flags);
+ preempt_enable();
+
+ if (ret)
+ return ret;
+
+ return task->thread.sve_vl;
}
/* PR_SVE_GET_VL */
int sve_get_task_vl(struct task_struct *task)
{
- return -EINVAL;
+ if (!(elf_hwcap & HWCAP_SVE))
+ return -EINVAL;
+
+ return task->thread.sve_vl;
}
#endif /* CONFIG_ARM64_SVE */
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 06/10] arm64/sve: Disallow VL setting for individual threads by default
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
General-purpose code in userspace is not expected to work correctly
if multiple threads are allowed to run concurrently with different
vector lengths in a single process.
This patch adds an explicit flag PR_SVE_SET_VL_THREAD to request
this behaviour. Without the flag, vector length setting is
permitted only for a single-threaded process (which matches the
expected usage model of setting the vector length at process
startup).
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/kernel/fpsimd.c | 12 +++++++++++-
include/uapi/linux/prctl.h | 1 +
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 5f2c24a..32caca3 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -21,6 +21,7 @@
#include <linux/cpu_pm.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/prctl.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/hardirq.h>
@@ -498,8 +499,17 @@ int sve_set_vector_length(struct task_struct *task,
{
BUG_ON(task == current && preemptible());
+ /*
+ * To avoid accidents, forbid setting for individual threads of a
+ * multithreaded process. User code that knows what it's doing can
+ * pass PR_SVE_SET_VL_THREAD to override this restriction:
+ */
+ if (!(flags & PR_SVE_SET_VL_THREAD) && get_nr_threads(task) != 1)
+ return -EINVAL;
+
+ flags &= ~(unsigned long)PR_SVE_SET_VL_THREAD;
if (flags)
- return -EINVAL; /* No flags defined yet */
+ return -EINVAL; /* No other flags defined yet */
if (!sve_vl_valid(vl))
return -EINVAL;
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index e32e2da..c55530b 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -199,6 +199,7 @@ struct prctl_mm_map {
/* arm64 Scalable Vector Extension controls */
#define PR_SVE_SET_VL 48 /* set task vector length */
+# define PR_SVE_SET_VL_THREAD (1 << 1) /* set just this thread */
#define PR_SVE_GET_VL 49 /* get task vector length */
#endif /* _LINUX_PRCTL_H */
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 07/10] arm64/sve: Add vector length inheritance control
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
Currently the vector length is inherited across both fork() and
exec().
Inheritance across fork() is desirable both for creating a copy of
a process (traditional fork) or creating a thread (where we want
all threads to share the same VL by default).
Inheritance across exec() is less desirable, because of the ABI
impact of large vector lengths on the size of the signal frame --
when running a new binary, there is no guarantee that the new
binary is compatible with these ABI changes.
This flag makes the vector length non-inherited by default.
Instead, the vector length is reset to a system default value,
unless the THREAD_VL_INHERIT flag has been set for the thread.
THREAD_VL_INHERIT is currently sticky: i.e., if set, it gets
inherited too. This behaviour may be refined in future if it is
not flexible enough.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/include/asm/processor.h | 7 +++++++
arch/arm64/kernel/fpsimd.c | 33 ++++++++++++++++++++++++++-------
include/uapi/linux/prctl.h | 5 +++++
3 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 96eada9..45ef11d 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -27,6 +27,7 @@
#ifdef __KERNEL__
+#include <linux/prctl.h>
#include <linux/string.h>
#include <asm/alternative.h>
@@ -84,11 +85,17 @@ struct thread_struct {
#endif
struct fpsimd_state fpsimd_state;
u16 sve_vl; /* SVE vector length */
+ u16 sve_flags; /* SVE related flags */
unsigned long fault_address; /* fault info */
unsigned long fault_code; /* ESR_EL1 value */
struct debug_info debug; /* debugging */
};
+/* Flags for sve_flags (intentionally defined to match the prctl flags) */
+
+/* Inherit sve_vl and sve_flags across execve(): */
+#define THREAD_VL_INHERIT PR_SVE_SET_VL_INHERIT
+
#ifdef CONFIG_COMPAT
#define task_user_tls(t) \
({ \
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 32caca3..f010a1c 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -292,12 +292,15 @@ void fpsimd_flush_thread(void)
* User tasks must have a valid vector length set, but tasks
* forked early (e.g., init) may not have one yet.
* By now, we will know what the hardware supports, so set the
- * task vector length if it doesn't have one:
+ * task vector length to default if doesn't have one, or if
+ * the thread wasn't configured to inherit SVE configuration:
*/
- if (!current->thread.sve_vl) {
+ if (!current->thread.sve_vl ||
+ !(current->thread.sve_flags & THREAD_VL_INHERIT)) {
BUG_ON(!sve_vl_valid(sve_max_vl));
current->thread.sve_vl = sve_max_vl;
+ current->thread.sve_flags = 0;
}
}
@@ -506,10 +509,10 @@ int sve_set_vector_length(struct task_struct *task,
*/
if (!(flags & PR_SVE_SET_VL_THREAD) && get_nr_threads(task) != 1)
return -EINVAL;
-
flags &= ~(unsigned long)PR_SVE_SET_VL_THREAD;
- if (flags)
- return -EINVAL; /* No other flags defined yet */
+
+ if (flags & ~(unsigned long)PR_SVE_SET_VL_INHERIT)
+ return -EINVAL;
if (!sve_vl_valid(vl))
return -EINVAL;
@@ -542,11 +545,27 @@ int sve_set_vector_length(struct task_struct *task,
task->thread.sve_vl = vl;
+ /* The THREAD_VL_* flag encodings match the relevant PR_* flags: */
+ task->thread.sve_flags = flags;
+
fpsimd_flush_task_state(task);
return 0;
}
+/*
+ * Encode the current vector length and flags for return.
+ * This is only required for prctl(): ptrace has separate fields
+ */
+static int sve_prctl_status(struct task_struct const *task)
+{
+ int ret = task->thread.sve_vl;
+
+ ret |= task->thread.sve_vl << 16;
+
+ return ret;
+}
+
/* PR_SVE_SET_VL */
int sve_set_task_vl(struct task_struct *task,
unsigned long vector_length, unsigned long flags)
@@ -565,7 +584,7 @@ int sve_set_task_vl(struct task_struct *task,
if (ret)
return ret;
- return task->thread.sve_vl;
+ return sve_prctl_status(task);
}
/* PR_SVE_GET_VL */
@@ -574,7 +593,7 @@ int sve_get_task_vl(struct task_struct *task)
if (!(elf_hwcap & HWCAP_SVE))
return -EINVAL;
- return task->thread.sve_vl;
+ return sve_prctl_status(task);
}
#endif /* CONFIG_ARM64_SVE */
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index c55530b..cff6214 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -200,6 +200,11 @@ struct prctl_mm_map {
/* arm64 Scalable Vector Extension controls */
#define PR_SVE_SET_VL 48 /* set task vector length */
# define PR_SVE_SET_VL_THREAD (1 << 1) /* set just this thread */
+# define PR_SVE_SET_VL_INHERIT (1 << 2) /* inherit across exec */
#define PR_SVE_GET_VL 49 /* get task vector length */
+/* Decode helpers for the return value from PR_SVE_GET_VL: */
+# define PR_SVE_GET_VL_LEN(ret) ((ret) & 0x3fff) /* vector length */
+# define PR_SVE_GET_VL_INHERIT (PR_SVE_SET_VL_INHERIT << 16)
+/* For conveinence, PR_SVE_SET_VL returns the result in the same encoding */
#endif /* _LINUX_PRCTL_H */
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 08/10] arm64/sve: ptrace: Wire up vector length control and reporting
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
This patch adds support for manipulating a task's vector length at
runtime via ptrace.
As a simplification, we turn the task back into an FPSIMD-only task
when changing the vector length. If the register data is written
too, we then turn the task back into an SVE task, with changed
task_struct layout for the SVE data, before the actual data writing
is done.
Because the vector length is now variable, sve_get() now needs to
return the real maximum for user_sve_header.max_vl, since .vl may
be less than this (that's the whole point).
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
arch/arm64/include/asm/fpsimd.h | 1 +
arch/arm64/include/uapi/asm/ptrace.h | 5 +++++
arch/arm64/kernel/ptrace.c | 25 +++++++++++++++----------
3 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 1ec2363..0f1b068 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -105,6 +105,7 @@ extern void sve_load_state(void const *state, u32 const *pfpsr,
extern unsigned int sve_get_vl(void);
extern int sve_set_vector_length(struct task_struct *task,
unsigned long vl, unsigned long flags);
+extern int sve_max_vl;
/*
* FPSIMD/SVE synchronisation helpers for ptrace:
diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
index 48b57a0..bcb542d 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -64,6 +64,8 @@
#ifndef __ASSEMBLY__
+#include <linux/prctl.h>
+
/*
* User structures for general purpose, floating point and debug registers.
*/
@@ -108,6 +110,9 @@ struct user_sve_header {
#define SVE_PT_REGS_FPSIMD 0
#define SVE_PT_REGS_SVE SVE_PT_REGS_MASK
+#define SVE_PT_VL_THREAD PR_SVE_SET_VL_THREAD
+#define SVE_PT_VL_INHERIT PR_SVE_SET_VL_INHERIT
+
/*
* The remainder of the SVE state follows struct user_sve_header. The
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 32debb8..7e40039 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -741,14 +741,15 @@ static int sve_get(struct task_struct *target,
BUG_ON(!sve_vl_valid(header.vl));
vq = sve_vq_from_vl(header.vl);
- /* Until runtime or per-task vector length changing is supported: */
- header.max_vl = header.vl;
+ BUG_ON(!sve_vl_valid(sve_max_vl));
+ header.max_vl = sve_max_vl;
header.flags = test_tsk_thread_flag(target, TIF_SVE) ?
SVE_PT_REGS_SVE : SVE_PT_REGS_FPSIMD;
header.size = SVE_PT_SIZE(vq, header.flags);
- header.max_size = SVE_PT_SIZE(vq, SVE_PT_REGS_SVE);
+ header.max_size = SVE_PT_SIZE(sve_vq_from_vl(header.max_vl),
+ SVE_PT_REGS_SVE);
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &header,
0, sizeof(header));
@@ -830,14 +831,18 @@ static int sve_set(struct task_struct *target,
if (ret)
goto out;
- if (header.vl != target->thread.sve_vl)
- return -EINVAL;
-
- BUG_ON(!sve_vl_valid(header.vl));
- vq = sve_vq_from_vl(header.vl);
+ /*
+ * Apart from PT_SVE_REGS_MASK, all PT_SVE_* flags are consumed by
+ * sve_set_vector_length(), which will also validate them for us:
+ */
+ ret = sve_set_vector_length(target, header.vl,
+ header.flags & ~SVE_PT_REGS_MASK);
+ if (ret)
+ goto out;
- if (header.flags & ~SVE_PT_REGS_MASK)
- return -EINVAL;
+ /* Actual VL set may be less than the user asked for: */
+ BUG_ON(!sve_vl_valid(target->thread.sve_vl));
+ vq = sve_vq_from_vl(target->thread.sve_vl);
/* Registers: FPSIMD-only case */
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 09/10] arm64/sve: Enable default vector length control via procfs
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
This patch makes the default SVE vector length at exec() for user tasks
controllable via procfs, in /proc/cpu/sve_default_vector_length.
Limited effort is made to return sensible errors when writing the
procfs file, and anyway the value gets silently clamped to the
maximum VL supported by the platform: users should close and reopen
the file and read back to see the result.
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
Caveats:
* /proc may not be the correct place for this (but it's not clear
where in sysfs it should go either, and it's a global control with
no corresponding kobject)
* There seems to be no suitable framework for writable controls of
this sort in /proc (unlike debugfs or sysfs). So, I had to write a
suspiciously large amount of code -- I may have missed an obvious
trick :P
arch/arm64/kernel/fpsimd.c | 160 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 158 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index f010a1c..3c0e08c 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -22,8 +22,12 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/prctl.h>
+#include <linux/proc_fs.h>
#include <linux/sched.h>
+#include <linux/seq_file.h>
#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <linux/hardirq.h>
#include <asm/fpsimd.h>
@@ -102,9 +106,132 @@ void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
/* Maximum supported vector length across all CPUs (initially poisoned) */
int sve_max_vl = -1;
+/* Default VL for tasks that don't set it explicitly: */
+int sve_default_vl = -1;
#ifdef CONFIG_ARM64_SVE
+#ifdef CONFIG_PROC_FS
+
+struct default_vl_write_state {
+ bool invalid;
+ size_t len;
+ char buf[40]; /* enough for "0x" + 64-bit hex integer + NUL */
+};
+
+static int sve_default_vl_show(struct seq_file *s, void *data)
+{
+ seq_printf(s, "%d\n", sve_default_vl);
+ return 0;
+}
+
+static ssize_t sve_default_vl_write(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ struct default_vl_write_state *state =
+ ((struct seq_file *)f->private_data)->private;
+ long ret;
+
+ if (!size)
+ return 0;
+
+ if (*pos > sizeof(state->buf) ||
+ size >= sizeof(state->buf) - *pos) {
+ ret = -ENOSPC;
+ goto error;
+ }
+
+ ret = copy_from_user(state->buf + *pos, buf, size);
+ if (ret > 0)
+ ret = -EINVAL;
+ if (ret)
+ goto error;
+
+ *pos += size;
+ if (*pos > state->len)
+ state->len = *pos;
+
+ return size;
+
+error:
+ state->invalid = true;
+ return ret;
+}
+
+static int sve_default_vl_release(struct inode *i, struct file *f)
+{
+ int ret = 0;
+ int t;
+ unsigned long value;
+ struct default_vl_write_state *state =
+ ((struct seq_file *)f->private_data)->private;
+
+ if (!(f->f_mode & FMODE_WRITE))
+ goto out;
+
+ if (state->invalid)
+ goto out;
+
+ if (state->len >= sizeof(state->buf)) {
+ WARN_ON(1);
+ state->len = sizeof(state->buf) - 1;
+ }
+
+ state->buf[state->len] = '\0';
+ t = kstrtoul(state->buf, 0, &value);
+ if (t)
+ ret = t;
+
+ if (!sve_vl_valid(value))
+ ret = -EINVAL;
+
+ if (!sve_vl_valid(sve_max_vl)) {
+ WARN_ON(1);
+ ret = -EINVAL;
+ }
+
+ if (value > sve_max_vl)
+ value = sve_max_vl;
+
+ if (!ret)
+ sve_default_vl = value;
+
+out:
+ t = seq_release_private(i, f);
+ return ret ? ret : t;
+}
+
+static int sve_default_vl_open(struct inode *i, struct file *f)
+{
+ struct default_vl_write_state *data = NULL;
+ int ret;
+
+ if (f->f_mode & FMODE_WRITE) {
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->invalid = false;
+ data->len = 0;
+ }
+
+ ret = single_open(f, sve_default_vl_show, data);
+ if (ret)
+ kfree(data);
+
+ return ret;
+}
+
+static const struct file_operations sve_default_vl_fops = {
+ .open = sve_default_vl_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = sve_default_vl_release,
+ .write = sve_default_vl_write,
+};
+
+#endif /* !CONFIG_PROC_FS */
+
static void task_fpsimd_to_sve(struct task_struct *task);
static void task_fpsimd_load(struct task_struct *task);
static void task_fpsimd_save(struct task_struct *task);
@@ -299,7 +426,7 @@ void fpsimd_flush_thread(void)
!(current->thread.sve_flags & THREAD_VL_INHERIT)) {
BUG_ON(!sve_vl_valid(sve_max_vl));
- current->thread.sve_vl = sve_max_vl;
+ current->thread.sve_vl = sve_default_vl;
current->thread.sve_flags = 0;
}
}
@@ -723,6 +850,14 @@ void __init fpsimd_init_task_struct_size(void)
& 0xf) == 1) {
/* FIXME: This should be the minimum across all CPUs */
sve_max_vl = sve_get_vl();
+ sve_default_vl = sve_max_vl;
+
+ /*
+ * To avoid enlarging the signal frame by default, clamp to
+ * 512 bits until/unless overridden by userspace:
+ */
+ if (sve_default_vl > 512 / 8)
+ sve_default_vl = 512 / 8;
arch_task_struct_size = sizeof(struct task_struct) +
35 * sve_max_vl;
@@ -734,6 +869,27 @@ void __init fpsimd_init_task_struct_size(void)
/*
* FP/SIMD support code initialisation.
*/
+static int __init sve_procfs_init(void)
+{
+#if defined(CONFIG_ARM64_SVE) && defined(CONFIG_PROC_FS)
+ struct proc_dir_entry *dir;
+
+ if (!(elf_hwcap & HWCAP_SVE))
+ return 0;
+
+ /* This should be moved elsewhere is anything else ever uses it: */
+ dir = proc_mkdir("cpu", NULL);
+ if (!dir)
+ return -ENOMEM;
+
+ if (!proc_create("sve_default_vector_length",
+ S_IRUGO | S_IWUSR, dir, &sve_default_vl_fops))
+ return -ENOMEM;
+#endif
+
+ return 0;
+}
+
static int __init fpsimd_init(void)
{
if (elf_hwcap & HWCAP_FP) {
@@ -749,6 +905,6 @@ static int __init fpsimd_init(void)
if (!(elf_hwcap & HWCAP_SVE))
pr_info("Scalable Vector Extension available\n");
- return 0;
+ return sve_procfs_init();
}
late_initcall(fpsimd_init);
--
2.1.4
^ permalink raw reply related
* [RFC PATCH 10/10] Revert "arm64/sve: Limit vector length to 512 bits by default"
From: Dave Martin @ 2017-01-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484220369-23970-1-git-send-email-Dave.Martin@arm.com>
This reverts commit cdedb254ccddd9c6a8db91b3737690327e48dfe7.
Vector length limiting via Kconfig is no longer required now that
the default vector length can be manipulated at runtime via procfs.
---
arch/arm64/Kconfig | 35 -----------------------------------
arch/arm64/mm/proc.S | 5 -----
2 files changed, 40 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 98c0934..bced568 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -900,41 +900,6 @@ config ARM64_SVE
To enable use of this extension on CPUs that implement it, say Y.
-if ARM64_SVE
-
-config ARM64_SVE_FULL_VECTOR_LENGTH
- bool "Enable full hardware vector length for userspace"
- default n
- help
- SVE vector lengths greater than 512 bits impact the size of signal
- frames and therefore the size requirements for any userspace stack
- onto which a signal may be delivered. Using larger vector lengths
- may therefore cause problems for some software. For this reason, the
- kernel currently limits the maximum vector length for userspace
- software to 512 bits by default.
-
- Enabling this option removes the limit, so that the full vector
- length implemented by the hardware is made available to userspace.
-
- Be aware: in general, software that (a) does not use SVE (including
- via libraries), or (b) does not handle signals, or (c) uses default
- process/thread stack sizes and does not use sigaltstack(2) should be
- unaffected by enabling larger vectors. Software that does not meet
- these criteria or that relies on certain legacy uses of the ucontext
- API may be affected however.
-
- This is a transitional compatibility option only and will be replaced
- by a userspace ABI extension in the future. Do not assume that this
- option will be available with compatible effect in future Linux
- releases.
-
- If you are developing software that uses SVE and understand the
- implications, you can consider saying Y here.
-
- If unsure, say N.
-
-endif
-
config ARM64_MODULE_CMODEL_LARGE
bool
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index da2d602..aa96b4c 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -200,11 +200,6 @@ ENTRY(__cpu_setup)
mrs_s x5, ZIDR_EL1 // SVE: Enable full vector len
and x5, x5, #ZCR_EL1_LEN_MASK // initially
-#ifndef CONFIG_ARM64_SVE_FULL_VECTOR_LENGTH
- mov x6, #(512 / 128 - 1) // Clamp VL to 512 bits
- cmp x5, x6
- csel x5, x5, x6, lo
-#endif
msr_s ZCR_EL1, x5
b 2f
--
2.1.4
^ permalink raw reply related
* [PATCH] rtc: armada38x: hide maybe-uninitialized warning
From: Alexandre Belloni @ 2017-01-12 11:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170111145112.722743-1-arnd@arndb.de>
Hi Arnd,
On 11/01/2017 at 15:50:31 +0100, Arnd Bergmann wrote :
> The function is too complicated for gcc to realize that this variable
> does eventually get initialized, causing a harmless warning:
>
> drivers/rtc/rtc-armada38x.c: In function 'read_rtc_register_wa':
> drivers/rtc/rtc-armada38x.c:131:25: warning: 'index_max' may be used uninitialized in this function [-Wmaybe-uninitialized]
>
> This adds an explicit initializion at the start of the function.
> I generally try to avoid that, but it seems appropriate here,
> as we start out with max=0 as well.
>
> Fixes: 61cffa2438e3 ("rtc: armada38x: Follow the new recommendation for errata implementation")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Actually, I fixed that one directly in the commit yesterday as it has
been reported to me multiple times already.
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [RFC PATCH 09/10] drivers/perf: Add support for ARMv8.2 Statistical Profiling Extension
From: Marc Zyngier @ 2017-01-12 11:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170110160419.4cc3d61c9d652e5d5da13f15@arm.com>
On 10/01/17 22:04, Kim Phillips wrote:
> On Tue, 3 Jan 2017 18:10:26 +0000
> Will Deacon <will.deacon@arm.com> wrote:
>
>> +#define DRVNAME "arm_spe_pmu"
>
> Based on Intel naming "intel_pt" and "intel_bts', I had expected
> "arm-spe" as the universal basename for SPE. I don't really care about
> whether '_pmu' is included, but it's yet another naming inconsistency we
> have with coresight's "cs_etm" (the other being prefixed with "arm_").
>
> Also, nit, since I don't know why perf userspace tools can't handle
> dashes in PMU names (commit 3d1ff755e367 "arm: perf: clean up PMU
> names" doesn't say), can we at least start to use dashes in our
> filenames? arm-spe-pmu.c is easier to type than arm_spe_pmu.c.
Fortunately, not everyone is using a UK/US keyboard... ;-)
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH] rtc: armada38x: avoid unused-function warning
From: Alexandre Belloni @ 2017-01-12 11:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170112111321.3219446-1-arnd@arndb.de>
Hi,
On 12/01/2017 at 12:13:08 +0100, Arnd Bergmann wrote :
> When CONFIG_PM_SLEEP is not set, rtc_update_mbus_timing_params becomes
> unused, now that armada38x_rtc_probe() no longer calls
> rtc_update_mbus_timing_params on startup:
>
> drivers/rtc/rtc-armada38x.c:79:13: error: 'rtc_update_mbus_timing_params' defined but not used [-Werror=unused-function]
>
> This addresses the warning by marking the PM functions as __maybe_unused,
> so the unused functions get silently dropped. I could not tell from
> the changelog if dropping the call to armada38x_rtc_probe() was
> intended here, and if that is the correct thing to do without
> CONFIG_PM_SLEEP, so we might need a different fix that brings it back.
>
Thanks for the report, Russell's patch didn't apply cleanly and it seems
I messed up when applying. I've just restored the
rtc_update_mbus_timing_params() call in probe as this should be.
Thanks again and sorry about this.
> Fixes: 4c492eb022c2 ("rtc: armada38x: make struct rtc_class_ops const")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/rtc/rtc-armada38x.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
> index 4f75c619bbba..2e451acccd9c 100644
> --- a/drivers/rtc/rtc-armada38x.c
> +++ b/drivers/rtc/rtc-armada38x.c
> @@ -338,8 +338,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
> return 0;
> }
>
> -#ifdef CONFIG_PM_SLEEP
> -static int armada38x_rtc_suspend(struct device *dev)
> +static int __maybe_unused armada38x_rtc_suspend(struct device *dev)
> {
> if (device_may_wakeup(dev)) {
> struct armada38x_rtc *rtc = dev_get_drvdata(dev);
> @@ -350,7 +349,7 @@ static int armada38x_rtc_suspend(struct device *dev)
> return 0;
> }
>
> -static int armada38x_rtc_resume(struct device *dev)
> +static int __maybe_unused armada38x_rtc_resume(struct device *dev)
> {
> if (device_may_wakeup(dev)) {
> struct armada38x_rtc *rtc = dev_get_drvdata(dev);
> @@ -363,7 +362,6 @@ static int armada38x_rtc_resume(struct device *dev)
>
> return 0;
> }
> -#endif
>
> static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
> armada38x_rtc_suspend, armada38x_rtc_resume);
> --
> 2.9.0
>
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH 16/62] watchdog: digicolor_wdt: Convert to use device managed functions and other improvements
From: Baruch Siach @ 2017-01-12 11:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1484091325-9199-17-git-send-email-linux@roeck-us.net>
Hi Guenter,
On Tue, Jan 10, 2017 at 03:34:33PM -0800, Guenter Roeck wrote:
> Use device managed functions to simplify error handling, reduce
> source code size, improve readability, and reduce the likelyhood of bugs.
> Other improvements as listed below.
>
> The conversion was done automatically with coccinelle using the
> following semantic patches. The semantic patches and the scripts used
> to generate this commit log are available at
> https://github.com/groeck/coccinelle-patches
>
> - Replace 'goto l; ... l: return e;' with 'return e;'
> - Replace 'val = e; return val;' with 'return e;'
> - Drop assignments to otherwise unused variables
> - Replace 'if (e) { return expr; }' with 'if (e) return expr;'
> - Drop remove function
> - Replace of_iomap() with platform_get_resource() followed by
> devm_ioremap_resource()
> - Drop platform_set_drvdata()
> - Replace &pdev->dev with dev if 'struct device *dev' is a declared
> variable
> - Use devm_watchdog_register_driver() to register watchdog device
> - Replace shutdown function with call to watchdog_stop_on_reboot()
>
> Cc: Baruch Siach <baruch@tkos.co.il>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Baruch Siach <baruch@tkos.co.il>
Tested-by: Baruch Siach <baruch@tkos.co.il>
Thanks,
baruch
--
http://baruch.siach.name/blog/ ~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch at tkos.co.il - tel: +972.52.368.4656, http://www.tkos.co.il -
^ permalink raw reply
* NVMe vs DMA addressing limitations
From: Arnd Bergmann @ 2017-01-12 11:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <80676b35-121b-0462-23fc-ed5608e1e671@grimberg.me>
On Thursday, January 12, 2017 12:09:11 PM CET Sagi Grimberg wrote:
> >> Another workaround me might need is to limit amount of concurrent DMA
> >> in the NVMe driver based on some platform quirk. The way that NVMe works,
> >> it can have very large amounts of data that is concurrently mapped into
> >> the device.
> >
> > That's not really just NVMe - other storage and network controllers also
> > can DMA map giant amounts of memory. There are a couple aspects to it:
> >
> > - dma coherent memoery - right now NVMe doesn't use too much of it,
> > but upcoming low-end NVMe controllers will soon start to require
> > fairl large amounts of it for the host memory buffer feature that
> > allows for DRAM-less controller designs. As an interesting quirk
> > that is memory only used by the PCIe devices, and never accessed
> > by the Linux host at all.
>
> Would it make sense to convert the nvme driver to use normal allocations
> and use the DMA streaming APIs (dma_sync_single_for_[cpu|device]) for
> both queues and future HMB?
That is an interesting question: We actually have the
"DMA_ATTR_NO_KERNEL_MAPPING" for this case, and ARM implements
it in the coherent interface, so that might be a good fit.
Implementing it in the streaming API makes no sense since we
already have a kernel mapping here, but using a normal allocation
(possibly with DMA_ATTR_NON_CONSISTENT or DMA_ATTR_SKIP_CPU_SYNC,
need to check) might help on other architectures that have
limited amounts of coherent memory and no CMA.
Another benefit of the coherent API for this kind of buffer is
that we can use CMA where available to get a large consecutive
chunk of RAM on architectures without an IOMMU when normal
memory is no longer available because of fragmentation.
Arnd
^ 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