* [PATCH v2 00/10] Add basic support for Rockchip RK1108 SOC
From: Andy Yan @ 2016-11-14 11:55 UTC (permalink / raw)
To: linux-arm-kernel
RK1108 is embedded with an ARM Cortex-A7 single core and a DSP core.
It is designed for varies application scenario such as car DVR, sports
DV, secure camera and UAV camera.
This patch series add basic support for it, which can boot a board with
initramfs into shell.
More new feathers will come soon.
Changes in v2:
- split dt-binding header from clk driver
- fix some CodingStyle issues
- add dt-binding documentation for pinctrl
- add pull and drive-strength functionality for pinctrl
- fix timer and gic dt description
- ordering devices by register address
- move the board in the rockchip.txt to the block of Rockchip boards
Andy Yan (6):
dt-bindings: add documentation for rk1108 pinctrl
pinctrl: rockchip: add support for rk1108
ARM: add low level debug uart for rk1108
ARM: dts: add basic support for Rockchip RK1108 SOC
ARM: rockchip: enable support for RK1108 SoC
ARM: dts: rockchip: add rockchip RK1108 Evaluation board
Shawn Lin (4):
dt-bindings: rockchip-dw-mshc: add RK1108 dw-mshc description
dt-bindings: add documentation for rk1108 cru
clk: rockchip: add dt-binding header for rk1108
clk: rockchip: add clock controller for rk1108
Documentation/devicetree/bindings/arm/rockchip.txt | 5 +-
.../bindings/clock/rockchip,rk1108-cru.txt | 60 +++
.../devicetree/bindings/mmc/rockchip-dw-mshc.txt | 1 +
.../bindings/pinctrl/rockchip,pinctrl.txt | 9 +-
arch/arm/Kconfig.debug | 30 ++
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/rk1108-evb.dts | 69 ++++
arch/arm/boot/dts/rk1108.dtsi | 428 +++++++++++++++++++
arch/arm/mach-rockchip/rockchip.c | 1 +
drivers/clk/rockchip/Makefile | 1 +
drivers/clk/rockchip/clk-rk1108.c | 451 +++++++++++++++++++++
drivers/clk/rockchip/clk.h | 14 +
drivers/pinctrl/pinctrl-rockchip.c | 87 +++-
include/dt-bindings/clock/rk1108-cru.h | 270 ++++++++++++
14 files changed, 1421 insertions(+), 6 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
create mode 100644 arch/arm/boot/dts/rk1108-evb.dts
create mode 100644 arch/arm/boot/dts/rk1108.dtsi
create mode 100644 drivers/clk/rockchip/clk-rk1108.c
create mode 100644 include/dt-bindings/clock/rk1108-cru.h
--
2.7.4
^ permalink raw reply
* [PATCH] dma-buf: Use fence_get_rcu_safe() for retrieving the exclusive fence
From: Chris Wilson @ 2016-11-14 11:55 UTC (permalink / raw)
To: dri-devel; +Cc: intel-gfx, Sumit Semwal
The current code is subject to a race where we may try to acquire a
reference on a stale fence:
[13703.335118] WARNING: CPU: 1 PID: 14975 at ./include/linux/kref.h:46 i915_gem_object_wait+0x1a3/0x1c0
[13703.335184] Modules linked in:
[13703.335202] CPU: 1 PID: 14975 Comm: gem_concurrent_ Not tainted 4.9.0-rc4+ #26
[13703.335216] Hardware name: / , BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015
[13703.335233] ffffc90002f5bcc8 ffffffff812807de 0000000000000000 0000000000000000
[13703.335257] ffffc90002f5bd08 ffffffff81073811 0000002e80000000 ffff88026bf7c780
[13703.335279] 7fffffffffffffff 0000000000000001 ffff88027045a550 ffff88026bf7c780
[13703.335301] Call Trace:
[13703.335316] [<ffffffff812807de>] dump_stack+0x4d/0x6f
[13703.335331] [<ffffffff81073811>] __warn+0xc1/0xe0
[13703.335343] [<ffffffff810738e8>] warn_slowpath_null+0x18/0x20
[13703.335355] [<ffffffff813ac443>] i915_gem_object_wait+0x1a3/0x1c0
[13703.335367] [<ffffffff813ae8ec>] i915_gem_set_domain_ioctl+0xcc/0x330
[13703.335386] [<ffffffff813534ab>] drm_ioctl+0x1cb/0x410
[13703.335400] [<ffffffff813ae820>] ? i915_gem_obj_prepare_shmem_write+0x1d0/0x1d0
[13703.335416] [<ffffffff8135359b>] ? drm_ioctl+0x2bb/0x410
[13703.335429] [<ffffffff8117d32f>] do_vfs_ioctl+0x8f/0x5c0
[13703.335442] [<ffffffff8117d89c>] SyS_ioctl+0x3c/0x70
[13703.335456] [<ffffffff815a07a4>] entry_SYSCALL_64_fastpath+0x17/0x98
[13703.335558] ---[ end trace fd24176416ba6981 ]---
[13703.382778] general protection fault: 0000 [#1] SMP
[13703.382802] Modules linked in:
[13703.382816] CPU: 1 PID: 14967 Comm: gem_concurrent_ Tainted: G W 4.9.0-rc4+ #26
[13703.382828] Hardware name: / , BIOS PYBSWCEL.86A.0027.2015.0507.1758 05/07/2015
[13703.382841] task: ffff880275458000 task.stack: ffffc90002f18000
[13703.382849] RIP: 0010:[<ffffffff813b3534>] [<ffffffff813b3534>] i915_gem_request_retire+0x2b4/0x320
[13703.382870] RSP: 0018:ffffc90002f1bbc8 EFLAGS: 00010293
[13703.382878] RAX: dead000000000200 RBX: ffff88026bf7dce8 RCX: dead000000000100
[13703.382887] RDX: dead000000000100 RSI: ffff88026bf7c930 RDI: ffff88026bf7dd00
[13703.382897] RBP: ffffc90002f1bbf8 R08: 00000000ffffffff R09: ffff88026b89a000
[13703.382905] R10: 0000000000000001 R11: ffff88026bbe8fe0 R12: ffff88026bf7c000
[13703.382913] R13: ffff880275af8000 R14: ffff88026bf7c180 R15: dead000000000200
[13703.382922] FS: 00007f89e787d740(0000) GS:ffff88027fd00000(0000) knlGS:0000000000000000
[13703.382934] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[13703.382942] CR2: 00007f9053d2e000 CR3: 000000026d414000 CR4: 00000000001006e0
[13703.382951] Stack:
[13703.382958] ffff880275413000 ffffc90002f1bde8 ffff880275af8000 ffff880274e8a600
[13703.382976] ffff880276a06000 ffffc90002f1bde8 ffffc90002f1bc38 ffffffff813b48c5
[13703.382995] ffffc90002f1bc00 ffffc90002f1bde8 ffff88026972a440 0000000000000000
[13703.383021] Call Trace:
[13703.383032] [<ffffffff813b48c5>] i915_gem_request_alloc+0xa5/0x350
[13703.383043] [<ffffffff813a17c3>] i915_gem_do_execbuffer.isra.41+0x7b3/0x18b0
[13703.383055] [<ffffffff813b144c>] ? i915_gem_object_get_sg+0x25c/0x2b0
[13703.383065] [<ffffffff813b1d4d>] ? i915_gem_object_get_page+0x1d/0x50
[13703.383076] [<ffffffff813b28cc>] ? i915_gem_pwrite_ioctl+0x66c/0x6d0
[13703.383086] [<ffffffff813a2c25>] i915_gem_execbuffer2+0x95/0x1e0
[13703.383096] [<ffffffff813534ab>] drm_ioctl+0x1cb/0x410
[13703.383105] [<ffffffff813a2b90>] ? i915_gem_execbuffer+0x2d0/0x2d0
[13703.383117] [<ffffffff810c3df0>] ? hrtimer_start_range_ns+0x1a0/0x310
[13703.383128] [<ffffffff8117d32f>] do_vfs_ioctl+0x8f/0x5c0
[13703.383140] [<ffffffff810c60e8>] ? SyS_timer_settime+0x118/0x1a0
[13703.383150] [<ffffffff8117d89c>] SyS_ioctl+0x3c/0x70
[13703.383162] [<ffffffff815a07a4>] entry_SYSCALL_64_fastpath+0x17/0x98
[13703.383172] Code: 49 39 c6 48 8d 70 e8 48 8d 5f e8 75 16 eb 47 48 8d 43 18 48 8b 53 18 48 89 de 49 39 c6 48 8d 5a e8 74 33 48 8b 56 08 48 8b 46 10 <48> 89 42 08 48 89 10 f6 46 38 01 48 89 4e 08 4c 89 7e 10 74 cf
[13703.383557] RIP [<ffffffff813b3534>] i915_gem_request_retire+0x2b4/0x320
[13703.383570] RSP <ffffc90002f1bbc8>
[13703.383586] ---[ end trace fd24176416ba6982 ]---
This is fixed by using the kref_get_unless_zero() as a full memory
barrier to validate the fence is still the current exclusive fence before
returning it back to the caller. (Note the fix only requires using
dma_fence_get_rcu() and correct handling, but we may as well use the
helper rather than inline equivalent code.)
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Sumit Semwal <sumit.semwal@linaro.org
---
include/linux/reservation.h | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)
diff --git a/include/linux/reservation.h b/include/linux/reservation.h
index 2e313cca08f0..d9706a6f5ae2 100644
--- a/include/linux/reservation.h
+++ b/include/linux/reservation.h
@@ -177,17 +177,14 @@ static inline struct dma_fence *
reservation_object_get_excl_rcu(struct reservation_object *obj)
{
struct dma_fence *fence;
- unsigned seq;
-retry:
- seq = read_seqcount_begin(&obj->seq);
+
+ if (!rcu_access_pointer(obj->fence_excl))
+ return NULL;
+
rcu_read_lock();
- fence = rcu_dereference(obj->fence_excl);
- if (read_seqcount_retry(&obj->seq, seq)) {
- rcu_read_unlock();
- goto retry;
- }
- fence = dma_fence_get(fence);
+ fence = dma_fence_get_rcu_safe(&obj->fence_excl);
rcu_read_unlock();
+
return fence;
}
--
2.10.2
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related
* Re: [Qemu-devel] virsh dump (qemu guest memory dump?): KASLR enabled linux guest support
From: Paolo Bonzini @ 2016-11-14 11:55 UTC (permalink / raw)
To: Daniel P. Berrange
Cc: Dave Young, Andrew Jones, bhe, qemu-devel, qiaonuohan, anderson,
Laszlo Ersek
In-Reply-To: <20161114103342.GI8314@redhat.com>
On 14/11/2016 11:33, Daniel P. Berrange wrote:
> On Mon, Nov 14, 2016 at 11:28:04AM +0100, Paolo Bonzini wrote:
>>
>>
>> On 14/11/2016 11:10, Daniel P. Berrange wrote:
>>> There's already patches posted to create a virtio-pstore device for
>>> QEMU, which is what led me to suggest this as an option:
>>>
>>> https://lists.nongnu.org/archive/html/qemu-devel/2016-09/msg00381.html
>>
>> It's also possible to use UEFI as a pstore backend.
>
> Presumably that'll also require some QEMU patches to provide storage
> for UEFI's pstore ?
That's just the UEFI variable store. But for some reason Fedora doesn't
set CONFIG_EFI_VARS, so the next possibility is to use ACPI ERST. This
would not require any change to guests, unlike virtio-pstore.
Paolo
^ permalink raw reply
* [PATCH v3] dts: omap5: board-common: fix wrong SMPS6 (VDD-DDR3) voltage
From: H. Nikolaus Schaller @ 2016-11-14 11:55 UTC (permalink / raw)
To: Benoît Cousson, Tony Lindgren, Rob Herring, Mark Rutland,
Russell King
Cc: linux-omap, devicetree, linux-kernel, kernel,
H. Nikolaus Schaller
DDR3L is usually specified as
JEDEC standard 1.35V(1.28V~1.45V) & 1.5V(1.425V~1.575V)
Therefore setting smps6 regulator to 1.2V is definitively below
minimum. It appears that real world chips are more forgiving than
data sheets indicate, but let's set the regulator right.
Note: a board that uses other voltages (DDR with 1.5V) can
overwrite by referencing &smps6_reg.
Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
---
arch/arm/boot/dts/omap5-board-common.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/omap5-board-common.dtsi b/arch/arm/boot/dts/omap5-board-common.dtsi
index ab60a8e..e4a14d5 100644
--- a/arch/arm/boot/dts/omap5-board-common.dtsi
+++ b/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -476,8 +476,8 @@
smps6_reg: smps6 {
/* VDD_DDR3 - over VDD_SMPS6 */
regulator-name = "smps6";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
};
--
2.7.3
^ permalink raw reply related
* Re: [PATCH V4 1/2] iio: adc: spmi-vadc: Update function for generic voltage conversion
From: Phani A, Rama Krishna @ 2016-11-14 11:47 UTC (permalink / raw)
To: Jonathan Cameron, linux-iio
Cc: linux-arm-msm, cdevired, smohanad, mgautam, sivaa, knaack.h, lars,
pmeerw, Julia.Lawall
In-Reply-To: <38428ee7-5d1b-2b36-99a9-988e0e7d29b5@kernel.org>
Hi Jonathan,
On 12-Nov-16 8:43 PM, Jonathan Cameron wrote:
> On 08/11/16 11:58, Rama Krishna Phani A wrote:
>> Several channels are supported in ADC of PMIC which can be used to
>> measure voltage, temperature, current etc. Hardware provides
>> readings for all channels in adc code. That adc code needs to be
>> converted to voltage. Logic for conversion of adc code to voltage
>> is common for all ADC channels(voltage, temperature, current etc).
>> Implement separate function for generic conversion logic.
>>
>> Signed-off-by: Rama Krishna Phani A <rphani@codeaurora.org>
> Looks good to me. Kind of the best we can do with minimal
> ABI changes.
>
> I had applied this but have now backed out to wait for patch 2.
>> ---
>> drivers/iio/adc/qcom-spmi-vadc.c | 52 +++++++++++++++++++++-------------------
>> 1 file changed, 28 insertions(+), 24 deletions(-)
>>
>> diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
>> index c2babe5..93c0639 100644
>> --- a/drivers/iio/adc/qcom-spmi-vadc.c
>> +++ b/drivers/iio/adc/qcom-spmi-vadc.c
>> @@ -1,5 +1,5 @@
>> /*
>> - * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
>> + * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
>> *
>> * This program is free software; you can redistribute it and/or modify
>> * it under the terms of the GNU General Public License version 2 and
>> @@ -468,27 +468,38 @@ static int vadc_measure_ref_points(struct vadc_priv *vadc)
>> return ret;
>> }
>>
>> -static s32 vadc_calibrate(struct vadc_priv *vadc,
>> - const struct vadc_channel_prop *prop, u16 adc_code)
>> +static void vadc_scale_calib(struct vadc_priv *vadc, u16 adc_code,
>> + const struct vadc_channel_prop *prop,
>> + s64 *scale_voltage)
>> {
>> - const struct vadc_prescale_ratio *prescale;
>> - s64 voltage;
>> + *scale_voltage = (adc_code -
>> + vadc->graph[prop->calibration].gnd);
>> + *scale_voltage *= vadc->graph[prop->calibration].dx;
>> + *scale_voltage = div64_s64(*scale_voltage,
>> + vadc->graph[prop->calibration].dy);
>> + if (prop->calibration == VADC_CALIB_ABSOLUTE)
>> + *scale_voltage +=
>> + vadc->graph[prop->calibration].dx;
>>
>> - voltage = adc_code - vadc->graph[prop->calibration].gnd;
>> - voltage *= vadc->graph[prop->calibration].dx;
>> - voltage = div64_s64(voltage, vadc->graph[prop->calibration].dy);
>> + if (*scale_voltage < 0)
>> + *scale_voltage = 0;
>> +}
>>
>> - if (prop->calibration == VADC_CALIB_ABSOLUTE)
>> - voltage += vadc->graph[prop->calibration].dx;
>> +static int vadc_scale_volt(struct vadc_priv *vadc,
>> + const struct vadc_channel_prop *prop, u16 adc_code,
>> + int *result_uv)
>> +{
>> + const struct vadc_prescale_ratio *prescale;
>> + s64 voltage = 0, result = 0;
>>
>> - if (voltage < 0)
>> - voltage = 0;
>> + vadc_scale_calib(vadc, adc_code, prop, &voltage);
>>
>> prescale = &vadc_prescale_ratios[prop->prescale];
>> -
>> voltage = voltage * prescale->den;
>> + result = div64_s64(voltage, prescale->num);
>> + *result_uv = result;
>>
>> - return div64_s64(voltage, prescale->num);
>> + return 0;
>> }
>>
>> static int vadc_decimation_from_dt(u32 value)
>> @@ -552,11 +563,8 @@ static int vadc_read_raw(struct iio_dev *indio_dev,
>> if (ret)
>> break;
>>
>> - *val = vadc_calibrate(vadc, prop, adc_code);
>> + vadc_scale_volt(vadc, prop, adc_code, val);
>>
>> - /* 2mV/K, return milli Celsius */
>> - *val /= 2;
>> - *val -= KELVINMIL_CELSIUSMIL;
>> return IIO_VAL_INT;
>> case IIO_CHAN_INFO_RAW:
>> prop = &vadc->chan_props[chan->address];
>> @@ -564,12 +572,8 @@ static int vadc_read_raw(struct iio_dev *indio_dev,
>> if (ret)
>> break;
>>
>> - *val = vadc_calibrate(vadc, prop, adc_code);
>> + *val = (int)adc_code;
>> return IIO_VAL_INT;
>> - case IIO_CHAN_INFO_SCALE:
>> - *val = 0;
>> - *val2 = 1000;
>> - return IIO_VAL_INT_PLUS_MICRO;
>> default:
>> ret = -EINVAL;
>> break;
>> @@ -617,7 +621,7 @@ struct vadc_channels {
>>
>> #define VADC_CHAN_VOLT(_dname, _pre) \
>> VADC_CHAN(_dname, IIO_VOLTAGE, \
>> - BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
>> + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),\
>> _pre) \
> This is still odd, but I guess justifiable from the point of view
> of maintaining backwards compatibility. The scale was simply wrong
> so not much we can do about that other than drop it!
ok., Will retain "IIO_CHAN_INFO_SCALE" to maintain backward
compatibility and include support for "IIO_CHAN_INFO_PROCESSED" as well
in the next patch.
>>
>> /*
>>
>
Thanks,
Ramakrishna
^ permalink raw reply
* RE: [Patch V3] i2c: imx: add low power i2c bus driver
From: Pandy Gao @ 2016-11-14 9:21 UTC (permalink / raw)
To: Vladimir Zapolskiy, wsa@the-dreams.de,
u.kleine-koenig@pengutronix.de, cmo@melexis.com
Cc: linux-i2c@vger.kernel.org, Frank Li, Andy Duan
In-Reply-To: <25d3aa71-cccd-320b-1bc4-cbfc829f019a@mleia.com>
From: Vladimir Zapolskiy <mailto:vz@mleia.com> Sent: Tuesday, October 25, 2016 7:15 AM
> To: Pandy Gao <pandy.gao@nxp.com>; wsa@the-dreams.de; u.kleine-
> koenig@pengutronix.de; cmo@melexis.com
> Cc: linux-i2c@vger.kernel.org; Frank Li <frank.li@nxp.com>; Andy Duan
> <fugang.duan@nxp.com>
> Subject: Re: [Patch V3] i2c: imx: add low power i2c bus driver
>
> Hello Pandy,
>
> On 17.08.2016 10:59, Gao Pan wrote:
> > This patch adds low power i2c bus driver to support new i.MX products
> > which use low power i2c instead of the old imx i2c.
> >
> > The low power i2c can continue operating in stop mode when an
> > appropriate clock is available. It is also designed for low CPU
> > overhead with DMA offloading of FIFO register accesses.
> >
> > Signed-off-by: Gao Pan <pandy.gao@nxp.com>
> > Reviewed-by: Fugang Duan <B38611@freescale.com>
> > ---
> > V2:
> > -stop i2c transfer under the wrong condition -add timeout check in
> > while() domain
> >
> > V3:
> > -fix typo inside commit message and the driver.
> >
> > .../devicetree/bindings/i2c/i2c-imx-lpi2c.txt | 25 +
> > drivers/i2c/busses/Kconfig | 10 +
> > drivers/i2c/busses/Makefile | 1 +
> > drivers/i2c/busses/i2c-imx-lpi2c.c | 667 +++++++++++++++++++++
> > 4 files changed, 703 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt
> > b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt
> > new file mode 100644
> > index 0000000..1f10cbf
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt
> > @@ -0,0 +1,25 @@
> > +* Freescale Low Power Inter IC (LPI2C) for i.MX
> > +
> > +Required properties:
> > +- compatible :
> > + - "fsl,imx8dv-lpi2c" for LPI2C compatible with the one integrated
> > +on i.MX8DV soc
> > + - "fsl,imx7ulp-lpi2c" for LPI2C compatible with the one integrated
> > +on i.MX7ULP soc
> > +- reg : Should contain LPI2C registers location and length
> > +- interrupts : Should contain LPI2C interrupt
> > +- clocks : Should contain LPI2C clock specifier
> > +- power-domains : should contain LPI2C power domain
> > +
> > +Optional properties:
> > +- clock-frequency : Constains desired LPI2C bus clock frequency in Hz.
>
> typo, what is "constains"? Contains, constrains?
It should be "contains", Thanks!
> > + The absence of the property indicates the default frequency 100 kHz.
> > +
> > +Examples:
> > +
> > +i2c1: i2c@5e110000 { /* LPI2C on i.MX8DV */
> > + compatible = "fsl,imx8dv-lpi2c";
> > + reg = <0x0 0x5e110000 0x0 0x4000>;
> > + interrupts = <0 88 4>;
> > + clocks = <&clk IMX8DV_I2C1_CLK>;
> > + clock-names = "per";
> > + power-domains = <&pd_lsio_i2c1>;
> > +};
>
> For this part please send the change to devicetree mailing list and get Rob
> Herring's ack. You may split it into a separate patch.
Thanks, it is better to split these part from i2c driver.
> > diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> > index efa3d9b..1fc7a10 100644
> > --- a/drivers/i2c/busses/Kconfig
> > +++ b/drivers/i2c/busses/Kconfig
> > @@ -596,6 +596,16 @@ config I2C_IMX
> > This driver can also be built as a module. If so, the module
> > will be called i2c-imx.
> >
> > +config I2C_IMX_LPI2C
> > + tristate "IMX Low Power I2C interface"
> > + depends on ARCH_MXC || COMPILE_TEST
> > + help
> > + Say Y here if you want to use the Low Power IIC bus controller
> > + on the Freescale i.MX processors.
> > +
> > + This driver can also be built as a module. If so, the module
> > + will be called i2c-imx-lpi2c.
> > +
> > config I2C_IOP3XX
> > tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
> > depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX ||
> ARCH_IOP13XX
> > diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> > index 37f2819..cc93457 100644
> > --- a/drivers/i2c/busses/Makefile
> > +++ b/drivers/i2c/busses/Makefile
> > @@ -56,6 +56,7 @@ obj-$(CONFIG_I2C_HIX5HD2) += i2c-hix5hd2.o
> > obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
> > obj-$(CONFIG_I2C_IMG) += i2c-img-scb.o
> > obj-$(CONFIG_I2C_IMX) += i2c-imx.o
> > +obj-$(CONFIG_I2C_IMX_LPI2C) += i2c-imx-lpi2c.o
> > obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
> > obj-$(CONFIG_I2C_JZ4780) += i2c-jz4780.o
> > obj-$(CONFIG_I2C_KEMPLD) += i2c-kempld.o
> > diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c
> > b/drivers/i2c/busses/i2c-imx-lpi2c.c
> > new file mode 100644
> > index 0000000..308ecf5
> > --- /dev/null
> > +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
> > @@ -0,0 +1,667 @@
> > +/*
> > + * This is i.MX low power i2c controller driver.
> > + *
> > + * Copyright 2016 Freescale Semiconductor, Inc.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License
> > + * as published by the Free Software Foundation; either version 2
> > + * of the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/completion.h>
> > +#include <linux/delay.h>
> > +#include <linux/err.h>
> > +#include <linux/errno.h>
> > +#include <linux/i2c.h>
> > +#include <linux/init.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.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/sched.h>
> > +#include <linux/slab.h>
> > +
> > +#define DRIVER_NAME "imx-lpi2c"
> > +
> > +#define LPI2C_PARAM 0x04 /* i2c RX/TX FIFO size */
> > +#define LPI2C_MCR 0x10 /* i2c contrl register */
> > +#define LPI2C_MSR 0x14 /* i2c status register */
> > +#define LPI2C_MIER 0x18 /* i2c interrupt enable */
> > +#define LPI2C_MCFGR0 0x20 /* i2c master configuration */
> > +#define LPI2C_MCFGR1 0x24 /* i2c master configuration */
> > +#define LPI2C_MCFGR2 0x28 /* i2c master configuration */
> > +#define LPI2C_MCFGR3 0x2C /* i2c master configuration */
> > +#define LPI2C_MCCR0 0x48 /* i2c master clk configuration */
> > +#define LPI2C_MCCR1 0x50 /* i2c master clk configuration */
> > +#define LPI2C_MFCR 0x58 /* i2c master FIFO control */
> > +#define LPI2C_MFSR 0x5C /* i2c master FIFO status */
> > +#define LPI2C_MTDR 0x60 /* i2c master TX data register */
> > +#define LPI2C_MRDR 0x70 /* i2c master RX data register */
> > +
> > +/* i2c command */
> > +#define TRAN_DATA 0X00
> > +#define RECV_DATA 0X01
> > +#define GEN_STOP 0X02
> > +#define RECV_DISCARD 0X03
> > +#define GEN_START 0X04
> > +#define START_NACK 0X05
> > +#define START_HIGH 0X06
> > +#define START_HIGH_NACK 0X07
> > +
> > +#define MCR_MEN (1 << 0)
> > +#define MCR_RST (1 << 1)
> > +#define MCR_DOZEN (1 << 2)
> > +#define MCR_DBGEN (1 << 3)
> > +#define MCR_RTF (1 << 8)
> > +#define MCR_RRF (1 << 9)
> > +#define MSR_TDF (1 << 0)
> > +#define MSR_RDF (1 << 1)
> > +#define MSR_SDF (1 << 9)
> > +#define MSR_NDF (1 << 10)
> > +#define MSR_ALF (1 << 11)
> > +#define MSR_MBF (1 << 24)
> > +#define MSR_BBF (1 << 25)
> > +#define MIER_TDIE (1 << 0)
> > +#define MIER_RDIE (1 << 1)
> > +#define MIER_SDIE (1 << 9)
> > +#define MIER_NDIE (1 << 10)
> > +#define MCFGR1_AUTOSTOP (1 << 8)
> > +#define MCFGR1_IGNACK (1 << 9)
> > +#define MRDR_RXEMPTY (1 << 14)
>
> Please use BIT() helper above.
Thanks, will change to BIT() in next version.
> Also please don't use tab symbol between #define and a token.
Got it, thanks!
> > +
> > +#define I2C_CLK_RATIO 2
> > +#define CHUNK_DATA 256
> > +
> > +#define LPI2C_RX_FIFOSIZE 4
> > +#define LPI2C_TX_FIFOSIZE 4
> > +
> > +#define LPI2C_DEFAULT_RATE 100000
> > +#define STARDARD_MAX_BITRATE 400000
> > +#define FAST_MAX_BITRATE 1000000
> > +#define FAST_PLUS_MAX_BITRATE 3400000
> > +#define HIGHSPEED_MAX_BITRATE 5000000
>
> Please don't use tab symbol right after #define
Thanks, will change it in next version.
> > +
> > +
>
> Double empty line, this kind of problem is reported by checkpatch --strict,
> please pay attention to all of them:
Thanks, I didn't use "--strict" option for checkpatch, so I missed this problem. Will change it in next version.
> total: 0 errors, 2 warnings, 33 checks, 715 lines checked
>
> > +enum lpi2c_imx_mode {
> > + STANDARD, /* 100+Kbps */
> > + FAST, /* 400+Kbps */
> > + FAST_PLUS, /* 1.0+Mbps */
> > + ULTRA_FAST, /* 5.0+Mbps */
> > + HS, /* 3.4+Mbps */
>
> Any reason why the list is not sorted by bus speed?
"HS" use different config with " ULTRA_FAST" and " FAST_PLUS", so I thought this order may be better. Will sort it by bus speed in next version. Thanks!
> > +};
> > +
> > +enum lpi2c_imx_pincfg {
> > + TWO_PIN_OD, /* 2-pin open drain mode */
> > + TWO_PIN_OO, /* 2-pin output only mode (utra-fast mode) */
> > + TWO_PIN_PP, /* 2-pin push-pull mode */
> > + FOUR_PIN_PP, /* 4-pin push-pull mode */
> > + TWO_PIN_OD_SS, /* 2-pin open drain mode with separate slave
> */
>
> Unused.
Will remove them in next version. Thanks!
> > + TWO_PIN_OO_SS, /* 2-pin output only mode with separate slave
> */
>
> Unused.
Thanks!
> > + TWO_PIN_PP_SS, /* 2-pin push-pull mode with separate slave */
>
> Unused.
Thanks!
> > + FOUR_PIN_PP_IO, /* 4-pin push-pull mode (inverted output) */
>
> Unused.
Thanks!
> > +};
> > +
> > +struct lpi2c_imx_clkcfg {
> > + u8 prescale;
> > + u8 filtscl;
> > + u8 filtsda;
> > + u8 sethold;
> > + u8 clklo;
> > + u8 clkhi;
> > + u8 datavd;
> > +};
> > +
> > +struct lpi2c_imx_struct {
> > + struct i2c_adapter adapter;
> > + struct clk *per_clk;
> > + void __iomem *base;
> > + __u8 *rx_buf;
> > + __u8 *tx_buf;
> > + struct completion complete;
> > + unsigned int msglen;
> > + unsigned int delivered;
> > + unsigned int block_data;
> > + unsigned int bitrate;
> > + enum lpi2c_imx_mode mode;
> > +};
> > +
> > +static void lpi2c_imx_intctrl(
> > + struct lpi2c_imx_struct *lpi2c_imx, unsigned int enable)
>
> Indentation issue.
Thanks!
> > +{
> > + writel(enable, lpi2c_imx->base + LPI2C_MIER); }
> > +
> > +static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx) {
> > + unsigned long orig_jiffies = jiffies;
> > + unsigned int temp;
> > +
> > + while (1) {
> > + temp = readl(lpi2c_imx->base + LPI2C_MSR);
> > +
> > + /* check for arbitration lost, clear if set */
> > + if (temp & MSR_ALF) {
> > + writel(temp, lpi2c_imx->base + LPI2C_MSR);
> > + return -EAGAIN;
> > + }
> > +
> > + if ((temp & MSR_BBF) && (temp & MSR_MBF))
>
> if (temp & (MSR_BBF | MSR_MBF))
Thanks, will change it in next version!
> > + break;
> > +
> > + if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
> > + dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
> > + return -ETIMEDOUT;
> > + }
> > + schedule();
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx) {
> > + enum lpi2c_imx_mode mode;
> > + unsigned int bitrate = lpi2c_imx->bitrate;
>
> unsigned int bitrate = lpi2c_imx->bitrate; enum lpi2c_imx_mode mode;
>
> If possible please use "reverse christmas tree" order while declaring local
> variables, this applies to some other functions below as well.
>
> I see that you mainly use "christmas tree" order, but this style isn't commonly
> used in the Linux kernel sources.
Thanks, will change it in next version.
> > +
> > + if (bitrate < STARDARD_MAX_BITRATE)
> > + mode = STANDARD;
> > + else if (bitrate < FAST_MAX_BITRATE)
> > + mode = FAST;
> > + else if (bitrate < FAST_PLUS_MAX_BITRATE)
> > + mode = FAST_PLUS;
> > + else if (bitrate < HIGHSPEED_MAX_BITRATE)
> > + mode = HS;
> > + else
> > + mode = ULTRA_FAST;
> > +
> > + lpi2c_imx->mode = mode;
> > +}
> > +
> > +static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
> > + struct i2c_msg *msgs)
> > +{
> > + u8 read;
> > + unsigned int temp;
> > +
> > + temp = readl(lpi2c_imx->base + LPI2C_MCR);
> > + temp |= MCR_RRF | MCR_RTF;
> > + writel(temp, lpi2c_imx->base + LPI2C_MCR);
> > + writel(0x7f00, lpi2c_imx->base + LPI2C_MSR);
> > +
> > + read = msgs->flags & I2C_M_RD;
> > + temp = (msgs->addr << 1 | read) | (GEN_START << 8);
> > + writel(temp, lpi2c_imx->base + LPI2C_MTDR);
> > +
> > + return lpi2c_imx_bus_busy(lpi2c_imx); }
> > +
> > +static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx) {
> > + unsigned int temp;
> > + unsigned long orig_jiffies = jiffies;
> > +
> > + writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
>
> Add an empty line here.
Thanks!
> > + do {
> > + temp = readl(lpi2c_imx->base + LPI2C_MSR);
> > + if (temp & MSR_SDF)
> > + break;
> > +
> > + if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
> > + dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
> > + break;
> > + }
> > + schedule();
> > +
> > + } while (1);
> > +}
> > +
> > +
> > +/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2
> > +*/ static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx) {
> > + unsigned int temp;
> > + unsigned int per_clk_rate;
> > + unsigned int prescale, clk_high, clk_low, clk_cycle;
> > + enum lpi2c_imx_pincfg pincfg;
> > + struct lpi2c_imx_clkcfg clkcfg;
> > +
> > + lpi2c_imx_set_mode(lpi2c_imx);
> > + per_clk_rate = clk_get_rate(lpi2c_imx->per_clk);
> > +
> > + if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
>
> if (lpi2c_imx->mode > FAST_PLUS)
>
> > + clkcfg.filtscl = clkcfg.filtsda = 0;
> > + else
> > + clkcfg.filtscl = clkcfg.filtsda = 2;
> > +
>
> Multiple assignments on a single line are not welcome, in this case one variable
> "filt" assigned to 0 or 2 should be enough.
Thanks, will change it in next version.
> Why do you need struct lpi2c_imx_clkcfg in general?
>
> clkcfg.filtscl, clkcfg.filtsda etc. are all used locally inside this function only, it
> should be sufficient to replace "clkcfg"
> with a number of local variables.
Yes, you are right. Will change it in next version. Thanks!
> > + for (prescale = 0; prescale <= 7; prescale++) {
> > + clk_cycle = per_clk_rate / ((1 << prescale) * lpi2c_imx->bitrate)
> > + - 3 - (clkcfg.filtscl >> 1);
> > + clk_high = (clk_cycle + I2C_CLK_RATIO) / (I2C_CLK_RATIO + 1);
> > + clk_low = clk_cycle - clk_high;
> > + if (clk_low < 64)
> > + break;
> > + }
> > +
> > + if (prescale > 7)
> > + return -EINVAL;
> > +
> > + clkcfg.prescale = prescale;
> > + clkcfg.sethold = clk_high;
> > + clkcfg.clklo = clk_low;
> > + clkcfg.clkhi = clk_high;
> > + clkcfg.datavd = clk_high >> 1;
>
> Useless duplication of variables, see a note above.
Thanks!
> > +
> > + /* set MCFGR1: PINCFG, PRESCALE, IGNACK */
> > + if (lpi2c_imx->mode == ULTRA_FAST)
> > + pincfg = TWO_PIN_OO;
> > + else
> > + pincfg = TWO_PIN_OD;
> > + temp = clkcfg.prescale | pincfg << 24;
> > +
> > + if (lpi2c_imx->mode == ULTRA_FAST)
> > + temp |= MCFGR1_IGNACK;
> > +
> > + writel(temp, lpi2c_imx->base + LPI2C_MCFGR1);
> > +
> > + /* set MCFGR2: FILTSDA, FILTSCL */
> > + temp = (clkcfg.filtscl << 16) | (clkcfg.filtsda << 24);
> > + writel(temp, lpi2c_imx->base + LPI2C_MCFGR2);
> > +
> > +
> > + /* set MCCR: DATAVD, SETHOLD, CLKHI, CLKLO */
> > + temp = clkcfg.datavd << 24 | clkcfg.sethold << 16 |
> > + clkcfg.clkhi << 8 | clkcfg.clklo;
> > +
> > + if (lpi2c_imx->mode == HS)
> > + writel(temp, lpi2c_imx->base + LPI2C_MCCR1);
> > + else
> > + writel(temp, lpi2c_imx->base + LPI2C_MCCR0);
> > +
> > + return 0;
> > +}
> > +
> > +static int lpi2c_imx_master_enable(struct lpi2c_imx_struct
> > +*lpi2c_imx) {
> > + int ret;
> > + unsigned int temp;
> > +
> > + ret = clk_prepare_enable(lpi2c_imx->per_clk);
>
> You can do clk_prepare() in probe function and clk_unprepare() in remove
> function to avoid potential sleeping in runtime, then here you just do
> clk_enable()/clk_disable().
Thanks, will change it in next version!
> > + if (ret)
> > + return ret;
> > +
> > + temp = MCR_RST;
> > + writel(temp, lpi2c_imx->base + LPI2C_MCR);
> > + writel(0, lpi2c_imx->base + LPI2C_MCR);
> > +
> > + ret = lpi2c_imx_config(lpi2c_imx);
> > + if (ret)
> > + return ret;
> > +
> > + temp = readl(lpi2c_imx->base + LPI2C_MCR);
> > + temp |= MCR_MEN;
> > + writel(temp, lpi2c_imx->base + LPI2C_MCR);
> > +
> > + return 0;
> > +}
> > +
> > +static int lpi2c_imx_master_disable(struct lpi2c_imx_struct
> > +*lpi2c_imx) {
> > + unsigned int temp = 0;
> > +
> > + temp = readl(lpi2c_imx->base + LPI2C_MCR);
> > + temp &= ~MCR_MEN;
> > + writel(temp, lpi2c_imx->base + LPI2C_MCR);
> > +
> > + clk_disable_unprepare(lpi2c_imx->per_clk);
>
> See a note above.
Thanks!
> > +
> > + return 0;
> > +}
> > +
> > +static int lpi2c_imx_msg_complete(struct lpi2c_imx_struct *lpi2c_imx)
> > +{
> > + unsigned int timeout;
> > +
> > + timeout = wait_for_completion_timeout(&lpi2c_imx->complete, HZ);
> > +
> > + return timeout ? 0 : -ETIMEDOUT;
> > +}
> > +
> > +static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx)
> > +{
> > + u32 txcnt;
> > + unsigned long orig_jiffies = jiffies;
> > +
> > + do {
> > + txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
> > +
> > + if (readl(lpi2c_imx->base + LPI2C_MSR) & MSR_NDF) {
> > + dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n");
> > + return -EIO;
> > + }
> > +
> > + if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
> > + dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty
> timeout\n");
> > + return -ETIMEDOUT;
> > + }
> > + schedule();
> > +
> > + } while (txcnt);
> > +
> > + return 0;
> > +}
> > +
> > +static void lpi2c_imx_set_tx_watermark(struct lpi2c_imx_struct
> > +*lpi2c_imx) {
> > + unsigned int temp;
> > +
> > + temp = LPI2C_TX_FIFOSIZE >> 1;
> > + writel(temp, lpi2c_imx->base + LPI2C_MFCR);
>
> writel(LPI2C_TX_FIFOSIZE >> 1, lpi2c_imx->base + LPI2C_MFCR);
Thanks, will change it in next version.
> > +}
> > +
> > +static void lpi2c_imx_set_rx_watermark(struct lpi2c_imx_struct
> > +*lpi2c_imx) {
> > + unsigned int temp, remaining;
> > +
> > + remaining = lpi2c_imx->msglen - lpi2c_imx->delivered;
> > +
> > + if (remaining > (LPI2C_RX_FIFOSIZE >> 1))
> > + temp = LPI2C_RX_FIFOSIZE >> 1;
> > + else
> > + temp = 0;
> > +
> > + writel(temp << 16, lpi2c_imx->base + LPI2C_MFCR); }
> > +
> > +static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct
> > +*lpi2c_imx) {
> > + unsigned int data, txcnt;
> > +
> > + txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
>
> Add an empty line here.
Thanks!
> > + while (txcnt < LPI2C_TX_FIFOSIZE) {
> > + if (lpi2c_imx->delivered == lpi2c_imx->msglen)
> > + break;
>
> Add an empty line here.
Thanks!
> > + data = lpi2c_imx->tx_buf[lpi2c_imx->delivered++];
> > + writel(data, lpi2c_imx->base + LPI2C_MTDR);
> > + txcnt++;
> > + }
> > +
> > + if (lpi2c_imx->delivered < lpi2c_imx->msglen)
> > + lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE | MIER_NDIE);
> > + else
> > + complete(&lpi2c_imx->complete);
> > +}
> > +
> > +static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
> > +{
> > + unsigned int temp, data;
> > + unsigned int blocklen, remaining;
> > +
> > + do {
> > + data = readl(lpi2c_imx->base + LPI2C_MRDR);
> > + if (data & MRDR_RXEMPTY)
> > + break;
> Add an empty line here.
Thanks!
>
> > + lpi2c_imx->rx_buf[lpi2c_imx->delivered++] = data & 0xff;
> > + } while (1);
> > +
> > + /*
> > + * First byte is the length of remaining packet in the SMBus block
> > + * data read. Add it to msgs->len.
> > + */
> > + if (lpi2c_imx->block_data) {
> > + blocklen = lpi2c_imx->rx_buf[0];
> > + lpi2c_imx->msglen += blocklen;
> > + }
> > +
> > + remaining = lpi2c_imx->msglen - lpi2c_imx->delivered;
> > + /* not finished, still waiting for rx data */
>
> Please move the comment under if (remaining) condition.
Thanks, will change it in next version!
> > + if (remaining) {
> > + lpi2c_imx_set_rx_watermark(lpi2c_imx);
> > + /* multiple receive commands */
> > + if (lpi2c_imx->block_data) {
> > + lpi2c_imx->block_data = 0;
> > + temp = remaining;
> > + temp |= (RECV_DATA << 8);
> > + writel(temp, lpi2c_imx->base + LPI2C_MTDR);
> > + } else if (!(lpi2c_imx->delivered & 0xff)) {
> > + temp = remaining > CHUNK_DATA ?
> > + CHUNK_DATA - 1 : (remaining - 1);
> > + temp |= (RECV_DATA << 8);
> > + writel(temp, lpi2c_imx->base + LPI2C_MTDR);
> > + }
> > +
> > + lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE);
> > + } else
> > + complete(&lpi2c_imx->complete);
>
> Start it from
>
> if (!remaining) {
> complete(&lpi2c_imx->complete);
> return;
> }
>
> /* not finished, still waiting for rx data */ ....
>
> Then you get less indentations. Generally please use more return points instead
> of if-if-if constructions.
>
Thanks, will change it in next version!
> > +}
> > +
> > +static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx,
> > + struct i2c_msg *msgs)
> > +{
> > + lpi2c_imx->tx_buf = msgs->buf;
> > + lpi2c_imx_set_tx_watermark(lpi2c_imx);
> > + lpi2c_imx_write_txfifo(lpi2c_imx);
> > +}
> > +
> > +static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
> > + struct i2c_msg *msgs)
> > +{
> > + unsigned int temp;
> > +
> > + lpi2c_imx->rx_buf = msgs->buf;
> > + lpi2c_imx->block_data = msgs->flags & I2C_M_RECV_LEN;
> > +
> > + lpi2c_imx_set_rx_watermark(lpi2c_imx);
> > + temp = msgs->len > CHUNK_DATA ? CHUNK_DATA - 1 : msgs->len - 1;
> > + temp |= (RECV_DATA << 8);
> > + writel(temp, lpi2c_imx->base + LPI2C_MTDR);
> > +
> > + lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE); }
> > +
> > +static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
> > + struct i2c_msg *msgs, int num)
> > +{
> > + int i, result;
> > + unsigned int temp;
> > + struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(adapter);
> > +
> > + result = lpi2c_imx_master_enable(lpi2c_imx);
> > + if (result)
> > + return result;
> > +
> > + for (i = 0; i < num; i++) {
> > + result = lpi2c_imx_start(lpi2c_imx, &msgs[i]);
> > + if (result)
> > + goto disable;
> > +
> > + /* quick smbus */
> > + if (num == 1 && msgs[0].len == 0)
> > + goto stop;
> > +
> > + lpi2c_imx->delivered = 0;
> > + lpi2c_imx->msglen = msgs[i].len;
> > + init_completion(&lpi2c_imx->complete);
> > +
> > + if (msgs[i].flags & I2C_M_RD)
> > + lpi2c_imx_read(lpi2c_imx, &msgs[i]);
> > + else
> > + lpi2c_imx_write(lpi2c_imx, &msgs[i]);
> > +
> > + result = lpi2c_imx_msg_complete(lpi2c_imx);
> > + if (result)
> > + goto stop;
> > +
> > + if (!(msgs[i].flags & I2C_M_RD)) {
> > + result = lpi2c_imx_txfifo_empty(lpi2c_imx);
> > + if (result)
> > + goto stop;
> > + }
> > + }
> > +
> > +stop:
> > + lpi2c_imx_stop(lpi2c_imx);
> > +
> > + temp = readl(lpi2c_imx->base + LPI2C_MSR);
> > + if ((temp & MSR_NDF) && !result)
> > + result = -EIO;
>
> Zero-length transactions are not supported, right?
The driver support zero-length transactions. For zero-length transactions, the transfer direction field represents data field.
It is transferred with i2c start CMD.
> > +
> > +disable:
> > + lpi2c_imx_master_disable(lpi2c_imx);
> > +
> > + dev_dbg(&lpi2c_imx->adapter.dev, "<%s> exit with: %s: %d\n",
> __func__,
> > + (result < 0) ? "error" : "success msg",
> > + (result < 0) ? result : num);
> > +
> > + return (result < 0) ? result : num;
> > +}
> > +
> > +static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) {
> > + unsigned int temp;
> > + struct lpi2c_imx_struct *lpi2c_imx = dev_id;
> > +
> > + lpi2c_imx_intctrl(lpi2c_imx, 0);
> > + temp = readl(lpi2c_imx->base + LPI2C_MSR);
> > +
> > + if (temp & MSR_RDF) {
> > + lpi2c_imx_read_rxfifo(lpi2c_imx);
> > + return IRQ_HANDLED;
> > + }
> > +
> > + if (temp & MSR_TDF) {
> > + lpi2c_imx_write_txfifo(lpi2c_imx);
> > + return IRQ_HANDLED;
> > + }
> > +
> > + complete(&lpi2c_imx->complete);
>
> Add an empty line here.
Thanks, will change it in next version.
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static u32 lpi2c_imx_func(struct i2c_adapter *adapter) {
> > + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
> > + | I2C_FUNC_SMBUS_READ_BLOCK_DATA;
>
> checkpatch does not complain? I expect it should be
>
> return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
> I2C_FUNC_SMBUS_READ_BLOCK_DATA;
>
Thanks, will change it in next version!
> > +}
> > +
> > +static struct i2c_algorithm lpi2c_imx_algo = {
> > + .master_xfer = lpi2c_imx_xfer,
> > + .functionality = lpi2c_imx_func,
> > +};
> > +
> > +static const struct of_device_id lpi2c_imx_of_match[] = {
> > + { .compatible = "fsl,imx8dv-lpi2c" },
> > + { .compatible = "fsl,imx7ulp-lpi2c" },
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match)
> > +
> > +static int lpi2c_imx_probe(struct platform_device *pdev) {
> > + int irq, ret;
> > + void __iomem *base;
> > + struct resource *res;
> > + struct lpi2c_imx_struct *lpi2c_imx;
> > +
> > + lpi2c_imx = devm_kzalloc(&pdev->dev,
> > + sizeof(*lpi2c_imx), GFP_KERNEL);
> > + if (!lpi2c_imx)
> > + return -ENOMEM;
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + base = devm_ioremap_resource(&pdev->dev, res);
> > + if (IS_ERR(base))
> > + return PTR_ERR(base);
> > +
> > + irq = platform_get_irq(pdev, 0);
> > + if (irq < 0) {
> > + dev_err(&pdev->dev, "can't get irq number\n");
> > + return irq;
> > + }
> > +
> > + lpi2c_imx->adapter.owner = THIS_MODULE;
> > + lpi2c_imx->adapter.algo = &lpi2c_imx_algo;
> > + lpi2c_imx->adapter.dev.parent = &pdev->dev;
> > + lpi2c_imx->adapter.nr = pdev->id;
>
> Do you really need it? Please consider to use i2c_add_adapter().
You are right, i2c_add_adapter() is a better option. Will change it in next version, Thanks.
> > + lpi2c_imx->base = base;
>
> For sake of consistency please initialize lpi2c_imx->adapter fields in a row.
>
> You don't need this local 'base' variable, use lpi2c_imx->base instead.
Thanks, Will change it in next version.
> > + lpi2c_imx->adapter.dev.of_node = pdev->dev.of_node;
> > + strlcpy(lpi2c_imx->adapter.name, pdev->name,
> > + sizeof(lpi2c_imx->adapter.name));
> > +
> > + lpi2c_imx->per_clk = devm_clk_get(&pdev->dev, NULL);
> > + if (IS_ERR(lpi2c_imx->per_clk)) {
> > + dev_err(&pdev->dev, "can't get I2C peripheral clock\n");
> > + return PTR_ERR(lpi2c_imx->per_clk);
> > + }
> > +
> > + ret = of_property_read_u32(pdev->dev.of_node,
> > + "clock-frequency", &lpi2c_imx->bitrate);
> > + if (ret)
> > + lpi2c_imx->bitrate = LPI2C_DEFAULT_RATE;
> > +
> > + ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0,
> > + pdev->name, lpi2c_imx);
> > + if (ret) {
> > + dev_err(&pdev->dev, "can't claim irq %d\n", irq);
> > + goto ret;
>
> Just return ret;
Thanks!
> > + }
> > +
> > + i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
> > + platform_set_drvdata(pdev, lpi2c_imx);
> > +
> > + ret = i2c_add_numbered_adapter(&lpi2c_imx->adapter);
> > + if (ret) {
> > + dev_err(&pdev->dev, "registration failed\n");
> > + goto ret;
>
> Just return ret;
Thanks!
> > + }
> > +
> > + dev_info(&lpi2c_imx->adapter.dev, "LPI2C adapter registered\n");
> > +
> > +ret:
> > + return ret;
>
> return 0;
Thanks!
> > +}
> > +
> > +static int lpi2c_imx_remove(struct platform_device *pdev) {
> > + struct lpi2c_imx_struct *lpi2c_imx = platform_get_drvdata(pdev);
> > +
> > + i2c_del_adapter(&lpi2c_imx->adapter);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver lpi2c_imx_driver = {
> > + .probe = lpi2c_imx_probe,
> > + .remove = lpi2c_imx_remove,
> > + .driver = {
> > + .name = DRIVER_NAME,
> > + .of_match_table = lpi2c_imx_of_match,
> > + },
> > +};
> > +
> > +static int __init i2c_adap_imx_init(void) {
> > + return platform_driver_register(&lpi2c_imx_driver);
> > +}
> > +module_init(i2c_adap_imx_init);
> > +
> > +static void __exit i2c_adap_imx_exit(void) {
> > + platform_driver_unregister(&lpi2c_imx_driver);
> > +}
> > +module_exit(i2c_adap_imx_exit);
> > +
>
> Please use module_platform_driver(lpi2c_imx_driver);
Thanks, will change it in next version!
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_AUTHOR("Gao Pan <pandy.gao@nxp.com>");
> MODULE_DESCRIPTION("I2C
> > +adapter driver for LPI2C bus"); MODULE_ALIAS("platform:"
> > +DRIVER_NAME);
> >
>
> Are you sure that the driver needs a platform alias here?
Thanks, will remove it in next version.
Thanks again for your precise review, it really helps to improve the code quality!
Best Regards
Gao Pan
^ permalink raw reply
* [PATCH 3/5] net: thunderx: Fix configuration of L3/L4 length checking
From: sunil.kovvuri @ 2016-11-14 10:54 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel, linux-arm-kernel, Sunil Goutham
In-Reply-To: <1479120886-13425-1-git-send-email-sunil.kovvuri@gmail.com>
From: Sunil Goutham <sgoutham@cavium.com>
This patch fixes enabling of HW verification of L3/L4 length and
TCP/UDP checksum which is currently being cleared. Also fixed VLAN
stripping config which is being cleared when multiqset is enabled.
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
---
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index f0e0ca6..3050177 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -538,9 +538,12 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
mbx.rq.cfg = (1ULL << 62) | (RQ_CQ_DROP << 8);
nicvf_send_msg_to_pf(nic, &mbx);
- nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0, 0x00);
- if (!nic->sqs_mode)
+ if (!nic->sqs_mode && (qidx == 0)) {
+ /* Enable checking L3/L4 length and TCP/UDP checksums */
+ nicvf_queue_reg_write(nic, NIC_QSET_RQ_GEN_CFG, 0,
+ ((1 << 24) | (1 << 23) | (1 << 21)));
nicvf_config_vlan_stripping(nic, nic->netdev->features);
+ }
/* Enable Receive queue */
memset(&rq_cfg, 0, sizeof(struct rq_cfg));
--
2.7.4
^ permalink raw reply related
* [U-Boot] [PATCH] MAINTAINERS: mark sunxi status as Orphan
From: Hans de Goede @ 2016-11-14 11:53 UTC (permalink / raw)
To: u-boot
Ian has not had any time for sunxi for some time now and I'm
in the same situation now, so I'm stepping down as sunxi
custodian and marking the sunxi support as Orphan.
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Ian Campbell <ijc@hellion.org.uk>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
MAINTAINERS | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 0bd8995..83a70df 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -167,9 +167,7 @@ F: arch/arm/cpu/armv7/stv0991/
F: arch/arm/include/asm/arch-stv0991/
ARM SUNXI
-M: Ian Campbell <ijc@hellion.org.uk>
-M: Hans De Goede <hdegoede@redhat.com>
-S: Maintained
+S: Orphan
T: git git://git.denx.de/u-boot-sunxi.git
F: arch/arm/cpu/armv7/sunxi/
F: arch/arm/include/asm/arch-sunxi/
--
2.9.3
^ permalink raw reply related
* [U-Boot] Stepping down as sunxi u-boot custodian (for real this time)
From: Hans de Goede @ 2016-11-14 11:53 UTC (permalink / raw)
To: u-boot
Hi All,
A while back I wrote:
"Between my $dayjob, linux-sunxi, other foss projects and last but
not least spending time with my wife and children I'm way too
busy lately.
So I've decided to seriously scale back my involvement in
linux-sunxi, as such I'm going to step down as u-boot sunxi
custodian."
After that I did get some breathing room, and kept doing
sunxi u-boot maintenance until now, but this still feels
too much like a job rather then a hobby. The problem is
that I don't want to think during the weekend:
"Oh !@#$ I still need to prep a u-boot sunxi pull-req"
This is nothing against the u-boot community, I think
you're all great and I still love thinkering with this
kind of stuff, but when a hobby starts feeling as a chore
something is wrong.
So after this mail I'm going to send a mail updating
the MAINTAINERS status of sunxi to orphan and I will also
unsubscribe myself from the u-boot list to protect myself
against getting dragged in again.
I do expect (after taking a break for a couple of weeks)
that I will likely submit the occasional patch, but at
this point in time I do not want any maintainer
responsibilities.
Yesterday and today I've gone over my pending patches
queue, reviewed then all and I've merged all the ones
which looked good into u-boot-sunxi/next, so that
should be a good starting point for the next
maintainer.
Jagan (in the Cc) has indicated in the past that he is
interested in taking over as sunxi custodian, Jagan already
is the SPI custodian, so I believe that he will do well.
So Jagan, if you still want the job, go for it.
Regards,
Hans
^ permalink raw reply
* Re: [PATCH 0/8] DMA: s3c64xx: Conversion to the new channel request API
From: Sylwester Nawrocki @ 2016-11-14 11:52 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: vinod.koul, kgene, linux-samsung-soc, linux-arm-kernel, dmaengine,
broonie, ckeepax, ym0914, arnd, javier, andi.shyti, sbkim73
In-Reply-To: <20161110184210.GA11835@kozik-lap>
On 11/10/2016 07:42 PM, Krzysztof Kozlowski wrote:
> On Thu, Nov 10, 2016 at 04:17:48PM +0100, Sylwester Nawrocki wrote:
>> > This patch series aims to convert the s3c64xx platform to use
>> > the new DMA channel request API, i.e. this is only meaningful
>> > for non-dt systems using s3c64xx SoCs.
>> >
>> > Presumably the first 2 or 4 patches in this series could be queued
>> > for v4.10-rc1 and the remaining patches could be left for subsequent
>> > release, to avoid non-trivial conflict with patches already applied
>> > in the ASoC tree.
>
> Sounds good to me. Should I put the ARM/s3c64xx commits on separate
> branch in case someone would like to pull a tag with it?
I think it makes sense to put first 4 patches from the series onto
a separate branch, and the remaining ones would need to wait for
next development cycle.
But of course firstly we need some feedback and Ack on the first
(DMA controller driver) patch.
--
Thanks,
Sylwester
^ permalink raw reply
* [PATCH 0/8] DMA: s3c64xx: Conversion to the new channel request API
From: Sylwester Nawrocki @ 2016-11-14 11:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161110184210.GA11835@kozik-lap>
On 11/10/2016 07:42 PM, Krzysztof Kozlowski wrote:
> On Thu, Nov 10, 2016 at 04:17:48PM +0100, Sylwester Nawrocki wrote:
>> > This patch series aims to convert the s3c64xx platform to use
>> > the new DMA channel request API, i.e. this is only meaningful
>> > for non-dt systems using s3c64xx SoCs.
>> >
>> > Presumably the first 2 or 4 patches in this series could be queued
>> > for v4.10-rc1 and the remaining patches could be left for subsequent
>> > release, to avoid non-trivial conflict with patches already applied
>> > in the ASoC tree.
>
> Sounds good to me. Should I put the ARM/s3c64xx commits on separate
> branch in case someone would like to pull a tag with it?
I think it makes sense to put first 4 patches from the series onto
a separate branch, and the remaining ones would need to wait for
next development cycle.
But of course firstly we need some feedback and Ack on the first
(DMA controller driver) patch.
--
Thanks,
Sylwester
^ permalink raw reply
* Re: [PATCH RFC 1/7] dma: pl08x: Add support for the DMA slave map
From: Sylwester Nawrocki @ 2016-11-14 11:51 UTC (permalink / raw)
To: Arnd Bergmann
Cc: dmaengine, vinod.koul, linux-arm-kernel, linux-samsung-soc,
sbkim73, andi.shyti, javier, broonie, kgene, ckeepax, ym0914
In-Reply-To: <3693046.Gh6DJsekH3@wuerfel>
On 11/07/2016 08:55 PM, Arnd Bergmann wrote:
>> diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
>> > index d5c75c8..0d1eb2e 100644
>> > --- a/drivers/dma/amba-pl08x.c
>> > +++ b/drivers/dma/amba-pl08x.c
>> > @@ -1793,6 +1793,23 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
>> > }
[...]
>> > +static bool pl08x_filter_fn(struct dma_chan *chan, void *chan_id)
>> > +{
>> > + struct pl08x_dma_chan *plchan;
[...]
>> > + plchan = to_pl08x_chan(chan);
>> > +
>> > + /* Check that the channel is not taken! */
>> > + if (plchan->cd == chan_id)
>> > + return true;
>
> What I had in mind was a bit different: Instead of comparing the
> channel, I was thinking of modifying the channel itself, something
> like:
>
> plchan->signal = chan_id->signal;
> plchan->periph_buses = chan_id->periph_buses;
>
> after that, remove the plchan->cd data. Unfortunately, the muxing in
> arch/arm/mach-spear/ makes this a bit harder. I'd have to think
> about it some more. It may be easier to do this after moving
> spear and lpc32xx over to use dma_slave_map.
I've posted updated version of this patch, please let me know
if you have any further comments.
--
Thanks,
Sylwester
^ permalink raw reply
* [PATCH RFC 1/7] dma: pl08x: Add support for the DMA slave map
From: Sylwester Nawrocki @ 2016-11-14 11:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3693046.Gh6DJsekH3@wuerfel>
On 11/07/2016 08:55 PM, Arnd Bergmann wrote:
>> diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
>> > index d5c75c8..0d1eb2e 100644
>> > --- a/drivers/dma/amba-pl08x.c
>> > +++ b/drivers/dma/amba-pl08x.c
>> > @@ -1793,6 +1793,23 @@ bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
>> > }
[...]
>> > +static bool pl08x_filter_fn(struct dma_chan *chan, void *chan_id)
>> > +{
>> > + struct pl08x_dma_chan *plchan;
[...]
>> > + plchan = to_pl08x_chan(chan);
>> > +
>> > + /* Check that the channel is not taken! */
>> > + if (plchan->cd == chan_id)
>> > + return true;
>
> What I had in mind was a bit different: Instead of comparing the
> channel, I was thinking of modifying the channel itself, something
> like:
>
> plchan->signal = chan_id->signal;
> plchan->periph_buses = chan_id->periph_buses;
>
> after that, remove the plchan->cd data. Unfortunately, the muxing in
> arch/arm/mach-spear/ makes this a bit harder. I'd have to think
> about it some more. It may be easier to do this after moving
> spear and lpc32xx over to use dma_slave_map.
I've posted updated version of this patch, please let me know
if you have any further comments.
--
Thanks,
Sylwester
^ permalink raw reply
* Re: [PATCH BlueZ] core/adapter: Fix using wrong address type to listen ATT
From: Johan Hedberg @ 2016-11-14 11:51 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1479123009-7190-1-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Mon, Nov 14, 2016, Luiz Augusto von Dentz wrote:
> bdaddr_type shall only matter for controllers supporting LE otherwise
> it may cause BDADDR_BREDR to be used for things like LE ATT socket
> listen breaking reconnections.
> ---
> src/adapter.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
Applied. Thanks.
Johan
^ permalink raw reply
* Re: Calculate average latencies on the fly
From: Piotr Gregor @ 2016-11-14 11:50 UTC (permalink / raw)
To: Clark Williams, John Kacur; +Cc: linux-rt-users
In-Reply-To: <CAK+oA4V8yFDnieAa4tsCQKTapNe6gA_VLJvvEh6_u_jgWpyahQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 91 bytes --]
There was an error in previous patch. Please find attached corrected patch.
cheers,
Piotr
[-- Attachment #2: calc_average_on_the_fly.patch --]
[-- Type: text/x-patch, Size: 1777 bytes --]
From 5610e2b01e5302a5ecff7ca368198863a6ce9f78 Mon Sep 17 00:00:00 2001
From: Piotr Gregor <piotrgregor@rsyncme.org>
Date: Fri, 11 Nov 2016 11:28:09 +0000
Subject: [PATCH] rt-tests: cyclictest: Calculate average latencies on the fly
Prevents stat->avg variable from overflow.
---
src/cyclictest/cyclictest.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 3f1bef1..0d2ddbc 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -1178,7 +1178,11 @@ static void *timerthread(void *param)
if (refresh_on_max)
pthread_cond_signal(&refresh_on_max_cond);
}
- stat->avg += (double) diff;
+ if (stat->cycles == 0) {
+ stat->avg = (double) diff;
+ } else {
+ stat->avg = (stat->avg + (double) diff / (double) stat->cycles) * ((double) stat->cycles / (double) (stat->cycles + 1));
+ }
if (trigger && (diff > trigger)) {
trigger_update(par, diff, calctime(now));
@@ -2005,7 +2009,7 @@ static void print_hist(struct thread_param *par[], int nthreads)
fprintf(fd, "# Avg Latencies:");
for (j = 0; j < nthreads; j++)
fprintf(fd, " %05lu", par[j]->stats->cycles ?
- (long)(par[j]->stats->avg/par[j]->stats->cycles) : 0);
+ (long)(par[j]->stats->avg) : 0);
fprintf(fd, "\n");
fprintf(fd, "# Max Latencies:");
maxmax = 0;
@@ -2059,7 +2063,7 @@ static void print_stat(FILE *fp, struct thread_param *par, int index, int verbos
fprintf(fp, fmt, index, stat->tid, par->prio,
par->interval, stat->cycles, stat->min,
stat->act, stat->cycles ?
- (long)(stat->avg/stat->cycles) : 0, stat->max);
+ (long)(stat->avg) : 0, stat->max);
if (smi)
fprintf(fp," SMI:%8ld", stat->smi_count);
--
2.7.4
^ permalink raw reply related
* Re: [PATCH 2/2] dmaengine: omap-dma: Support for slave devices with data port window
From: Peter Ujfalusi @ 2016-11-14 11:49 UTC (permalink / raw)
To: Vinod Koul
Cc: dan.j.williams, Tony Lindgren, Russell King - ARM Linux,
dmaengine, linux-kernel, linux-omap, arnd
In-Reply-To: <20161114105546.GF3000@localhost>
On 11/14/2016 12:55 PM, Vinod Koul wrote:
> On Mon, Nov 14, 2016 at 11:44:33AM +0200, Peter Ujfalusi wrote:
>> On 11/14/2016 06:35 AM, Vinod Koul wrote:
>
>>>> } else {
>>>> - d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC;
>>>> d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
>>>> +
>>>> + d->ccr |= CCR_SRC_AMODE_POSTINC;
>>>> + if (port_window) {
>>>> + d->ccr |= CCR_DST_AMODE_DBLIDX;
>>>> +
>>>> + if (port_window / 64)
>>>> + d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
>>>> + else if (port_window / 32)
>>>> + d->csdp = CSDP_DST_BURST_32 | CSDP_DST_PACKED;
>>>> + else if (port_window / 16)
>>>> + d->csdp = CSDP_DST_BURST_16 | CSDP_DST_PACKED;
>>>
>>> what does these mean?
>>
>> To optimize the speed on the write side. First check if the window size is
>> multiple of 64 bytes, we enable the 64byte burst and packed transfer, if not
>> try the 32bytes, then 16bytes.
>> Same for the opposite direction previously.
>
> Ah and how does client know the size of window..?
Clients configuring the DMA should know what they are configuring for. If the
window size can be different they might have DT property if they need.
>
>>
>>>
>>>> + } else {
>>>> + d->ccr |= CCR_DST_AMODE_CONSTANT;
>>>> + }
>>>> }
>>>>
>>>> d->cicr = CICR_DROP_IE | CICR_BLOCK_IE;
>>>> @@ -945,6 +979,9 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
>>>> d->ccr |= CCR_TRIGGER_SRC;
>>>>
>>>> d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
>>>> +
>>>> + if (port_window)
>>>> + d->csdp |= CSDP_WRITE_LAST_NON_POSTED;
>>>> }
>>>> if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
>>>> d->clnk_ctrl = c->dma_ch;
>>>> @@ -970,6 +1007,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
>>>> osg->addr = sg_dma_address(sgent);
>>>> osg->en = en;
>>>> osg->fn = sg_dma_len(sgent) / frame_bytes;
>>>> + if (port_window && dir == DMA_MEM_TO_DEV) {
>>>> + osg->ei = 1;
>>>> + osg->fi = (-1) * (port_window - 1);
>>>> + }
>>>
>>> can you describe what you are trying here..
>>
>> The DMA is set up so one frame covers the port window. When the frame is
>> finished we need to start reading the next frame from the start of the window
>> again. The FI as (-1) * (port_window - 1) will take us to the start of the
>> window. When the frame is finished the DMA is pointing to the last byte of the
>> window.
>
> Sound right to me, would help to add this as a comment..
OK, I will add a comment describing it.
>
--
Péter
^ permalink raw reply
* Re: [PATCH] Revert "tty: serial: 8250: add CON_CONSDEV to flags"
From: Greg Kroah-Hartman @ 2016-11-14 11:49 UTC (permalink / raw)
To: Huacai Chen; +Cc: linux-serial, Matthew Leach, stable, Ce Sun
In-Reply-To: <1479092021-14885-1-git-send-email-chenhc@lemote.com>
On Mon, Nov 14, 2016 at 10:53:41AM +0800, Huacai Chen wrote:
> This reverts commit d03516df837587368fc6e75591f6329c072b9eb5. From
> Documentation/serial-console.txt we can know that serial port becomes
> the system console only when it appears in the kernel parameters as the
> last console device. But commit d03516df837587 adds a CON_CONSDEV flag
> to univ8250_console and breaks this convention. After that either we
> use "console=tty console=ttyS0" or "console=ttyS0 console=tty", serial
> port will always be the system console.
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Ce Sun <sunc@lemote.com>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> ---
> drivers/tty/serial/8250/8250_core.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 240a361..e8819aa 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -675,7 +675,7 @@ static struct console univ8250_console = {
> .device = uart_console_device,
> .setup = univ8250_console_setup,
> .match = univ8250_console_match,
> - .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_CONSDEV,
> + .flags = CON_PRINTBUFFER | CON_ANYTIME,
> .index = -1,
> .data = &serial8250_reg,
> };
Odd. Matthew, any thoughts here? This seems to be the opposite of why
you submitted this change...
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH v3 2/2] arm64: Support systems without FP/ASIMD
From: Catalin Marinas @ 2016-11-14 11:48 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: linux-arm-kernel, mark.rutland, ard.biesheuvel, marc.zyngier,
will.deacon, linux-kernel, kvmarm, Christoffer Dall
In-Reply-To: <1478613381-5718-3-git-send-email-suzuki.poulose@arm.com>
Hi Suzuki,
On Tue, Nov 08, 2016 at 01:56:21PM +0000, Suzuki K. Poulose wrote:
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index 87b4465..4174f09 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -34,7 +34,8 @@
> #define ARM64_HAS_32BIT_EL0 13
> #define ARM64_HYP_OFFSET_LOW 14
> #define ARM64_MISMATCHED_CACHE_LINE_SIZE 15
> +#define ARM64_HAS_NO_FPSIMD 16
>
> -#define ARM64_NCAPS 16
> +#define ARM64_NCAPS 17
>
> #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 9890d20..ce45770 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -213,6 +213,11 @@ static inline bool system_supports_mixed_endian_el0(void)
> return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
> }
>
> +static inline bool system_supports_fpsimd(void)
> +{
> + return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
> +}
Any particular reason why using negation instead of a ARM64_HAS_FPSIMD?
A potential problem would be the default cpus_have_const_cap()
implementation and the default static key having a slight performance
impact.
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index fc2bd19..f89385d 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -746,6 +746,14 @@ static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry,
> return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode();
> }
>
> +static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unused)
> +{
> + u64 pfr0 = read_system_reg(SYS_ID_AA64PFR0_EL1);
> +
> + return cpuid_feature_extract_signed_field(pfr0,
> + ID_AA64PFR0_FP_SHIFT) < 0;
> +}
> +
> static const struct arm64_cpu_capabilities arm64_features[] = {
> {
> .desc = "GIC system register CPU interface",
> @@ -829,6 +837,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> .def_scope = SCOPE_SYSTEM,
> .matches = hyp_offset_low,
> },
> + {
> + /* FP/SIMD is not implemented */
> + .capability = ARM64_HAS_NO_FPSIMD,
> + .def_scope = SCOPE_SYSTEM,
> + .min_field_value = 0,
> + .matches = has_no_fpsimd,
> + },
If we go for negation, I don't think we need a min_field_value at all,
the matching is done by the has_no_fpsimd() function.
--
Catalin
^ permalink raw reply
* [RFC][PATCH 2/2] fsnotify: handle permission events without holding fsnotify_mark_srcu[0]
From: Amir Goldstein @ 2016-11-14 11:48 UTC (permalink / raw)
To: Jan Kara
Cc: Jeff Layton, Miklos Szeredi, Eric Paris, Eryu Guan, linux-kernel,
linux-fsdevel
In-Reply-To: <1479124107-8477-1-git-send-email-amir73il@gmail.com>
Handling fanotify events does not entail dereferencing fsnotify_mark
beyond the point of fanotify_should_send_event().
For the case of permission events, which may block indefinitely,
return -EAGAIN and then fsnotify() will call handle_event() again
without a reference to the mark.
Without a reference to the mark, there is no need to call
handle_event() under fsnotify_mark_srcu[0] read side lock,
so we drop fsnotify_mark_srcu[0] while handling the event
and grab it back before continuing to the next mark.
After this change, a blocking permission event will no longer
block closing of any file descriptors of 0 priority groups,
i.e: inotify and fanotify groups of class FAN_CLASS_NOTIF.
Reported-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/notify/fanotify/fanotify.c | 15 +++++++++++----
fs/notify/fsnotify.c | 23 +++++++++++++++++++++++
2 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index e0e5f7c..c7689ad 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -176,7 +176,7 @@ init: __maybe_unused
static int fanotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *fanotify_mark,
+ struct fsnotify_mark *vfsmnt_mark,
u32 mask, void *data, int data_type,
const unsigned char *file_name, u32 cookie)
{
@@ -195,9 +195,16 @@ static int fanotify_handle_event(struct fsnotify_group *group,
BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
- if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data,
- data_type))
- return 0;
+ if (inode_mark || vfsmnt_mark) {
+ if (!fanotify_should_send_event(inode_mark, vfsmnt_mark, mask,
+ data, data_type))
+ return 0;
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+ /* Ask to be called again without a reference to mark */
+ if (mask & FAN_ALL_PERM_EVENTS)
+ return -EAGAIN;
+#endif
+ }
pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
mask);
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index af5c523a..5b9a248 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -291,6 +291,29 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
data, data_is, cookie, file_name);
+ /*
+ * If handle_event() is going to block, we call it again
+ * witout holding fsnotify_mark_srcu[0], which is protecting
+ * the low priority mark lists.
+ * We are still holding fsnotify_mark_srcu[1], which
+ * is protecting the high priority marks in the first half
+ * of the mark list, which is where we are at.
+ */
+ if (group->priority > 0 && ret == -EAGAIN) {
+ srcu_read_unlock(&fsnotify_mark_srcu[0], idx);
+
+ ret = group->ops->handle_event(group, to_tell,
+ NULL, NULL,
+ mask, data, data_is,
+ file_name, cookie);
+
+ /*
+ * We need to hold fsnotify_mark_srcu[0], because
+ * next mark may be low priority.
+ */
+ idx = srcu_read_lock(&fsnotify_mark_srcu[0]);
+ }
+
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
goto out;
--
2.7.4
^ permalink raw reply related
* [RFC][PATCH 1/2] fsnotify: separate fsnotify_mark_srcu for groups with permission events
From: Amir Goldstein @ 2016-11-14 11:48 UTC (permalink / raw)
To: Jan Kara
Cc: Jeff Layton, Miklos Szeredi, Eric Paris, Eryu Guan, linux-kernel,
linux-fsdevel
In-Reply-To: <1479124107-8477-1-git-send-email-amir73il@gmail.com>
fsnotify_mark_srcu[1] protects reads of the first half of inode/vfsmount
mark lists, which consist of the high priority (>0) marks, whose masks
may contain permission events.
fsnotify_mark_srcu[0] protects reads of the second half of inode/vfsmount
mark lists, which consist of the low priority (0) marks, whose masks
do not contain permission events.
High priority marks and low priority marks are added to different
destroy lists and freed by different reapers, who synchronize only
the relevant srcu.
A follow up change will use this separation to guaranty that
destroying low priority groups will not block on handling of
permission events.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/notify/fsnotify.c | 34 ++++++++++++++++++-----
fs/notify/fsnotify.h | 17 ++++++++++--
fs/notify/group.c | 2 +-
fs/notify/mark.c | 77 +++++++++++++++++++++++++++++++++++++++-------------
4 files changed, 100 insertions(+), 30 deletions(-)
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index db39de2..af5c523a 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -192,9 +192,10 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
{
struct hlist_node *inode_node = NULL, *vfsmount_node = NULL;
struct fsnotify_mark *inode_mark = NULL, *vfsmount_mark = NULL;
- struct fsnotify_group *inode_group, *vfsmount_group;
+ struct fsnotify_group *inode_group, *vfsmount_group, *group;
struct mount *mnt;
- int idx, ret = 0;
+ int perm_idx, idx;
+ int ret = 0;
/* global tests shouldn't care about events on child only the specific event */
__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
@@ -223,7 +224,14 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
!(mnt && test_mask & mnt->mnt_fsnotify_mask))
return 0;
- idx = srcu_read_lock(&fsnotify_mark_srcu);
+ /*
+ * First mark on the list may be either low or high priority, so
+ * when traversing to first mark we must hold read side of both srcu.
+ * When we reach the first low priority mark, we may drop the
+ * read side of fsnotify_mark_srcu[1]
+ */
+ idx = srcu_read_lock(&fsnotify_mark_srcu[0]);
+ perm_idx = srcu_read_lock(&fsnotify_mark_srcu[1]);
if ((mask & FS_MODIFY) ||
(test_mask & to_tell->i_fsnotify_mask))
@@ -252,13 +260,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
if (inode_node) {
inode_mark = hlist_entry(srcu_dereference(inode_node, &fsnotify_mark_srcu),
struct fsnotify_mark, obj_list);
- inode_group = inode_mark->group;
+ group = inode_group = inode_mark->group;
}
if (vfsmount_node) {
vfsmount_mark = hlist_entry(srcu_dereference(vfsmount_node, &fsnotify_mark_srcu),
struct fsnotify_mark, obj_list);
- vfsmount_group = vfsmount_mark->group;
+ group = vfsmount_group = vfsmount_mark->group;
}
if (inode_group && vfsmount_group) {
@@ -270,8 +278,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
} else if (cmp < 0) {
vfsmount_group = NULL;
vfsmount_mark = NULL;
+ group = inode_group;
}
}
+
+ if (group->priority == 0 && perm_idx >= 0) {
+ /* We are done iterating the high priority marks */
+ srcu_read_unlock(&fsnotify_mark_srcu[1], perm_idx);
+ perm_idx = -1;
+ }
+
ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
data, data_is, cookie, file_name);
@@ -287,7 +303,9 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
}
ret = 0;
out:
- srcu_read_unlock(&fsnotify_mark_srcu, idx);
+ srcu_read_unlock(&fsnotify_mark_srcu[0], idx);
+ if (perm_idx >= 0)
+ srcu_read_unlock(&fsnotify_mark_srcu[1], perm_idx);
return ret;
}
@@ -299,7 +317,9 @@ static __init int fsnotify_init(void)
BUG_ON(hweight32(ALL_FSNOTIFY_EVENTS) != 23);
- ret = init_srcu_struct(&fsnotify_mark_srcu);
+ ret = init_srcu_struct(&fsnotify_mark_srcu[0]);
+ if (!ret)
+ ret = init_srcu_struct(&fsnotify_mark_srcu[1]);
if (ret)
panic("initializing fsnotify_mark_srcu");
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h
index 0a3bc2c..c1d6ae6 100644
--- a/fs/notify/fsnotify.h
+++ b/fs/notify/fsnotify.h
@@ -11,8 +11,19 @@
/* destroy all events sitting in this groups notification queue */
extern void fsnotify_flush_notify(struct fsnotify_group *group);
-/* protects reads of inode and vfsmount marks list */
-extern struct srcu_struct fsnotify_mark_srcu;
+/*
+ * fsnotify_mark_srcu[1] protects reads of the first half of inode/vfsmount
+ * mark lists, which consist of the high priority (>0) marks, whose masks
+ * may contain permission events.
+ *
+ * fsnotify_mark_srcu[0] protects reads of the second half of inode/vfsmount
+ * mark lists, which consist of the low priority (0) marks, whose masks
+ * do not contain permission events.
+ */
+#define FS_PRIO_SRCU(prio) ((int)(prio > FS_PRIO_0))
+#define FS_PRIO_SRCU_NUM 2
+
+extern struct srcu_struct fsnotify_mark_srcu[FS_PRIO_SRCU_NUM];
/* Calculate mask of events for a list of marks */
extern u32 fsnotify_recalc_mask(struct hlist_head *head);
@@ -61,7 +72,7 @@ extern void fsnotify_detach_group_marks(struct fsnotify_group *group);
/*
* wait for fsnotify_mark_srcu period to end and free all marks in destroy_list
*/
-extern void fsnotify_mark_destroy_list(void);
+extern void fsnotify_mark_destroy_list(int priority);
/*
* update the dentry->d_flags of all of inode's children to indicate if inode cares
diff --git a/fs/notify/group.c b/fs/notify/group.c
index fbe3cbe..ef946c0 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -73,7 +73,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
* Wait for fsnotify_mark_srcu period to end and free all marks in
* destroy_list
*/
- fsnotify_mark_destroy_list();
+ fsnotify_mark_destroy_list(group->priority);
/*
* Since we have waited for fsnotify_mark_srcu in
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index d3fea0b..44e39a5 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -93,12 +93,50 @@
#define FSNOTIFY_REAPER_DELAY (1) /* 1 jiffy */
-struct srcu_struct fsnotify_mark_srcu;
+/*
+ * fsnotify_mark_srcu[1] protects reads of the first half of inode/vfsmount
+ * mark lists, which consist of the high priority (>0) marks, whose masks
+ * may contain permission events.
+ *
+ * fsnotify_mark_srcu[0] protects reads of the second half of inode/vfsmount
+ * mark lists, which consist of the low priority (0) marks, whose masks
+ * do not contain permission events.
+ *
+ * High priority marks and low priority marks are added to different
+ * destroy lists and freed by different reapers, who synchronize only
+ * the relevant srcu.
+ */
+struct srcu_struct fsnotify_mark_srcu[FS_PRIO_SRCU_NUM];
static DEFINE_SPINLOCK(destroy_lock);
-static LIST_HEAD(destroy_list);
+static LIST_HEAD(destroy_list_0);
+static LIST_HEAD(destroy_list_1);
+static struct list_head *destroy_lists[FS_PRIO_SRCU_NUM] = {
+ &destroy_list_0,
+ &destroy_list_1
+};
static void fsnotify_mark_destroy_workfn(struct work_struct *work);
-static DECLARE_DELAYED_WORK(reaper_work, fsnotify_mark_destroy_workfn);
+static DECLARE_DELAYED_WORK(reaper_work_0, fsnotify_mark_destroy_workfn);
+static DECLARE_DELAYED_WORK(reaper_work_1, fsnotify_mark_destroy_workfn);
+static struct delayed_work *reapers[FS_PRIO_SRCU_NUM] = {
+ &reaper_work_0,
+ &reaper_work_1
+};
+
+static inline void fsnotify_destroy_list_add(struct fsnotify_mark *mark,
+ int priority)
+{
+ spin_lock(&destroy_lock);
+ list_add(&mark->g_list, destroy_lists[FS_PRIO_SRCU(priority)]);
+ spin_unlock(&destroy_lock);
+}
+
+static inline void fsnotify_destroy_list_reap(int priority)
+{
+ queue_delayed_work(system_unbound_wq,
+ reapers[FS_PRIO_SRCU(priority)],
+ FSNOTIFY_REAPER_DELAY);
+}
void fsnotify_get_mark(struct fsnotify_mark *mark)
{
@@ -202,9 +240,7 @@ static bool __fsnotify_free_mark(struct fsnotify_mark *mark)
if (group->ops->freeing_mark)
group->ops->freeing_mark(mark, group);
- spin_lock(&destroy_lock);
- list_add(&mark->g_list, &destroy_list);
- spin_unlock(&destroy_lock);
+ fsnotify_destroy_list_add(mark, group->priority);
return true;
}
@@ -216,10 +252,8 @@ static bool __fsnotify_free_mark(struct fsnotify_mark *mark)
*/
void fsnotify_free_mark(struct fsnotify_mark *mark)
{
- if (__fsnotify_free_mark(mark)) {
- queue_delayed_work(system_unbound_wq, &reaper_work,
- FSNOTIFY_REAPER_DELAY);
- }
+ if (__fsnotify_free_mark(mark))
+ fsnotify_destroy_list_reap(mark->group->priority);
}
void fsnotify_destroy_mark(struct fsnotify_mark *mark,
@@ -407,11 +441,8 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
spin_unlock(&mark->lock);
- spin_lock(&destroy_lock);
- list_add(&mark->g_list, &destroy_list);
- spin_unlock(&destroy_lock);
- queue_delayed_work(system_unbound_wq, &reaper_work,
- FSNOTIFY_REAPER_DELAY);
+ fsnotify_destroy_list_add(mark, group->priority);
+ fsnotify_destroy_list_reap(group->priority);
return ret;
}
@@ -537,18 +568,26 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
/*
* Destroy all marks in destroy_list, waits for SRCU period to finish before
* actually freeing marks.
+ * High priority (>0) marks are on destroy_lists[1] and protected by
+ * fsnotify_mark_srcu[1].
+ * Low priority (0) marks are on destroy_lists[0] and protected by
+ * fsnotify_mark_srcu[0].
*/
-void fsnotify_mark_destroy_list(void)
+void fsnotify_mark_destroy_list(int priority)
{
struct fsnotify_mark *mark, *next;
struct list_head private_destroy_list;
+ int id = FS_PRIO_SRCU(priority);
spin_lock(&destroy_lock);
/* exchange the list head */
- list_replace_init(&destroy_list, &private_destroy_list);
+ list_replace_init(destroy_lists[id], &private_destroy_list);
spin_unlock(&destroy_lock);
- synchronize_srcu(&fsnotify_mark_srcu);
+ if (list_empty(&private_destroy_list))
+ return;
+
+ synchronize_srcu(&fsnotify_mark_srcu[id]);
list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) {
list_del_init(&mark->g_list);
@@ -558,5 +597,5 @@ void fsnotify_mark_destroy_list(void)
static void fsnotify_mark_destroy_workfn(struct work_struct *work)
{
- fsnotify_mark_destroy_list();
+ fsnotify_mark_destroy_list((void *)work != reapers[0]);
}
--
2.7.4
^ permalink raw reply related
* [PATCH v3 2/2] arm64: Support systems without FP/ASIMD
From: Catalin Marinas @ 2016-11-14 11:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1478613381-5718-3-git-send-email-suzuki.poulose@arm.com>
Hi Suzuki,
On Tue, Nov 08, 2016 at 01:56:21PM +0000, Suzuki K. Poulose wrote:
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index 87b4465..4174f09 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -34,7 +34,8 @@
> #define ARM64_HAS_32BIT_EL0 13
> #define ARM64_HYP_OFFSET_LOW 14
> #define ARM64_MISMATCHED_CACHE_LINE_SIZE 15
> +#define ARM64_HAS_NO_FPSIMD 16
>
> -#define ARM64_NCAPS 16
> +#define ARM64_NCAPS 17
>
> #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 9890d20..ce45770 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -213,6 +213,11 @@ static inline bool system_supports_mixed_endian_el0(void)
> return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
> }
>
> +static inline bool system_supports_fpsimd(void)
> +{
> + return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
> +}
Any particular reason why using negation instead of a ARM64_HAS_FPSIMD?
A potential problem would be the default cpus_have_const_cap()
implementation and the default static key having a slight performance
impact.
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index fc2bd19..f89385d 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -746,6 +746,14 @@ static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry,
> return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode();
> }
>
> +static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unused)
> +{
> + u64 pfr0 = read_system_reg(SYS_ID_AA64PFR0_EL1);
> +
> + return cpuid_feature_extract_signed_field(pfr0,
> + ID_AA64PFR0_FP_SHIFT) < 0;
> +}
> +
> static const struct arm64_cpu_capabilities arm64_features[] = {
> {
> .desc = "GIC system register CPU interface",
> @@ -829,6 +837,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> .def_scope = SCOPE_SYSTEM,
> .matches = hyp_offset_low,
> },
> + {
> + /* FP/SIMD is not implemented */
> + .capability = ARM64_HAS_NO_FPSIMD,
> + .def_scope = SCOPE_SYSTEM,
> + .min_field_value = 0,
> + .matches = has_no_fpsimd,
> + },
If we go for negation, I don't think we need a min_field_value at all,
the matching is done by the has_no_fpsimd() function.
--
Catalin
^ permalink raw reply
* [RFC][PATCH 0/2] fsnotify: reduce coupling of permission and non permission events
From: Amir Goldstein @ 2016-11-14 11:48 UTC (permalink / raw)
To: Jan Kara
Cc: Jeff Layton, Miklos Szeredi, Eric Paris, Eryu Guan, linux-kernel,
linux-fsdevel
The issue reported by Miklos Szeredi was processes blocking when trying
to close an inotify file descriptor, while another fanotify listener is
failing to handle permission events.
Miklos included a test program with the report.
His test program with some modifications is available on my github:
https://github.com/amir73il/fsnotify-utils/blob/master/fanotify_bug.c
Ideally, we would want that destruction of a group would only block
if an event handled by this group is in progress, but this is not easy
to achieve. Instead, we make sure that destrurction of a group would
only block if an event handled by a group of similar class (priority)
is in progress.
Amir Goldstein (2):
fsnotify: separate fsnotify_mark_srcu for groups with permission
events
fsnotify: handle permission events without holding
fsnotify_mark_srcu[0]
fs/notify/fanotify/fanotify.c | 15 ++++++---
fs/notify/fsnotify.c | 57 ++++++++++++++++++++++++++++----
fs/notify/fsnotify.h | 17 ++++++++--
fs/notify/group.c | 2 +-
fs/notify/mark.c | 77 ++++++++++++++++++++++++++++++++-----------
5 files changed, 134 insertions(+), 34 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: [PATCH] broadcom/brcm80211/brcmfmac/cfg80211 driver, bad regulatory domain frequency value
From: Gianfranco Costamagna @ 2016-11-14 11:47 UTC (permalink / raw)
To: Arend Van Spriel, brcm80211-dev-list@broadcom.com,
linux-wireless@vger.kernel.org
Cc: nsmaldone@tierratelematics.com, Marco.Arlone@roj.com
In-Reply-To: <fba3cf06-917f-f1c9-6735-f166a18aa222@broadcom.com>
[-- Attachment #1: Type: text/plain, Size: 465 bytes --]
Hi Arend,
>Well, not before you pointed it out ;-). You are welcome to send a patch
>fixing it. Otherwise, I will take care of it.
attaching a format-patch like version.
I don't think we need a Tested-by or whatever, because it is just a typo in a comment.
(this is my first contribution, feel free to rebase or change whatever you prefer
to make it in line with other styles)
(I gave authorship to Marco, the first one who discovered such typo)
thanks!
G.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-cfg80211-fix-typo-in-REG-channel-frequency-comment.patch --]
[-- Type: text/x-diff, Size: 1229 bytes --]
From bf0cdd8ad27833639447a3071d662f79a7219b1d Mon Sep 17 00:00:00 2001
From: Arlone Marco <marco.arlone@roj.com>
Date: Sat, 22 Oct 2016 15:08:35 +0200
Subject: [PATCH] broadcom cfg80211: fix typo in REG channel frequency comment
frequency 2472 corresponds to channel 13, not channel 11
Signed-off-by: Gianfranco Costamagna <gianfranco.costamagna@abinsula.com>
Signed-off-by: Nicola Smaldone <nicola.smaldone@tierraservice.com>
Signed-off-by: Arlone Marco <marco.arlone@roj.com>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index b777e1b..b4d8b1b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -203,7 +203,7 @@ static const struct ieee80211_regdomain brcmf_regdom = {
.n_reg_rules = 4,
.alpha2 = "99",
.reg_rules = {
- /* IEEE 802.11b/g, channels 1..11 */
+ /* IEEE 802.11b/g, channels 1..13 */
REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
/* If any */
/* IEEE 802.11 channel 14 - Only JP enables
--
2.7.4
^ permalink raw reply related
* Re: [PATCH v3 2/2] arm64: Support systems without FP/ASIMD
From: Catalin Marinas @ 2016-11-14 11:48 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: ard.biesheuvel, marc.zyngier, will.deacon, linux-kernel, kvmarm,
linux-arm-kernel
In-Reply-To: <1478613381-5718-3-git-send-email-suzuki.poulose@arm.com>
Hi Suzuki,
On Tue, Nov 08, 2016 at 01:56:21PM +0000, Suzuki K. Poulose wrote:
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index 87b4465..4174f09 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -34,7 +34,8 @@
> #define ARM64_HAS_32BIT_EL0 13
> #define ARM64_HYP_OFFSET_LOW 14
> #define ARM64_MISMATCHED_CACHE_LINE_SIZE 15
> +#define ARM64_HAS_NO_FPSIMD 16
>
> -#define ARM64_NCAPS 16
> +#define ARM64_NCAPS 17
>
> #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 9890d20..ce45770 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -213,6 +213,11 @@ static inline bool system_supports_mixed_endian_el0(void)
> return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
> }
>
> +static inline bool system_supports_fpsimd(void)
> +{
> + return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
> +}
Any particular reason why using negation instead of a ARM64_HAS_FPSIMD?
A potential problem would be the default cpus_have_const_cap()
implementation and the default static key having a slight performance
impact.
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index fc2bd19..f89385d 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -746,6 +746,14 @@ static bool hyp_offset_low(const struct arm64_cpu_capabilities *entry,
> return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode();
> }
>
> +static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unused)
> +{
> + u64 pfr0 = read_system_reg(SYS_ID_AA64PFR0_EL1);
> +
> + return cpuid_feature_extract_signed_field(pfr0,
> + ID_AA64PFR0_FP_SHIFT) < 0;
> +}
> +
> static const struct arm64_cpu_capabilities arm64_features[] = {
> {
> .desc = "GIC system register CPU interface",
> @@ -829,6 +837,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
> .def_scope = SCOPE_SYSTEM,
> .matches = hyp_offset_low,
> },
> + {
> + /* FP/SIMD is not implemented */
> + .capability = ARM64_HAS_NO_FPSIMD,
> + .def_scope = SCOPE_SYSTEM,
> + .min_field_value = 0,
> + .matches = has_no_fpsimd,
> + },
If we go for negation, I don't think we need a min_field_value at all,
the matching is done by the has_no_fpsimd() function.
--
Catalin
^ permalink raw reply
* Re: [PATCH v3 08/14] drm/i915/scheduler: Execute requests in order of priorities
From: Tvrtko Ursulin @ 2016-11-14 11:48 UTC (permalink / raw)
To: Chris Wilson, intel-gfx
In-Reply-To: <20161114114113.GE32240@nuc-i3427.alporthouse.com>
On 14/11/2016 11:41, Chris Wilson wrote:
> On Mon, Nov 14, 2016 at 11:15:52AM +0000, Tvrtko Ursulin wrote:
>> On 14/11/2016 08:56, Chris Wilson wrote:
>>> +static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
>>> +{
>>> + struct intel_engine_cs *engine = NULL;
>>> + struct i915_dependency *dep, *p;
>>> + struct i915_dependency stack;
>>> + LIST_HEAD(dfs);
>>> +
>>> + if (prio <= READ_ONCE(request->priotree.priority))
>>> + return;
>>> +
>>> + /* Need BKL in order to use the temporary link inside i915_dependency */
>>> + lockdep_assert_held(&request->i915->drm.struct_mutex);
>>> +
>>> + stack.signaler = &request->priotree;
>>> + list_add(&stack.dfs_link, &dfs);
>>> +
>>> + /* Recursively bump all dependent priorities to match the new request */
>>
>> Missed last time round that the comment needs updating.
>
> It still is a recursive design though, just flat. That one word was
> saving a paragraph :|
>
> I think the easiest way to describe what the code is doing here is to
> show the recursive version in the comment and then hope for inspiration
> in describing how that maps onto the search list.
I can see that angle yes. Maybe the just add a second sentence saying
something like "To avoid having recursive code to do this recursive
update we build a flat list of dependencies in a depth first search
manner."?
Regards,
Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.