* [linux-sunxi] [PATCH 3/5] Input: add driver for Ilitek ili2139 touch IC
From: Hans de Goede @ 2016-10-11 9:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161011003359.26079-3-icenowy@aosc.xyz>
Hi,
On 10/11/2016 02:33 AM, Icenowy Zheng wrote:
> This driver adds support for Ilitek ili2139 touch IC, which is used in
> several Colorfly tablets (for example, Colorfly E708 Q1, which is an
> Allwinner A31s tablet with mainline kernel support).
>
> Theortically it may support more Ilitek touch ICs, however, only ili2139
> is used in any mainlined device.
>
> It supports device tree enumeration, with screen resolution and axis
> quirks configurable.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
> ---
> drivers/input/touchscreen/Kconfig | 14 ++
> drivers/input/touchscreen/Makefile | 1 +
> drivers/input/touchscreen/ili2139.c | 320 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 335 insertions(+)
> create mode 100644 drivers/input/touchscreen/ili2139.c
>
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 5079813..bb4d9d2 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -348,6 +348,20 @@ config TOUCHSCREEN_ILI210X
> To compile this driver as a module, choose M here: the
> module will be called ili210x.
>
> +config TOUCHSCREEN_ILI2139
> + tristate "Ilitek ILI2139 based touchscreen"
> + depends on I2C
> + depends on OF
> + help
> + Say Y here if you have a ILI2139 based touchscreen
> + controller. Such kind of chipsets can be found in several
> + Colorfly tablets.
> +
> + If unsure, say N.
> +
> + To compile this driver as a module, choose M here; the
> + module will be called ili2139.
> +
> config TOUCHSCREEN_IPROC
> tristate "IPROC touch panel driver support"
> depends on ARCH_BCM_IPROC || COMPILE_TEST
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 81b8645..930b5e2 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o
> obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
> obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
> obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
> +obj-$(CONFIG_TOUCHSCREEN_ILI2139) += ili2139.o
> obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o
> obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
> obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
> diff --git a/drivers/input/touchscreen/ili2139.c b/drivers/input/touchscreen/ili2139.c
> new file mode 100644
> index 0000000..65c2dea
> --- /dev/null
> +++ b/drivers/input/touchscreen/ili2139.c
> @@ -0,0 +1,320 @@
> +/* -------------------------------------------------------------------------
> + * Copyright (C) 2016, Icenowy Zheng <icenowy@aosc.xyz>
> + *
> + * Derived from:
> + * ili210x.c
> + * Copyright (C) Olivier Sobrie <olivier@sobrie.be>
> + *
> + * 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/module.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/slab.h>
> +#include <linux/input.h>
> +#include <linux/input/mt.h>
> +#include <linux/input/touchscreen.h>
> +#include <linux/delay.h>
> +#include <linux/workqueue.h>
> +
> +#define DEFAULT_POLL_PERIOD 20
> +
> +#define MAX_TOUCHES 10
> +#define COMPATIBLE_TOUCHES 2
> +
> +/* Touchscreen commands */
> +#define REG_TOUCHDATA 0x10
> +#define REG_TOUCHSUBDATA 0x11
> +#define REG_PANEL_INFO 0x20
> +#define REG_FIRMWARE_VERSION 0x40
> +#define REG_PROTO_VERSION 0x42
> +
> +#define SUBDATA_STATUS_TOUCH_POINT 0x80
> +#define SUBDATA_STATUS_RELEASE_POINT 0x00
> +
> +struct finger {
> + u8 x_low;
> + u8 x_high;
> + u8 y_low;
> + u8 y_high;
> +} __packed;
> +
> +struct touchdata {
> + u8 length;
> + struct finger finger[COMPATIBLE_TOUCHES];
> +} __packed;
> +
> +struct touch_subdata {
> + u8 status;
> + struct finger finger;
> +} __packed;
> +
> +struct panel_info {
> + struct finger finger_max;
> + u8 xchannel_num;
> + u8 ychannel_num;
> +} __packed;
> +
> +struct firmware_version {
> + u8 id;
> + u8 major;
> + u8 minor;
> +} __packed;
> +
> +struct ili2139 {
> + struct i2c_client *client;
> + struct input_dev *input;
> + unsigned int poll_period;
> + struct delayed_work dwork;
> + struct touchscreen_properties prop;
> + int slots[MAX_TOUCHES];
> + int ids[MAX_TOUCHES];
> + struct input_mt_pos pos[MAX_TOUCHES];
> +};
> +
> +static int ili2139_read_reg(struct i2c_client *client, u8 reg, void *buf,
> + size_t len)
> +{
> + struct i2c_msg msg[2] = {
> + {
> + .addr = client->addr,
> + .flags = 0,
> + .len = 1,
> + .buf = ®,
> + },
> + {
> + .addr = client->addr,
> + .flags = I2C_M_RD,
> + .len = len,
> + .buf = buf,
> + }
> + };
> +
> + if (i2c_transfer(client->adapter, msg, 2) != 2) {
> + dev_err(&client->dev, "i2c transfer failed\n");
> + return -EIO;
> + }
> +
> + return 0;
> +}
This just i2c_smbus_read_i2c_block_data, please use that instead.
> +static void ili2139_work(struct work_struct *work)
> +{
> + int id;
> + struct ili2139 *priv = container_of(work, struct ili2139,
> + dwork.work);
> + struct i2c_client *client = priv->client;
> + struct touchdata touchdata;
> + struct touch_subdata subdata;
> + int error;
> +
> + error = ili2139_read_reg(client, REG_TOUCHDATA,
> + &touchdata, sizeof(touchdata));
> + if (error) {
> + dev_err(&client->dev,
> + "Unable to get touchdata, err = %d\n", error);
> + return;
> + }
> +
> + for (id = 0; id < touchdata.length; id++) {
> + error = ili2139_read_reg(client, REG_TOUCHSUBDATA, &subdata,
> + sizeof(subdata));
> + if (error) {
> + dev_err(&client->dev,
> + "Unable to get touch subdata, err = %d\n",
> + error);
> + return;
> + }
> +
> + priv->ids[id] = subdata.status & 0x3F;
> +
> + /* The sequence changed in the v2 subdata protocol. */
> + touchscreen_set_mt_pos(&priv->pos[id], &priv->prop,
> + (subdata.finger.x_high | (subdata.finger.x_low << 8)),
> + (subdata.finger.y_high | (subdata.finger.y_low << 8)));
> + }
> +
> + input_mt_assign_slots(priv->input, priv->slots, priv->pos,
> + touchdata.length, 0);
> +
> + for (id = 0; id < touchdata.length; id++) {
> + input_mt_slot(priv->input, priv->slots[id]);
> + input_mt_report_slot_state(priv->input, MT_TOOL_FINGER,
> + subdata.status &
> + SUBDATA_STATUS_TOUCH_POINT);
> + input_report_abs(priv->input, ABS_MT_POSITION_X,
> + priv->pos[id].x);
> + input_report_abs(priv->input, ABS_MT_POSITION_Y,
> + priv->pos[id].y);
> + }
> +
> + input_mt_sync_frame(priv->input);
> + input_sync(priv->input);
> +
> + schedule_delayed_work(&priv->dwork,
> + msecs_to_jiffies(priv->poll_period));
If the irq is working properly there should be no need for this,
can you try with this schedule call removed ?
> +}
> +
> +static irqreturn_t ili2139_irq(int irq, void *irq_data)
> +{
> + struct ili2139 *priv = irq_data;
> +
> + schedule_delayed_work(&priv->dwork, 0);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int ili2139_i2c_probe(struct i2c_client *client,
> + const struct i2c_device_id *id)
> +{
> + struct device *dev = &client->dev;
> + struct ili2139 *priv;
> + struct input_dev *input;
> + struct panel_info panel;
> + struct firmware_version firmware;
> + int xmax, ymax;
> + int error;
> +
> + dev_dbg(dev, "Probing for ILI2139 I2C Touschreen driver");
> +
> + if (client->irq <= 0) {
> + dev_err(dev, "No IRQ!\n");
> + return -ENODEV;
> + }
> +
> + /* Get firmware version */
> + error = ili2139_read_reg(client, REG_FIRMWARE_VERSION,
> + &firmware, sizeof(firmware));
> + if (error) {
> + dev_err(dev, "Failed to get firmware version, err: %d\n",
> + error);
> + return error;
> + }
> +
> + /* get panel info */
> + error = ili2139_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
> + if (error) {
> + dev_err(dev, "Failed to get panel information, err: %d\n",
> + error);
> + return error;
> + }
> +
> + xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
> + ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + input = devm_input_allocate_device(dev);
> + if (!priv || !input)
> + return -ENOMEM;
> +
> + priv->client = client;
> + priv->input = input;
> + priv->poll_period = DEFAULT_POLL_PERIOD;
> + INIT_DELAYED_WORK(&priv->dwork, ili2139_work);
> +
> + /* Setup input device */
> + input->name = "ILI2139 Touchscreen";
> + input->id.bustype = BUS_I2C;
> + input->dev.parent = dev;
> +
> + __set_bit(EV_SYN, input->evbit);
> + __set_bit(EV_KEY, input->evbit);
> + __set_bit(EV_ABS, input->evbit);
> +
> + /* Multi touch */
> + input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_DIRECT |
> + INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);
> + input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
> + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
> +
> + touchscreen_parse_properties(input, true, &priv->prop);
> +
> + input_set_drvdata(input, priv);
> + i2c_set_clientdata(client, priv);
> +
> + error = devm_request_irq(dev, client->irq, ili2139_irq,
> + IRQF_TRIGGER_FALLING, client->name, priv);
If things work with the re-scheduleing of the delayed work
from the work removed, then you can use request_threaded_irq here,
pass in ili2139_irq as the threaded handler (and NULL as the non threaded
handler) and do all the i2c reading directly in ili2139_irq without needing
to use any work struct at all.
Regards,
Hans
> + if (error) {
> + dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
> + error);
> + return error;
> + }
> +
> + error = input_register_device(priv->input);
> + if (error) {
> + dev_err(dev, "Cannot register input device, err: %d\n", error);
> + return error;
> + }
> +
> + device_init_wakeup(&client->dev, 1);
> +
> + dev_dbg(dev,
> + "ILI2139 initialized (IRQ: %d), firmware version %d.%d.%d",
> + client->irq, firmware.id, firmware.major, firmware.minor);
> +
> + return 0;
> +}
> +
> +static int ili2139_i2c_remove(struct i2c_client *client)
> +{
> + struct ili2139 *priv = i2c_get_clientdata(client);
> +
> + cancel_delayed_work_sync(&priv->dwork);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused ili2139_i2c_suspend(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> +
> + if (device_may_wakeup(&client->dev))
> + enable_irq_wake(client->irq);
> +
> + return 0;
> +}
> +
> +static int __maybe_unused ili2139_i2c_resume(struct device *dev)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> +
> + if (device_may_wakeup(&client->dev))
> + disable_irq_wake(client->irq);
> +
> + return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(ili2139_i2c_pm,
> + ili2139_i2c_suspend, ili2139_i2c_resume);
> +
> +static const struct i2c_device_id ili2139_i2c_id[] = {
> + { "ili2139", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, ili2139_i2c_id);
> +
> +static struct i2c_driver ili2139_ts_driver = {
> + .driver = {
> + .name = "ili2139_i2c",
> + .pm = &ili2139_i2c_pm,
> + },
> + .id_table = ili2139_i2c_id,
> + .probe = ili2139_i2c_probe,
> + .remove = ili2139_i2c_remove,
> +};
> +
> +module_i2c_driver(ili2139_ts_driver);
> +
> +MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
> +MODULE_DESCRIPTION("ILI2139 I2C Touchscreen Driver");
> +MODULE_LICENSE("GPL");
>
^ permalink raw reply
* [PATCH 2/9] drm/sun4i: tcon: Move SoC specific quirks to a DT matched data structure
From: Maxime Ripard @ 2016-10-11 9:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGb2v67vZLCtUOaqBwtAnHmCMpoxmh3pxjtD5TL2nWp3Lm-Pzg@mail.gmail.com>
On Tue, Oct 11, 2016 at 05:16:21PM +0800, Chen-Yu Tsai wrote:
> On Fri, Oct 7, 2016 at 4:38 PM, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Hi,
> >
> > On Fri, Oct 07, 2016 at 12:06:22AM +0800, Chen-Yu Tsai wrote:
> >> +struct sun4i_tcon_quirks {
> >> + bool is_sun5i; /* sun5i has undocumented mux */
> >> + bool has_channel_1; /* a33 does not have channel 1 */
> >> + bool has_bypass_src; /* has separate input bypassing CEU */
> >> + bool has_dma_src; /* has DMA input */
> >> +};
> >> +
> >
> > I'd really prefer to keep the has_mux quirk name. is_sun5i doesn't
> > really relate to what we're doing there, is redundant with the
> > compatible, and render the other quirks name useless, since we could
> > just have is_sun.i quirks and deal with that (which is essentially
> > what we were doing before).
>
> Lets call it has_unknown_mux then. has_mux would be confusing with
> the HDMI and MIPI DSI muxes on sun6i.
That works for me.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161011/c35796a0/attachment.sig>
^ permalink raw reply
* [PATCH] ARM: dts: rockchip: initialize rk3066 PLL clock rate
From: Heiko Stuebner @ 2016-10-11 9:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161006194221.GA4895@vaio-ubuntu>
Am Donnerstag, 6. Oktober 2016, 21:42:21 CEST schrieb Pawe? Jarosz:
> Initialize PLL rate while kernel init. No other module does than.
> Clock rates are taken from rk3066 TRM. Assigned values are for 125 degrees
> celcius operating point.
> This gives us performance boost observable for example in mmc transfers.
>
> Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
> ---
> arch/arm/boot/dts/rk3066a.dtsi | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
> index 0d0dae3..cf215e8 100644
> --- a/arch/arm/boot/dts/rk3066a.dtsi
> +++ b/arch/arm/boot/dts/rk3066a.dtsi
> @@ -151,6 +151,10 @@
>
> #clock-cells = <1>;
> #reset-cells = <1>;
> + assigned-clocks = <&cru PLL_DPLL>, <&cru PLL_APLL>,
we shouldn't touch the DPLL and APLL at all in this context. They are quite
reliant on the underlying voltages and the bootloader might've set other
values. Also changing the DDR frequency through the DPLL requires special
handling on the DDR side.
> + <&cru PLL_CPLL>, <&cru PLL_GPLL>;
please also initialize the PERI and BUS clocks (similar to what the rk3288 clk
settings do), so that they stay sane, even if we change CPLL and GPLL
frequencies.
> + assigned-clock-rates = <533000000>, <600000000>,
> + <600000000>, <600000000>;
Also setting both CPLL and GPLL to the same value might be unhelpful to
achieve special divided frequencies? Again see rk3288.dtsi where we have a 594
/ 400 MHz division. Especially the downstream clocks normally can select
between CPLL and GPLL.
Heiko
^ permalink raw reply
* [PATCH v2] sdhci-esdhc-imx: Correct two register accesses
From: Adrian Hunter @ 2016-10-11 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476124792-18441-1-git-send-email-aaron.brice@datasoft.com>
On 10/10/16 21:39, Aaron Brice wrote:
> - The DMA error interrupt bit is in a different position as
> compared to the sdhci standard. This is accounted for in
> many cases, but not handled in the case of clearing the
> INT_STATUS register by writing a 1 to that location.
> - The HOST_CONTROL register is very different as compared to
> the sdhci standard. This is accounted for in the write
> case, but not when read back out (which it is in the sdhci
> code).
>
> Signed-off-by: Dave Russell <david.russell@datasoft.com>
> Signed-off-by: Aaron Brice <aaron.brice@datasoft.com>
> Acked-by: Dong Aisheng <aisheng.dong@nxp.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
^ permalink raw reply
* [PATCH 5/6] clk: stm32f469: Add QSPI clock
From: Gabriel Fernandez @ 2016-10-11 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161008205003.GB17455@rob-hp-laptop>
Hi Rob,
Thanks for reviewing
On 10/08/2016 10:50 PM, Rob Herring wrote:
> On Fri, Sep 30, 2016 at 04:25:08PM +0200, gabriel.fernandez at st.com wrote:
>> From: Gabriel Fernandez <gabriel.fernandez@st.com>
>>
>> This patch adds the QSPI clock for stm32f469 discovery board.
>> The gate mapping is a little bit different from stm32f429 soc.
>>
>> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
>> ---
>> .../devicetree/bindings/clock/st,stm32-rcc.txt | 4 +-
>> drivers/clk/clk-stm32f4.c | 173 ++++++++++++++++++---
>> 2 files changed, 158 insertions(+), 19 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
>> index fee3205..eace3de 100644
>> --- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
>> +++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
>> @@ -8,7 +8,9 @@ Please also refer to clock-bindings.txt in this directory for common clock
>> controller binding usage.
>>
>> Required properties:
>> -- compatible: Should be "st,stm32f42xx-rcc"
>> +- compatible: Should be:
>> + "st,stm32f42xx-rcc"
>> + "st,stm32f46xx-rcc"
> Generally, we don't use wildcards in compatible strings. I know there's
> lots of part numbers of stm32 parts which I guess are often same die
> with different fusing or package. Your compatible strings should be at
> least specific enough to identify parts that are really different die.
okay i will propose "st,stm32f469-rcc" if no one is against.
BR
Gabriel
>
>> - reg: should be register base and length as documented in the
>> datasheet
>> - #clock-cells: 2, device nodes should specify the clock in their "clocks"
^ permalink raw reply
* [PATCH 2/9] drm/sun4i: tcon: Move SoC specific quirks to a DT matched data structure
From: Chen-Yu Tsai @ 2016-10-11 9:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161007083853.GH4684@lukather>
On Fri, Oct 7, 2016 at 4:38 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Fri, Oct 07, 2016 at 12:06:22AM +0800, Chen-Yu Tsai wrote:
>> +struct sun4i_tcon_quirks {
>> + bool is_sun5i; /* sun5i has undocumented mux */
>> + bool has_channel_1; /* a33 does not have channel 1 */
>> + bool has_bypass_src; /* has separate input bypassing CEU */
>> + bool has_dma_src; /* has DMA input */
>> +};
>> +
>
> I'd really prefer to keep the has_mux quirk name. is_sun5i doesn't
> really relate to what we're doing there, is redundant with the
> compatible, and render the other quirks name useless, since we could
> just have is_sun.i quirks and deal with that (which is essentially
> what we were doing before).
Lets call it has_unknown_mux then. has_mux would be confusing with
the HDMI and MIPI DSI muxes on sun6i.
ChenYu
^ permalink raw reply
* [PATCH] arm64: mmu: set the contiguous for kernel mappings when appropriate
From: Ard Biesheuvel @ 2016-10-11 9:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPvkgC1p5yZLtENYMi6zd5-pPDOYUtMw0Lxvb592u975gc+Zvg@mail.gmail.com>
On 11 October 2016 at 09:48, Steve Capper <steve.capper@linaro.org> wrote:
>
>
> On 11 October 2016 at 08:44, Mark Rutland <mark.rutland@arm.com> wrote:
>>
>> Hi Ard,
>>
>> On Mon, Oct 10, 2016 at 07:12:44PM +0100, Ard Biesheuvel wrote:
>> > Now that we no longer allow live kernel PMDs to be split, it is safe to
>> > start using the contiguous bit for kernel mappings. So set the
>> > contiguous
>> > bit in the kernel page mappings for regions whose size and alignment are
>> > suitable for this.
>> >
>> > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>>
>> Given the splitting is now gone, using the contiguous bit makes sense to
>> me.
>>
>> With 16K pages, we can have contiguous PMD entries. Should we handle
>> those,
>> too? e.g. have separate {PMD,PTE}_CONT{,_SIZE}?
>>
>> Otherwise, I have some comments below.
>
>
> Hi,
>
> So in arch/arm64/include/asm/pgtable-hwdef.h, we have:
> CONT_PTE_SHIFT
> CONT_PMD_SHIFT
> CONT_PTES
> CONT_PMDS
> CONT_PTE_SIZE
> CONT_PTE_MASK
> ...
>
> which are used by the contiguous hint HugeTLB code.
> Can those be adopted instead of CONT_MASK and CONT_SIZE?
>
That seems more appropriate, yes. I wonder why we have CONT_MASK and
CONT_SIZE in the first place then.
^ permalink raw reply
* [PATCH] arm64: mmu: set the contiguous for kernel mappings when appropriate
From: Ard Biesheuvel @ 2016-10-11 8:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161011074419.GA20213@remoulade>
On 11 October 2016 at 08:44, Mark Rutland <mark.rutland@arm.com> wrote:
> Hi Ard,
>
> On Mon, Oct 10, 2016 at 07:12:44PM +0100, Ard Biesheuvel wrote:
>> Now that we no longer allow live kernel PMDs to be split, it is safe to
>> start using the contiguous bit for kernel mappings. So set the contiguous
>> bit in the kernel page mappings for regions whose size and alignment are
>> suitable for this.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>
> Given the splitting is now gone, using the contiguous bit makes sense to me.
>
> With 16K pages, we can have contiguous PMD entries. Should we handle those,
> too? e.g. have separate {PMD,PTE}_CONT{,_SIZE}?
>
Amusingly, this was exactly the feedback I gave to Jeremy when he
proposed this functionality originally. Yes, I think it makes sense,
especially for the linear mapping of system RAM. However, I think it
makes sense for someone else (with access to actual 16k granule
capable hardware) to contribute this functionality on top of this
patch.
> Otherwise, I have some comments below.
>
>> ---
>> arch/arm64/mm/mmu.c | 23 ++++++++++++++++++++---
>> 1 file changed, 20 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index 05615a3fdc6f..c491025c6a70 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -98,8 +98,11 @@ static phys_addr_t __init early_pgtable_alloc(void)
>> static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
>> unsigned long end, unsigned long pfn,
>> pgprot_t prot,
>> - phys_addr_t (*pgtable_alloc)(void))
>> + phys_addr_t (*pgtable_alloc)(void),
>> + bool allow_block_mappings)
>
> Not a big deal, but the 'block' part here and elsewhere is now arguably
> misleading (given 'block' is an architectural term).
>
> I haven't come up with a better term, so again, not a big deal. ;)
>
Indeed. I could simply call it 'allow_cont_mappings' in the context of
this function, and keep the call below as is.
>> {
>> + pgprot_t prot_cont = __pgprot(pgprot_val(prot) | PTE_CONT);
>> + bool cont = false;
>> pte_t *pte;
>>
>> BUG_ON(pmd_sect(*pmd));
>> @@ -115,7 +118,20 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
>>
>> pte = pte_set_fixmap_offset(pmd, addr);
>> do {
>> - set_pte(pte, pfn_pte(pfn, prot));
>> + /*
>> + * Set the contiguous bit for the subsequent group of PTEs if
>> + * its size and alignment are suitable.
>> + */
>> + if (((addr | PFN_PHYS(pfn)) & ~CONT_MASK) == 0)
>> + cont = allow_block_mappings && end - addr >= CONT_SIZE;
[...]
>> +
>> + /*
>> + * Ensure that we do not change the contiguous bit once this
>> + * PTE has been assigned.
>> + */
>> + BUG_ON(!pte_none(*pte) && (cont ^ !!(pte_val(*pte) & PTE_CONT)));
>
> IIRC, we only ever intended to mess with the AP bits when remapping an existing region.
>
> So we could mask those out and ensure everything else is identical, rather than
> checking the cont bit specifically. Likewise at the {PMD,PUD,PGD} level.
>
Yes, that should be better, I can put that in a separate preparatory patch.
>> +
>> + set_pte(pte, pfn_pte(pfn, cont ? prot_cont : prot));
>
> It would be clearer if we just assigned to a local pte_prot variable when
> checking allow_block_mappings and so on above (or split the loop as above).
>
Well, the local pte_prot variable's scope should still cover the
entire function, since cont does not change value at each iteration.
^ permalink raw reply
* [PATCH] n900 device tree: cleanup
From: Pavel Machek @ 2016-10-11 8:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161011075416.GA22453@amd>
Fix GPIO comment to be consistent with rest of file and add comment what
tpa6130 is.
Signed-off-by: Pavel Machek <pavel@ucw.cz>
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index bfffd6c..ca9fe8c 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -47,7 +47,7 @@
compatible = "gpio-leds";
heartbeat {
label = "debug::sleep";
- gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* gpio162 */
+ gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* 162 */
linux,default-trigger = "default-on";
pinctrl-names = "default";
pinctrl-0 = <&debug_leds>;
@@ -637,6 +637,7 @@
reg = <0x55>;
};
+ /* Stereo headphone amplifier */
tpa6130a2: tpa6130a2 at 60 {
compatible = "ti,tpa6130a2";
reg = <0x60>;
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161011/d5839fd2/attachment.sig>
^ permalink raw reply related
* [PATCH] n900 device tree: cleanup, add camera flash
From: Pavel Machek @ 2016-10-11 8:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161011080139.GK4467@pali>
On Tue 2016-10-11 10:01:39, Pali Roh?r wrote:
> On Tuesday 11 October 2016 09:54:17 Pavel Machek wrote:
> > @@ -669,6 +670,22 @@
> >
> > ti,usb-charger-detection = <&isp1707>;
> > };
> > +
> > + adp1653: led-controller at 30 {
> > + compatible = "adi,adp1653";
> > + reg = <0x30>;
> > + gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>; /* 88 */
> > +
> > + flash {
> > + flash-timeout-us = <500000>;
> > + flash-max-microamp = <320000>;
> > + max-microamp = <50000>;
> > + };
> > +
> > + indicator {
> > + max-microamp = <17500>;
> > + };
> > + };
> > };
> >
> > &i2c3 {
> >
>
> This part of patch is already in mainline kernel, isn't?
Oops, sorry about that. Disregard the patch.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161011/89240514/attachment-0001.sig>
^ permalink raw reply
* [PATCH] n900 device tree: cleanup, add camera flash
From: Pali Rohár @ 2016-10-11 8:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161011075416.GA22453@amd>
On Tuesday 11 October 2016 09:54:17 Pavel Machek wrote:
> @@ -669,6 +670,22 @@
>
> ti,usb-charger-detection = <&isp1707>;
> };
> +
> + adp1653: led-controller at 30 {
> + compatible = "adi,adp1653";
> + reg = <0x30>;
> + gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>; /* 88 */
> +
> + flash {
> + flash-timeout-us = <500000>;
> + flash-max-microamp = <320000>;
> + max-microamp = <50000>;
> + };
> +
> + indicator {
> + max-microamp = <17500>;
> + };
> + };
> };
>
> &i2c3 {
>
This part of patch is already in mainline kernel, isn't?
--
Pali Roh?r
pali.rohar at gmail.com
^ permalink raw reply
* [PATCH v2 3/3] ARM64: dts: meson-gxbb: Add GXBB AO Clock and Reset node
From: Michael Turquette @ 2016-10-11 8:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <m260qjjx26.fsf@baylibre.com>
Quoting Kevin Hilman (2016-08-29 10:37:37)
> Michael Turquette <mturquette@baylibre.com> writes:
>
> > Quoting Kevin Hilman (2016-08-19 15:03:06)
> >> Neil Armstrong <narmstrong@baylibre.com> writes:
> >>
> >> > Add the AO clock controller node for the AmLogic GXBB SoC.
> >> >
> >> > Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> >> > ---
> >>
> >> Applying this to the amlogic tree, but will need to wait a cycle due to
> >> include dependencies on the bindings, which are going through the clock
> >> tree.
> >
> > FYI, for picked patches, Stephen and I create a stable branch for each
> > platform. You can pull this into your tree if you want, just let us know
> > so we'll be sure not to rebase:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git clk-meson-gxbb-ao
> >
>
> OK, I'll be using clk-meson-gxb and clk-meson-gxbb-ao.
Heads up, I merged clk-meson-gxbb-ao into clk-meson-gxbb yesterday to
make it easier to merge the emmc clock gate patches. If you haven't
pulled clk-meson-gxbb-ao already then you can just re-pull
clk-meson-gxbb and you'll get it.
Regards,
Mike
>
> Thanks,
>
> Kevin
^ permalink raw reply
* [PATCH] clk: meson-gxbb: Export PWM related clocks for DT
From: Michael Turquette @ 2016-10-11 7:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1471870177-10609-1-git-send-email-narmstrong@baylibre.com>
Quoting Neil Armstrong (2016-08-22 05:49:37)
> Add the PWM related clocks in order to be referenced as PWM source
> clocks.
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Applied.
Regards,
Mike
> ---
> drivers/clk/meson/gxbb.h | 6 +++---
> include/dt-bindings/clock/gxbb-clkc.h | 3 +++
> 2 files changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
> index a2adf34..523b494 100644
> --- a/drivers/clk/meson/gxbb.h
> +++ b/drivers/clk/meson/gxbb.h
> @@ -170,11 +170,11 @@
> */
> #define CLKID_SYS_PLL 0
> /* CLKID_CPUCLK */
> -#define CLKID_HDMI_PLL 2
> +/* CLKID_HDMI_PLL */
> #define CLKID_FIXED_PLL 3
> #define CLKID_FCLK_DIV2 4
> -#define CLKID_FCLK_DIV3 5
> -#define CLKID_FCLK_DIV4 6
> +/* CLKID_FCLK_DIV3 */
> +/* CLKID_FCLK_DIV4 */
> #define CLKID_FCLK_DIV5 7
> #define CLKID_FCLK_DIV7 8
> #define CLKID_GP0_PLL 9
> diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
> index f889d80..a5897f3 100644
> --- a/include/dt-bindings/clock/gxbb-clkc.h
> +++ b/include/dt-bindings/clock/gxbb-clkc.h
> @@ -6,6 +6,9 @@
> #define __GXBB_CLKC_H
>
> #define CLKID_CPUCLK 1
> +#define CLKID_HDMI_PLL 2
> +#define CLKID_FCLK_DIV3 5
> +#define CLKID_FCLK_DIV4 6
> #define CLKID_CLK81 12
> #define CLKID_ETH 36
>
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH 0/6] clk: oxnas: Rework driver to add support for OX820
From: Michael Turquette @ 2016-10-11 7:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161005150752.22618-1-narmstrong@baylibre.com>
Quoting Neil Armstrong (2016-10-05 17:07:46)
> In order to to support the Oxford Semiconductor OX820 Soc clock gates,
> rework the original driver with a structure inspired from the Qcom or Meson
> drivers and using the new devm_clk_hw_register() call.
>
> The first patches add dt-bindings include file to clarify the clock indices.
>
> In future work, OX820 PLLs should also be handled by this driver.
Series looks good to me. Will apply after -rc1 drops.
Regards,
Mike
>
> Neil Armstrong (6):
> clk: oxnas: Add dt-bindings include file for OX810SE
> clk: oxnas: Add dt-bindings include file for OX820
> clk: oxnas: Rename to clk_oxnas_gate
> clk: oxnas: Refactor to make use of devm_clk_hw_register()
> clk: oxnas: Add OX820 Gate clocks
> dt-bindings: clk: oxnas,stdclk: Add OX820 bindings
>
> .../devicetree/bindings/clock/oxnas,stdclk.txt | 19 +-
> drivers/clk/clk-oxnas.c | 232 ++++++++++++++-------
> include/dt-bindings/clock/oxsemi,ox810se.h | 30 +++
> include/dt-bindings/clock/oxsemi,ox820.h | 40 ++++
> 4 files changed, 231 insertions(+), 90 deletions(-)
> create mode 100644 include/dt-bindings/clock/oxsemi,ox810se.h
> create mode 100644 include/dt-bindings/clock/oxsemi,ox820.h
>
> --
> 2.7.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] n900 device tree: cleanup, add camera flash
From: Pavel Machek @ 2016-10-11 7:54 UTC (permalink / raw)
To: linux-arm-kernel
Fix GPIO comment to be consistent with rest of file, add comment what
tpa6130 is, and addd support for adp1653 camera flash.
Signed-off-by: Pavel Machek <pavel@ucw.cz>
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index bfffd6c..ca9fe8c 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -47,7 +47,7 @@
compatible = "gpio-leds";
heartbeat {
label = "debug::sleep";
- gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* gpio162 */
+ gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* 162 */
linux,default-trigger = "default-on";
pinctrl-names = "default";
pinctrl-0 = <&debug_leds>;
@@ -637,6 +637,7 @@
reg = <0x55>;
};
+ /* Stereo headphone amplifier */
tpa6130a2: tpa6130a2 at 60 {
compatible = "ti,tpa6130a2";
reg = <0x60>;
@@ -669,6 +670,22 @@
ti,usb-charger-detection = <&isp1707>;
};
+
+ adp1653: led-controller at 30 {
+ compatible = "adi,adp1653";
+ reg = <0x30>;
+ gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>; /* 88 */
+
+ flash {
+ flash-timeout-us = <500000>;
+ flash-max-microamp = <320000>;
+ max-microamp = <50000>;
+ };
+
+ indicator {
+ max-microamp = <17500>;
+ };
+ };
};
&i2c3 {
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161011/b5958bee/attachment.sig>
^ permalink raw reply related
* [PATCH] arm64: mmu: set the contiguous for kernel mappings when appropriate
From: Mark Rutland @ 2016-10-11 7:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161011074419.GA20213@remoulade>
On Tue, Oct 11, 2016 at 08:44:19AM +0100, Mark Rutland wrote:
> > {
> > + pgprot_t prot_cont = __pgprot(pgprot_val(prot) | PTE_CONT);
> > + bool cont = false;
> > pte_t *pte;
> >
> > BUG_ON(pmd_sect(*pmd));
> > @@ -115,7 +118,20 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
> >
> > pte = pte_set_fixmap_offset(pmd, addr);
> > do {
> > - set_pte(pte, pfn_pte(pfn, prot));
> > + /*
> > + * Set the contiguous bit for the subsequent group of PTEs if
> > + * its size and alignment are suitable.
> > + */
> > + if (((addr | PFN_PHYS(pfn)) & ~CONT_MASK) == 0)
> > + cont = allow_block_mappings && end - addr >= CONT_SIZE;
>
> Given we increment addr by PAGE_SIZE in the loop, isn't this only true for the
> first CONT_SIZE aligned entry, and not its (intended-to-be-contiguous)
> siblings?
Looking again, I'd mis-read the above; it will work as expected.
Sorry for the noise.
Thanks,
Mark.
^ permalink raw reply
* latest version of bluetooth for n950?
From: Pavel Machek @ 2016-10-11 7:47 UTC (permalink / raw)
To: linux-arm-kernel
Hi, Sebastian!
I got some free cycles to play with n900 and bluetooth. There's still
some unrelated config option that breaks even the old vesion of
patches, but I'm ready for more debugging now.
Could I have the latest version of the (clean) bluetooth patch? I have
feeling it might work with the right config option, and would like to
try.
For the record, here's working .config and the tricky tricky oneliner
that took me week to figure out.
Best regards,
Pavel
diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
index b4c0484..1304009 100644
--- a/include/uapi/linux/serial_reg.h
+++ b/include/uapi/linux/serial_reg.h
@@ -32,7 +32,7 @@
#define UART_IIR 2 /* In: Interrupt ID Register */
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
-#define UART_IIR_ID 0x0e /* Mask for the interrupt ID */
+#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: config.gz
Type: application/gzip
Size: 24468 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161011/c0992560/attachment-0001.gz>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161011/c0992560/attachment-0001.sig>
^ permalink raw reply related
* [PATCH 4/5] rpmsg: Driver for user space endpoint interface
From: loic pallardy @ 2016-10-11 7:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475900595-8375-4-git-send-email-bjorn.andersson@linaro.org>
On 10/08/2016 06:23 AM, Bjorn Andersson wrote:
> This driver allows rpmsg instances to expose access to rpmsg endpoints
> to user space processes. It provides a control interface, allowing
> userspace to export endpoints and an endpoint interface for each exposed
> endpoint.
>
> The implementation is based on prior art by Texas Instrument, Google,
> PetaLogix and was derived from a FreeRTOS performance statistics driver
> written by Michal Simek.
>
> The control interface provides a "create endpoint" ioctl, which is fed a
> name, source and destination address. The three values are used to
> create the endpoint, in a backend-specific way, and a rpmsg endpoint
> device is created - with the three parameters are available in sysfs for
> udev usage.
>
> E.g. to create an endpoint device for one of the Qualcomm SMD channel
> related to DIAG one would issue:
>
> struct rpmsg_endpoint_info info = { "DIAG_CNTL", 0, 0 };
> int fd = open("/dev/rpmsg_ctrl0", O_RDWR);
> ioctl(fd, RPMSG_CREATE_EPT_IOCTL, &info);
>
> Each created endpoint device shows up as an individual character device
> in /dev, allowing permission to be controlled on a per-endpoint basis.
> The rpmsg endpoint will be created and destroyed following the opening
> and closing of the endpoint device, allowing rpmsg backends to open and
> close the physical channel, if supported by the wire protocol.
>
> Cc: Marek Novak <marek.novak@nxp.com>
> Cc: Matteo Sartori <matteo.sartori@t3lab.it>
> Cc: Michal Simek <monstr@monstr.eu>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
> Documentation/ioctl/ioctl-number.txt | 1 +
> drivers/rpmsg/Makefile | 2 +-
> drivers/rpmsg/rpmsg_char.c | 576 +++++++++++++++++++++++++++++++++++
> drivers/rpmsg/rpmsg_internal.h | 2 +
> include/uapi/linux/rpmsg.h | 35 +++
> 5 files changed, 615 insertions(+), 1 deletion(-)
> create mode 100644 drivers/rpmsg/rpmsg_char.c
> create mode 100644 include/uapi/linux/rpmsg.h
>
> diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
> index 81c7f2bb7daf..08244bea5048 100644
> --- a/Documentation/ioctl/ioctl-number.txt
> +++ b/Documentation/ioctl/ioctl-number.txt
> @@ -321,6 +321,7 @@ Code Seq#(hex) Include File Comments
> 0xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
> 0xB3 00 linux/mmc/ioctl.h
> 0xB4 00-0F linux/gpio.h <mailto:linux-gpio@vger.kernel.org>
> +0xB5 00-0F uapi/linux/rpmsg.h <mailto:linux-remoteproc@vger.kernel.org>
> 0xC0 00-0F linux/usb/iowarrior.h
> 0xCA 00-0F uapi/misc/cxl.h
> 0xCA 80-8F uapi/scsi/cxlflash_ioctl.h
> diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
> index ae9c9132cf76..5daf1209b77d 100644
> --- a/drivers/rpmsg/Makefile
> +++ b/drivers/rpmsg/Makefile
> @@ -1,3 +1,3 @@
> -obj-$(CONFIG_RPMSG) += rpmsg_core.o
> +obj-$(CONFIG_RPMSG) += rpmsg_core.o rpmsg_char.o
Hi Bjorn,
Could you please create a dedicated Kconfig entry for this new interface?
This should be an option like i2C_dev.
Regards,
Loic
> obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o
> obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
> diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
> new file mode 100644
> index 000000000000..a398a63e8d44
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_char.c
> @@ -0,0 +1,576 @@
> +/*
> + * Copyright (c) 2016, Linaro Ltd.
> + * Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
> + * Copyright (c) 2012, PetaLogix
> + * Copyright (c) 2011, Texas Instruments, Inc.
> + * Copyright (c) 2011, Google, Inc.
> + *
> + * Based on rpmsg performance statistics driver by Michal Simek, which in turn
> + * was based on TI & Google OMX rpmsg driver.
> + *
> + * 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
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * 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/cdev.h>
> +#include <linux/device.h>
> +#include <linux/fs.h>
> +#include <linux/idr.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/rpmsg.h>
> +#include <linux/skbuff.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +#include <uapi/linux/rpmsg.h>
> +
> +#include "rpmsg_internal.h"
> +
> +#define RPMSG_DEV_MAX 256
> +
> +static dev_t rpmsg_major;
> +static struct class *rpmsg_class;
> +
> +static DEFINE_IDA(rpmsg_ctrl_ida);
> +static DEFINE_IDA(rpmsg_ept_ida);
> +static DEFINE_IDA(rpmsg_minor_ida);
> +
> +#define dev_to_eptdev(dev) container_of(dev, struct rpmsg_eptdev, dev)
> +#define cdev_to_eptdev(i_cdev) container_of(i_cdev, struct rpmsg_eptdev, cdev)
> +
> +#define dev_to_ctrldev(dev) container_of(dev, struct rpmsg_ctrldev, dev)
> +#define cdev_to_ctrldev(i_cdev) container_of(i_cdev, struct rpmsg_ctrldev, cdev)
> +
> +struct rpmsg_ctrldev {
> + struct rpmsg_device *rpdev;
> + struct cdev cdev;
> + struct device dev;
> +};
> +
> +struct rpmsg_eptdev {
> + struct device dev;
> + struct cdev cdev;
> +
> + struct rpmsg_device *rpdev;
> + struct rpmsg_channel_info chinfo;
> +
> + struct mutex ept_lock;
> + struct rpmsg_endpoint *ept;
> +
> + spinlock_t queue_lock;
> + struct sk_buff_head queue;
> + wait_queue_head_t readq;
> +};
> +
> +static int rpmsg_eptdev_destroy(struct rpmsg_eptdev *eptdev);
> +
> +
> +static int rpmsg_cdev_register(struct device *dev,
> + struct cdev *cdev,
> + const struct file_operations *fops,
> + dev_t *assigned_devt)
> +{
> + dev_t devt;
> + int ret;
> +
> + ret = ida_simple_get(&rpmsg_minor_ida, 0, 0, GFP_KERNEL);
> + if (ret < 0)
> + return ret;
> +
> + devt = MKDEV(MAJOR(rpmsg_major), ret);
> +
> + cdev_init(cdev, fops);
> + cdev->owner = THIS_MODULE;
> + ret = cdev_add(cdev, devt, 1);
> + if (ret < 0) {
> + dev_err(dev, "cdev_add failed: %d\n", ret);
> + ida_simple_remove(&rpmsg_minor_ida, MINOR(devt));
> + return ret;
> + }
> +
> + *assigned_devt = devt;
> + return 0;
> +}
> +
> +static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
> + void *priv, u32 addr)
> +{
> + struct rpmsg_eptdev *eptdev = priv;
> + struct sk_buff *skb;
> +
> + skb = alloc_skb(len, GFP_ATOMIC);
> + if (!skb)
> + return -ENOMEM;
> +
> + memcpy(skb_put(skb, len), buf, len);
> +
> + spin_lock(&eptdev->queue_lock);
> + skb_queue_tail(&eptdev->queue, skb);
> + spin_unlock(&eptdev->queue_lock);
> +
> + /* wake up any blocking processes, waiting for new data */
> + wake_up_interruptible(&eptdev->readq);
> +
> + return 0;
> +}
> +
> +static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
> +{
> + struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
> + struct rpmsg_endpoint *ept;
> + struct rpmsg_device *rpdev = eptdev->rpdev;
> + struct device *dev = &eptdev->dev;
> +
> + get_device(dev);
> +
> + ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo);
> + if (!ept) {
> + dev_err(dev, "failed to open %s\n", eptdev->chinfo.name);
> + put_device(dev);
> + return -EINVAL;
> + }
> +
> + eptdev->ept = ept;
> + filp->private_data = eptdev;
> +
> + return 0;
> +}
> +
> +static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
> +{
> + struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev);
> + struct device *dev = &eptdev->dev;
> + struct sk_buff *skb;
> +
> + /* Close the endpoint, if it's not already destroyed by the parent */
> + if (eptdev->ept)
> + rpmsg_destroy_ept(eptdev->ept);
> +
> + /* Discard all SKBs */
> + while (!skb_queue_empty(&eptdev->queue)) {
> + skb = skb_dequeue(&eptdev->queue);
> + kfree_skb(skb);
> + }
> +
> + put_device(dev);
> +
> + return 0;
> +}
> +
> +static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
> + unsigned long arg)
> +{
> + struct rpmsg_eptdev *eptdev = fp->private_data;
> +
> + if (cmd != RPMSG_DESTROY_EPT_IOCTL)
> + return -EINVAL;
> +
> + return rpmsg_eptdev_destroy(eptdev);
> +}
> +
> +static ssize_t rpmsg_eptdev_read(struct file *filp, char __user *buf,
> + size_t count, loff_t *f_pos)
> +{
> + struct rpmsg_eptdev *eptdev = filp->private_data;
> + unsigned long flags;
> + struct sk_buff *skb;
> + int use;
> +
> + spin_lock_irqsave(&eptdev->queue_lock, flags);
> +
> + /* Wait for data in the queue */
> + if (skb_queue_empty(&eptdev->queue)) {
> + spin_unlock_irqrestore(&eptdev->queue_lock, flags);
> +
> + if (filp->f_flags & O_NONBLOCK)
> + return -EAGAIN;
> +
> + /* Wait until we get data or the endpoint goes away */
> + if (wait_event_interruptible(eptdev->readq,
> + !skb_queue_empty(&eptdev->queue) ||
> + !eptdev->ept))
> + return -ERESTARTSYS;
> +
> + /* We lost the endpoint while waiting */
> + if (!eptdev->ept)
> + return -EPIPE;
> +
> + spin_lock_irqsave(&eptdev->queue_lock, flags);
> + }
> +
> + skb = skb_dequeue(&eptdev->queue);
> + if (!skb)
> + return -EFAULT;
> +
> + spin_unlock_irqrestore(&eptdev->queue_lock, flags);
> +
> + use = min_t(size_t, count, skb->len);
> + if (copy_to_user(buf, skb->data, use))
> + use = -EFAULT;
> +
> + kfree_skb(skb);
> +
> + return use;
> +}
> +
> +static ssize_t rpmsg_eptdev_write(struct file *filp, const char __user *buf,
> + size_t count, loff_t *f_pos)
> +{
> + struct rpmsg_eptdev *eptdev = filp->private_data;
> + void *kbuf;
> + int ret;
> +
> + kbuf = kzalloc(count, GFP_KERNEL);
> + if (!kbuf)
> + return -ENOMEM;
> +
> + if (copy_from_user(kbuf, buf, count)) {
> + ret = -EFAULT;
> + goto free_kbuf;
> + }
> +
> + if (mutex_lock_interruptible(&eptdev->ept_lock)) {
> + ret = -ERESTARTSYS;
> + goto free_kbuf;
> + }
> +
> + if (!eptdev->ept) {
> + ret = -EPIPE;
> + goto unlock_eptdev;
> + }
> +
> + if (filp->f_flags & O_NONBLOCK)
> + ret = rpmsg_trysend(eptdev->ept, kbuf, count);
> + else
> + ret = rpmsg_send(eptdev->ept, kbuf, count);
> +
> +unlock_eptdev:
> + mutex_unlock(&eptdev->ept_lock);
> +
> +free_kbuf:
> + kfree(kbuf);
> + return ret;
> +}
> +
> +static const struct file_operations rpmsg_eptdev_fops = {
> + .owner = THIS_MODULE,
> + .open = rpmsg_eptdev_open,
> + .release = rpmsg_eptdev_release,
> + .read = rpmsg_eptdev_read,
> + .write = rpmsg_eptdev_write,
> + .unlocked_ioctl = rpmsg_eptdev_ioctl,
> +};
> +
> +static ssize_t name_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> +
> + return sprintf(buf, "%s\n", eptdev->chinfo.name);
> +}
> +static DEVICE_ATTR_RO(name);
> +
> +static ssize_t src_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> +
> + return sprintf(buf, "%d\n", eptdev->chinfo.src);
> +}
> +static DEVICE_ATTR_RO(src);
> +
> +static ssize_t dst_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + struct rpmsg_eptdev *eptdev = dev_get_drvdata(dev);
> +
> + return sprintf(buf, "%d\n", eptdev->chinfo.dst);
> +}
> +static DEVICE_ATTR_RO(dst);
> +
> +static struct attribute *rpmsg_eptdev_attrs[] = {
> + &dev_attr_name.attr,
> + &dev_attr_src.attr,
> + &dev_attr_dst.attr,
> + NULL
> +};
> +ATTRIBUTE_GROUPS(rpmsg_eptdev);
> +
> +static void rpmsg_eptdev_release_device(struct device *dev)
> +{
> + struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
> +
> + ida_simple_remove(&rpmsg_minor_ida, MINOR(eptdev->dev.devt));
> + kfree(eptdev);
> +}
> +
> +static int rpmsg_eptdev_create(struct rpmsg_ctrldev *ctrldev,
> + struct rpmsg_channel_info chinfo)
> +{
> + struct rpmsg_device *rpdev = ctrldev->rpdev;
> + struct rpmsg_eptdev *eptdev;
> + struct device *dev;
> + int ret;
> + int id;
> +
> + eptdev = kzalloc(sizeof(*eptdev), GFP_KERNEL);
> + if (!eptdev)
> + return -ENOMEM;
> +
> + eptdev->rpdev = rpdev;
> + eptdev->chinfo = chinfo;
> +
> + mutex_init(&eptdev->ept_lock);
> + spin_lock_init(&eptdev->queue_lock);
> + skb_queue_head_init(&eptdev->queue);
> + init_waitqueue_head(&eptdev->readq);
> +
> + id = ida_simple_get(&rpmsg_ept_ida, 0, 0, GFP_KERNEL);
> + if (id < 0) {
> + kfree(eptdev);
> + return id;
> + }
> +
> + dev = &eptdev->dev;
> + device_initialize(dev);
> + dev->class = rpmsg_class;
> + dev->id = id;
> + dev->parent = &ctrldev->dev;
> + dev->release = rpmsg_eptdev_release_device;
> + dev->groups = rpmsg_eptdev_groups;
> + dev_set_name(dev, "rpmsg%d", id);
> + dev_set_drvdata(dev, eptdev);
> +
> + ret = rpmsg_cdev_register(dev, &eptdev->cdev,
> + &rpmsg_eptdev_fops, &dev->devt);
> + if (ret) {
> + dev_err(dev, "cdev_add failed: %d\n", ret);
> + goto out;
> + }
> +
> + ret = device_add(dev);
> + if (ret) {
> + dev_err(dev, "device_register failed: %d\n", ret);
> + goto out;
> + }
> +
> +out:
> + if (ret < 0)
> + put_device(dev);
> +
> + return ret;
> +}
> +
> +static int rpmsg_eptdev_destroy(struct rpmsg_eptdev *eptdev)
> +{
> + struct rpmsg_endpoint *ept = eptdev->ept;
> +
> + mutex_lock(&eptdev->ept_lock);
> + eptdev->ept = NULL;
> + mutex_unlock(&eptdev->ept_lock);
> +
> + rpmsg_destroy_ept(ept);
> +
> + /* wake up any blocking processes */
> + wake_up_interruptible(&eptdev->readq);
> +
> + cdev_del(&eptdev->cdev);
> + device_del(&eptdev->dev);
> + put_device(&eptdev->dev);
> +
> + return 0;
> +}
> +
> +static int rpmsg_ctrldev_open(struct inode *inode, struct file *filp)
> +{
> + struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> +
> + get_device(&ctrldev->rpdev->dev);
> + filp->private_data = ctrldev;
> +
> + return 0;
> +}
> +
> +static int rpmsg_ctrldev_release(struct inode *inode, struct file *filp)
> +{
> + struct rpmsg_ctrldev *ctrldev = cdev_to_ctrldev(inode->i_cdev);
> +
> + put_device(&ctrldev->rpdev->dev);
> +
> + return 0;
> +}
> +
> +static long rpmsg_ctrldev_ioctl(struct file *fp, unsigned int cmd,
> + unsigned long arg)
> +{
> + struct rpmsg_ctrldev *ctrldev = fp->private_data;
> + void __user *argp = (void __user *)arg;
> + struct rpmsg_endpoint_info eptinfo;
> + struct rpmsg_channel_info chinfo;
> +
> + if (cmd != RPMSG_CREATE_EPT_IOCTL)
> + return -EINVAL;
> +
> + if (copy_from_user(&eptinfo, argp, sizeof(eptinfo)))
> + return -EFAULT;
> +
> + memcpy(chinfo.name, eptinfo.name, RPMSG_NAME_SIZE);
> + chinfo.name[RPMSG_NAME_SIZE-1] = '\0';
> + chinfo.src = eptinfo.src;
> + chinfo.dst = eptinfo.dst;
> +
> + return rpmsg_eptdev_create(ctrldev, chinfo);
> +};
> +
> +static const struct file_operations rpmsg_ctrldev_fops = {
> + .owner = THIS_MODULE,
> + .open = rpmsg_ctrldev_open,
> + .release = rpmsg_ctrldev_release,
> + .unlocked_ioctl = rpmsg_ctrldev_ioctl,
> +};
> +
> +static void rpmsg_chrdev_release_device(struct device *dev)
> +{
> + struct rpmsg_ctrldev *ctrldev = dev_to_ctrldev(dev);
> +
> + ida_simple_remove(&rpmsg_ctrl_ida, MINOR(dev->devt));
> + cdev_del(&ctrldev->cdev);
> + kfree(ctrldev);
> +}
> +
> +static int rpmsg_chrdev_probe(struct rpmsg_device *rpdev)
> +{
> + struct rpmsg_ctrldev *ctrldev;
> + struct device *dev;
> + int ret;
> + int id;
> +
> + ctrldev = kzalloc(sizeof(*ctrldev), GFP_KERNEL);
> + if (!ctrldev)
> + return -ENOMEM;
> +
> + dev = &ctrldev->dev;
> +
> + ctrldev->rpdev = rpdev;
> +
> + id = ida_simple_get(&rpmsg_ctrl_ida, 0, 0, GFP_KERNEL);
> + if (id < 0) {
> + kfree(ctrldev);
> + return id;
> + }
> +
> + device_initialize(dev);
> + dev->parent = &rpdev->dev;
> + dev->class = rpmsg_class;
> + dev->release = rpmsg_chrdev_release_device;
> + dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", id);
> +
> + ret = rpmsg_cdev_register(dev, &ctrldev->cdev,
> + &rpmsg_ctrldev_fops, &dev->devt);
> + if (ret < 0) {
> + put_device(dev);
> + return ret;
> + }
> +
> + ret = device_add(dev);
> + if (ret) {
> + dev_err(&rpdev->dev, "device_register failed: %d\n", ret);
> + put_device(dev);
> + }
> +
> + dev_set_drvdata(&rpdev->dev, ctrldev);
> +
> + return ret;
> +}
> +
> +static int _rpmsg_eptdev_destroy(struct device *dev, void *data)
> +{
> + struct rpmsg_eptdev *eptdev = dev_to_eptdev(dev);
> +
> + return rpmsg_eptdev_destroy(eptdev);
> +}
> +
> +static void rpmsg_chrdev_remove(struct rpmsg_device *rpdev)
> +{
> + struct rpmsg_ctrldev *ctrldev = dev_get_drvdata(&rpdev->dev);
> + int ret;
> +
> + /* Destroy all endpoints */
> + ret = device_for_each_child(&ctrldev->dev, NULL, _rpmsg_eptdev_destroy);
> + if (ret)
> + dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
> +
> + device_del(&ctrldev->dev);
> + put_device(&ctrldev->dev);
> +}
> +
> +static struct rpmsg_driver rpmsg_chrdev_driver = {
> + .probe = rpmsg_chrdev_probe,
> + .remove = rpmsg_chrdev_remove,
> + .drv = {
> + .name = "rpmsg_chrdev",
> + },
> +};
> +
> +/**
> + * rpmsg_chrdev_register_device() - register chrdev device based on rpdev
> + * @rpdev: prepared rpdev to be used for creating endpoints
> + *
> + * This function wraps rpmsg_register_device() preparing the rpdev for use as
> + * basis for the rpmsg chrdev.
> + */
> +int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev)
> +{
> + strcpy(rpdev->id.name, "rpmsg_chrdev");
> + rpdev->driver_override = "rpmsg_chrdev";
> +
> + return rpmsg_register_device(rpdev);
> +}
> +EXPORT_SYMBOL(rpmsg_chrdev_register_device);
> +
> +static int rpmsg_char_init(void)
> +{
> + int ret;
> +
> + ret = alloc_chrdev_region(&rpmsg_major, 0, RPMSG_DEV_MAX, "rpmsg");
> + if (ret < 0) {
> + pr_err("rpmsg: failed to allocate char dev region\n");
> + return ret;
> + }
> +
> + rpmsg_class = class_create(THIS_MODULE, "rpmsg");
> + if (IS_ERR(rpmsg_class)) {
> + pr_err("failed to create rpmsg class\n");
> + ret = PTR_ERR(rpmsg_class);
> + goto unregister_chrdev;
> + }
> +
> + ret = register_rpmsg_driver(&rpmsg_chrdev_driver);
> + if (ret < 0) {
> + pr_err("rpmsgchr: failed to register rpmsg driver\n");
> + goto destroy_class;
> + }
> +
> + return 0;
> +
> +destroy_class:
> + class_destroy(rpmsg_class);
> +
> +unregister_chrdev:
> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> +
> + return ret;
> +}
> +postcore_initcall(rpmsg_char_init);
> +
> +static void rpmsg_chrdev_exit(void)
> +{
> + unregister_rpmsg_driver(&rpmsg_chrdev_driver);
> + unregister_chrdev_region(rpmsg_major, RPMSG_DEV_MAX);
> +}
> +module_exit(rpmsg_chrdev_exit);
> diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
> index 8075a20f919b..53d300eacc1c 100644
> --- a/drivers/rpmsg/rpmsg_internal.h
> +++ b/drivers/rpmsg/rpmsg_internal.h
> @@ -79,4 +79,6 @@ int rpmsg_unregister_device(struct device *parent,
> struct device *rpmsg_find_device(struct device *parent,
> struct rpmsg_channel_info *chinfo);
>
> +int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev);
> +
> #endif
> diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
> new file mode 100644
> index 000000000000..dedc226e0d3f
> --- /dev/null
> +++ b/include/uapi/linux/rpmsg.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (c) 2016, Linaro Ltd.
> + *
> + * 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
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * 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.
> + */
> +
> +#ifndef _UAPI_RPMSG_H_
> +#define _UAPI_RPMSG_H_
> +
> +#include <linux/ioctl.h>
> +#include <linux/types.h>
> +
> +/**
> + * struct rpmsg_endpoint_info - endpoint info representation
> + * @name: name of service
> + * @src: local address
> + * @dst: destination address
> + */
> +struct rpmsg_endpoint_info {
> + char name[32];
> + __u32 src;
> + __u32 dst;
> +};
> +
> +#define RPMSG_CREATE_EPT_IOCTL _IOW(0xb5, 0x1, struct rpmsg_endpoint_info)
> +#define RPMSG_DESTROY_EPT_IOCTL _IO(0xb5, 0x2)
> +
> +#endif
>
^ permalink raw reply
* [PATCH] arm64: mmu: set the contiguous for kernel mappings when appropriate
From: Mark Rutland @ 2016-10-11 7:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476123164-10532-1-git-send-email-ard.biesheuvel@linaro.org>
Hi Ard,
On Mon, Oct 10, 2016 at 07:12:44PM +0100, Ard Biesheuvel wrote:
> Now that we no longer allow live kernel PMDs to be split, it is safe to
> start using the contiguous bit for kernel mappings. So set the contiguous
> bit in the kernel page mappings for regions whose size and alignment are
> suitable for this.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Given the splitting is now gone, using the contiguous bit makes sense to me.
With 16K pages, we can have contiguous PMD entries. Should we handle those,
too? e.g. have separate {PMD,PTE}_CONT{,_SIZE}?
Otherwise, I have some comments below.
> ---
> arch/arm64/mm/mmu.c | 23 ++++++++++++++++++++---
> 1 file changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 05615a3fdc6f..c491025c6a70 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -98,8 +98,11 @@ static phys_addr_t __init early_pgtable_alloc(void)
> static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
> unsigned long end, unsigned long pfn,
> pgprot_t prot,
> - phys_addr_t (*pgtable_alloc)(void))
> + phys_addr_t (*pgtable_alloc)(void),
> + bool allow_block_mappings)
Not a big deal, but the 'block' part here and elsewhere is now arguably
misleading (given 'block' is an architectural term).
I haven't come up with a better term, so again, not a big deal. ;)
> {
> + pgprot_t prot_cont = __pgprot(pgprot_val(prot) | PTE_CONT);
> + bool cont = false;
> pte_t *pte;
>
> BUG_ON(pmd_sect(*pmd));
> @@ -115,7 +118,20 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
>
> pte = pte_set_fixmap_offset(pmd, addr);
> do {
> - set_pte(pte, pfn_pte(pfn, prot));
> + /*
> + * Set the contiguous bit for the subsequent group of PTEs if
> + * its size and alignment are suitable.
> + */
> + if (((addr | PFN_PHYS(pfn)) & ~CONT_MASK) == 0)
> + cont = allow_block_mappings && end - addr >= CONT_SIZE;
Given we increment addr by PAGE_SIZE in the loop, isn't this only true for the
first CONT_SIZE aligned entry, and not its (intended-to-be-contiguous)
siblings?
It be better to loop over CONT_SIZE increments, and then within that, pass the
prot (with the contiguous bit set as required) to a loop with a PAGE_SIZE
increment.
Or have I misunderstood something?
> +
> + /*
> + * Ensure that we do not change the contiguous bit once this
> + * PTE has been assigned.
> + */
> + BUG_ON(!pte_none(*pte) && (cont ^ !!(pte_val(*pte) & PTE_CONT)));
IIRC, we only ever intended to mess with the AP bits when remapping an existing region.
So we could mask those out and ensure everything else is identical, rather than
checking the cont bit specifically. Likewise at the {PMD,PUD,PGD} level.
> +
> + set_pte(pte, pfn_pte(pfn, cont ? prot_cont : prot));
It would be clearer if we just assigned to a local pte_prot variable when
checking allow_block_mappings and so on above (or split the loop as above).
Thanks,
Mark.
^ permalink raw reply
* [PATCH 15/19] reset: sti: Remove STiH415/6 reset support
From: Patrice Chotard @ 2016-10-11 7:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474963347.2494.8.camel@pengutronix.de>
Hi Philipp
On 09/27/2016 10:02 AM, Philipp Zabel wrote:
> Hi Peter,
>
> Am Mittwoch, den 14.09.2016, 14:27 +0100 schrieb Peter Griffin:
>> Support for STiH415/6 SoCs is being removed from the
>> kernel because the platforms are obsolete. This patch removes
>> the reset drivers for these SoC's.
>>
>> Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
>> Cc: <p.zabel@pengutronix.de>
>> ---
[...]
>> - .driver = {
>> - .name = "reset-stih416",
>> - .of_match_table = stih416_reset_match,
>> - },
>> -};
>> -
>> -static int __init stih416_reset_init(void)
>> -{
>> - return platform_driver_register(&stih416_reset_driver);
>> -}
>> -arch_initcall(stih416_reset_init);
>
> Can I pick up patches 15 and 19, or are there dependencies in the
> series?
Yes, you can pick up patches 15 and 19
> In the latter case,
> Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
> to merge both together with the other patches. Currently there is no
> conflict with changes queued from the reset tree.
>
> regards
> Philipp
>
Thanks
Patrice
^ permalink raw reply
* [PATCH] mm/vmalloc: reduce the number of lazy_max_pages to reduce latency
From: Joel Fernandes @ 2016-10-11 5:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAD=GYpZQOQYE7x0kGTmLSeybh4Tn-CCEDouzkFVkdevq02j3SA@mail.gmail.com>
On Mon, Oct 10, 2016 at 10:06 PM, Joel Fernandes <agnel.joel@gmail.com> wrote:
> On Sun, Oct 9, 2016 at 12:26 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
>> On Sun, Oct 09, 2016 at 12:00:31PM -0700, Joel Fernandes wrote:
>>> Ok. So I'll submit a patch with mutex for purge_lock and use
>>> cond_resched_lock for the vmap_area_lock as you suggested. I'll also
>>> drop the lazy_max_pages to 8MB as Andi suggested to reduce the lock
>>> hold time. Let me know if you have any objections.
>>
>> The downside of using a mutex here though, is that we may be called
>> from contexts that cannot sleep (alloc_vmap_area), or reschedule for
>> that matter! If we change the notion of purged, we can forgo the mutex
>> in favour of spinning on the direct reclaim path. That just leaves the
>> complication of whether to use cond_resched_lock() or a lock around
>> the individual __free_vmap_area().
>
> Good point. I agree with you. I think we still need to know if purging
> is in progress to preserve previous trylock behavior. How about
> something like the following diff? (diff is untested).
>
> This drops the purge lock and uses a ref count to indicate if purging
> is in progress, so that callers who don't want to purge if purging is
> already in progress can be kept happy. Also I am reducing vmap_lazy_nr
> as we go, and, not all at once, so that we don't reduce the counter
> too soon as we're not holding purge lock anymore. Lastly, I added the
> cond_resched as you suggested.
>
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index f2481cb..5616ca4 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -626,7 +626,7 @@ void set_iounmap_nonlazy(void)
> static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
> int sync, int force_flush)
> {
> - static DEFINE_SPINLOCK(purge_lock);
> + static atomic_t purging;
> struct llist_node *valist;
> struct vmap_area *va;
> struct vmap_area *n_va;
> @@ -638,10 +638,10 @@ static void __purge_vmap_area_lazy(unsigned long
> *start, unsigned long *end,
> * the case that isn't actually used at the moment anyway.
> */
> if (!sync && !force_flush) {
> - if (!spin_trylock(&purge_lock))
> + if (atomic_cmpxchg(&purging, 0, 1))
> return;
> } else
> - spin_lock(&purge_lock);
> + atomic_inc(&purging);
>
> if (sync)
> purge_fragmented_blocks_allcpus();
> @@ -655,9 +655,6 @@ static void __purge_vmap_area_lazy(unsigned long
> *start, unsigned long *end,
> nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
> }
>
> - if (nr)
> - atomic_sub(nr, &vmap_lazy_nr);
> -
> if (nr || force_flush)
> flush_tlb_kernel_range(*start, *end);
>
> @@ -665,9 +662,11 @@ static void __purge_vmap_area_lazy(unsigned long
> *start, unsigned long *end,
> spin_lock(&vmap_area_lock);
> llist_for_each_entry_safe(va, n_va, valist, purge_list)
> __free_vmap_area(va);
> + atomic_sub(1, &vmap_lazy_nr);
> + cond_resched_lock(&vmap_area_lock);
> spin_unlock(&vmap_area_lock);
For this particular hunk, I forgot the braces. sorry, I meant to say:
@@ -665,9 +662,11 @@ static void __purge_vmap_area_lazy(unsigned long
*start, unsigned long *end,
spin_lock(&vmap_area_lock);
- llist_for_each_entry_safe(va, n_va, valist, purge_list)
+ llist_for_each_entry_safe(va, n_va, valist,
purge_list) {
__free_vmap_area(va);
+ atomic_sub(1, &vmap_lazy_nr);
+ cond_resched_lock(&vmap_area_lock);
+ }
spin_unlock(&vmap_area_lock);
Regards,
Joel
^ permalink raw reply
* [PATCH] mm/vmalloc: reduce the number of lazy_max_pages to reduce latency
From: Joel Fernandes @ 2016-10-11 5:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161009192610.GB2718@nuc-i3427.alporthouse.com>
On Sun, Oct 9, 2016 at 12:26 PM, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> On Sun, Oct 09, 2016 at 12:00:31PM -0700, Joel Fernandes wrote:
>> Ok. So I'll submit a patch with mutex for purge_lock and use
>> cond_resched_lock for the vmap_area_lock as you suggested. I'll also
>> drop the lazy_max_pages to 8MB as Andi suggested to reduce the lock
>> hold time. Let me know if you have any objections.
>
> The downside of using a mutex here though, is that we may be called
> from contexts that cannot sleep (alloc_vmap_area), or reschedule for
> that matter! If we change the notion of purged, we can forgo the mutex
> in favour of spinning on the direct reclaim path. That just leaves the
> complication of whether to use cond_resched_lock() or a lock around
> the individual __free_vmap_area().
Good point. I agree with you. I think we still need to know if purging
is in progress to preserve previous trylock behavior. How about
something like the following diff? (diff is untested).
This drops the purge lock and uses a ref count to indicate if purging
is in progress, so that callers who don't want to purge if purging is
already in progress can be kept happy. Also I am reducing vmap_lazy_nr
as we go, and, not all at once, so that we don't reduce the counter
too soon as we're not holding purge lock anymore. Lastly, I added the
cond_resched as you suggested.
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index f2481cb..5616ca4 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -626,7 +626,7 @@ void set_iounmap_nonlazy(void)
static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
int sync, int force_flush)
{
- static DEFINE_SPINLOCK(purge_lock);
+ static atomic_t purging;
struct llist_node *valist;
struct vmap_area *va;
struct vmap_area *n_va;
@@ -638,10 +638,10 @@ static void __purge_vmap_area_lazy(unsigned long
*start, unsigned long *end,
* the case that isn't actually used at the moment anyway.
*/
if (!sync && !force_flush) {
- if (!spin_trylock(&purge_lock))
+ if (atomic_cmpxchg(&purging, 0, 1))
return;
} else
- spin_lock(&purge_lock);
+ atomic_inc(&purging);
if (sync)
purge_fragmented_blocks_allcpus();
@@ -655,9 +655,6 @@ static void __purge_vmap_area_lazy(unsigned long
*start, unsigned long *end,
nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
}
- if (nr)
- atomic_sub(nr, &vmap_lazy_nr);
-
if (nr || force_flush)
flush_tlb_kernel_range(*start, *end);
@@ -665,9 +662,11 @@ static void __purge_vmap_area_lazy(unsigned long
*start, unsigned long *end,
spin_lock(&vmap_area_lock);
llist_for_each_entry_safe(va, n_va, valist, purge_list)
__free_vmap_area(va);
+ atomic_sub(1, &vmap_lazy_nr);
+ cond_resched_lock(&vmap_area_lock);
spin_unlock(&vmap_area_lock);
}
- spin_unlock(&purge_lock);
+ atomic_dec(&purging);
}
^ permalink raw reply related
* [PATCH v14 2/4] CMDQ: Mediatek CMDQ driver
From: Jassi Brar @ 2016-10-11 4:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476153632.477.2.camel@mtksdaap41>
On 11 October 2016 at 08:10, Horng-Shyang Liao <hs.liao@mediatek.com> wrote:
> On Thu, 2016-10-06 at 18:40 +0530, Jassi Brar wrote:
>> On 6 October 2016 at 18:31, Horng-Shyang Liao <hs.liao@mediatek.com> wrote:
>>
>> > Back to our original statement, we need to flush all tasks to queue
>> > in GCE HW; i.e. we need to use mbox_client_txdone after
>> > mbox_send_message, or send tx_done once mailbox controller receive
>> > message (task). However, we still need a way to notice done tasks to
>> > clients. Currently, we don't have a good way to call callback in mailbox
>> > framework. Therefore, CMDQ driver has its owner callback functions.
>> >
>> mbox_client_txdone() is called by the client driver when only it knows
>> the messages has been transmitted (i.e your submitted tasks are done).
>> Obviously the client driver should do any callbacks to its users
>> upstream.
>
> Hi Jassi,
>
> In current CMDQ driver, mbox_client_txdone() is called to prevent the
> blocking of chan->active_req. It is not the real point of CMDQ task
> done, so the client driver cannot do any callbacks to its user upstream.
>
> (1) If we don't use mbox_client_txdone(), could you tell us an
> alternative way to prevent the blocking of chan->active_req?
> And then we can use tx_done when CMDQ task is relly done.
>
mbox_client_txdone() should be used only when the mailbox controller
driver can't figure when the TX is done. Client driver (by like some
reply packet) realises the TX is done (for the reply to have arrived).
If your hardware does flag/irq when tx is done, you should prefer
that over mbox_client_txdone().
> (2) If we use mbox_client_txdone() to prevent the blocking of
> chan->active_req, could CMDQ driver just uses self-defined callback
> function to notice client driver CMDQ task done?
>
Anything above the mailbox api, is none of its business. Your platform
specific 'server' driver can implement its own callbacks to notify its
users.
^ permalink raw reply
* [PATCH 1/5] dt-bindings: add vendor prefix for ILI Technology Corp
From: Icenowy Zheng @ 2016-10-11 3:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKdAkRT0WJ8EL62bumM1yz58LEAEqvmeX_hYzOZzAA0RvxJa3A@mail.gmail.com>
11.10.2016, 11:13, "Dmitry Torokhov" <dmitry.torokhov@gmail.com>:
> On Mon, Oct 10, 2016 at 5:33 PM, Icenowy Zheng <icenowy@aosc.xyz> wrote:
>> ?ILI Technology Corp (a.k.a Ilitek, http://www.ilitek.com/index-e.asp ) is a
>> ?company that produces LCD driver ICs and touch screen controller ICs.
>
> Was there patch 3/5? I do not see it in my mailbox.
Maybe it's spammed.
It can be retrieved at https://groups.google.com/d/msg/linux-sunxi/FY88KGfeCvk/tkEt6C4uBwAJ or http://lists.infradead.org/pipermail/linux-arm-kernel/2016-October/460908.html .
>
>> ?Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>
>> ?---
>> ??Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>> ??1 file changed, 1 insertion(+)
>>
>> ?diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
>> ?index 24c6f65..4d37fdc 100644
>> ?--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
>> ?+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
>> ?@@ -130,6 +130,7 @@ i2se I2SE GmbH
>> ??ibm International Business Machines (IBM)
>> ??idt Integrated Device Technologies, Inc.
>> ??ifi Ingenieurburo Fur Ic-Technologie (I/F/I)
>> ?+ilitek ILI Technologies Corp.
>> ??img Imagination Technologies Ltd.
>> ??infineon Infineon Technologies
>> ??inforce Inforce Computing
>> ?--
>> ?2.10.1
>
> --
> Dmitry
^ permalink raw reply
* [RESEND PATCH v6, 4/5] usb: Add MediaTek USB3 DRD Driver
From: Chunfeng Yun @ 2016-10-11 3:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <49293f1b-42b5-f06b-8fdc-f46fe996e237@gmail.com>
On Mon, 2016-10-10 at 13:00 +0200, Matthias Brugger wrote:
>
> On 09/21/2016 07:54 AM, Chunfeng Yun wrote:
> > This patch adds support for the MediaTek USB3 controller
> > integrated into MT8173. It can be configured as Dual-Role
> > Device (DRD), Peripheral Only and Host Only (xHCI) modes.
> >
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > drivers/usb/Kconfig | 2 +
> > drivers/usb/Makefile | 1 +
> > drivers/usb/mtu3/Kconfig | 54 +++
> > drivers/usb/mtu3/Makefile | 19 +
> > drivers/usb/mtu3/mtu3.h | 422 +++++++++++++++++
> > drivers/usb/mtu3/mtu3_core.c | 871 +++++++++++++++++++++++++++++++++++
> > drivers/usb/mtu3/mtu3_dr.c | 379 ++++++++++++++++
> > drivers/usb/mtu3/mtu3_dr.h | 108 +++++
> > drivers/usb/mtu3/mtu3_gadget.c | 731 +++++++++++++++++++++++++++++
> > drivers/usb/mtu3/mtu3_gadget_ep0.c | 883 ++++++++++++++++++++++++++++++++++++
> > drivers/usb/mtu3/mtu3_host.c | 294 ++++++++++++
> > drivers/usb/mtu3/mtu3_hw_regs.h | 473 +++++++++++++++++++
> > drivers/usb/mtu3/mtu3_plat.c | 490 ++++++++++++++++++++
> > drivers/usb/mtu3/mtu3_qmu.c | 599 ++++++++++++++++++++++++
> > drivers/usb/mtu3/mtu3_qmu.h | 43 ++
> > 15 files changed, 5369 insertions(+)
> > create mode 100644 drivers/usb/mtu3/Kconfig
> > create mode 100644 drivers/usb/mtu3/Makefile
> > create mode 100644 drivers/usb/mtu3/mtu3.h
> > create mode 100644 drivers/usb/mtu3/mtu3_core.c
> > create mode 100644 drivers/usb/mtu3/mtu3_dr.c
> > create mode 100644 drivers/usb/mtu3/mtu3_dr.h
> > create mode 100644 drivers/usb/mtu3/mtu3_gadget.c
> > create mode 100644 drivers/usb/mtu3/mtu3_gadget_ep0.c
> > create mode 100644 drivers/usb/mtu3/mtu3_host.c
> > create mode 100644 drivers/usb/mtu3/mtu3_hw_regs.h
> > create mode 100644 drivers/usb/mtu3/mtu3_plat.c
> > create mode 100644 drivers/usb/mtu3/mtu3_qmu.c
> > create mode 100644 drivers/usb/mtu3/mtu3_qmu.h
> >
>
> As Oliver already said, this patch is quiet big which makes it difficult
> to review.
> I propose to provide a first implementation with minimal functionality
> and incremental patches on top of this when the first got merged.
>
> You could split the patch in three series/parts:
> 1. Host only
> 2. Peripheral only
> 3. Dual mode
>
> What do you think?
Ok, I'll split the patch into some small ones as many as possible.
Thanks a lot
>
> Regards,
> Matthias
>
^ 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