[sysfs] Sysfs acceptable paths to custom functionality

2017-10-05 Thread steven
I am developing a driver for an audio codec that has fixed DSP 
functionality. On the device there are coefficients that can be 
programmed to implement different types of filters that can be used to 
implement an EQ or 3D sound effects.


Based on what I have seen in the Kernel so far our device is the only 
one that has this type of feature, but I do believe others exist. Due to 
this I would like to generalize this as much as possible so user space 
applications can take advantage of it.


1. Where under /sys/ should I expose these features?

My initial thought for the interface would look something like this:

some_device/
..features/
eq1/
..band1/
coefficient_a1
coefficient_a2
eq2/
3dbass/
3dtreb/

2. Do you see anything wrong with this approach?

Please CC me in your responses.

Regards,

Steven



[sysfs] Sysfs acceptable paths to custom functionality

2017-10-05 Thread steven
I am developing a driver for an audio codec that has fixed DSP 
functionality. On the device there are coefficients that can be 
programmed to implement different types of filters that can be used to 
implement an EQ or 3D sound effects.


Based on what I have seen in the Kernel so far our device is the only 
one that has this type of feature, but I do believe others exist. Due to 
this I would like to generalize this as much as possible so user space 
applications can take advantage of it.


1. Where under /sys/ should I expose these features?

My initial thought for the interface would look something like this:

some_device/
..features/
eq1/
..band1/
coefficient_a1
coefficient_a2
eq2/
3dbass/
3dtreb/

2. Do you see anything wrong with this approach?

Please CC me in your responses.

Regards,

Steven



Re: [v10 3/6] mm, oom: cgroup-aware OOM killer

2017-10-05 Thread Michal Hocko
On Thu 05-10-17 15:02:18, David Rientjes wrote:
[...]
> I would need to add patches to add the "evaluate as a whole but do not 
> kill all" knob and a knob for "oom priority" so that userspace has the 
> same influence over a cgroup based comparison that it does with a process 
> based comparison to meet business goals.

I do not think 2 knobs would be really necessary for your usecase. If we
allow priorities on non-leaf memcgs then a non 0 priority on such a
memcg would mean that we have to check the cumulative consumption. You
can safely use kill all knob on top of that if you need.
-- 
Michal Hocko
SUSE Labs


Re: [v10 3/6] mm, oom: cgroup-aware OOM killer

2017-10-05 Thread Michal Hocko
On Thu 05-10-17 15:02:18, David Rientjes wrote:
[...]
> I would need to add patches to add the "evaluate as a whole but do not 
> kill all" knob and a knob for "oom priority" so that userspace has the 
> same influence over a cgroup based comparison that it does with a process 
> based comparison to meet business goals.

I do not think 2 knobs would be really necessary for your usecase. If we
allow priorities on non-leaf memcgs then a non 0 priority on such a
memcg would mean that we have to check the cumulative consumption. You
can safely use kill all knob on top of that if you need.
-- 
Michal Hocko
SUSE Labs


Re: [PATCH v2 09/16] driver core: add iommu device fault reporting data

2017-10-05 Thread Greg Kroah-Hartman
On Thu, Oct 05, 2017 at 04:03:37PM -0700, Jacob Pan wrote:
> DMA faults can be detected by IOMMU at device level. Adding a pointer
> to struct device allows IOMMU subsystem to report relevant faults
> back to the device driver for further handling.
> For direct assigned device (or user space drivers), guest OS holds
> responsibility to handle and respond per device IOMMU fault.
> Therefore we need fault reporting mechanism to propagate faults beyond
> IOMMU subsystem.
> 
> Signed-off-by: Jacob Pan 

Acked-by: Greg Kroah-Hartman 


Re: [PATCH v2 09/16] driver core: add iommu device fault reporting data

2017-10-05 Thread Greg Kroah-Hartman
On Thu, Oct 05, 2017 at 04:03:37PM -0700, Jacob Pan wrote:
> DMA faults can be detected by IOMMU at device level. Adding a pointer
> to struct device allows IOMMU subsystem to report relevant faults
> back to the device driver for further handling.
> For direct assigned device (or user space drivers), guest OS holds
> responsibility to handle and respond per device IOMMU fault.
> Therefore we need fault reporting mechanism to propagate faults beyond
> IOMMU subsystem.
> 
> Signed-off-by: Jacob Pan 

Acked-by: Greg Kroah-Hartman 


Re: [PATCH 1/4] dt-bindings: media: Binding document for Qualcomm Camera Control Interface driver

2017-10-05 Thread Bjorn Andersson
On Mon 02 Oct 07:13 PDT 2017, Todor Tomov wrote:
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt 
> b/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt
> new file mode 100644
> index 000..f4c5338
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt
> @@ -0,0 +1,55 @@
> +Qualcomm Camera Control Interface I2C controller

Well, it's not a I2C controller, it is a MIPI CCI controller.

> +
> +Required properties:
> + - compatible: Should be one of:
> +   - "qcom,cci-v1.0.8" for 8916;
> +   - "qcom,cci-v1.4.0" for 8996.
> + - #address-cells: Should be <1>.
> + - #size-cells: Should be <0>.
> + - reg: Base address of the controller and length of memory mapped region.
> + - reg-names: Should be "cci".

No need for reg-names, as we only have one.

> + - interrupts: Specifier for CCI interrupt.
> + - interrupt-names: Should be "cci".

No need for interrupt-names, as we only have one.

> + - clocks: List of clock specifiers, one for each entry in clock-names.
> + - clock-names: Should contain:
> +   - "mmss_mmagic_ahb" - on 8996 only;
> +   - "camss_top_ahb";
> +   - "cci_ahb";
> +   - "cci";
> +   - "camss_ahb".
> + - pinctrl-names: Should contain only one value - "default".
> + - pinctrl-0: Pin control group to be used for this controller.

No need to document that the node can have the default pinctrl
properties.

> +
> +
> +Required properties on 8996:
> + - power-domains: Power domain specifier.
> +
> +Optional:
> + - clock-frequency: Desired I2C bus clock frequency in Hz, defaults to 100 
> kHz
> +   if omitted.
> +
> +Example:
> +
> +cci: qcom,cci@a0c000 {

Don't do qcom, in the node name, and there's probably no reason to have
a label for this node either. So just make it

   cci@a0c000 {

> +compatible = "qcom,cci-v1.4.0";
> +#address-cells = <1>;
> +#size-cells = <0>;
> +reg = <0xa0c000 0x1000>;
> +reg-names = "cci";
> +interrupts = ;
> +interrupt-names = "cci";
> +power-domains = < CAMSS_GDSC>;
> +clocks = < MMSS_MMAGIC_AHB_CLK>,
> +< CAMSS_TOP_AHB_CLK>,
> +< CAMSS_CCI_AHB_CLK>,
> +< CAMSS_CCI_CLK>,
> +< CAMSS_AHB_CLK>;
> +clock-names = "mmss_mmagic_ahb",
> +"camss_top_ahb",
> +"cci_ahb",
> +"cci",
> +"camss_ahb";
> +pinctrl-names = "default";
> +pinctrl-0 = <_default>;
> +clock-frequency = <40>;
> +};

In the case of this single cci block having two masters we need a way to
describe the two sets of clients. I think the two options we have are:

cci {
client {
reg = <0 0x2c>;
};
};

The reg here being 

or:

cci {
master0 {
client {
reg = <0x2c>;
};
};
};

The name "master0" could be made significant and picked up by name, and
in the case of single-master this level could be omitted.


I like the first one, but it looks really hard to get implemented in
Linux, based on the i2c core's expectation that #address-cells is 1. So
I think the latter is the favourable option.

Regards,
Bjorn


Re: [PATCH 1/4] dt-bindings: media: Binding document for Qualcomm Camera Control Interface driver

2017-10-05 Thread Bjorn Andersson
On Mon 02 Oct 07:13 PDT 2017, Todor Tomov wrote:
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt 
> b/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt
> new file mode 100644
> index 000..f4c5338
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/i2c/i2c-qcom-cci.txt
> @@ -0,0 +1,55 @@
> +Qualcomm Camera Control Interface I2C controller

Well, it's not a I2C controller, it is a MIPI CCI controller.

> +
> +Required properties:
> + - compatible: Should be one of:
> +   - "qcom,cci-v1.0.8" for 8916;
> +   - "qcom,cci-v1.4.0" for 8996.
> + - #address-cells: Should be <1>.
> + - #size-cells: Should be <0>.
> + - reg: Base address of the controller and length of memory mapped region.
> + - reg-names: Should be "cci".

No need for reg-names, as we only have one.

> + - interrupts: Specifier for CCI interrupt.
> + - interrupt-names: Should be "cci".

No need for interrupt-names, as we only have one.

> + - clocks: List of clock specifiers, one for each entry in clock-names.
> + - clock-names: Should contain:
> +   - "mmss_mmagic_ahb" - on 8996 only;
> +   - "camss_top_ahb";
> +   - "cci_ahb";
> +   - "cci";
> +   - "camss_ahb".
> + - pinctrl-names: Should contain only one value - "default".
> + - pinctrl-0: Pin control group to be used for this controller.

No need to document that the node can have the default pinctrl
properties.

> +
> +
> +Required properties on 8996:
> + - power-domains: Power domain specifier.
> +
> +Optional:
> + - clock-frequency: Desired I2C bus clock frequency in Hz, defaults to 100 
> kHz
> +   if omitted.
> +
> +Example:
> +
> +cci: qcom,cci@a0c000 {

Don't do qcom, in the node name, and there's probably no reason to have
a label for this node either. So just make it

   cci@a0c000 {

> +compatible = "qcom,cci-v1.4.0";
> +#address-cells = <1>;
> +#size-cells = <0>;
> +reg = <0xa0c000 0x1000>;
> +reg-names = "cci";
> +interrupts = ;
> +interrupt-names = "cci";
> +power-domains = < CAMSS_GDSC>;
> +clocks = < MMSS_MMAGIC_AHB_CLK>,
> +< CAMSS_TOP_AHB_CLK>,
> +< CAMSS_CCI_AHB_CLK>,
> +< CAMSS_CCI_CLK>,
> +< CAMSS_AHB_CLK>;
> +clock-names = "mmss_mmagic_ahb",
> +"camss_top_ahb",
> +"cci_ahb",
> +"cci",
> +"camss_ahb";
> +pinctrl-names = "default";
> +pinctrl-0 = <_default>;
> +clock-frequency = <40>;
> +};

In the case of this single cci block having two masters we need a way to
describe the two sets of clients. I think the two options we have are:

cci {
client {
reg = <0 0x2c>;
};
};

The reg here being 

or:

cci {
master0 {
client {
reg = <0x2c>;
};
};
};

The name "master0" could be made significant and picked up by name, and
in the case of single-master this level could be omitted.


I like the first one, but it looks really hard to get implemented in
Linux, based on the i2c core's expectation that #address-cells is 1. So
I think the latter is the favourable option.

Regards,
Bjorn


Re: [PATCH 2/4] i2c: Add Qualcomm Camera Control Interface driver

2017-10-05 Thread Bjorn Andersson
On Mon 02 Oct 07:13 PDT 2017, Todor Tomov wrote:
> diff --git a/drivers/i2c/busses/i2c-qcom-cci.c 
> b/drivers/i2c/busses/i2c-qcom-cci.c
[..]
> +#define NUM_MASTERS 1

So you will only register one of the masters?

[..]
> +enum cci_i2c_queue_t {
> + QUEUE_0,
> + QUEUE_1

Could these be called QUEUE_READ and QUEUE_WRITE instead?

> +};
> +
> +enum cci_i2c_master_t {
> + MASTER_0,
> + MASTER_1

Just use 0 and 1 when denoting the two masters.

> +};
> +
> +struct resources {

This struct name is not awesome, name it something like cci_res instead.

> + char *clock[CCI_RES_MAX];
> + u32 clock_rate[CCI_RES_MAX];
> + char *reg[CCI_RES_MAX];
> + char *interrupt[CCI_RES_MAX];
> +};
[..]
> +
> +struct cci_master {
> + u32 status;

You use this to pass 0 or negative errno between functions, so make it
int.

> + u8 complete_pending;

bool

> + struct completion irq_complete;
> +};
> +
> +struct cci {
> + struct device *dev;
> + struct i2c_adapter adap;
> + void __iomem *base;
> + u32 irq;

"irq" is generally supposed to be a "int".

> + char irq_name[30];
> + struct cci_clock *clock;

If you set the rate of your clocks initially you can replace this array
with clk_bulk_data and use the clk_bulk_prepare_enable() and
clk_bulk_disable_unprepare().

> + int nclocks;
> + u8 mode;
> + u16 queue_size[NUM_QUEUES];
> + struct cci_master master[NUM_MASTERS];
> +};
> +
> +static const struct resources res_v1_0_8 = {
> + .clock = { "camss_top_ahb",
> +"cci_ahb",
> +"camss_ahb",
> +"cci" },

The code consuming this will read until NULL, so please add terminator.
It happens to work as the first clock_rate is 0 in both cases.

> + .clock_rate = { 0,
> + 8000,
> + 0,
> + 1920 },
> + .reg = { "cci" },
> + .interrupt = { "cci" }

No need to specify reg and interrupt here until they actually need to be
configured; just put the strings in the code.

> +};
> +
[..]
> +
> +/*
> + * cci_enable_clocks - Enable multiple clocks

Correct kerneldoc would be:

/**
 * cci_enable_clocks() - Enable multiple clocks

> + * @nclocks: Number of clocks in clock array
> + * @clock: Clock array
> + * @dev: Device
> + *
> + * Return 0 on success or a negative error code otherwise
> + */
> +int cci_enable_clocks(int nclocks, struct cci_clock *clock, struct device 
> *dev)

Overall this is clk_bulk_prepare_enable(), please use that.

[..]
> +/*
> + * cci_disable_clocks - Disable multiple clocks
> + * @nclocks: Number of clocks in clock array
> + * @clock: Clock array
> + */
> +void cci_disable_clocks(int nclocks, struct cci_clock *clock)

Overall this is clk_bulk_disable_unprepare(), so please use that.

> +{
> + int i;
> +
> + for (i = nclocks - 1; i >= 0; i--)
> + clk_disable_unprepare(clock[i].clk);
> +}
> +
[..]
> +
> +static int cci_init(struct cci *cci, const struct hw_params *hw)
> +{
> + u32 val = CCI_IRQ_MASK_0_I2C_M0_RD_DONE |
> + CCI_IRQ_MASK_0_I2C_M0_Q0_REPORT |
> + CCI_IRQ_MASK_0_I2C_M0_Q1_REPORT |
> + CCI_IRQ_MASK_0_I2C_M1_RD_DONE |
> + CCI_IRQ_MASK_0_I2C_M1_Q0_REPORT |
> + CCI_IRQ_MASK_0_I2C_M1_Q1_REPORT |
> + CCI_IRQ_MASK_0_RST_DONE_ACK |
> + CCI_IRQ_MASK_0_I2C_M0_Q0Q1_HALT_ACK |
> + CCI_IRQ_MASK_0_I2C_M1_Q0Q1_HALT_ACK |
> + CCI_IRQ_MASK_0_I2C_M0_ERROR |
> + CCI_IRQ_MASK_0_I2C_M1_ERROR;
> + int i;
> +
> + writel(val, cci->base + CCI_IRQ_MASK_0);
> +
> + for (i = 0; i < NUM_MASTERS; i++) {
> + val = hw->thigh << 16 | hw->tlow;
> + writel(val, cci->base + CCI_I2C_Mm_SCL_CTL(i));
> +
> + val = hw->tsu_sto << 16 | hw->tsu_sta;
> + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_0(i));
> +
> + val = hw->thd_dat << 16 | hw->thd_sta;
> + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_1(i));
> +
> + val = hw->tbuf;
> + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_2(i));
> +
> + val = hw->scl_stretch_en << 8 | hw->trdhld << 4 | hw->tsp;
> + writel(val, cci->base + CCI_I2C_Mm_MISC_CTL(i));
> +
> + cci->master[i].status = 0;

I don't think you need to initialize status here, it's always written
before read in the rest of the driver.

> + }
> +
> + return 0;
> +}
> +
> +static int cci_run_queue(struct cci *cci, u8 master, u8 queue)
> +{
> + unsigned long time;
> + u32 val;
> + int ret;
> +
> + val = readl(cci->base + CCI_I2C_Mm_Qn_CUR_WORD_CNT(master, queue));
> + writel(val, cci->base + CCI_I2C_Mm_Qn_EXEC_WORD_CNT(master, queue));
> +
> + val = 1 << ((master * 2) + queue);

BIT(master * 2 + queue)

> + writel(val, cci->base + CCI_QUEUE_START);
> +
> + 

Re: [PATCH 2/4] i2c: Add Qualcomm Camera Control Interface driver

2017-10-05 Thread Bjorn Andersson
On Mon 02 Oct 07:13 PDT 2017, Todor Tomov wrote:
> diff --git a/drivers/i2c/busses/i2c-qcom-cci.c 
> b/drivers/i2c/busses/i2c-qcom-cci.c
[..]
> +#define NUM_MASTERS 1

So you will only register one of the masters?

[..]
> +enum cci_i2c_queue_t {
> + QUEUE_0,
> + QUEUE_1

Could these be called QUEUE_READ and QUEUE_WRITE instead?

> +};
> +
> +enum cci_i2c_master_t {
> + MASTER_0,
> + MASTER_1

Just use 0 and 1 when denoting the two masters.

> +};
> +
> +struct resources {

This struct name is not awesome, name it something like cci_res instead.

> + char *clock[CCI_RES_MAX];
> + u32 clock_rate[CCI_RES_MAX];
> + char *reg[CCI_RES_MAX];
> + char *interrupt[CCI_RES_MAX];
> +};
[..]
> +
> +struct cci_master {
> + u32 status;

You use this to pass 0 or negative errno between functions, so make it
int.

> + u8 complete_pending;

bool

> + struct completion irq_complete;
> +};
> +
> +struct cci {
> + struct device *dev;
> + struct i2c_adapter adap;
> + void __iomem *base;
> + u32 irq;

"irq" is generally supposed to be a "int".

> + char irq_name[30];
> + struct cci_clock *clock;

If you set the rate of your clocks initially you can replace this array
with clk_bulk_data and use the clk_bulk_prepare_enable() and
clk_bulk_disable_unprepare().

> + int nclocks;
> + u8 mode;
> + u16 queue_size[NUM_QUEUES];
> + struct cci_master master[NUM_MASTERS];
> +};
> +
> +static const struct resources res_v1_0_8 = {
> + .clock = { "camss_top_ahb",
> +"cci_ahb",
> +"camss_ahb",
> +"cci" },

The code consuming this will read until NULL, so please add terminator.
It happens to work as the first clock_rate is 0 in both cases.

> + .clock_rate = { 0,
> + 8000,
> + 0,
> + 1920 },
> + .reg = { "cci" },
> + .interrupt = { "cci" }

No need to specify reg and interrupt here until they actually need to be
configured; just put the strings in the code.

> +};
> +
[..]
> +
> +/*
> + * cci_enable_clocks - Enable multiple clocks

Correct kerneldoc would be:

/**
 * cci_enable_clocks() - Enable multiple clocks

> + * @nclocks: Number of clocks in clock array
> + * @clock: Clock array
> + * @dev: Device
> + *
> + * Return 0 on success or a negative error code otherwise
> + */
> +int cci_enable_clocks(int nclocks, struct cci_clock *clock, struct device 
> *dev)

Overall this is clk_bulk_prepare_enable(), please use that.

[..]
> +/*
> + * cci_disable_clocks - Disable multiple clocks
> + * @nclocks: Number of clocks in clock array
> + * @clock: Clock array
> + */
> +void cci_disable_clocks(int nclocks, struct cci_clock *clock)

Overall this is clk_bulk_disable_unprepare(), so please use that.

> +{
> + int i;
> +
> + for (i = nclocks - 1; i >= 0; i--)
> + clk_disable_unprepare(clock[i].clk);
> +}
> +
[..]
> +
> +static int cci_init(struct cci *cci, const struct hw_params *hw)
> +{
> + u32 val = CCI_IRQ_MASK_0_I2C_M0_RD_DONE |
> + CCI_IRQ_MASK_0_I2C_M0_Q0_REPORT |
> + CCI_IRQ_MASK_0_I2C_M0_Q1_REPORT |
> + CCI_IRQ_MASK_0_I2C_M1_RD_DONE |
> + CCI_IRQ_MASK_0_I2C_M1_Q0_REPORT |
> + CCI_IRQ_MASK_0_I2C_M1_Q1_REPORT |
> + CCI_IRQ_MASK_0_RST_DONE_ACK |
> + CCI_IRQ_MASK_0_I2C_M0_Q0Q1_HALT_ACK |
> + CCI_IRQ_MASK_0_I2C_M1_Q0Q1_HALT_ACK |
> + CCI_IRQ_MASK_0_I2C_M0_ERROR |
> + CCI_IRQ_MASK_0_I2C_M1_ERROR;
> + int i;
> +
> + writel(val, cci->base + CCI_IRQ_MASK_0);
> +
> + for (i = 0; i < NUM_MASTERS; i++) {
> + val = hw->thigh << 16 | hw->tlow;
> + writel(val, cci->base + CCI_I2C_Mm_SCL_CTL(i));
> +
> + val = hw->tsu_sto << 16 | hw->tsu_sta;
> + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_0(i));
> +
> + val = hw->thd_dat << 16 | hw->thd_sta;
> + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_1(i));
> +
> + val = hw->tbuf;
> + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_2(i));
> +
> + val = hw->scl_stretch_en << 8 | hw->trdhld << 4 | hw->tsp;
> + writel(val, cci->base + CCI_I2C_Mm_MISC_CTL(i));
> +
> + cci->master[i].status = 0;

I don't think you need to initialize status here, it's always written
before read in the rest of the driver.

> + }
> +
> + return 0;
> +}
> +
> +static int cci_run_queue(struct cci *cci, u8 master, u8 queue)
> +{
> + unsigned long time;
> + u32 val;
> + int ret;
> +
> + val = readl(cci->base + CCI_I2C_Mm_Qn_CUR_WORD_CNT(master, queue));
> + writel(val, cci->base + CCI_I2C_Mm_Qn_EXEC_WORD_CNT(master, queue));
> +
> + val = 1 << ((master * 2) + queue);

BIT(master * 2 + queue)

> + writel(val, cci->base + CCI_QUEUE_START);
> +
> + 

Re: [PATCH] net/ipv6: remove unused err variable on icmpv6_push_pending_frames

2017-10-05 Thread David Miller
From: Tim Hansen 
Date: Thu, 5 Oct 2017 15:45:32 -0400

> int err is unused by icmpv6_push_pending_frames(), this patch returns removes 
> the variable and returns the function with 0.
> 
> git bisect shows this variable has been around since linux has been in git in 
> commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.  
> 
> This was found by running make coccicheck M=net/ipv6/ on linus' tree on 
> commit 77ede3a014a32746002f7889211f0cecf4803163 (current HEAD as of this 
> patch).
> 
> Signed-off-by: Tim Hansen 

Applied.


Re: [PATCH] net/ipv6: remove unused err variable on icmpv6_push_pending_frames

2017-10-05 Thread David Miller
From: Tim Hansen 
Date: Thu, 5 Oct 2017 15:45:32 -0400

> int err is unused by icmpv6_push_pending_frames(), this patch returns removes 
> the variable and returns the function with 0.
> 
> git bisect shows this variable has been around since linux has been in git in 
> commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.  
> 
> This was found by running make coccicheck M=net/ipv6/ on linus' tree on 
> commit 77ede3a014a32746002f7889211f0cecf4803163 (current HEAD as of this 
> patch).
> 
> Signed-off-by: Tim Hansen 

Applied.


[PATCH v2 3/3] arm64: dts: uniphier: add efuse node for LD20

2017-10-05 Thread Keiji Hayashibara
Add efuse node for UniPhier LD20 SoC.
This efuse node is included in soc-glue.

Signed-off-by: Keiji Hayashibara 
---
 arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi 
b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
index a29c279..ddefde6 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
@@ -376,6 +376,24 @@
};
};
 
+   soc-glue@5f90 {
+   compatible = "socionext,uniphier-ld20-soc-glue-debug",
+"simple-mfd";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0x5f90 0x2000>;
+
+   efuse@100 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x100 0x28>;
+   };
+
+   efuse@200 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x200 0x68>;
+   };
+   };
+
aidet: aidet@5fc2 {
compatible = "socionext,uniphier-ld20-aidet";
reg = <0x5fc2 0x200>;
-- 
2.7.4



[PATCH v2 3/3] arm64: dts: uniphier: add efuse node for LD20

2017-10-05 Thread Keiji Hayashibara
Add efuse node for UniPhier LD20 SoC.
This efuse node is included in soc-glue.

Signed-off-by: Keiji Hayashibara 
---
 arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi 
b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
index a29c279..ddefde6 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
@@ -376,6 +376,24 @@
};
};
 
+   soc-glue@5f90 {
+   compatible = "socionext,uniphier-ld20-soc-glue-debug",
+"simple-mfd";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0x5f90 0x2000>;
+
+   efuse@100 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x100 0x28>;
+   };
+
+   efuse@200 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x200 0x68>;
+   };
+   };
+
aidet: aidet@5fc2 {
compatible = "socionext,uniphier-ld20-aidet";
reg = <0x5fc2 0x200>;
-- 
2.7.4



[PATCH v2 0/3] add UniPhier efuse support

2017-10-05 Thread Keiji Hayashibara
This series adds support for eFuse implemented on UniPhier LD20 SoCs.
The eFuse device is under soc-glue and this register implements as read only.

patch V1
https://lkml.org/lkml/2017/8/31/880

Changes between V2 and V1
=
1. Fix sparse warnings
2. Changed to implement without regmap
3. Convert devm_kzalloc to stack
4. Divide efuse into two areas in devicetree
5. Remove .owner settings of struct nvmem_config
6. Remove enable of CONFIG_UNIPHIER_EFUSE in defconfig
7. Other minor fixes

Keiji Hayashibara (3):
  dt-bindings: nvmem: add description for UniPhier eFuse
  nvmem: uniphier: add UniPhier eFuse driver
  arm64: dts: uniphier: add efuse node for LD20

 .../devicetree/bindings/nvmem/uniphier-efuse.txt   | 49 +++
 arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi   | 18 
 drivers/nvmem/Kconfig  | 11 +++
 drivers/nvmem/Makefile |  2 +
 drivers/nvmem/uniphier-efuse.c | 97 ++
 5 files changed, 177 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
 create mode 100644 drivers/nvmem/uniphier-efuse.c

-- 
2.7.4



[PATCH v2 2/3] nvmem: uniphier: add UniPhier eFuse driver

2017-10-05 Thread Keiji Hayashibara
Add eFuse driver for Socionext UniPhier series SoC.
Note that eFuse device is under soc-glue and this register
implements as read only.

Signed-off-by: Keiji Hayashibara 
---
 drivers/nvmem/Kconfig  | 11 +
 drivers/nvmem/Makefile |  2 +
 drivers/nvmem/uniphier-efuse.c | 97 ++
 3 files changed, 110 insertions(+)
 create mode 100644 drivers/nvmem/uniphier-efuse.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 101ced4..9c32cfe 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -123,6 +123,17 @@ config NVMEM_SUNXI_SID
  This driver can also be built as a module. If so, the module
  will be called nvmem_sunxi_sid.
 
+config UNIPHIER_EFUSE
+   tristate "UniPhier SoCs eFuse support"
+   depends on ARCH_UNIPHIER || COMPILE_TEST
+   depends on HAS_IOMEM
+   help
+ This is a simple driver to dump specified values of UniPhier SoC
+ from eFuse.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-uniphier-efuse.
+
 config NVMEM_VF610_OCOTP
tristate "VF610 SoC OCOTP support"
depends on SOC_VF610 || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 1731406..2d07162 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_ROCKCHIP_EFUSE)  += nvmem_rockchip_efuse.o
 nvmem_rockchip_efuse-y := rockchip-efuse.o
 obj-$(CONFIG_NVMEM_SUNXI_SID)  += nvmem_sunxi_sid.o
 nvmem_sunxi_sid-y  := sunxi_sid.o
+obj-$(CONFIG_UNIPHIER_EFUSE)   += nvmem-uniphier-efuse.o
+nvmem-uniphier-efuse-y := uniphier-efuse.o
 obj-$(CONFIG_NVMEM_VF610_OCOTP)+= nvmem-vf610-ocotp.o
 nvmem-vf610-ocotp-y:= vf610-ocotp.o
 obj-$(CONFIG_MESON_EFUSE)  += nvmem_meson_efuse.o
diff --git a/drivers/nvmem/uniphier-efuse.c b/drivers/nvmem/uniphier-efuse.c
new file mode 100644
index 000..2bb45c4
--- /dev/null
+++ b/drivers/nvmem/uniphier-efuse.c
@@ -0,0 +1,97 @@
+/*
+ * UniPhier eFuse driver
+ *
+ * Copyright (C) 2017 Socionext Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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 
+#include 
+#include 
+#include 
+#include 
+
+struct uniphier_efuse_priv {
+   void __iomem *base;
+};
+
+static int uniphier_reg_read(void *context,
+unsigned int reg, void *_val, size_t bytes)
+{
+   struct uniphier_efuse_priv *priv = context;
+   u32 *val = _val;
+   int offs;
+
+   for (offs = 0; offs < bytes; offs += sizeof(u32))
+   *val++ = readl(priv->base + reg + offs);
+
+   return 0;
+}
+
+static int uniphier_efuse_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct resource *res;
+   struct nvmem_device *nvmem;
+   struct nvmem_config econfig ={};
+   struct uniphier_efuse_priv *priv;
+
+   priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   priv->base = devm_ioremap_resource(dev, res);
+   if (IS_ERR(priv->base))
+   return PTR_ERR(priv->base);
+
+   econfig.stride = 4;
+   econfig.word_size = 4;
+   econfig.read_only = true;
+   econfig.reg_read = uniphier_reg_read;
+   econfig.size = resource_size(res);
+   econfig.priv = priv;
+   econfig.dev = dev;
+   nvmem = nvmem_register();
+   if (IS_ERR(nvmem))
+   return PTR_ERR(nvmem);
+
+   platform_set_drvdata(pdev, nvmem);
+
+   return 0;
+}
+
+static int uniphier_efuse_remove(struct platform_device *pdev)
+{
+   struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+   return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id uniphier_efuse_of_match[] = {
+   { .compatible = "socionext,uniphier-efuse",},
+   {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, uniphier_efuse_of_match);
+
+static struct platform_driver uniphier_efuse_driver = {
+   .probe = uniphier_efuse_probe,
+   .remove = uniphier_efuse_remove,
+   .driver = {
+   .name = "uniphier-efuse",
+   .of_match_table = uniphier_efuse_of_match,
+   },
+};
+module_platform_driver(uniphier_efuse_driver);
+
+MODULE_AUTHOR("Keiji Hayashibara ");
+MODULE_DESCRIPTION("UniPhier eFuse driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4



[PATCH v2 0/3] add UniPhier efuse support

2017-10-05 Thread Keiji Hayashibara
This series adds support for eFuse implemented on UniPhier LD20 SoCs.
The eFuse device is under soc-glue and this register implements as read only.

patch V1
https://lkml.org/lkml/2017/8/31/880

Changes between V2 and V1
=
1. Fix sparse warnings
2. Changed to implement without regmap
3. Convert devm_kzalloc to stack
4. Divide efuse into two areas in devicetree
5. Remove .owner settings of struct nvmem_config
6. Remove enable of CONFIG_UNIPHIER_EFUSE in defconfig
7. Other minor fixes

Keiji Hayashibara (3):
  dt-bindings: nvmem: add description for UniPhier eFuse
  nvmem: uniphier: add UniPhier eFuse driver
  arm64: dts: uniphier: add efuse node for LD20

 .../devicetree/bindings/nvmem/uniphier-efuse.txt   | 49 +++
 arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi   | 18 
 drivers/nvmem/Kconfig  | 11 +++
 drivers/nvmem/Makefile |  2 +
 drivers/nvmem/uniphier-efuse.c | 97 ++
 5 files changed, 177 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
 create mode 100644 drivers/nvmem/uniphier-efuse.c

-- 
2.7.4



[PATCH v2 2/3] nvmem: uniphier: add UniPhier eFuse driver

2017-10-05 Thread Keiji Hayashibara
Add eFuse driver for Socionext UniPhier series SoC.
Note that eFuse device is under soc-glue and this register
implements as read only.

Signed-off-by: Keiji Hayashibara 
---
 drivers/nvmem/Kconfig  | 11 +
 drivers/nvmem/Makefile |  2 +
 drivers/nvmem/uniphier-efuse.c | 97 ++
 3 files changed, 110 insertions(+)
 create mode 100644 drivers/nvmem/uniphier-efuse.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 101ced4..9c32cfe 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -123,6 +123,17 @@ config NVMEM_SUNXI_SID
  This driver can also be built as a module. If so, the module
  will be called nvmem_sunxi_sid.
 
+config UNIPHIER_EFUSE
+   tristate "UniPhier SoCs eFuse support"
+   depends on ARCH_UNIPHIER || COMPILE_TEST
+   depends on HAS_IOMEM
+   help
+ This is a simple driver to dump specified values of UniPhier SoC
+ from eFuse.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-uniphier-efuse.
+
 config NVMEM_VF610_OCOTP
tristate "VF610 SoC OCOTP support"
depends on SOC_VF610 || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 1731406..2d07162 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -26,6 +26,8 @@ obj-$(CONFIG_ROCKCHIP_EFUSE)  += nvmem_rockchip_efuse.o
 nvmem_rockchip_efuse-y := rockchip-efuse.o
 obj-$(CONFIG_NVMEM_SUNXI_SID)  += nvmem_sunxi_sid.o
 nvmem_sunxi_sid-y  := sunxi_sid.o
+obj-$(CONFIG_UNIPHIER_EFUSE)   += nvmem-uniphier-efuse.o
+nvmem-uniphier-efuse-y := uniphier-efuse.o
 obj-$(CONFIG_NVMEM_VF610_OCOTP)+= nvmem-vf610-ocotp.o
 nvmem-vf610-ocotp-y:= vf610-ocotp.o
 obj-$(CONFIG_MESON_EFUSE)  += nvmem_meson_efuse.o
diff --git a/drivers/nvmem/uniphier-efuse.c b/drivers/nvmem/uniphier-efuse.c
new file mode 100644
index 000..2bb45c4
--- /dev/null
+++ b/drivers/nvmem/uniphier-efuse.c
@@ -0,0 +1,97 @@
+/*
+ * UniPhier eFuse driver
+ *
+ * Copyright (C) 2017 Socionext Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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 
+#include 
+#include 
+#include 
+#include 
+
+struct uniphier_efuse_priv {
+   void __iomem *base;
+};
+
+static int uniphier_reg_read(void *context,
+unsigned int reg, void *_val, size_t bytes)
+{
+   struct uniphier_efuse_priv *priv = context;
+   u32 *val = _val;
+   int offs;
+
+   for (offs = 0; offs < bytes; offs += sizeof(u32))
+   *val++ = readl(priv->base + reg + offs);
+
+   return 0;
+}
+
+static int uniphier_efuse_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   struct resource *res;
+   struct nvmem_device *nvmem;
+   struct nvmem_config econfig ={};
+   struct uniphier_efuse_priv *priv;
+
+   priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   priv->base = devm_ioremap_resource(dev, res);
+   if (IS_ERR(priv->base))
+   return PTR_ERR(priv->base);
+
+   econfig.stride = 4;
+   econfig.word_size = 4;
+   econfig.read_only = true;
+   econfig.reg_read = uniphier_reg_read;
+   econfig.size = resource_size(res);
+   econfig.priv = priv;
+   econfig.dev = dev;
+   nvmem = nvmem_register();
+   if (IS_ERR(nvmem))
+   return PTR_ERR(nvmem);
+
+   platform_set_drvdata(pdev, nvmem);
+
+   return 0;
+}
+
+static int uniphier_efuse_remove(struct platform_device *pdev)
+{
+   struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+   return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id uniphier_efuse_of_match[] = {
+   { .compatible = "socionext,uniphier-efuse",},
+   {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, uniphier_efuse_of_match);
+
+static struct platform_driver uniphier_efuse_driver = {
+   .probe = uniphier_efuse_probe,
+   .remove = uniphier_efuse_remove,
+   .driver = {
+   .name = "uniphier-efuse",
+   .of_match_table = uniphier_efuse_of_match,
+   },
+};
+module_platform_driver(uniphier_efuse_driver);
+
+MODULE_AUTHOR("Keiji Hayashibara ");
+MODULE_DESCRIPTION("UniPhier eFuse driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4



[PATCH v2 1/3] dt-bindings: nvmem: add description for UniPhier eFuse

2017-10-05 Thread Keiji Hayashibara
Add uniphier-efuse dt-bindings documentation.

Signed-off-by: Keiji Hayashibara 
---
 .../devicetree/bindings/nvmem/uniphier-efuse.txt   | 49 ++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt

diff --git a/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
new file mode 100644
index 000..1a394e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
@@ -0,0 +1,49 @@
+= UniPhier eFuse device tree bindings =
+
+This UniPhier eFuse must be under soc-glue.
+
+Required properties:
+- compatible: should be "socionext,uniphier-efuse"
+- reg: should contain the register location and length
+
+= Data cells =
+Are child nodes of efuse, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+   soc-glue@5f90 {
+   compatible = "socionext,uniphier-ld20-soc-glue-debug",
+"simple-mfd";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0x5f90 0x2000>;
+
+   efuse@100 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x100 0x28>;
+   };
+
+   efuse@200 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x200 0x68>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   /* Data cells */
+   usb_mon: usb_mon {
+   reg = <0x54 0xc>;
+   };
+   };
+   };
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+Example:
+
+   usb {
+   ...
+   nvmem-cells = <_mon>;
+   nvmem-cell-names = "usb_mon";
+   }
-- 
2.7.4



[PATCH v2 1/3] dt-bindings: nvmem: add description for UniPhier eFuse

2017-10-05 Thread Keiji Hayashibara
Add uniphier-efuse dt-bindings documentation.

Signed-off-by: Keiji Hayashibara 
---
 .../devicetree/bindings/nvmem/uniphier-efuse.txt   | 49 ++
 1 file changed, 49 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt

diff --git a/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt 
b/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
new file mode 100644
index 000..1a394e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/uniphier-efuse.txt
@@ -0,0 +1,49 @@
+= UniPhier eFuse device tree bindings =
+
+This UniPhier eFuse must be under soc-glue.
+
+Required properties:
+- compatible: should be "socionext,uniphier-efuse"
+- reg: should contain the register location and length
+
+= Data cells =
+Are child nodes of efuse, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+   soc-glue@5f90 {
+   compatible = "socionext,uniphier-ld20-soc-glue-debug",
+"simple-mfd";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0x0 0x5f90 0x2000>;
+
+   efuse@100 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x100 0x28>;
+   };
+
+   efuse@200 {
+   compatible = "socionext,uniphier-efuse";
+   reg = <0x200 0x68>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   /* Data cells */
+   usb_mon: usb_mon {
+   reg = <0x54 0xc>;
+   };
+   };
+   };
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+Example:
+
+   usb {
+   ...
+   nvmem-cells = <_mon>;
+   nvmem-cell-names = "usb_mon";
+   }
-- 
2.7.4



Re: [PATCH] firmware: add firmware to new device's devres list for second time cache

2017-10-05 Thread Kai-Heng Feng
On Thu, Oct 5, 2017 at 5:17 AM, Luis R. Rodriguez  wrote:
> On Tue, Aug 22, 2017 at 03:52:46PM +0800, Kai-Heng Feng wrote:
>> Currently, firmware will only be chached if assign_firmware_buf() gets
>> called.
>
> True, but also more importantly we peg the fw cache to the device via devres
> *iff* the firmware actually was found. We do this so that we don't try to look
> for bogus firmwares or firmwares which we currently do not have on our
> filesystem (consider a driver that uses a series of revisions of firmwares).
>
>> When a device loses its power or a USB device gets plugged to another
>> port under suspend, request_firmware() can still find cached firmware,
>> but firmware name no longer associates with the new device's devres.
>> So next time the system suspend, those firmware won't be cached.
>
> Gah, its a bit more complicated than that. During suspend we call out to
> request firmware proactively for all firmwares in our fw cache. The
> fw cache is used simply to fetch the caches for firwmares during suspend
> so that on resume they exist to avoid races against the filesystem. It
> however uses the same functionality as the batched firwmare feature, which
> in turn is used to share one buf over different requests.
>
> If a device is unplugged its not clear to me why the old cache would
> not work for the new one as its all shared, so the only thing that I
> can think of is if the old device being disconnected is processed first,
> and therefore releases the old cache, so when the new device is processed
> it does not use the new cache. This should still not be an issue though,
> unless of course real races happen with the filesystem.

Because the new one's devres doesn't have the fw, i.e.
fw_add_devm_name() not gets called in this case.

>
> As of recently though we have had new findings which indicate that the
> old UMH lock was causing issues on resume on BT devices which *only*
> needed firmware on resume, but not on boot, so their first fw cache
> was not generated. That issue can resemble this one, in that no cache
> can be present, and a race happens on resume.
>
> The old UMH lock then was causing a failure on resume, and one of the
> solutions which could have worked was a proactive "hey set this cache
> up for me" even though the device didn't need the firmware. This
> is no longer needed given that the UMH lock stuff is gone from
> direct FS lookups and the issue should no longer be present.
>
> That is, Linus' revert of commit f007cad159e99fa2acd3b2e9364fbb32ad28b971
> ("Revert "firmware: add sanity check on shutdown/suspend") I believe
> should fix this issue.
>
> I'm actually inclined to remove the fw cache stuff as I no longer see
> the advantage of it given we are doing FS lookups and I see no races
> possible anymore.
>
>> Hence, we should add the firmware name to the devres when the firmware
>> is found in cache, to make the firmware cacheable next time.
>>
>> Signed-off-by: Kai-Heng Feng 
>> ---
>>  drivers/base/firmware_class.c | 4 
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
>> index bfbe1e154128..a99de34e3fdc 100644
>> --- a/drivers/base/firmware_class.c
>> +++ b/drivers/base/firmware_class.c
>> @@ -1177,6 +1177,10 @@ _request_firmware_prepare(struct firmware 
>> **firmware_p, const char *name,
>>
>>   ret = fw_lookup_and_allocate_buf(name, _cache, , dbuf, size);
>>
>> + /* device might be a new one, add it to devres list */
>> + if (ret == 0 || ret == 1)
>> + fw_add_devm_name(device, name);
>> +
>
> Even if this was correct notice we have requests for which a FW cache is not
> desired -- see FW_OPT_NOCACHE, and the above does not respect it.

I think this is needed when it's not FW_OPT_NOCACHE.

>
> Given all the above, can you test with a kernel which has
> commit f007cad159e99fa2acd3b2e9364fbb32ad28b971 and tell me if you
> still see the issue?

It's fixed after f007cad159e99fa2acd3b2e9364fbb32ad28b971.
Again, thanks for your detailed explanation.


Kai-Heng,

>
>   Luis


Re: [PATCH] firmware: add firmware to new device's devres list for second time cache

2017-10-05 Thread Kai-Heng Feng
On Thu, Oct 5, 2017 at 5:17 AM, Luis R. Rodriguez  wrote:
> On Tue, Aug 22, 2017 at 03:52:46PM +0800, Kai-Heng Feng wrote:
>> Currently, firmware will only be chached if assign_firmware_buf() gets
>> called.
>
> True, but also more importantly we peg the fw cache to the device via devres
> *iff* the firmware actually was found. We do this so that we don't try to look
> for bogus firmwares or firmwares which we currently do not have on our
> filesystem (consider a driver that uses a series of revisions of firmwares).
>
>> When a device loses its power or a USB device gets plugged to another
>> port under suspend, request_firmware() can still find cached firmware,
>> but firmware name no longer associates with the new device's devres.
>> So next time the system suspend, those firmware won't be cached.
>
> Gah, its a bit more complicated than that. During suspend we call out to
> request firmware proactively for all firmwares in our fw cache. The
> fw cache is used simply to fetch the caches for firwmares during suspend
> so that on resume they exist to avoid races against the filesystem. It
> however uses the same functionality as the batched firwmare feature, which
> in turn is used to share one buf over different requests.
>
> If a device is unplugged its not clear to me why the old cache would
> not work for the new one as its all shared, so the only thing that I
> can think of is if the old device being disconnected is processed first,
> and therefore releases the old cache, so when the new device is processed
> it does not use the new cache. This should still not be an issue though,
> unless of course real races happen with the filesystem.

Because the new one's devres doesn't have the fw, i.e.
fw_add_devm_name() not gets called in this case.

>
> As of recently though we have had new findings which indicate that the
> old UMH lock was causing issues on resume on BT devices which *only*
> needed firmware on resume, but not on boot, so their first fw cache
> was not generated. That issue can resemble this one, in that no cache
> can be present, and a race happens on resume.
>
> The old UMH lock then was causing a failure on resume, and one of the
> solutions which could have worked was a proactive "hey set this cache
> up for me" even though the device didn't need the firmware. This
> is no longer needed given that the UMH lock stuff is gone from
> direct FS lookups and the issue should no longer be present.
>
> That is, Linus' revert of commit f007cad159e99fa2acd3b2e9364fbb32ad28b971
> ("Revert "firmware: add sanity check on shutdown/suspend") I believe
> should fix this issue.
>
> I'm actually inclined to remove the fw cache stuff as I no longer see
> the advantage of it given we are doing FS lookups and I see no races
> possible anymore.
>
>> Hence, we should add the firmware name to the devres when the firmware
>> is found in cache, to make the firmware cacheable next time.
>>
>> Signed-off-by: Kai-Heng Feng 
>> ---
>>  drivers/base/firmware_class.c | 4 
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
>> index bfbe1e154128..a99de34e3fdc 100644
>> --- a/drivers/base/firmware_class.c
>> +++ b/drivers/base/firmware_class.c
>> @@ -1177,6 +1177,10 @@ _request_firmware_prepare(struct firmware 
>> **firmware_p, const char *name,
>>
>>   ret = fw_lookup_and_allocate_buf(name, _cache, , dbuf, size);
>>
>> + /* device might be a new one, add it to devres list */
>> + if (ret == 0 || ret == 1)
>> + fw_add_devm_name(device, name);
>> +
>
> Even if this was correct notice we have requests for which a FW cache is not
> desired -- see FW_OPT_NOCACHE, and the above does not respect it.

I think this is needed when it's not FW_OPT_NOCACHE.

>
> Given all the above, can you test with a kernel which has
> commit f007cad159e99fa2acd3b2e9364fbb32ad28b971 and tell me if you
> still see the issue?

It's fixed after f007cad159e99fa2acd3b2e9364fbb32ad28b971.
Again, thanks for your detailed explanation.


Kai-Heng,

>
>   Luis


Re: [PATCH] net/mlx4_core: Convert timers to use timer_setup()

2017-10-05 Thread Leon Romanovsky
On Wed, Oct 04, 2017 at 05:51:54PM -0700, Kees Cook wrote:
> In preparation for unconditionally passing the struct timer_list pointer to
> all timer callbacks, switch to using the new timer_setup() and from_timer()
> to pass the timer pointer explicitly.
>
> Cc: Tariq Toukan 
> Cc: net...@vger.kernel.org
> Cc: linux-r...@vger.kernel.org
> Cc: Thomas Gleixner 
> Signed-off-by: Kees Cook 
> ---
> This requires commit 686fef928bba ("timer: Prepare to change timer
> callback argument type") in v4.14-rc3, but should be otherwise
> stand-alone.
> ---
>  drivers/net/ethernet/mellanox/mlx4/catas.c | 10 --
>  1 file changed, 4 insertions(+), 6 deletions(-)
>

Hi Kees,

In RDMA, we had very similar patch [1] to your patch series, but it converts to
setup_timer, while you are converting to timer_setup.

Which conversion is the right one?

[1] https://patchwork.kernel.org/patch/9980701/

Thanks

> diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c 
> b/drivers/net/ethernet/mellanox/mlx4/catas.c
> index 53daa6ca5d83..e2b6b0cac1ac 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/catas.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/catas.c
> @@ -231,10 +231,10 @@ static void dump_err_buf(struct mlx4_dev *dev)
>i, swab32(readl(priv->catas_err.map + i)));
>  }
>
> -static void poll_catas(unsigned long dev_ptr)
> +static void poll_catas(struct timer_list *t)
>  {
> - struct mlx4_dev *dev = (struct mlx4_dev *) dev_ptr;
> - struct mlx4_priv *priv = mlx4_priv(dev);
> + struct mlx4_priv *priv = from_timer(priv, t, catas_err.timer);
> + struct mlx4_dev *dev = >dev;
>   u32 slave_read;
>
>   if (mlx4_is_slave(dev)) {
> @@ -277,7 +277,7 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev)
>   phys_addr_t addr;
>
>   INIT_LIST_HEAD(>catas_err.list);
> - init_timer(>catas_err.timer);
> + timer_setup(>catas_err.timer, poll_catas, 0);
>   priv->catas_err.map = NULL;
>
>   if (!mlx4_is_slave(dev)) {
> @@ -293,8 +293,6 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev)
>   }
>   }
>
> - priv->catas_err.timer.data = (unsigned long) dev;
> - priv->catas_err.timer.function = poll_catas;
>   priv->catas_err.timer.expires  =
>   round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL);
>   add_timer(>catas_err.timer);
> --
> 2.7.4
>
>
> --
> Kees Cook
> Pixel Security
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


signature.asc
Description: PGP signature


Re: [PATCH] net/mlx4_core: Convert timers to use timer_setup()

2017-10-05 Thread Leon Romanovsky
On Wed, Oct 04, 2017 at 05:51:54PM -0700, Kees Cook wrote:
> In preparation for unconditionally passing the struct timer_list pointer to
> all timer callbacks, switch to using the new timer_setup() and from_timer()
> to pass the timer pointer explicitly.
>
> Cc: Tariq Toukan 
> Cc: net...@vger.kernel.org
> Cc: linux-r...@vger.kernel.org
> Cc: Thomas Gleixner 
> Signed-off-by: Kees Cook 
> ---
> This requires commit 686fef928bba ("timer: Prepare to change timer
> callback argument type") in v4.14-rc3, but should be otherwise
> stand-alone.
> ---
>  drivers/net/ethernet/mellanox/mlx4/catas.c | 10 --
>  1 file changed, 4 insertions(+), 6 deletions(-)
>

Hi Kees,

In RDMA, we had very similar patch [1] to your patch series, but it converts to
setup_timer, while you are converting to timer_setup.

Which conversion is the right one?

[1] https://patchwork.kernel.org/patch/9980701/

Thanks

> diff --git a/drivers/net/ethernet/mellanox/mlx4/catas.c 
> b/drivers/net/ethernet/mellanox/mlx4/catas.c
> index 53daa6ca5d83..e2b6b0cac1ac 100644
> --- a/drivers/net/ethernet/mellanox/mlx4/catas.c
> +++ b/drivers/net/ethernet/mellanox/mlx4/catas.c
> @@ -231,10 +231,10 @@ static void dump_err_buf(struct mlx4_dev *dev)
>i, swab32(readl(priv->catas_err.map + i)));
>  }
>
> -static void poll_catas(unsigned long dev_ptr)
> +static void poll_catas(struct timer_list *t)
>  {
> - struct mlx4_dev *dev = (struct mlx4_dev *) dev_ptr;
> - struct mlx4_priv *priv = mlx4_priv(dev);
> + struct mlx4_priv *priv = from_timer(priv, t, catas_err.timer);
> + struct mlx4_dev *dev = >dev;
>   u32 slave_read;
>
>   if (mlx4_is_slave(dev)) {
> @@ -277,7 +277,7 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev)
>   phys_addr_t addr;
>
>   INIT_LIST_HEAD(>catas_err.list);
> - init_timer(>catas_err.timer);
> + timer_setup(>catas_err.timer, poll_catas, 0);
>   priv->catas_err.map = NULL;
>
>   if (!mlx4_is_slave(dev)) {
> @@ -293,8 +293,6 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev)
>   }
>   }
>
> - priv->catas_err.timer.data = (unsigned long) dev;
> - priv->catas_err.timer.function = poll_catas;
>   priv->catas_err.timer.expires  =
>   round_jiffies(jiffies + MLX4_CATAS_POLL_INTERVAL);
>   add_timer(>catas_err.timer);
> --
> 2.7.4
>
>
> --
> Kees Cook
> Pixel Security
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


signature.asc
Description: PGP signature


Re: [RFC PATCH -tip 0/5] kprobes: Abolish jprobe APIs

2017-10-05 Thread Masami Hiramatsu
On Thu, 5 Oct 2017 19:58:08 -0400
Steven Rostedt  wrote:

> On Thu, 5 Oct 2017 16:35:22 -0700
> Kees Cook  wrote:
> 
> > > As far as I can see, tcp probe, dccp probe, sctp probe and lkdtm
> > > are using jprobe to probe function. Please consider to migrate.  
> > 
> > I'm happy to do so, but I'm quite unfamiliar with how to do this (I
> > didn't write lkdtm's jprobe code originally). lkdtm just wants to hook
> > function entry and call it's own function before.
> 
> That can be done with ftrace. That's how live kernel patching works. It
> registers a callback via register_ftrace_function(), and with fentry
> (gcc 4.6 and later on x86), you can "hijack" the function. If you don't
> modify the regs->ip, then the function you hooked to will be called.
> 
> > 
> > It uses struct jprobe like this:
> > 
> > .jprobe = { \
> > .kp.symbol_name = _symbol,  \
> > .entry = (kprobe_opcode_t *)_entry, \
> > },  \
> > 
> > and defines a bunch of handlers like this for the _symbol and _entry pairs:
> > 
> >"do_IRQ",jp_do_irq),
> > ...
> >"tasklet_action",jp_tasklet_action),
> > 
> > where all the handlers look exactly the same (and don't care about 
> > arguments):
> 
> Hell, this is really easy then!
> 
> > 
> > static unsigned int jp_do_irq(unsigned int irq)
> > {
> > lkdtm_handler();
> > jprobe_return();
> > return 0;
> > }
> > 
> > What's the right way to migrate away from jprobe for lkdtm?
> 
> Perhaps something like:
> 
> #include 
> 
> static void lkdtm_callback(unsigned long ip, unsigned long parent_ip,
>   struct ftrace_ops *ops, struct pt_regs *regs)
> {
>   lkdt_handler();
> }
> 
> 
> static struct ftrace_ops ops = {
>   .func   = lkdtm_callback,
> };
> 
> [..]
>   ftrace_set_filter(, "do_IRQ", strlen("do_IRQ"), 0);
>   ftrace_set_filter(, "tasklet_action", strlen("tasklet_action"), 0);
>   [..]
> 
>   /* to add the hook */
> 
>   register_ftrace_function();
> 
> Now all functions you set the filter for will be traced.
> 
> Oh you may want to check the return status of ftrace_set_filter()
> otherwise, if they all fail, you will be tracing all functions.

Steve, could you write a documentation how to use ftrace callback?
I think I should update the Documentation/kprobes.txt so that jprobe
user can easily migrate on that.

Thank you,


-- 
Masami Hiramatsu 


Re: [RFC PATCH -tip 0/5] kprobes: Abolish jprobe APIs

2017-10-05 Thread Masami Hiramatsu
On Thu, 5 Oct 2017 19:58:08 -0400
Steven Rostedt  wrote:

> On Thu, 5 Oct 2017 16:35:22 -0700
> Kees Cook  wrote:
> 
> > > As far as I can see, tcp probe, dccp probe, sctp probe and lkdtm
> > > are using jprobe to probe function. Please consider to migrate.  
> > 
> > I'm happy to do so, but I'm quite unfamiliar with how to do this (I
> > didn't write lkdtm's jprobe code originally). lkdtm just wants to hook
> > function entry and call it's own function before.
> 
> That can be done with ftrace. That's how live kernel patching works. It
> registers a callback via register_ftrace_function(), and with fentry
> (gcc 4.6 and later on x86), you can "hijack" the function. If you don't
> modify the regs->ip, then the function you hooked to will be called.
> 
> > 
> > It uses struct jprobe like this:
> > 
> > .jprobe = { \
> > .kp.symbol_name = _symbol,  \
> > .entry = (kprobe_opcode_t *)_entry, \
> > },  \
> > 
> > and defines a bunch of handlers like this for the _symbol and _entry pairs:
> > 
> >"do_IRQ",jp_do_irq),
> > ...
> >"tasklet_action",jp_tasklet_action),
> > 
> > where all the handlers look exactly the same (and don't care about 
> > arguments):
> 
> Hell, this is really easy then!
> 
> > 
> > static unsigned int jp_do_irq(unsigned int irq)
> > {
> > lkdtm_handler();
> > jprobe_return();
> > return 0;
> > }
> > 
> > What's the right way to migrate away from jprobe for lkdtm?
> 
> Perhaps something like:
> 
> #include 
> 
> static void lkdtm_callback(unsigned long ip, unsigned long parent_ip,
>   struct ftrace_ops *ops, struct pt_regs *regs)
> {
>   lkdt_handler();
> }
> 
> 
> static struct ftrace_ops ops = {
>   .func   = lkdtm_callback,
> };
> 
> [..]
>   ftrace_set_filter(, "do_IRQ", strlen("do_IRQ"), 0);
>   ftrace_set_filter(, "tasklet_action", strlen("tasklet_action"), 0);
>   [..]
> 
>   /* to add the hook */
> 
>   register_ftrace_function();
> 
> Now all functions you set the filter for will be traced.
> 
> Oh you may want to check the return status of ftrace_set_filter()
> otherwise, if they all fail, you will be tracing all functions.

Steve, could you write a documentation how to use ftrace callback?
I think I should update the Documentation/kprobes.txt so that jprobe
user can easily migrate on that.

Thank you,


-- 
Masami Hiramatsu 


Re: [RFC PATCH -tip 0/5] kprobes: Abolish jprobe APIs

2017-10-05 Thread Masami Hiramatsu
On Thu, 5 Oct 2017 21:11:30 -0400
Steven Rostedt  wrote:

> On Fri, 6 Oct 2017 09:32:52 +0900
> Masami Hiramatsu  wrote:
> 
> > I think using ftrace gives you lower latency, but you need to depend on
> > CONFIG_FUNCTION_TRACER instead of CONFIG_KPROBES.
> 
> Which shouldn't be an issue, since all distros now have that enabled.

Yeah, so both are good option :)

Thanks,

-- 
Masami Hiramatsu 


Re: [RFC PATCH -tip 0/5] kprobes: Abolish jprobe APIs

2017-10-05 Thread Masami Hiramatsu
On Thu, 5 Oct 2017 21:11:30 -0400
Steven Rostedt  wrote:

> On Fri, 6 Oct 2017 09:32:52 +0900
> Masami Hiramatsu  wrote:
> 
> > I think using ftrace gives you lower latency, but you need to depend on
> > CONFIG_FUNCTION_TRACER instead of CONFIG_KPROBES.
> 
> Which shouldn't be an issue, since all distros now have that enabled.

Yeah, so both are good option :)

Thanks,

-- 
Masami Hiramatsu 


Re: [PATCH] md: raid10: remove VLAIS

2017-10-05 Thread Shaohua Li
On Fri, Oct 06, 2017 at 01:22:12PM +1100, Neil Brown wrote:
> On Thu, Oct 05 2017, Matthias Kaehlcke wrote:
> 
> > Hi Neil,
> >
> > El Fri, Oct 06, 2017 at 10:58:59AM +1100 NeilBrown ha dit:
> >
> >> On Thu, Oct 05 2017, Matthias Kaehlcke wrote:
> >> 
> >> > The raid10 driver can't be built with clang since it uses a variable
> >> > length array in a structure (VLAIS):
> >> >
> >> > drivers/md/raid10.c:4583:17: error: fields must have a constant size:
> >> >   'variable length array in structure' extension will never be supported
> >> >
> >> > Allocate the r10bio struct with kmalloc instead of using the VLAIS
> >> > construct.
> >> >
> >> > Signed-off-by: Matthias Kaehlcke 
> >> > ---
> >> >  drivers/md/raid10.c | 13 -
> >> >  1 file changed, 8 insertions(+), 5 deletions(-)
> >> >
> >> > diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
> >> > index 374df5796649..9616163eaf8c 100644
> >> > --- a/drivers/md/raid10.c
> >> > +++ b/drivers/md/raid10.c
> >> > @@ -4578,15 +4578,16 @@ static int handle_reshape_read_error(struct 
> >> > mddev *mddev,
> >> >  /* Use sync reads to get the blocks from somewhere else */
> >> >  int sectors = r10_bio->sectors;
> >> >  struct r10conf *conf = mddev->private;
> >> > -struct {
> >> > -struct r10bio r10_bio;
> >> > -struct r10dev devs[conf->copies];
> >> > -} on_stack;
> >> > -struct r10bio *r10b = _stack.r10_bio;
> >> > +struct r10bio *r10b;
> >> >  int slot = 0;
> >> >  int idx = 0;
> >> >  struct page **pages;
> >> >  
> >> > +r10b = kmalloc(sizeof(*r10b) +
> >> > +   sizeof(struct r10dev) * conf->copies, GFP_KERNEL);
> >> 
> >> GFP_KERNEL isn't a good idea here.
> >> This could wait for writeback, and if writeback tries to write to the
> >> region of the array which is being reshaped, it might deadlock.
> >> 
> >> GFP_NOIO is safer.
> >
> > Good point, thanks!
> >
> >> given that conf->copies is almost always 2 it might be nicer to
> >> have
> >> 
> >>struct {
> >>struct r10bio r10_bio;
> >>struct r10dev devs[2];
> >>} on_stack;
> >> 
> >> struct r10bio *r10b;
> >> 
> >>if (conf->copies <= ARRAY_SIZE(on_stack.devs))
> >>r10b = _stack.r10_bio;
> >> else
> >>r10b = kmalloc(sizeof(*r10b) +
> >>   sizeof(struct r10dev) * conf->copies, GFP_NOIO);
> >
> > It would add also add an extra condition to determine if r10b needs to
> > be freed or not.
> 
> True.
> 
> >
> > Given that array reshaping is a rare operation and an error during
> > this operation is an exceptional condition I think the simpler code
> > with always dynamic allocation is preferable. That said I'm fine with
> > reworking the patch according to your suggestion if you or Shaohua
> > prefer it.
> 
> I don't feel strongly about it.  As long as the GFP_KERNEL->GFP_NOIO
> change happens I'm OK with this patch.

Let's use GFP_NOIO then, should not be big deal. I updated the patch.

Thanks,
Shaohua


Re: [PATCH] md: raid10: remove VLAIS

2017-10-05 Thread Shaohua Li
On Fri, Oct 06, 2017 at 01:22:12PM +1100, Neil Brown wrote:
> On Thu, Oct 05 2017, Matthias Kaehlcke wrote:
> 
> > Hi Neil,
> >
> > El Fri, Oct 06, 2017 at 10:58:59AM +1100 NeilBrown ha dit:
> >
> >> On Thu, Oct 05 2017, Matthias Kaehlcke wrote:
> >> 
> >> > The raid10 driver can't be built with clang since it uses a variable
> >> > length array in a structure (VLAIS):
> >> >
> >> > drivers/md/raid10.c:4583:17: error: fields must have a constant size:
> >> >   'variable length array in structure' extension will never be supported
> >> >
> >> > Allocate the r10bio struct with kmalloc instead of using the VLAIS
> >> > construct.
> >> >
> >> > Signed-off-by: Matthias Kaehlcke 
> >> > ---
> >> >  drivers/md/raid10.c | 13 -
> >> >  1 file changed, 8 insertions(+), 5 deletions(-)
> >> >
> >> > diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
> >> > index 374df5796649..9616163eaf8c 100644
> >> > --- a/drivers/md/raid10.c
> >> > +++ b/drivers/md/raid10.c
> >> > @@ -4578,15 +4578,16 @@ static int handle_reshape_read_error(struct 
> >> > mddev *mddev,
> >> >  /* Use sync reads to get the blocks from somewhere else */
> >> >  int sectors = r10_bio->sectors;
> >> >  struct r10conf *conf = mddev->private;
> >> > -struct {
> >> > -struct r10bio r10_bio;
> >> > -struct r10dev devs[conf->copies];
> >> > -} on_stack;
> >> > -struct r10bio *r10b = _stack.r10_bio;
> >> > +struct r10bio *r10b;
> >> >  int slot = 0;
> >> >  int idx = 0;
> >> >  struct page **pages;
> >> >  
> >> > +r10b = kmalloc(sizeof(*r10b) +
> >> > +   sizeof(struct r10dev) * conf->copies, GFP_KERNEL);
> >> 
> >> GFP_KERNEL isn't a good idea here.
> >> This could wait for writeback, and if writeback tries to write to the
> >> region of the array which is being reshaped, it might deadlock.
> >> 
> >> GFP_NOIO is safer.
> >
> > Good point, thanks!
> >
> >> given that conf->copies is almost always 2 it might be nicer to
> >> have
> >> 
> >>struct {
> >>struct r10bio r10_bio;
> >>struct r10dev devs[2];
> >>} on_stack;
> >> 
> >> struct r10bio *r10b;
> >> 
> >>if (conf->copies <= ARRAY_SIZE(on_stack.devs))
> >>r10b = _stack.r10_bio;
> >> else
> >>r10b = kmalloc(sizeof(*r10b) +
> >>   sizeof(struct r10dev) * conf->copies, GFP_NOIO);
> >
> > It would add also add an extra condition to determine if r10b needs to
> > be freed or not.
> 
> True.
> 
> >
> > Given that array reshaping is a rare operation and an error during
> > this operation is an exceptional condition I think the simpler code
> > with always dynamic allocation is preferable. That said I'm fine with
> > reworking the patch according to your suggestion if you or Shaohua
> > prefer it.
> 
> I don't feel strongly about it.  As long as the GFP_KERNEL->GFP_NOIO
> change happens I'm OK with this patch.

Let's use GFP_NOIO then, should not be big deal. I updated the patch.

Thanks,
Shaohua


Re: btusb "firmware request while host is not available" at resume

2017-10-05 Thread Kai-Heng Feng
Hi Luis,

On Wed, Oct 4, 2017 at 8:20 AM, Luis R. Rodriguez  wrote:
> So please retest now that the revert happened: commit
> f007cad159e99fa2acd3b2e9364fbb32ad28b971 ("Revert "firmware: add sanity check
> on shutdown/suspend").

I can confirm the issue is gone after the commit.
Also, thanks for your detailed explanation.


Kai-Heng

>
>   Luis


Re: btusb "firmware request while host is not available" at resume

2017-10-05 Thread Kai-Heng Feng
Hi Luis,

On Wed, Oct 4, 2017 at 8:20 AM, Luis R. Rodriguez  wrote:
> So please retest now that the revert happened: commit
> f007cad159e99fa2acd3b2e9364fbb32ad28b971 ("Revert "firmware: add sanity check
> on shutdown/suspend").

I can confirm the issue is gone after the commit.
Also, thanks for your detailed explanation.


Kai-Heng

>
>   Luis


[RFC 2/2] phy: exynos5-usbdrd: remove disable and enable of phy clk

2017-10-05 Thread Anand Moon
remove the disable and enable of phy clk.
phy clk is needed to tune the phy controller.

Before:
mout_usbd300  112400  0 0
   dout_usbd300   002400  0 0
  sclk_usbd300002400  0 0
   dout_usbphy300 112400  0 0
  sclk_usbphy300  332400  0 0
mout_usbd301  112400  0 0
   dout_usbd301   002400  0 0
  sclk_usbd301002400  0 0
   dout_usbphy301 112400  0 0
  sclk_usbphy301  222400  0 0
After:
mout_usbd300  222400  0 0
   dout_usbd300   112400  0 0
  sclk_usbd300222400  0 0
   dout_usbphy300 112400  0 0
  sclk_usbphy300  332400  0 0
mout_usbd301  222400  0 0
   dout_usbd301   112400  0 0
  sclk_usbd301222400  0 0
   dout_usbphy301 112400  0 0
  sclk_usbphy301  222400  0 0

Signed-off-by: Anand Moon 
---
 drivers/phy/samsung/phy-exynos5-usbdrd.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c 
b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index 22c68f5..5e8054c 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -409,22 +409,15 @@ static int exynos5_usbdrd_phy_init(struct phy *phy)
reg &= ~PHYCLKRST_PORTRESET;
writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
 
-   clk_disable_unprepare(phy_drd->clk);
-
return 0;
 }
 
 static int exynos5_usbdrd_phy_exit(struct phy *phy)
 {
-   int ret;
u32 reg;
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
 
-   ret = clk_prepare_enable(phy_drd->clk);
-   if (ret)
-   return ret;
-
reg =   PHYUTMI_OTGDISABLE |
PHYUTMI_FORCESUSPEND |
PHYUTMI_FORCESLEEP;
-- 
2.7.4



[RFC 2/2] phy: exynos5-usbdrd: remove disable and enable of phy clk

2017-10-05 Thread Anand Moon
remove the disable and enable of phy clk.
phy clk is needed to tune the phy controller.

Before:
mout_usbd300  112400  0 0
   dout_usbd300   002400  0 0
  sclk_usbd300002400  0 0
   dout_usbphy300 112400  0 0
  sclk_usbphy300  332400  0 0
mout_usbd301  112400  0 0
   dout_usbd301   002400  0 0
  sclk_usbd301002400  0 0
   dout_usbphy301 112400  0 0
  sclk_usbphy301  222400  0 0
After:
mout_usbd300  222400  0 0
   dout_usbd300   112400  0 0
  sclk_usbd300222400  0 0
   dout_usbphy300 112400  0 0
  sclk_usbphy300  332400  0 0
mout_usbd301  222400  0 0
   dout_usbd301   112400  0 0
  sclk_usbd301222400  0 0
   dout_usbphy301 112400  0 0
  sclk_usbphy301  222400  0 0

Signed-off-by: Anand Moon 
---
 drivers/phy/samsung/phy-exynos5-usbdrd.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c 
b/drivers/phy/samsung/phy-exynos5-usbdrd.c
index 22c68f5..5e8054c 100644
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -409,22 +409,15 @@ static int exynos5_usbdrd_phy_init(struct phy *phy)
reg &= ~PHYCLKRST_PORTRESET;
writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
 
-   clk_disable_unprepare(phy_drd->clk);
-
return 0;
 }
 
 static int exynos5_usbdrd_phy_exit(struct phy *phy)
 {
-   int ret;
u32 reg;
struct phy_usb_instance *inst = phy_get_drvdata(phy);
struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
 
-   ret = clk_prepare_enable(phy_drd->clk);
-   if (ret)
-   return ret;
-
reg =   PHYUTMI_OTGDISABLE |
PHYUTMI_FORCESUSPEND |
PHYUTMI_FORCESLEEP;
-- 
2.7.4



[RFC 1/2] ARM: dts: exynos: update the usbdrd phy and ref clk

2017-10-05 Thread Anand Moon
update the usbdrd link control and phy contol clks.

Signed-off-by: Anand Moon 
---
Tested on Odroid XU4 and Odroid HC1 develpment board.
Did not test Odroid XU develpment board.
---
 arch/arm/boot/dts/exynos5410.dtsi | 4 ++--
 arch/arm/boot/dts/exynos5420.dtsi | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi 
b/arch/arm/boot/dts/exynos5410.dtsi
index 7eab4bc..5af9f4b 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -385,7 +385,7 @@
 };
 
 _phy0 {
-   clocks = < CLK_USBD300>, < CLK_SCLK_USBPHY300>;
+   clocks = < CLK_SCLK_USBPHY300>, < CLK_SCLK_USBD300>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
@@ -400,7 +400,7 @@
 };
 
 _phy1 {
-   clocks = < CLK_USBD301>, < CLK_SCLK_USBPHY301>;
+   clocks = < CLK_SCLK_USBPHY301>, < CLK_SCLK_USBD301>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
diff --git a/arch/arm/boot/dts/exynos5420.dtsi 
b/arch/arm/boot/dts/exynos5420.dtsi
index 88e5d6d..36d26ab 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -1461,7 +1461,7 @@
 };
 
 _phy0 {
-   clocks = < CLK_USBD300>, < CLK_SCLK_USBPHY300>;
+   clocks = < CLK_SCLK_USBPHY300>, < CLK_SCLK_USBD300>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
@@ -1476,7 +1476,7 @@
 };
 
 _phy1 {
-   clocks = < CLK_USBD301>, < CLK_SCLK_USBPHY301>;
+   clocks = < CLK_SCLK_USBPHY301>, < CLK_SCLK_USBD301>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
-- 
2.7.4



[RFC 1/2] ARM: dts: exynos: update the usbdrd phy and ref clk

2017-10-05 Thread Anand Moon
update the usbdrd link control and phy contol clks.

Signed-off-by: Anand Moon 
---
Tested on Odroid XU4 and Odroid HC1 develpment board.
Did not test Odroid XU develpment board.
---
 arch/arm/boot/dts/exynos5410.dtsi | 4 ++--
 arch/arm/boot/dts/exynos5420.dtsi | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/exynos5410.dtsi 
b/arch/arm/boot/dts/exynos5410.dtsi
index 7eab4bc..5af9f4b 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -385,7 +385,7 @@
 };
 
 _phy0 {
-   clocks = < CLK_USBD300>, < CLK_SCLK_USBPHY300>;
+   clocks = < CLK_SCLK_USBPHY300>, < CLK_SCLK_USBD300>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
@@ -400,7 +400,7 @@
 };
 
 _phy1 {
-   clocks = < CLK_USBD301>, < CLK_SCLK_USBPHY301>;
+   clocks = < CLK_SCLK_USBPHY301>, < CLK_SCLK_USBD301>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
diff --git a/arch/arm/boot/dts/exynos5420.dtsi 
b/arch/arm/boot/dts/exynos5420.dtsi
index 88e5d6d..36d26ab 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -1461,7 +1461,7 @@
 };
 
 _phy0 {
-   clocks = < CLK_USBD300>, < CLK_SCLK_USBPHY300>;
+   clocks = < CLK_SCLK_USBPHY300>, < CLK_SCLK_USBD300>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
@@ -1476,7 +1476,7 @@
 };
 
 _phy1 {
-   clocks = < CLK_USBD301>, < CLK_SCLK_USBPHY301>;
+   clocks = < CLK_SCLK_USBPHY301>, < CLK_SCLK_USBD301>;
clock-names = "phy", "ref";
samsung,pmu-syscon = <_system_controller>;
 };
-- 
2.7.4



Re: [PATCH] kvm, mm: account kvm related kmem slabs to kmemcg

2017-10-05 Thread Anshuman Khandual
On 10/06/2017 06:37 AM, Shakeel Butt wrote:
> The kvm slabs can consume a significant amount of system memory
> and indeed in our production environment we have observed that
> a lot of machines are spending significant amount of memory that
> can not be left as system memory overhead. Also the allocations
> from these slabs can be triggered directly by user space applications
> which has access to kvm and thus a buggy application can leak
> such memory. So, these caches should be accounted to kmemcg.

But there may be other situations like this where user space can
trigger allocation from various SLAB objects inside the kernel
which are accounted as system memory. So how we draw the line
which ones should be accounted for memcg. Just being curious.



Re: [PATCH] kvm, mm: account kvm related kmem slabs to kmemcg

2017-10-05 Thread Anshuman Khandual
On 10/06/2017 06:37 AM, Shakeel Butt wrote:
> The kvm slabs can consume a significant amount of system memory
> and indeed in our production environment we have observed that
> a lot of machines are spending significant amount of memory that
> can not be left as system memory overhead. Also the allocations
> from these slabs can be triggered directly by user space applications
> which has access to kvm and thus a buggy application can leak
> such memory. So, these caches should be accounted to kmemcg.

But there may be other situations like this where user space can
trigger allocation from various SLAB objects inside the kernel
which are accounted as system memory. So how we draw the line
which ones should be accounted for memcg. Just being curious.



Re: [PATCH] net: qcom/emac: make function emac_isr static

2017-10-05 Thread David Miller
From: Colin King 
Date: Thu,  5 Oct 2017 10:10:23 +0100

> From: Colin Ian King 
> 
> The function emac_isr is local to the source and does not need to
> be in global scope, so make it static.
> 
> Cleans up sparse warnings:
> symbol 'emac_isr' was not declared. Should it be static?
> 
> Signed-off-by: Colin Ian King 

Applied.


Re: [PATCH] ALSA: usb-audio: Add sample rate quirk for Plantronics P610

2017-10-05 Thread Kai-Heng Feng
Hi,

On Fri, Oct 6, 2017 at 2:22 AM, Takashi Iwai  wrote:
> On Thu, 05 Oct 2017 20:04:06 +0200,
> Kai-Heng Feng wrote:
>>
>> Like other Plantronics devices, P610 does not support sample
>> rate reading. Apply sample rate quirk to it.
>>
>> BugLink: https://bugs.launchpad.net/bugs/1719853
>>
>> Signed-off-by: Kai-Heng Feng 
>
> Hrm, maybe we should ignore all Plantronics devices?
> Also MS Lifecam and Phoenix devices are such candidates.
>
> So something like below.
>
> Takashi
>
> -- 8< --
> From: Takashi Iwai 
> Subject: [PATCH] ALSA: usb-audio: Apply vendor ID matching for sample rate
>  quirk
>
> So far, lots of Plantronics, MS and Phoenix Audio devices need the
> quirk not to read sample rate back, and the list just grows.
> In this patch, instead of adding each device, apply the quirk by
> matching with these vendors.
>
> Signed-off-by: Takashi Iwai 
> ---
>  sound/usb/quirks.c | 23 +--
>  1 file changed, 9 insertions(+), 14 deletions(-)
>
> diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
> index b8cb57aeec77..9aeb05f61f78 100644
> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -1128,29 +1128,24 @@ bool snd_usb_get_sample_rate_quirk(struct 
> snd_usb_audio *chip)
> /* devices which do not support reading the sample rate. */
> switch (chip->usb_id) {
> case USB_ID(0x041E, 0x4080): /* Creative Live Cam VF0610 */
> -   case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema  */
> -   case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
> -   case USB_ID(0x045E, 0x076E): /* MS Lifecam HD-5001 */
> -   case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
> -   case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
> -   case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
> -   case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */
> -   case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
> -   case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
> -   case USB_ID(0x047F, 0xC022): /* Plantronics C310 */
> -   case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */
> case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
> case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
> case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
> case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
> case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
> case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
> -   case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */
> -   case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */
> -   case USB_ID(0x1de7, 0x0114): /* Phoenix Audio MT202pcs */
> case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
> return true;
> }
> +
> +   /* devices of these vendors don't support reading rate, either */
> +   switch (USB_ID_VENDOR(chip->usb_id)) {
> +   case 0x045E: /* MS Lifecam */
> +   case 0x047F: /* Plantronics */
> +   case 0x1de7: /* Phoenix Audio */
> +   return true;
> +   }
> +
> return false;
>  }
>

This is definitely a better approach. Thanks!

Acked-by: Kai-Heng Feng 

> --
> 2.14.2
>


Re: [PATCH] net: qcom/emac: make function emac_isr static

2017-10-05 Thread David Miller
From: Colin King 
Date: Thu,  5 Oct 2017 10:10:23 +0100

> From: Colin Ian King 
> 
> The function emac_isr is local to the source and does not need to
> be in global scope, so make it static.
> 
> Cleans up sparse warnings:
> symbol 'emac_isr' was not declared. Should it be static?
> 
> Signed-off-by: Colin Ian King 

Applied.


Re: [PATCH] ALSA: usb-audio: Add sample rate quirk for Plantronics P610

2017-10-05 Thread Kai-Heng Feng
Hi,

On Fri, Oct 6, 2017 at 2:22 AM, Takashi Iwai  wrote:
> On Thu, 05 Oct 2017 20:04:06 +0200,
> Kai-Heng Feng wrote:
>>
>> Like other Plantronics devices, P610 does not support sample
>> rate reading. Apply sample rate quirk to it.
>>
>> BugLink: https://bugs.launchpad.net/bugs/1719853
>>
>> Signed-off-by: Kai-Heng Feng 
>
> Hrm, maybe we should ignore all Plantronics devices?
> Also MS Lifecam and Phoenix devices are such candidates.
>
> So something like below.
>
> Takashi
>
> -- 8< --
> From: Takashi Iwai 
> Subject: [PATCH] ALSA: usb-audio: Apply vendor ID matching for sample rate
>  quirk
>
> So far, lots of Plantronics, MS and Phoenix Audio devices need the
> quirk not to read sample rate back, and the list just grows.
> In this patch, instead of adding each device, apply the quirk by
> matching with these vendors.
>
> Signed-off-by: Takashi Iwai 
> ---
>  sound/usb/quirks.c | 23 +--
>  1 file changed, 9 insertions(+), 14 deletions(-)
>
> diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
> index b8cb57aeec77..9aeb05f61f78 100644
> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -1128,29 +1128,24 @@ bool snd_usb_get_sample_rate_quirk(struct 
> snd_usb_audio *chip)
> /* devices which do not support reading the sample rate. */
> switch (chip->usb_id) {
> case USB_ID(0x041E, 0x4080): /* Creative Live Cam VF0610 */
> -   case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema  */
> -   case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
> -   case USB_ID(0x045E, 0x076E): /* MS Lifecam HD-5001 */
> -   case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
> -   case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
> -   case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
> -   case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */
> -   case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
> -   case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
> -   case USB_ID(0x047F, 0xC022): /* Plantronics C310 */
> -   case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */
> case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
> case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
> case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
> case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
> case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
> case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
> -   case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */
> -   case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */
> -   case USB_ID(0x1de7, 0x0114): /* Phoenix Audio MT202pcs */
> case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
> return true;
> }
> +
> +   /* devices of these vendors don't support reading rate, either */
> +   switch (USB_ID_VENDOR(chip->usb_id)) {
> +   case 0x045E: /* MS Lifecam */
> +   case 0x047F: /* Plantronics */
> +   case 0x1de7: /* Phoenix Audio */
> +   return true;
> +   }
> +
> return false;
>  }
>

This is definitely a better approach. Thanks!

Acked-by: Kai-Heng Feng 

> --
> 2.14.2
>


Re: [PATCH resend] platform/x86: peaq-wmi: Add DMI check before binding to the WMI interface

2017-10-05 Thread Kai-Heng Feng
Hi Hans,

On Fri, Oct 6, 2017 at 2:04 AM, Hans de Goede  wrote:
> Hi All,
>
> This is a resend with Kai Heng Feng added to the Cc. Kai can you please
> test this patch. This patch replaces yours, as many devices seem to be
> affected so a whitelist is the better approach here.

I'll let the affected user to test the patch.

Thanks!

>
> Regards,
>
> Hans


Re: [PATCH resend] platform/x86: peaq-wmi: Add DMI check before binding to the WMI interface

2017-10-05 Thread Kai-Heng Feng
Hi Hans,

On Fri, Oct 6, 2017 at 2:04 AM, Hans de Goede  wrote:
> Hi All,
>
> This is a resend with Kai Heng Feng added to the Cc. Kai can you please
> test this patch. This patch replaces yours, as many devices seem to be
> affected so a whitelist is the better approach here.

I'll let the affected user to test the patch.

Thanks!

>
> Regards,
>
> Hans


Re: [PATCH] net/ipv4: Remove unused variable in route.c

2017-10-05 Thread David Miller
From: Tim Hansen 
Date: Wed, 4 Oct 2017 15:59:49 -0400

> int rc is unmodified after initalization in net/ipv4/route.c, this patch 
> simply cleans up that variable and returns 0.
> 
> This was found with coccicheck M=net/ipv4/ on linus' tree.
> 
> Signed-off-by: Tim Hansen 

Applied to net-next.


Re: [PATCH net v2] RDS: IB: Initialize max_items based on underlying device attributes

2017-10-05 Thread David Miller
From: Avinash Repaka 
Date: Wed,  4 Oct 2017 12:11:29 -0700

> Use max_1m_mrs/max_8k_mrs while setting max_items, as the former
> variables are set based on the underlying device attributes.
> 
> Signed-off-by: Avinash Repaka 
> Acked-by: Santosh Shilimkar 

Applied to net-next.


Re: [PATCH net v2] RDS: IB: Initialize max_items based on underlying device attributes

2017-10-05 Thread David Miller
From: Avinash Repaka 
Date: Wed,  4 Oct 2017 12:11:29 -0700

> Use max_1m_mrs/max_8k_mrs while setting max_items, as the former
> variables are set based on the underlying device attributes.
> 
> Signed-off-by: Avinash Repaka 
> Acked-by: Santosh Shilimkar 

Applied to net-next.


Re: [PATCH] net/ipv4: Remove unused variable in route.c

2017-10-05 Thread David Miller
From: Tim Hansen 
Date: Wed, 4 Oct 2017 15:59:49 -0400

> int rc is unmodified after initalization in net/ipv4/route.c, this patch 
> simply cleans up that variable and returns 0.
> 
> This was found with coccicheck M=net/ipv4/ on linus' tree.
> 
> Signed-off-by: Tim Hansen 

Applied to net-next.


Re: [PATCH net v2] RDS: IB: Limit the scope of has_fr/has_fmr variables

2017-10-05 Thread David Miller
From: Avinash Repaka 
Date: Wed,  4 Oct 2017 12:10:43 -0700

> This patch fixes the scope of has_fr and has_fmr variables as they are
> needed only in rds_ib_add_one().
> 
> Signed-off-by: Avinash Repaka 
> Acked-by: Santosh Shilimkar 

Applied to net-next.


Re: [PATCH net v2] RDS: IB: Limit the scope of has_fr/has_fmr variables

2017-10-05 Thread David Miller
From: Avinash Repaka 
Date: Wed,  4 Oct 2017 12:10:43 -0700

> This patch fixes the scope of has_fr and has_fmr variables as they are
> needed only in rds_ib_add_one().
> 
> Signed-off-by: Avinash Repaka 
> Acked-by: Santosh Shilimkar 

Applied to net-next.


Re: [PATCH net v2 3/9] net/mac89x0: Fix and modernize log messages

2017-10-05 Thread David Miller
From: Finn Thain 
Date: Thu,  5 Oct 2017 21:11:05 -0400 (EDT)

> Fix misplaced newlines in conditional log messages.

Please don't do this, the way the author formatted the strings
was intentional, they intended to print out:

NAME: cs89%c0%s rev %c found at %#8lx IRQ %d ADDR %pM

But now you are splitting it into multiple lines.  Also, you're
printing the IRQ information after register_netdev() which is
bad.  As soon as register_netdev() is called, the driver's
->open() routine can be invoked, and during which time some
log messages could be emitted during that operation.

And that would cut the probe messages up.

I know how you got to this state, you saw a reference to dev->name
before it had a real value.  You just removed the "eth%d" string
entirely.  And since you removed the dev->name reference, you had
no reason to move log messages after register_netdev() at all.

Anyways, you can also see the intention of the author here becuase
they have _explicit_ leading newlines in the error path messages that
come after the inital probe printk.

The real way to fix the early dev->name reference is to replace it
with a dev_info() call and have it use the struct device name rather
than the netdev device one.

Again, I think you really shouldn't be making these small weird
changes to these old drivers.



Re: [PATCH net v2 3/9] net/mac89x0: Fix and modernize log messages

2017-10-05 Thread David Miller
From: Finn Thain 
Date: Thu,  5 Oct 2017 21:11:05 -0400 (EDT)

> Fix misplaced newlines in conditional log messages.

Please don't do this, the way the author formatted the strings
was intentional, they intended to print out:

NAME: cs89%c0%s rev %c found at %#8lx IRQ %d ADDR %pM

But now you are splitting it into multiple lines.  Also, you're
printing the IRQ information after register_netdev() which is
bad.  As soon as register_netdev() is called, the driver's
->open() routine can be invoked, and during which time some
log messages could be emitted during that operation.

And that would cut the probe messages up.

I know how you got to this state, you saw a reference to dev->name
before it had a real value.  You just removed the "eth%d" string
entirely.  And since you removed the dev->name reference, you had
no reason to move log messages after register_netdev() at all.

Anyways, you can also see the intention of the author here becuase
they have _explicit_ leading newlines in the error path messages that
come after the inital probe printk.

The real way to fix the early dev->name reference is to replace it
with a dev_info() call and have it use the struct device name rather
than the netdev device one.

Again, I think you really shouldn't be making these small weird
changes to these old drivers.



Re: [PATCH v6 3/3] drm/panel: Add support for the Raspberry Pi 7" Touchscreen.

2017-10-05 Thread Archit Taneja



On 09/28/2017 01:06 AM, Eric Anholt wrote:

This driver communicates with the Atmel microcontroller for sequencing
the poweron of the TC358762 DSI-DPI bridge and controlling the
backlight PWM.

v2: Set the same default orientation as the closed source firmware
 used, which is the best for viewing angle.
v3: Rewrite as an i2c client driver after bridge driver rejection.
v4: Finish probe without the DSI host, using the new delayed
 registration, and attach to the host during mipi_dsi_driver probe.
v5: Rework to drop the "probe without DSI host" mode again, now that
 vc4 will create the host early on.


Reviewed-by: Archit Taneja 



Signed-off-by: Eric Anholt 
---
  drivers/gpu/drm/panel/Kconfig  |   8 +
  drivers/gpu/drm/panel/Makefile |   1 +
  .../gpu/drm/panel/panel-raspberrypi-touchscreen.c  | 517 +
  3 files changed, 526 insertions(+)
  create mode 100644 drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 718d8ce15b1f..726f3fb3312d 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -82,6 +82,14 @@ config DRM_PANEL_PANASONIC_VVX10F034N00
  WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some
  Xperia Z2 tablets
  
+config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN

+   tristate "Raspberry Pi 7-inch touchscreen panel"
+   depends on DRM_MIPI_DSI
+   help
+ Say Y here if you want to enable support for the Raspberry
+ Pi 7" Touchscreen.  To compile this driver as a module,
+ choose M here.
+
  config DRM_PANEL_SAMSUNG_S6E3HA2
tristate "Samsung S6E3HA2 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index c8483fdd5b9b..77ede3467324 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += 
panel-jdi-lt070me05000.o
  obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
  obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o
  obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
+obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += 
panel-raspberrypi-touchscreen.o
  obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
  obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
  obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c 
b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
new file mode 100644
index ..4237a0cbcdcc
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright © 2016-2017 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Portions of this file (derived from panel-simple.c) are:
+ *
+ * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Raspberry Pi 7" touchscreen panel driver.
+ *
+ * The 7" touchscreen consists of a DPI LCD panel, a Toshiba
+ * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR
+ * controlling power management, the LCD PWM, and initial register
+ * setup of the Tohsiba.
+ *
+ * This driver controls the TC358762 and ATTINY88, presenting a DSI
+ * device with a drm_panel.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RPI_DSI_DRIVER_NAME "rpi-ts-dsi"
+

Re: [PATCH v6 3/3] drm/panel: Add support for the Raspberry Pi 7" Touchscreen.

2017-10-05 Thread Archit Taneja



On 09/28/2017 01:06 AM, Eric Anholt wrote:

This driver communicates with the Atmel microcontroller for sequencing
the poweron of the TC358762 DSI-DPI bridge and controlling the
backlight PWM.

v2: Set the same default orientation as the closed source firmware
 used, which is the best for viewing angle.
v3: Rewrite as an i2c client driver after bridge driver rejection.
v4: Finish probe without the DSI host, using the new delayed
 registration, and attach to the host during mipi_dsi_driver probe.
v5: Rework to drop the "probe without DSI host" mode again, now that
 vc4 will create the host early on.


Reviewed-by: Archit Taneja 



Signed-off-by: Eric Anholt 
---
  drivers/gpu/drm/panel/Kconfig  |   8 +
  drivers/gpu/drm/panel/Makefile |   1 +
  .../gpu/drm/panel/panel-raspberrypi-touchscreen.c  | 517 +
  3 files changed, 526 insertions(+)
  create mode 100644 drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c

diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 718d8ce15b1f..726f3fb3312d 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -82,6 +82,14 @@ config DRM_PANEL_PANASONIC_VVX10F034N00
  WUXGA (1920x1200) Novatek NT1397-based DSI panel as found in some
  Xperia Z2 tablets
  
+config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN

+   tristate "Raspberry Pi 7-inch touchscreen panel"
+   depends on DRM_MIPI_DSI
+   help
+ Say Y here if you want to enable support for the Raspberry
+ Pi 7" Touchscreen.  To compile this driver as a module,
+ choose M here.
+
  config DRM_PANEL_SAMSUNG_S6E3HA2
tristate "Samsung S6E3HA2 DSI video mode panel"
depends on OF
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index c8483fdd5b9b..77ede3467324 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += 
panel-jdi-lt070me05000.o
  obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
  obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o
  obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += 
panel-panasonic-vvx10f034n00.o
+obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += 
panel-raspberrypi-touchscreen.o
  obj-$(CONFIG_DRM_PANEL_SAMSUNG_LD9040) += panel-samsung-ld9040.o
  obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2) += panel-samsung-s6e3ha2.o
  obj-$(CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03) += panel-samsung-s6e63j0x03.o
diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c 
b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
new file mode 100644
index ..4237a0cbcdcc
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright © 2016-2017 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Portions of this file (derived from panel-simple.c) are:
+ *
+ * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * Raspberry Pi 7" touchscreen panel driver.
+ *
+ * The 7" touchscreen consists of a DPI LCD panel, a Toshiba
+ * TC358762XBG DSI-DPI bridge, and an I2C-connected Atmel ATTINY88-MUR
+ * controlling power management, the LCD PWM, and initial register
+ * setup of the Tohsiba.
+ *
+ * This driver controls the TC358762 and ATTINY88, presenting a DSI
+ * device with a drm_panel.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define RPI_DSI_DRIVER_NAME "rpi-ts-dsi"
+
+/* I2C registers of the Atmel 

Re: [PATCH] staging: ccree: local variable "dev" not required

2017-10-05 Thread Suniel Mahesh
On Thursday 05 October 2017 11:30 PM, Joe Perches wrote:
> On Thu, 2017-10-05 at 10:07 +0300, Gilad Ben-Yossef wrote:
>> On Wed, Oct 4, 2017 at 10:12 PM,   wrote:
>>> There is no need to create a local pointer variable "dev" and
>>> pass it various API's, instead use plat_dev which is enumerated
>>> by platform core on successful probe.
> []
>> I'm sorry but I don't understand what is the problem you are trying to solve 
>> or
>> what is the improvement suggested.

Hi Gilad and all,

Actually this patch is not a major improvement nor trying to solve some thing.

As struct device is a member of struct platform_device, I thought why can't we 
use
plat_dev (pointer to struct platform_device) through out the code. May be I was 
trying
to make code look compact, may be I am wrong.

>>
>> Why is having a local variable undesirable? I think having it makes
>> the code more readable, not less.
> 
> IMO: The local variable is _not_ undesirable.
>  It does make the code more readable and
>  shortens line lengths too.
> 

Yes, as you guys pointed out, we can use local variables. It is definitely 
making
the code more readable and shortening line lengths.

Please drop the patch, if this not helping the code look better.

Thanks
Suniel 


Re: [PATCH] staging: ccree: local variable "dev" not required

2017-10-05 Thread Suniel Mahesh
On Thursday 05 October 2017 11:30 PM, Joe Perches wrote:
> On Thu, 2017-10-05 at 10:07 +0300, Gilad Ben-Yossef wrote:
>> On Wed, Oct 4, 2017 at 10:12 PM,   wrote:
>>> There is no need to create a local pointer variable "dev" and
>>> pass it various API's, instead use plat_dev which is enumerated
>>> by platform core on successful probe.
> []
>> I'm sorry but I don't understand what is the problem you are trying to solve 
>> or
>> what is the improvement suggested.

Hi Gilad and all,

Actually this patch is not a major improvement nor trying to solve some thing.

As struct device is a member of struct platform_device, I thought why can't we 
use
plat_dev (pointer to struct platform_device) through out the code. May be I was 
trying
to make code look compact, may be I am wrong.

>>
>> Why is having a local variable undesirable? I think having it makes
>> the code more readable, not less.
> 
> IMO: The local variable is _not_ undesirable.
>  It does make the code more readable and
>  shortens line lengths too.
> 

Yes, as you guys pointed out, we can use local variables. It is definitely 
making
the code more readable and shortening line lengths.

Please drop the patch, if this not helping the code look better.

Thanks
Suniel 


Re: [PATCHv2 1/2] mm: Introduce wrappers to access mm->nr_ptes

2017-10-05 Thread Anshuman Khandual
On 10/05/2017 03:44 PM, Kirill A. Shutemov wrote:
> Let's add wrappers for ->nr_ptes with the same interface as for nr_pmd
> and nr_pud.
> 
> It's preparation for consolidation of page-table counters in mm_struct.
> 
> Signed-off-by: Kirill A. Shutemov 

Hey Kirill,

This patch does not apply cleanly either on mainline or on the latest
mmotm branch mmotm-2017-10-03-17-08. Is there any other branch like
'linux next' you might have rebased these patches against ?

- Anshuman



Re: [PATCHv2 1/2] mm: Introduce wrappers to access mm->nr_ptes

2017-10-05 Thread Anshuman Khandual
On 10/05/2017 03:44 PM, Kirill A. Shutemov wrote:
> Let's add wrappers for ->nr_ptes with the same interface as for nr_pmd
> and nr_pud.
> 
> It's preparation for consolidation of page-table counters in mm_struct.
> 
> Signed-off-by: Kirill A. Shutemov 

Hey Kirill,

This patch does not apply cleanly either on mainline or on the latest
mmotm branch mmotm-2017-10-03-17-08. Is there any other branch like
'linux next' you might have rebased these patches against ?

- Anshuman



Re: [PATCH v2 1/2] staging: Introduce NVIDIA Tegra20 video decoder driver

2017-10-05 Thread kbuild test robot
Hi Dmitry,

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on v4.14-rc3 next-20170929]
[cannot apply to tegra/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/staging-Introduce-NVIDIA-Tegra20-video-decoder-driver/20171006-101015
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=ia64 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:13:0,
from include/linux/clk.h:16,
from drivers/staging/tegra-vde/vde.c:11:
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_setup_hw_context':
>> drivers/staging/tegra-vde/vde.c:51:11: warning: format '%X' expects argument 
>> of type 'unsigned int', but argument 5 has type 'long long unsigned int' 
>> [-Wformat=]
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
  ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
#define pr_fmt(fmt) fmt
^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
 dynamic_pr_debug(fmt, ##__VA_ARGS__)
 ^~~~
   drivers/staging/tegra-vde/vde.c:51:2: note: in expansion of macro 'pr_debug'
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
 ^~~~
   drivers/staging/tegra-vde/vde.c:362:2: note: in expansion of macro 'VDE_WR'
 VDE_WR(bitstream_data_paddr + bitstream_data_size,
 ^~
>> drivers/staging/tegra-vde/vde.c:51:11: warning: format '%X' expects argument 
>> of type 'unsigned int', but argument 5 has type 'phys_addr_t {aka long long 
>> unsigned int}' [-Wformat=]
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
  ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
#define pr_fmt(fmt) fmt
^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
 dynamic_pr_debug(fmt, ##__VA_ARGS__)
 ^~~~
   drivers/staging/tegra-vde/vde.c:51:2: note: in expansion of macro 'pr_debug'
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
 ^~~~
   drivers/staging/tegra-vde/vde.c:435:2: note: in expansion of macro 'VDE_WR'
 VDE_WR(bitstream_data_paddr, vde->regs + SXE(0x6C));
 ^~
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_attach_dmabuf':
   drivers/staging/tegra-vde/vde.c:531:40: warning: format '%d' expects 
argument of type 'int', but argument 3 has type 'size_t {aka long unsigned 
int}' [-Wformat=]
  dev_err(dev, "Too small dmabuf size %d @0x%lX, "
   ^
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_ioctl_decode_h264':
   drivers/staging/tegra-vde/vde.c:855:16: warning: format '%X' expects 
argument of type 'unsigned int', but argument 3 has type 'phys_addr_t {aka long 
long unsigned int}' [-Wformat=]
  dev_err(dev, "Decoding failed, "
   ^~~

vim +51 drivers/staging/tegra-vde/vde.c

  > 11  #include 
12  #include 
13  #include 
14  #include 
15  #include 
16  #include 
17  #include 
18  #include 
19  #include 
20  #include 
21  #include 
22  #include 
23  #include 
24  
25  #include 
26  
27  #include "uapi.h"
28  
29  #define SXE(offt)   (0x + (offt)) /* Syntax Engine */
30  #define BSEV(offt)  (0x1000 + (offt)) /* Video Bitstream 
Engine */
31  #define MBE(offt)   (0x2000 + (offt)) /* Macroblock Engine 
*/
32  #define PPE(offt)   (0x2200 + (offt)) /* Post-processing 
Engine */
33  #define MCE(offt)   (0x2400 + (offt)) /* Motion 
Compensation Eng. */
34  #define TFE(offt)   (0x2600 + (offt)) /* Transform Engine */
35  #define VDMA(offt)  (0x2A00 + (offt)) /* Video DMA */
36  #define FRAMEID(offt)   (0x3800 + (offt))
37  
38  #define ICMDQUE_WR  0x00
39  #define CMDQUE_CONTROL  0x08
40  #define INTR_STATUS 0x18
41  #define BSE_INT_ENB 0x40
42  #define BSE_CONFIG  0x44
43  
44  #define BSE_ICMDQUE_EMPTY   BIT(3)
45  #define BSE_DMA_BUSYBIT(23)
46  
47  #define TEGRA_VDE_TIMEOUT   msecs_to_jiffies(1000)
48  
49  #define VDE_WR(__data, __addr)  \
50  do {\
  > 51  pr_debug("%s: %d: 0x%08X => " #__addr ")\n",\
52__func__, __LINE__, (__data));\
53  

Re: [PATCH v2 1/2] staging: Introduce NVIDIA Tegra20 video decoder driver

2017-10-05 Thread kbuild test robot
Hi Dmitry,

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on v4.14-rc3 next-20170929]
[cannot apply to tegra/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/staging-Introduce-NVIDIA-Tegra20-video-decoder-driver/20171006-101015
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=ia64 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:13:0,
from include/linux/clk.h:16,
from drivers/staging/tegra-vde/vde.c:11:
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_setup_hw_context':
>> drivers/staging/tegra-vde/vde.c:51:11: warning: format '%X' expects argument 
>> of type 'unsigned int', but argument 5 has type 'long long unsigned int' 
>> [-Wformat=]
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
  ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
#define pr_fmt(fmt) fmt
^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
 dynamic_pr_debug(fmt, ##__VA_ARGS__)
 ^~~~
   drivers/staging/tegra-vde/vde.c:51:2: note: in expansion of macro 'pr_debug'
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
 ^~~~
   drivers/staging/tegra-vde/vde.c:362:2: note: in expansion of macro 'VDE_WR'
 VDE_WR(bitstream_data_paddr + bitstream_data_size,
 ^~
>> drivers/staging/tegra-vde/vde.c:51:11: warning: format '%X' expects argument 
>> of type 'unsigned int', but argument 5 has type 'phys_addr_t {aka long long 
>> unsigned int}' [-Wformat=]
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
  ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
#define pr_fmt(fmt) fmt
^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
 dynamic_pr_debug(fmt, ##__VA_ARGS__)
 ^~~~
   drivers/staging/tegra-vde/vde.c:51:2: note: in expansion of macro 'pr_debug'
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
 ^~~~
   drivers/staging/tegra-vde/vde.c:435:2: note: in expansion of macro 'VDE_WR'
 VDE_WR(bitstream_data_paddr, vde->regs + SXE(0x6C));
 ^~
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_attach_dmabuf':
   drivers/staging/tegra-vde/vde.c:531:40: warning: format '%d' expects 
argument of type 'int', but argument 3 has type 'size_t {aka long unsigned 
int}' [-Wformat=]
  dev_err(dev, "Too small dmabuf size %d @0x%lX, "
   ^
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_ioctl_decode_h264':
   drivers/staging/tegra-vde/vde.c:855:16: warning: format '%X' expects 
argument of type 'unsigned int', but argument 3 has type 'phys_addr_t {aka long 
long unsigned int}' [-Wformat=]
  dev_err(dev, "Decoding failed, "
   ^~~

vim +51 drivers/staging/tegra-vde/vde.c

  > 11  #include 
12  #include 
13  #include 
14  #include 
15  #include 
16  #include 
17  #include 
18  #include 
19  #include 
20  #include 
21  #include 
22  #include 
23  #include 
24  
25  #include 
26  
27  #include "uapi.h"
28  
29  #define SXE(offt)   (0x + (offt)) /* Syntax Engine */
30  #define BSEV(offt)  (0x1000 + (offt)) /* Video Bitstream 
Engine */
31  #define MBE(offt)   (0x2000 + (offt)) /* Macroblock Engine 
*/
32  #define PPE(offt)   (0x2200 + (offt)) /* Post-processing 
Engine */
33  #define MCE(offt)   (0x2400 + (offt)) /* Motion 
Compensation Eng. */
34  #define TFE(offt)   (0x2600 + (offt)) /* Transform Engine */
35  #define VDMA(offt)  (0x2A00 + (offt)) /* Video DMA */
36  #define FRAMEID(offt)   (0x3800 + (offt))
37  
38  #define ICMDQUE_WR  0x00
39  #define CMDQUE_CONTROL  0x08
40  #define INTR_STATUS 0x18
41  #define BSE_INT_ENB 0x40
42  #define BSE_CONFIG  0x44
43  
44  #define BSE_ICMDQUE_EMPTY   BIT(3)
45  #define BSE_DMA_BUSYBIT(23)
46  
47  #define TEGRA_VDE_TIMEOUT   msecs_to_jiffies(1000)
48  
49  #define VDE_WR(__data, __addr)  \
50  do {\
  > 51  pr_debug("%s: %d: 0x%08X => " #__addr ")\n",\
52__func__, __LINE__, (__data));\
53  

[PATCH 3/3] binfmt_elf: Search an unmapped area with total_size but not map the whole image

2017-10-05 Thread Baoquan He
In elf_map(), we can search an unmapped area for the whole image of dynamic
loader with total_size, then map the first PT_LOAD segment with its own size.
But not map the while image, then unmap the remainder at the end.

And also update the code comment in elf_map() accordingly.

Signed-off-by: Baoquan He 
---
 fs/binfmt_elf.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d7a8a53a6f18..bebb9f2c934e 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -357,20 +357,23 @@ static unsigned long elf_map(struct file *filep, unsigned 
long addr,
return addr;
 
/*
-   * total_size is the size of the ELF (interpreter) image.
-   * The _first_ mmap needs to know the full size, otherwise
-   * randomization might put this image into an overlapping
-   * position with the ELF binary image. (since size < total_size)
-   * So we first map the 'big' image - and unmap the remainder at
-   * the end. (which unmap is needed for ELF images with holes.)
+   * total_size is the size of the ELF (interpreter) image if non-zero.
+   * It gets value either in load_elf_interp(), or in load_elf_binary()
+   * for "./ld.so someprog" testing. The _first_ mmap needs to know the
+   * full size, otherwise the first PT_LOAD segment is mapped below
+   * mm->mmap_base, the subsequent PT_LOAD segment(s) end up being mapped
+   * above mm->mmap_base into the area that is supposed to be the "gap"
+   * between the stack and the binary. So we search an unmapped area of
+   * total_size big, then use the found address as hint to do mmap.
*/
if (total_size) {
total_size = ELF_PAGEALIGN(total_size);
-   map_addr = vm_mmap(filep, addr, total_size, prot, flags, off);
-   if (!BAD_ADDR(map_addr))
-   vm_munmap(map_addr+size, total_size-size);
-   } else
-   map_addr = vm_mmap(filep, addr, size, prot, flags, off);
+   addr = get_unmapped_area(file, addr, total_size, off, flags);
+   if (offset_in_page(addr))
+   return addr;
+   }
+
+   map_addr = vm_mmap(filep, addr, size, prot, flags, off);
 
return(map_addr);
 }
-- 
2.5.5



[PATCH 2/3] binfmt_elf: Get the total_size only for dynamic loader in load_elf_binary()

2017-10-05 Thread Baoquan He
In commit:

  eab09532d4 ("binfmt_elf: use ELF_ET_DYN_BASE only for PIE")

... PIE programs are loaded offset from ELF_ET_DYN_BASE, and its map
has been set as MAP_FIXED. Only dynamic loader will be mapped from
below mm->mmap_base (E.g "./ld.so someprog"), and need take account
of the need to allocate sufficient space for the entire loader image
to avoid the case that the first PT_LOAD segment is mapped below
mm->mmap_base, the subsequent PT_LOAD segment(s) end up being mapped
above mm->mmap_base into the area that is supposed to be the "gap"
between the stack and mm->mmap_base.

Whether it's harmless or not, we should not allow program to map above
mm->mmap_base. So here change to get the total_size only for dynamic
loader in load_elf_binary().

Signed-off-by: Baoquan He 
---
 fs/binfmt_elf.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 72b7ecba7ead..d7a8a53a6f18 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -967,9 +967,17 @@ static int load_elf_binary(struct linux_binprm *bprm)
if (current->flags & PF_RANDOMIZE)
load_bias += arch_mmap_rnd();
elf_flags |= MAP_FIXED;
-   } else
+   } else {
load_bias = 0;
 
+   total_size = total_mapping_size(elf_phdata,
+   loc->elf_ex.e_phnum);
+   if (!total_size) {
+   retval = -EINVAL;
+   goto out_free_dentry;
+   }
+   }
+
/*
 * Since load_bias is used for all subsequent loading
 * calculations, we must lower it by the first vaddr
@@ -978,13 +986,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
 * is then page aligned.
 */
load_bias = ELF_PAGESTART(load_bias - vaddr);
-
-   total_size = total_mapping_size(elf_phdata,
-   loc->elf_ex.e_phnum);
-   if (!total_size) {
-   retval = -EINVAL;
-   goto out_free_dentry;
-   }
}
 
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-- 
2.5.5



[PATCH 3/3] binfmt_elf: Search an unmapped area with total_size but not map the whole image

2017-10-05 Thread Baoquan He
In elf_map(), we can search an unmapped area for the whole image of dynamic
loader with total_size, then map the first PT_LOAD segment with its own size.
But not map the while image, then unmap the remainder at the end.

And also update the code comment in elf_map() accordingly.

Signed-off-by: Baoquan He 
---
 fs/binfmt_elf.c | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d7a8a53a6f18..bebb9f2c934e 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -357,20 +357,23 @@ static unsigned long elf_map(struct file *filep, unsigned 
long addr,
return addr;
 
/*
-   * total_size is the size of the ELF (interpreter) image.
-   * The _first_ mmap needs to know the full size, otherwise
-   * randomization might put this image into an overlapping
-   * position with the ELF binary image. (since size < total_size)
-   * So we first map the 'big' image - and unmap the remainder at
-   * the end. (which unmap is needed for ELF images with holes.)
+   * total_size is the size of the ELF (interpreter) image if non-zero.
+   * It gets value either in load_elf_interp(), or in load_elf_binary()
+   * for "./ld.so someprog" testing. The _first_ mmap needs to know the
+   * full size, otherwise the first PT_LOAD segment is mapped below
+   * mm->mmap_base, the subsequent PT_LOAD segment(s) end up being mapped
+   * above mm->mmap_base into the area that is supposed to be the "gap"
+   * between the stack and the binary. So we search an unmapped area of
+   * total_size big, then use the found address as hint to do mmap.
*/
if (total_size) {
total_size = ELF_PAGEALIGN(total_size);
-   map_addr = vm_mmap(filep, addr, total_size, prot, flags, off);
-   if (!BAD_ADDR(map_addr))
-   vm_munmap(map_addr+size, total_size-size);
-   } else
-   map_addr = vm_mmap(filep, addr, size, prot, flags, off);
+   addr = get_unmapped_area(file, addr, total_size, off, flags);
+   if (offset_in_page(addr))
+   return addr;
+   }
+
+   map_addr = vm_mmap(filep, addr, size, prot, flags, off);
 
return(map_addr);
 }
-- 
2.5.5



[PATCH 2/3] binfmt_elf: Get the total_size only for dynamic loader in load_elf_binary()

2017-10-05 Thread Baoquan He
In commit:

  eab09532d4 ("binfmt_elf: use ELF_ET_DYN_BASE only for PIE")

... PIE programs are loaded offset from ELF_ET_DYN_BASE, and its map
has been set as MAP_FIXED. Only dynamic loader will be mapped from
below mm->mmap_base (E.g "./ld.so someprog"), and need take account
of the need to allocate sufficient space for the entire loader image
to avoid the case that the first PT_LOAD segment is mapped below
mm->mmap_base, the subsequent PT_LOAD segment(s) end up being mapped
above mm->mmap_base into the area that is supposed to be the "gap"
between the stack and mm->mmap_base.

Whether it's harmless or not, we should not allow program to map above
mm->mmap_base. So here change to get the total_size only for dynamic
loader in load_elf_binary().

Signed-off-by: Baoquan He 
---
 fs/binfmt_elf.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 72b7ecba7ead..d7a8a53a6f18 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -967,9 +967,17 @@ static int load_elf_binary(struct linux_binprm *bprm)
if (current->flags & PF_RANDOMIZE)
load_bias += arch_mmap_rnd();
elf_flags |= MAP_FIXED;
-   } else
+   } else {
load_bias = 0;
 
+   total_size = total_mapping_size(elf_phdata,
+   loc->elf_ex.e_phnum);
+   if (!total_size) {
+   retval = -EINVAL;
+   goto out_free_dentry;
+   }
+   }
+
/*
 * Since load_bias is used for all subsequent loading
 * calculations, we must lower it by the first vaddr
@@ -978,13 +986,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
 * is then page aligned.
 */
load_bias = ELF_PAGESTART(load_bias - vaddr);
-
-   total_size = total_mapping_size(elf_phdata,
-   loc->elf_ex.e_phnum);
-   if (!total_size) {
-   retval = -EINVAL;
-   goto out_free_dentry;
-   }
}
 
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
-- 
2.5.5



[PATCH 0/3] binfmt_elf: Clean up codes related to total_size passed into elf_map()

2017-10-05 Thread Baoquan He
Currently total_size passed into elf_map() is non-zero only for dynamic
loader, either in load_elf_interp(), or in load_elf_binary() for ET_DYN
without INTERP case. Now PIE programs are loaded offset from ELF_ET_DYN_BASE,
and map flags has been set as MAP_FIXED, no need to use tatal_size strategy.

And in elf_map(), Oleg pointed out that the mmap(total_size) + 
munmap(extra_size)
way looks very ugly. We can search the unmapped area of total_size big,
then only map the 1st PT_LOAD segment with the searched address.

In this patchset, clean up them all.

Baoquan He (3):
  binfmt_elf: Clean up the variable name of map flags
  binfmt_elf: Get the total_size only for dynamic loader in
load_elf_binary()
  binfmt_elf: Search an unmapped area with total_size but not map the
whole image

 fs/binfmt_elf.c | 50 +++---
 1 file changed, 27 insertions(+), 23 deletions(-)

-- 
2.5.5



[PATCH 1/3] binfmt_elf: Clean up the variable name of map flags

2017-10-05 Thread Baoquan He
In load_elf_interp() and elf_map(), variables with value of map flags
are named as type or elf_type. That may bring confusion since their
values not only contain map type which is MAP_SHARED or MAP_PRIVATE,
also MAP_FIXED or MAP_DENYWRITE, etc.

So change them as flags or elf_flags.

Signed-off-by: Baoquan He 
---
 fs/binfmt_elf.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 73b01e474fdc..72b7ecba7ead 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -342,7 +342,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr 
*exec,
 #ifndef elf_map
 
 static unsigned long elf_map(struct file *filep, unsigned long addr,
-   struct elf_phdr *eppnt, int prot, int type,
+   struct elf_phdr *eppnt, int prot, int flags,
unsigned long total_size)
 {
unsigned long map_addr;
@@ -366,11 +366,11 @@ static unsigned long elf_map(struct file *filep, unsigned 
long addr,
*/
if (total_size) {
total_size = ELF_PAGEALIGN(total_size);
-   map_addr = vm_mmap(filep, addr, total_size, prot, type, off);
+   map_addr = vm_mmap(filep, addr, total_size, prot, flags, off);
if (!BAD_ADDR(map_addr))
vm_munmap(map_addr+size, total_size-size);
} else
-   map_addr = vm_mmap(filep, addr, size, prot, type, off);
+   map_addr = vm_mmap(filep, addr, size, prot, flags, off);
 
return(map_addr);
 }
@@ -556,7 +556,7 @@ static unsigned long load_elf_interp(struct elfhdr 
*interp_elf_ex,
eppnt = interp_elf_phdata;
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
-   int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+   int elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
int elf_prot = 0;
unsigned long vaddr = 0;
unsigned long k, map_addr;
@@ -569,12 +569,12 @@ static unsigned long load_elf_interp(struct elfhdr 
*interp_elf_ex,
elf_prot |= PROT_EXEC;
vaddr = eppnt->p_vaddr;
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
-   elf_type |= MAP_FIXED;
+   elf_flags |= MAP_FIXED;
else if (no_base && interp_elf_ex->e_type == ET_DYN)
load_addr = -vaddr;
 
map_addr = elf_map(interpreter, load_addr + vaddr,
-   eppnt, elf_prot, elf_type, total_size);
+   eppnt, elf_prot, elf_flags, total_size);
total_size = 0;
if (!*interp_map_addr)
*interp_map_addr = map_addr;
-- 
2.5.5



[PATCH 0/3] binfmt_elf: Clean up codes related to total_size passed into elf_map()

2017-10-05 Thread Baoquan He
Currently total_size passed into elf_map() is non-zero only for dynamic
loader, either in load_elf_interp(), or in load_elf_binary() for ET_DYN
without INTERP case. Now PIE programs are loaded offset from ELF_ET_DYN_BASE,
and map flags has been set as MAP_FIXED, no need to use tatal_size strategy.

And in elf_map(), Oleg pointed out that the mmap(total_size) + 
munmap(extra_size)
way looks very ugly. We can search the unmapped area of total_size big,
then only map the 1st PT_LOAD segment with the searched address.

In this patchset, clean up them all.

Baoquan He (3):
  binfmt_elf: Clean up the variable name of map flags
  binfmt_elf: Get the total_size only for dynamic loader in
load_elf_binary()
  binfmt_elf: Search an unmapped area with total_size but not map the
whole image

 fs/binfmt_elf.c | 50 +++---
 1 file changed, 27 insertions(+), 23 deletions(-)

-- 
2.5.5



[PATCH 1/3] binfmt_elf: Clean up the variable name of map flags

2017-10-05 Thread Baoquan He
In load_elf_interp() and elf_map(), variables with value of map flags
are named as type or elf_type. That may bring confusion since their
values not only contain map type which is MAP_SHARED or MAP_PRIVATE,
also MAP_FIXED or MAP_DENYWRITE, etc.

So change them as flags or elf_flags.

Signed-off-by: Baoquan He 
---
 fs/binfmt_elf.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 73b01e474fdc..72b7ecba7ead 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -342,7 +342,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr 
*exec,
 #ifndef elf_map
 
 static unsigned long elf_map(struct file *filep, unsigned long addr,
-   struct elf_phdr *eppnt, int prot, int type,
+   struct elf_phdr *eppnt, int prot, int flags,
unsigned long total_size)
 {
unsigned long map_addr;
@@ -366,11 +366,11 @@ static unsigned long elf_map(struct file *filep, unsigned 
long addr,
*/
if (total_size) {
total_size = ELF_PAGEALIGN(total_size);
-   map_addr = vm_mmap(filep, addr, total_size, prot, type, off);
+   map_addr = vm_mmap(filep, addr, total_size, prot, flags, off);
if (!BAD_ADDR(map_addr))
vm_munmap(map_addr+size, total_size-size);
} else
-   map_addr = vm_mmap(filep, addr, size, prot, type, off);
+   map_addr = vm_mmap(filep, addr, size, prot, flags, off);
 
return(map_addr);
 }
@@ -556,7 +556,7 @@ static unsigned long load_elf_interp(struct elfhdr 
*interp_elf_ex,
eppnt = interp_elf_phdata;
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
-   int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+   int elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
int elf_prot = 0;
unsigned long vaddr = 0;
unsigned long k, map_addr;
@@ -569,12 +569,12 @@ static unsigned long load_elf_interp(struct elfhdr 
*interp_elf_ex,
elf_prot |= PROT_EXEC;
vaddr = eppnt->p_vaddr;
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
-   elf_type |= MAP_FIXED;
+   elf_flags |= MAP_FIXED;
else if (no_base && interp_elf_ex->e_type == ET_DYN)
load_addr = -vaddr;
 
map_addr = elf_map(interpreter, load_addr + vaddr,
-   eppnt, elf_prot, elf_type, total_size);
+   eppnt, elf_prot, elf_flags, total_size);
total_size = 0;
if (!*interp_map_addr)
*interp_map_addr = map_addr;
-- 
2.5.5



Re: [PATCH RFC hack dont apply] intel_idle: support running within a VM

2017-10-05 Thread Michael S. Tsirkin
On Wed, Oct 04, 2017 at 11:31:43AM -0700, Jacob Pan wrote:
> On Wed, 4 Oct 2017 20:12:28 +0300
> "Michael S. Tsirkin"  wrote:
> 
> > On Wed, Oct 04, 2017 at 10:09:39AM -0700, Jacob Pan wrote:
> > > On Wed, 4 Oct 2017 05:09:09 +0300
> > > "Michael S. Tsirkin"  wrote:
> > >   
> > > > On Mon, Oct 02, 2017 at 10:12:49AM -0700, Jacob Pan wrote:  
> > > > > On Sat, 30 Sep 2017 01:21:43 +0200
> > > > > "Rafael J. Wysocki"  wrote:
> > > > > 
> > > > > > On Sat, Sep 30, 2017 at 12:01 AM, Michael S. Tsirkin
> > > > > >  wrote:
> > > > > > > intel idle driver does not DTRT when running within a VM:
> > > > > > > when going into a deep power state, the right thing to
> > > > > > > do is to exit to hypervisor rather than to keep polling
> > > > > > > within guest using mwait.
> > > > > > >
> > > > > > > Currently the solution is just to exit to hypervisor each
> > > > > > > time we go idle - this is why kvm does not expose the mwait
> > > > > > > leaf to guests even when it allows guests to do mwait.
> > > > > > >
> > > > > > > But that's not ideal - it seems better to use the idle
> > > > > > > driver to guess when will the next interrupt arrive.  
> > > > > > 
> > > > > > The idle driver alone is not sufficient for that, though.
> > > > > > 
> > > > > I second that. Why try to solve this problem at vendor specific
> > > > > driver level?
> > > > 
> > > > Well we still want to e.g. mwait if possible - saves power.
> > > >   
> > > > > perhaps just a pv idle driver that decide whether to vmexit
> > > > > based on something like local per vCPU timer expiration? I
> > > > > guess we can't predict other wake events such as interrupts.
> > > > > e.g.
> > > > > if (get_next_timer_interrupt() > kvm_halt_target_residency)
> > > > >   vmexit
> > > > > else
> > > > >   poll
> > > > > 
> > > > > Jacob
> > > > 
> > > > It's not always a poll, on x86 putting the CPU in a low power
> > > > state is possible within a VM.
> > > >   
> > > Are you talking about using mwait/monitor in the user space which
> > > are available on some Intel CPUs, such as Xeon Phi? I guess if the
> > > guest can identify host CPU id, it is doable.  
> > 
> > Not really.
> > 
> > Please take a look at the patch in question - it does mwait in guest
> > kernel and no need to identify host CPU id.
> > 
> I may be missing something, in your patch I only see HLT being used in
> the guest OS, that would cause VM exit right? If you do mwait in the
> guest kernel, it will also exit.


No mwait won't exit if running on kvm.
See 668fffa3f838edfcb1679f842f7ef1afa61c3e9a


> So I don't see how you can enter low
> power state within VM guest.
> 
> +static int intel_halt(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> +{
> + printk_once(KERN_ERR "safe_halt started\n");
> + safe_halt();
> + printk_once(KERN_ERR "safe_halt done\n");
> + return index;
> +}
> > 
> > > > Does not seem possible on other CPUs that's why it's vendor
> > > > specific. 
> > > 
> > > [Jacob Pan]  
> 
> [Jacob Pan]


Re: [PATCH RFC hack dont apply] intel_idle: support running within a VM

2017-10-05 Thread Michael S. Tsirkin
On Wed, Oct 04, 2017 at 11:31:43AM -0700, Jacob Pan wrote:
> On Wed, 4 Oct 2017 20:12:28 +0300
> "Michael S. Tsirkin"  wrote:
> 
> > On Wed, Oct 04, 2017 at 10:09:39AM -0700, Jacob Pan wrote:
> > > On Wed, 4 Oct 2017 05:09:09 +0300
> > > "Michael S. Tsirkin"  wrote:
> > >   
> > > > On Mon, Oct 02, 2017 at 10:12:49AM -0700, Jacob Pan wrote:  
> > > > > On Sat, 30 Sep 2017 01:21:43 +0200
> > > > > "Rafael J. Wysocki"  wrote:
> > > > > 
> > > > > > On Sat, Sep 30, 2017 at 12:01 AM, Michael S. Tsirkin
> > > > > >  wrote:
> > > > > > > intel idle driver does not DTRT when running within a VM:
> > > > > > > when going into a deep power state, the right thing to
> > > > > > > do is to exit to hypervisor rather than to keep polling
> > > > > > > within guest using mwait.
> > > > > > >
> > > > > > > Currently the solution is just to exit to hypervisor each
> > > > > > > time we go idle - this is why kvm does not expose the mwait
> > > > > > > leaf to guests even when it allows guests to do mwait.
> > > > > > >
> > > > > > > But that's not ideal - it seems better to use the idle
> > > > > > > driver to guess when will the next interrupt arrive.  
> > > > > > 
> > > > > > The idle driver alone is not sufficient for that, though.
> > > > > > 
> > > > > I second that. Why try to solve this problem at vendor specific
> > > > > driver level?
> > > > 
> > > > Well we still want to e.g. mwait if possible - saves power.
> > > >   
> > > > > perhaps just a pv idle driver that decide whether to vmexit
> > > > > based on something like local per vCPU timer expiration? I
> > > > > guess we can't predict other wake events such as interrupts.
> > > > > e.g.
> > > > > if (get_next_timer_interrupt() > kvm_halt_target_residency)
> > > > >   vmexit
> > > > > else
> > > > >   poll
> > > > > 
> > > > > Jacob
> > > > 
> > > > It's not always a poll, on x86 putting the CPU in a low power
> > > > state is possible within a VM.
> > > >   
> > > Are you talking about using mwait/monitor in the user space which
> > > are available on some Intel CPUs, such as Xeon Phi? I guess if the
> > > guest can identify host CPU id, it is doable.  
> > 
> > Not really.
> > 
> > Please take a look at the patch in question - it does mwait in guest
> > kernel and no need to identify host CPU id.
> > 
> I may be missing something, in your patch I only see HLT being used in
> the guest OS, that would cause VM exit right? If you do mwait in the
> guest kernel, it will also exit.


No mwait won't exit if running on kvm.
See 668fffa3f838edfcb1679f842f7ef1afa61c3e9a


> So I don't see how you can enter low
> power state within VM guest.
> 
> +static int intel_halt(struct cpuidle_device *dev,
> + struct cpuidle_driver *drv, int index)
> +{
> + printk_once(KERN_ERR "safe_halt started\n");
> + safe_halt();
> + printk_once(KERN_ERR "safe_halt done\n");
> + return index;
> +}
> > 
> > > > Does not seem possible on other CPUs that's why it's vendor
> > > > specific. 
> > > 
> > > [Jacob Pan]  
> 
> [Jacob Pan]


Re: [PATCH 2/2] perf, tools, stat: Reset ids counter when retrying events

2017-10-05 Thread Andi Kleen
>   Poisoned by user:  f7
>   ASan internal: fe
> 

Forgot add. This should be 

Cc: sta...@vger.kernel.org  # 4.4+

[it breaks pmu-tools]

-Andi


Re: [PATCH 2/2] perf, tools, stat: Reset ids counter when retrying events

2017-10-05 Thread Andi Kleen
>   Poisoned by user:  f7
>   ASan internal: fe
> 

Forgot add. This should be 

Cc: sta...@vger.kernel.org  # 4.4+

[it breaks pmu-tools]

-Andi


Re: [PATCH v2 1/2] staging: Introduce NVIDIA Tegra20 video decoder driver

2017-10-05 Thread kbuild test robot
Hi Dmitry,

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on v4.14-rc3 next-20170929]
[cannot apply to tegra/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/staging-Introduce-NVIDIA-Tegra20-video-decoder-driver/20171006-101015
config: blackfin-allyesconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 6.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=blackfin 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:13:0,
from include/linux/clk.h:16,
from drivers/staging/tegra-vde/vde.c:11:
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_setup_hw_context':
>> drivers/staging/tegra-vde/vde.c:51:11: warning: format '%X' expects argument 
>> of type 'unsigned int', but argument 5 has type 'long unsigned int' 
>> [-Wformat=]
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
  ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
#define pr_fmt(fmt) fmt
^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
 dynamic_pr_debug(fmt, ##__VA_ARGS__)
 ^~~~
>> drivers/staging/tegra-vde/vde.c:51:2: note: in expansion of macro 'pr_debug'
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
 ^~~~
>> drivers/staging/tegra-vde/vde.c:362:2: note: in expansion of macro 'VDE_WR'
 VDE_WR(bitstream_data_paddr + bitstream_data_size,
 ^~
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_attach_dmabuf':
>> drivers/staging/tegra-vde/vde.c:531:40: warning: format '%d' expects 
>> argument of type 'int', but argument 3 has type 'size_t {aka long unsigned 
>> int}' [-Wformat=]
  dev_err(dev, "Too small dmabuf size %d @0x%lX, "
   ^

vim +51 drivers/staging/tegra-vde/vde.c

  > 11  #include 
12  #include 
13  #include 
14  #include 
15  #include 
16  #include 
17  #include 
18  #include 
19  #include 
20  #include 
21  #include 
22  #include 
23  #include 
24  
25  #include 
26  
27  #include "uapi.h"
28  
29  #define SXE(offt)   (0x + (offt)) /* Syntax Engine */
30  #define BSEV(offt)  (0x1000 + (offt)) /* Video Bitstream 
Engine */
31  #define MBE(offt)   (0x2000 + (offt)) /* Macroblock Engine 
*/
32  #define PPE(offt)   (0x2200 + (offt)) /* Post-processing 
Engine */
33  #define MCE(offt)   (0x2400 + (offt)) /* Motion 
Compensation Eng. */
34  #define TFE(offt)   (0x2600 + (offt)) /* Transform Engine */
35  #define VDMA(offt)  (0x2A00 + (offt)) /* Video DMA */
36  #define FRAMEID(offt)   (0x3800 + (offt))
37  
38  #define ICMDQUE_WR  0x00
39  #define CMDQUE_CONTROL  0x08
40  #define INTR_STATUS 0x18
41  #define BSE_INT_ENB 0x40
42  #define BSE_CONFIG  0x44
43  
44  #define BSE_ICMDQUE_EMPTY   BIT(3)
45  #define BSE_DMA_BUSYBIT(23)
46  
47  #define TEGRA_VDE_TIMEOUT   msecs_to_jiffies(1000)
48  
49  #define VDE_WR(__data, __addr)  \
50  do {\
  > 51  pr_debug("%s: %d: 0x%08X => " #__addr ")\n",\
52__func__, __LINE__, (__data));\
53  writel_relaxed(__data, __addr); \
54  } while (0)
55  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH v2 1/2] staging: Introduce NVIDIA Tegra20 video decoder driver

2017-10-05 Thread kbuild test robot
Hi Dmitry,

[auto build test WARNING on staging/staging-testing]
[also build test WARNING on v4.14-rc3 next-20170929]
[cannot apply to tegra/for-next]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Dmitry-Osipenko/staging-Introduce-NVIDIA-Tegra20-video-decoder-driver/20171006-101015
config: blackfin-allyesconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 6.2.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=blackfin 

All warnings (new ones prefixed by >>):

   In file included from include/linux/kernel.h:13:0,
from include/linux/clk.h:16,
from drivers/staging/tegra-vde/vde.c:11:
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_setup_hw_context':
>> drivers/staging/tegra-vde/vde.c:51:11: warning: format '%X' expects argument 
>> of type 'unsigned int', but argument 5 has type 'long unsigned int' 
>> [-Wformat=]
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
  ^
   include/linux/printk.h:285:21: note: in definition of macro 'pr_fmt'
#define pr_fmt(fmt) fmt
^~~
   include/linux/printk.h:333:2: note: in expansion of macro 'dynamic_pr_debug'
 dynamic_pr_debug(fmt, ##__VA_ARGS__)
 ^~~~
>> drivers/staging/tegra-vde/vde.c:51:2: note: in expansion of macro 'pr_debug'
 pr_debug("%s: %d: 0x%08X => " #__addr ")\n", \
 ^~~~
>> drivers/staging/tegra-vde/vde.c:362:2: note: in expansion of macro 'VDE_WR'
 VDE_WR(bitstream_data_paddr + bitstream_data_size,
 ^~
   drivers/staging/tegra-vde/vde.c: In function 'tegra_vde_attach_dmabuf':
>> drivers/staging/tegra-vde/vde.c:531:40: warning: format '%d' expects 
>> argument of type 'int', but argument 3 has type 'size_t {aka long unsigned 
>> int}' [-Wformat=]
  dev_err(dev, "Too small dmabuf size %d @0x%lX, "
   ^

vim +51 drivers/staging/tegra-vde/vde.c

  > 11  #include 
12  #include 
13  #include 
14  #include 
15  #include 
16  #include 
17  #include 
18  #include 
19  #include 
20  #include 
21  #include 
22  #include 
23  #include 
24  
25  #include 
26  
27  #include "uapi.h"
28  
29  #define SXE(offt)   (0x + (offt)) /* Syntax Engine */
30  #define BSEV(offt)  (0x1000 + (offt)) /* Video Bitstream 
Engine */
31  #define MBE(offt)   (0x2000 + (offt)) /* Macroblock Engine 
*/
32  #define PPE(offt)   (0x2200 + (offt)) /* Post-processing 
Engine */
33  #define MCE(offt)   (0x2400 + (offt)) /* Motion 
Compensation Eng. */
34  #define TFE(offt)   (0x2600 + (offt)) /* Transform Engine */
35  #define VDMA(offt)  (0x2A00 + (offt)) /* Video DMA */
36  #define FRAMEID(offt)   (0x3800 + (offt))
37  
38  #define ICMDQUE_WR  0x00
39  #define CMDQUE_CONTROL  0x08
40  #define INTR_STATUS 0x18
41  #define BSE_INT_ENB 0x40
42  #define BSE_CONFIG  0x44
43  
44  #define BSE_ICMDQUE_EMPTY   BIT(3)
45  #define BSE_DMA_BUSYBIT(23)
46  
47  #define TEGRA_VDE_TIMEOUT   msecs_to_jiffies(1000)
48  
49  #define VDE_WR(__data, __addr)  \
50  do {\
  > 51  pr_debug("%s: %d: 0x%08X => " #__addr ")\n",\
52__func__, __LINE__, (__data));\
53  writel_relaxed(__data, __addr); \
54  } while (0)
55  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


[PATCH]Support new Alps HID Touchpad device

2017-10-05 Thread Masaki Ota
Hi, Jiri,

Sorry, I have fixed the build warning error, and send the patch again.

Best Regards,
Masaki Ota


[PATCH 1/7] Delete unnecessary structure

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Delete "struct u1_dev devInfo" structure, because u1_dev structure is already 
declared as "struct u1_dev *data", and this structure is used for getting U1 
data in [PATCH 2/7].

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 69 +-
 1 file changed, 34 insertions(+), 35 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index ed9c0ea5b026..519bfcf9eaf0 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -259,7 +259,6 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 {
struct u1_dev *data = hid_get_drvdata(hdev);
struct input_dev *input = hi->input, *input2;
-   struct u1_dev devInfo;
int ret;
int res_x, res_y, i;
 
@@ -275,58 +274,58 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 
/* Device initialization */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   _ctrl, 0, true);
+   >dev_ctrl, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
goto exit;
}
 
-   devInfo.dev_ctrl &= ~U1_DISABLE_DEV;
-   devInfo.dev_ctrl |= U1_TP_ABS_MODE;
+   data->dev_ctrl &= ~U1_DISABLE_DEV;
+   data->dev_ctrl |= U1_TP_ABS_MODE;
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   NULL, devInfo.dev_ctrl, false);
+   NULL, data->dev_ctrl, false);
if (ret < 0) {
dev_err(>dev, "failed to change TP mode (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
-   _line_num_x, 0, true);
+   >sen_line_num_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
-   _line_num_y, 0, true);
+   >sen_line_num_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
-   _x, 0, true);
+   >pitch_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
-   _y, 0, true);
+   >pitch_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
-   , 0, true);
+   >resolution, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
-   _info, 0, true);
+   >btn_info, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PAD_BTN (%d)\n", ret);
goto exit;
@@ -334,29 +333,29 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 
/* Check StickPointer device */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEVICE_TYP,
-   _type, 0, true);
+   >dev_type, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEVICE_TYP (%d)\n", ret);
goto exit;
}
 
-   devInfo.x_active_len_mm =
-   (devInfo.pitch_x * (devInfo.sen_line_num_x - 1)) / 10;
-   devInfo.y_active_len_mm =
-   (devInfo.pitch_y * (devInfo.sen_line_num_y - 1)) / 10;
+   data->x_active_len_mm =
+   (data->pitch_x * (data->sen_line_num_x - 1)) / 10;
+   data->y_active_len_mm =
+   (data->pitch_y * (data->sen_line_num_y - 1)) / 10;
 
-   devInfo.x_max =
-   (devInfo.resolution << 2) * (devInfo.sen_line_num_x - 1);
-   devInfo.y_max =
-   (devInfo.resolution << 2) * (devInfo.sen_line_num_y - 1);
+   data->x_max =
+   (data->resolution << 2) * (data->sen_line_num_x - 1);
+   data->y_max =
+   (data->resolution << 2) * (data->sen_line_num_y - 1);
 
__set_bit(EV_ABS, input->evbit);
-   input_set_abs_params(input, ABS_MT_POSITION_X, 1, devInfo.x_max, 0, 0);
-   input_set_abs_params(input, ABS_MT_POSITION_Y, 1, devInfo.y_max, 0, 0);
+   input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->x_max, 0, 0);
+   input_set_abs_params(input, 

[PATCH]Support new Alps HID Touchpad device

2017-10-05 Thread Masaki Ota
Hi, Jiri,

Sorry, I have fixed the build warning error, and send the patch again.

Best Regards,
Masaki Ota


[PATCH 1/7] Delete unnecessary structure

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Delete "struct u1_dev devInfo" structure, because u1_dev structure is already 
declared as "struct u1_dev *data", and this structure is used for getting U1 
data in [PATCH 2/7].

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 69 +-
 1 file changed, 34 insertions(+), 35 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index ed9c0ea5b026..519bfcf9eaf0 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -259,7 +259,6 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 {
struct u1_dev *data = hid_get_drvdata(hdev);
struct input_dev *input = hi->input, *input2;
-   struct u1_dev devInfo;
int ret;
int res_x, res_y, i;
 
@@ -275,58 +274,58 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 
/* Device initialization */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   _ctrl, 0, true);
+   >dev_ctrl, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
goto exit;
}
 
-   devInfo.dev_ctrl &= ~U1_DISABLE_DEV;
-   devInfo.dev_ctrl |= U1_TP_ABS_MODE;
+   data->dev_ctrl &= ~U1_DISABLE_DEV;
+   data->dev_ctrl |= U1_TP_ABS_MODE;
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   NULL, devInfo.dev_ctrl, false);
+   NULL, data->dev_ctrl, false);
if (ret < 0) {
dev_err(>dev, "failed to change TP mode (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
-   _line_num_x, 0, true);
+   >sen_line_num_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
-   _line_num_y, 0, true);
+   >sen_line_num_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
-   _x, 0, true);
+   >pitch_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
-   _y, 0, true);
+   >pitch_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
-   , 0, true);
+   >resolution, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
-   _info, 0, true);
+   >btn_info, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PAD_BTN (%d)\n", ret);
goto exit;
@@ -334,29 +333,29 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 
/* Check StickPointer device */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEVICE_TYP,
-   _type, 0, true);
+   >dev_type, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEVICE_TYP (%d)\n", ret);
goto exit;
}
 
-   devInfo.x_active_len_mm =
-   (devInfo.pitch_x * (devInfo.sen_line_num_x - 1)) / 10;
-   devInfo.y_active_len_mm =
-   (devInfo.pitch_y * (devInfo.sen_line_num_y - 1)) / 10;
+   data->x_active_len_mm =
+   (data->pitch_x * (data->sen_line_num_x - 1)) / 10;
+   data->y_active_len_mm =
+   (data->pitch_y * (data->sen_line_num_y - 1)) / 10;
 
-   devInfo.x_max =
-   (devInfo.resolution << 2) * (devInfo.sen_line_num_x - 1);
-   devInfo.y_max =
-   (devInfo.resolution << 2) * (devInfo.sen_line_num_y - 1);
+   data->x_max =
+   (data->resolution << 2) * (data->sen_line_num_x - 1);
+   data->y_max =
+   (data->resolution << 2) * (data->sen_line_num_y - 1);
 
__set_bit(EV_ABS, input->evbit);
-   input_set_abs_params(input, ABS_MT_POSITION_X, 1, devInfo.x_max, 0, 0);
-   input_set_abs_params(input, ABS_MT_POSITION_Y, 1, devInfo.y_max, 0, 0);
+   input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->x_max, 0, 0);
+   input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->y_max, 0, 0);
 
-   if 

[PATCH 2/7] Separate U1 device code

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Create "static int u1_init()" function for separate U1 device initialization 
code from Main initialization.
-Create "has_sp" variable for checking whether it has SP device or not.

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 120 +++--
 1 file changed, 67 insertions(+), 53 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 519bfcf9eaf0..c4ea5c6c9be9 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -75,6 +75,7 @@
  * @y_max: maximum y coordinate value
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
+ * @has_sp: boolean of sp existense
  */
 struct u1_dev {
struct input_dev *input;
@@ -96,6 +97,7 @@ struct u1_dev {
u32 y_max;
u32 btn_cnt;
u32 sp_btn_cnt;
+   u8  has_sp;
 };
 
 static int u1_read_write_register(struct hid_device *hdev, u32 address,
@@ -255,99 +257,130 @@ static int alps_post_resume(struct hid_device *hdev)
 }
 #endif /* CONFIG_PM */
 
-static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int u1_init(struct hid_device *hdev, struct u1_dev *pri_data)
 {
-   struct u1_dev *data = hid_get_drvdata(hdev);
-   struct input_dev *input = hi->input, *input2;
int ret;
-   int res_x, res_y, i;
-
-   data->input = input;
-
-   hid_dbg(hdev, "Opening low level driver\n");
-   ret = hid_hw_open(hdev);
-   if (ret)
-   return ret;
-
-   /* Allow incoming hid reports */
-   hid_device_io_start(hdev);
 
/* Device initialization */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   >dev_ctrl, 0, true);
+   _data->dev_ctrl, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
goto exit;
}
 
-   data->dev_ctrl &= ~U1_DISABLE_DEV;
-   data->dev_ctrl |= U1_TP_ABS_MODE;
+   pri_data->dev_ctrl &= ~U1_DISABLE_DEV;
+   pri_data->dev_ctrl |= U1_TP_ABS_MODE;
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   NULL, data->dev_ctrl, false);
+   NULL, pri_data->dev_ctrl, false);
if (ret < 0) {
dev_err(>dev, "failed to change TP mode (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
-   >sen_line_num_x, 0, true);
+   _data->sen_line_num_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
-   >sen_line_num_y, 0, true);
+   _data->sen_line_num_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
-   >pitch_x, 0, true);
+   _data->pitch_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
-   >pitch_y, 0, true);
+   _data->pitch_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
-   >resolution, 0, true);
+   _data->resolution, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
goto exit;
}
+   pri_data->x_active_len_mm =
+   (pri_data->pitch_x * (pri_data->sen_line_num_x - 1)) / 10;
+   pri_data->y_active_len_mm =
+   (pri_data->pitch_y * (pri_data->sen_line_num_y - 1)) / 10;
+
+   pri_data->x_max =
+   (pri_data->resolution << 2) * (pri_data->sen_line_num_x - 1);
+   pri_data->y_max =
+   (pri_data->resolution << 2) * (pri_data->sen_line_num_y - 1);
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
-   >btn_info, 0, true);
+   _data->btn_info, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PAD_BTN (%d)\n", ret);
goto exit;
}
 
+   pri_data->has_sp = 0;
/* Check StickPointer device */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEVICE_TYP,
-   >dev_type, 0, true);
+   _data->dev_type, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEVICE_TYP (%d)\n", 

[PATCH 2/7] Separate U1 device code

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Create "static int u1_init()" function for separate U1 device initialization 
code from Main initialization.
-Create "has_sp" variable for checking whether it has SP device or not.

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 120 +++--
 1 file changed, 67 insertions(+), 53 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 519bfcf9eaf0..c4ea5c6c9be9 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -75,6 +75,7 @@
  * @y_max: maximum y coordinate value
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
+ * @has_sp: boolean of sp existense
  */
 struct u1_dev {
struct input_dev *input;
@@ -96,6 +97,7 @@ struct u1_dev {
u32 y_max;
u32 btn_cnt;
u32 sp_btn_cnt;
+   u8  has_sp;
 };
 
 static int u1_read_write_register(struct hid_device *hdev, u32 address,
@@ -255,99 +257,130 @@ static int alps_post_resume(struct hid_device *hdev)
 }
 #endif /* CONFIG_PM */
 
-static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int u1_init(struct hid_device *hdev, struct u1_dev *pri_data)
 {
-   struct u1_dev *data = hid_get_drvdata(hdev);
-   struct input_dev *input = hi->input, *input2;
int ret;
-   int res_x, res_y, i;
-
-   data->input = input;
-
-   hid_dbg(hdev, "Opening low level driver\n");
-   ret = hid_hw_open(hdev);
-   if (ret)
-   return ret;
-
-   /* Allow incoming hid reports */
-   hid_device_io_start(hdev);
 
/* Device initialization */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   >dev_ctrl, 0, true);
+   _data->dev_ctrl, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
goto exit;
}
 
-   data->dev_ctrl &= ~U1_DISABLE_DEV;
-   data->dev_ctrl |= U1_TP_ABS_MODE;
+   pri_data->dev_ctrl &= ~U1_DISABLE_DEV;
+   pri_data->dev_ctrl |= U1_TP_ABS_MODE;
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   NULL, data->dev_ctrl, false);
+   NULL, pri_data->dev_ctrl, false);
if (ret < 0) {
dev_err(>dev, "failed to change TP mode (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
-   >sen_line_num_x, 0, true);
+   _data->sen_line_num_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
-   >sen_line_num_y, 0, true);
+   _data->sen_line_num_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
-   >pitch_x, 0, true);
+   _data->pitch_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
-   >pitch_y, 0, true);
+   _data->pitch_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
-   >resolution, 0, true);
+   _data->resolution, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
goto exit;
}
+   pri_data->x_active_len_mm =
+   (pri_data->pitch_x * (pri_data->sen_line_num_x - 1)) / 10;
+   pri_data->y_active_len_mm =
+   (pri_data->pitch_y * (pri_data->sen_line_num_y - 1)) / 10;
+
+   pri_data->x_max =
+   (pri_data->resolution << 2) * (pri_data->sen_line_num_x - 1);
+   pri_data->y_max =
+   (pri_data->resolution << 2) * (pri_data->sen_line_num_y - 1);
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
-   >btn_info, 0, true);
+   _data->btn_info, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PAD_BTN (%d)\n", ret);
goto exit;
}
 
+   pri_data->has_sp = 0;
/* Check StickPointer device */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEVICE_TYP,
-   >dev_type, 0, true);
+   _data->dev_type, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEVICE_TYP (%d)\n", ret);
goto exit;
}
 
-   

[PATCH 4/7] replace some variables

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Move some variables(dev_ctrl, dev_type, sen_line_num_x, sen_line_num_y, 
pitch_x, pitch_y, resolution, btn_info) from u1_dev structure to "u1_init()", 
because these variables are only used in "u1_init()" function.

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 67 --
 1 file changed, 27 insertions(+), 40 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 201fe175cba3..4c323b58e009 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -61,14 +61,10 @@
  * @input2: pointer to the kernel input2 device
  * @hdev: pointer to the struct hid_device
  *
- * @dev_ctrl: device control parameter
  * @dev_type: device type
- * @sen_line_num_x: number of sensor line of X
- * @sen_line_num_y: number of sensor line of Y
- * @pitch_x: sensor pitch of X
- * @pitch_y: sensor pitch of Y
- * @resolution: resolution
- * @btn_info: button information
+ * @max_fingers: total number of fingers
+ * @has_sp: boolean of sp existense
+ * @sp_btn_info: button information
  * @x_active_len_mm: active area length of X (mm)
  * @y_active_len_mm: active area length of Y (mm)
  * @x_max: maximum x coordinate value
@@ -77,22 +73,14 @@
  * @y_min: minimum y coordinate value
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
- * @has_sp: boolean of sp existense
- * @max_fingers: total number of fingers
  */
 struct u1_dev {
struct input_dev *input;
struct input_dev *input2;
struct hid_device *hdev;
 
-   u8  dev_ctrl;
-   u8  dev_type;
-   u8  sen_line_num_x;
-   u8  sen_line_num_y;
-   u8  pitch_x;
-   u8  pitch_y;
-   u8  resolution;
-   u8  btn_info;
+   u8  max_fingers;
+   u8  has_sp;
u8  sp_btn_info;
u32 x_active_len_mm;
u32 y_active_len_mm;
@@ -102,8 +90,6 @@ struct u1_dev {
u32 y_min;
u32 btn_cnt;
u32 sp_btn_cnt;
-   u8  has_sp;
-   u8  max_fingers;
 };
 
 static int u1_read_write_register(struct hid_device *hdev, u32 address,
@@ -266,78 +252,80 @@ static int alps_post_resume(struct hid_device *hdev)
 static int u1_init(struct hid_device *hdev, struct u1_dev *pri_data)
 {
int ret;
+   u8 tmp, dev_ctrl, sen_line_num_x, sen_line_num_y;
+   u8 pitch_x, pitch_y, resolution;
 
/* Device initialization */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   _data->dev_ctrl, 0, true);
+   _ctrl, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
goto exit;
}
 
-   pri_data->dev_ctrl &= ~U1_DISABLE_DEV;
-   pri_data->dev_ctrl |= U1_TP_ABS_MODE;
+   dev_ctrl &= ~U1_DISABLE_DEV;
+   dev_ctrl |= U1_TP_ABS_MODE;
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   NULL, pri_data->dev_ctrl, false);
+   NULL, dev_ctrl, false);
if (ret < 0) {
dev_err(>dev, "failed to change TP mode (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
-   _data->sen_line_num_x, 0, true);
+   _line_num_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
-   _data->sen_line_num_y, 0, true);
+   _line_num_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
-   _data->pitch_x, 0, true);
+   _x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
-   _data->pitch_y, 0, true);
+   _y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
-   _data->resolution, 0, true);
+   , 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
goto exit;
}
pri_data->x_active_len_mm =
-   (pri_data->pitch_x * (pri_data->sen_line_num_x - 1)) / 10;
+   (pitch_x * (sen_line_num_x - 1)) / 10;
pri_data->y_active_len_mm =
-   (pri_data->pitch_y * (pri_data->sen_line_num_y - 1)) / 10;
+ 

[PATCH 4/7] replace some variables

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Move some variables(dev_ctrl, dev_type, sen_line_num_x, sen_line_num_y, 
pitch_x, pitch_y, resolution, btn_info) from u1_dev structure to "u1_init()", 
because these variables are only used in "u1_init()" function.

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 67 --
 1 file changed, 27 insertions(+), 40 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 201fe175cba3..4c323b58e009 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -61,14 +61,10 @@
  * @input2: pointer to the kernel input2 device
  * @hdev: pointer to the struct hid_device
  *
- * @dev_ctrl: device control parameter
  * @dev_type: device type
- * @sen_line_num_x: number of sensor line of X
- * @sen_line_num_y: number of sensor line of Y
- * @pitch_x: sensor pitch of X
- * @pitch_y: sensor pitch of Y
- * @resolution: resolution
- * @btn_info: button information
+ * @max_fingers: total number of fingers
+ * @has_sp: boolean of sp existense
+ * @sp_btn_info: button information
  * @x_active_len_mm: active area length of X (mm)
  * @y_active_len_mm: active area length of Y (mm)
  * @x_max: maximum x coordinate value
@@ -77,22 +73,14 @@
  * @y_min: minimum y coordinate value
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
- * @has_sp: boolean of sp existense
- * @max_fingers: total number of fingers
  */
 struct u1_dev {
struct input_dev *input;
struct input_dev *input2;
struct hid_device *hdev;
 
-   u8  dev_ctrl;
-   u8  dev_type;
-   u8  sen_line_num_x;
-   u8  sen_line_num_y;
-   u8  pitch_x;
-   u8  pitch_y;
-   u8  resolution;
-   u8  btn_info;
+   u8  max_fingers;
+   u8  has_sp;
u8  sp_btn_info;
u32 x_active_len_mm;
u32 y_active_len_mm;
@@ -102,8 +90,6 @@ struct u1_dev {
u32 y_min;
u32 btn_cnt;
u32 sp_btn_cnt;
-   u8  has_sp;
-   u8  max_fingers;
 };
 
 static int u1_read_write_register(struct hid_device *hdev, u32 address,
@@ -266,78 +252,80 @@ static int alps_post_resume(struct hid_device *hdev)
 static int u1_init(struct hid_device *hdev, struct u1_dev *pri_data)
 {
int ret;
+   u8 tmp, dev_ctrl, sen_line_num_x, sen_line_num_y;
+   u8 pitch_x, pitch_y, resolution;
 
/* Device initialization */
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   _data->dev_ctrl, 0, true);
+   _ctrl, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_DEV_CTRL_1 (%d)\n", ret);
goto exit;
}
 
-   pri_data->dev_ctrl &= ~U1_DISABLE_DEV;
-   pri_data->dev_ctrl |= U1_TP_ABS_MODE;
+   dev_ctrl &= ~U1_DISABLE_DEV;
+   dev_ctrl |= U1_TP_ABS_MODE;
ret = u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1,
-   NULL, pri_data->dev_ctrl, false);
+   NULL, dev_ctrl, false);
if (ret < 0) {
dev_err(>dev, "failed to change TP mode (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_X,
-   _data->sen_line_num_x, 0, true);
+   _line_num_x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_NUM_SENS_Y,
-   _data->sen_line_num_y, 0, true);
+   _line_num_y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_NUM_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_X,
-   _data->pitch_x, 0, true);
+   _x, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_X (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PITCH_SENS_Y,
-   _data->pitch_y, 0, true);
+   _y, 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_PITCH_SENS_Y (%d)\n", ret);
goto exit;
}
 
ret = u1_read_write_register(hdev, ADDRESS_U1_RESO_DWN_ABS,
-   _data->resolution, 0, true);
+   , 0, true);
if (ret < 0) {
dev_err(>dev, "failed U1_RESO_DWN_ABS (%d)\n", ret);
goto exit;
}
pri_data->x_active_len_mm =
-   (pri_data->pitch_x * (pri_data->sen_line_num_x - 1)) / 10;
+   (pitch_x * (sen_line_num_x - 1)) / 10;
pri_data->y_active_len_mm =
-   (pri_data->pitch_y * (pri_data->sen_line_num_y - 1)) / 10;
+   (pitch_y * (sen_line_num_y - 1)) / 

[PATCH 6/7] Add new U1 device ID

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Add new U1 device Product ID
-This device is used on HP Elite book x360 series

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 3 +++
 drivers/hid/hid-core.c | 1 +
 drivers/hid/hid-ids.h  | 1 +
 3 files changed, 5 insertions(+)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 5ae2cba8fe76..b1eeb4839bfc 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -767,6 +767,7 @@ static int alps_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
data->dev_type = T4;
break;
case HID_DEVICE_ID_ALPS_U1_DUAL:
+   case HID_DEVICE_ID_ALPS_U1:
data->dev_type = U1;
break;
default:
@@ -791,6 +792,8 @@ static const struct hid_device_id alps_id[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
+   USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
+   { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) },
{ }
 };
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9c3cb2e467e9..779e26cb3ba9 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1775,6 +1775,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
+   { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) 
},
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) 
},
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 
USB_DEVICE_ID_APPLE_MAGICMOUSE) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 0b9726d321ee..2b50d12b993e 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -75,6 +75,7 @@
 
 #define USB_VENDOR_ID_ALPS_JP  0x044E
 #define HID_DEVICE_ID_ALPS_U1_DUAL 0x120B
+#define HID_DEVICE_ID_ALPS_U1  0x1215
 #define HID_DEVICE_ID_ALPS_T4_BTNLESS  0x120C
 
 #define USB_VENDOR_ID_AMI  0x046b
-- 
2.11.0



[PATCH 6/7] Add new U1 device ID

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Add new U1 device Product ID
-This device is used on HP Elite book x360 series

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 3 +++
 drivers/hid/hid-core.c | 1 +
 drivers/hid/hid-ids.h  | 1 +
 3 files changed, 5 insertions(+)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 5ae2cba8fe76..b1eeb4839bfc 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -767,6 +767,7 @@ static int alps_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
data->dev_type = T4;
break;
case HID_DEVICE_ID_ALPS_U1_DUAL:
+   case HID_DEVICE_ID_ALPS_U1:
data->dev_type = U1;
break;
default:
@@ -791,6 +792,8 @@ static const struct hid_device_id alps_id[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
+   USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
+   { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) },
{ }
 };
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 9c3cb2e467e9..779e26cb3ba9 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1775,6 +1775,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
+   { HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) 
},
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) 
},
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 
USB_DEVICE_ID_APPLE_MAGICMOUSE) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 0b9726d321ee..2b50d12b993e 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -75,6 +75,7 @@
 
 #define USB_VENDOR_ID_ALPS_JP  0x044E
 #define HID_DEVICE_ID_ALPS_U1_DUAL 0x120B
+#define HID_DEVICE_ID_ALPS_U1  0x1215
 #define HID_DEVICE_ID_ALPS_T4_BTNLESS  0x120C
 
 #define USB_VENDOR_ID_AMI  0x046b
-- 
2.11.0



[PATCH 5/7] Support Alps T4 Touchpad device

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Define T4 device specification value for support T4 device.
-Create "t4_contact_data" and "t4_input_report" structure for decode T4 data 
and store it.
-Create "t4_calc_check_sum()" function for calculate checksum value to send the 
device. T4 needs to send this value when read/write device address value.
-Create "t4_read_write_register()" function for read/write device address value.
-Create "t4_raw_event()" function for decode device XYZ data, palm and button 
data.
-Replace "MAX_TOUCHES" fixed variable to "max_fingers" variable.
-Add T4 devuce product ID. (0x120C)
-T4 device is used on HP EliteBook 1000 series and Zbook Stduio

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 339 ++---
 drivers/hid/hid-core.c |   3 +-
 drivers/hid/hid-ids.h  |   1 +
 3 files changed, 322 insertions(+), 21 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 4c323b58e009..5ae2cba8fe76 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -52,8 +52,30 @@
 #define ADDRESS_U1_PAD_BTN 0x00800052
 #define ADDRESS_U1_SP_BTN  0x0080009F
 
+#define T4_INPUT_REPORT_LENsizeof(struct t4_input_report)
+#define T4_FEATURE_REPORT_LEN  T4_INPUT_REPORT_LEN
+#define T4_FEATURE_REPORT_ID   7
+#define T4_CMD_REGISTER_READ   0x08
+#define T4_CMD_REGISTER_WRITE  0x07
+
+#define T4_ADDRESS_BASE0xC2C0
+#define PRM_SYS_CONFIG_1   (T4_ADDRESS_BASE + 0x0002)
+#define T4_PRM_FEED_CONFIG_1   (T4_ADDRESS_BASE + 0x0004)
+#define T4_PRM_FEED_CONFIG_4   (T4_ADDRESS_BASE + 0x001A)
+#define T4_PRM_ID_CONFIG_3 (T4_ADDRESS_BASE + 0x00B0)
+
+
+#define T4_FEEDCFG4_ADVANCED_ABS_ENABLE0x01
+#define T4_I2C_ABS 0x78
+
+#define T4_COUNT_PER_ELECTRODE 256
 #define MAX_TOUCHES5
 
+enum dev_num {
+   U1,
+   T4,
+   UNKNOWN,
+};
 /**
  * struct u1_data
  *
@@ -74,11 +96,12 @@
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
  */
-struct u1_dev {
+struct alps_dev {
struct input_dev *input;
struct input_dev *input2;
struct hid_device *hdev;
 
+   enum dev_num dev_type;
u8  max_fingers;
u8  has_sp;
u8  sp_btn_info;
@@ -92,6 +115,141 @@ struct u1_dev {
u32 sp_btn_cnt;
 };
 
+struct t4_contact_data {
+   u8  palm;
+   u8  x_lo;
+   u8  x_hi;
+   u8  y_lo;
+   u8  y_hi;
+};
+
+struct t4_input_report {
+   u8  reportID;
+   u8  numContacts;
+   struct t4_contact_data contact[5];
+   u8  button;
+   u8  track[5];
+   u8  zx[5], zy[5];
+   u8  palmTime[5];
+   u8  kilroy;
+   u16 timeStamp;
+};
+
+static u16 t4_calc_check_sum(u8 *buffer,
+   unsigned long offset, unsigned long length)
+{
+   u16 sum1 = 0xFF, sum2 = 0xFF;
+   unsigned long i = 0;
+
+   if (offset + length >= 50)
+   return 0;
+
+   while (length > 0) {
+   u32 tlen = length > 20 ? 20 : length;
+
+   length -= tlen;
+
+   do {
+   sum1 += buffer[offset + i];
+   sum2 += sum1;
+   i++;
+   } while (--tlen > 0);
+
+   sum1 = (sum1 & 0xFF) + (sum1 >> 8);
+   sum2 = (sum2 & 0xFF) + (sum2 >> 8);
+   }
+
+   sum1 = (sum1 & 0xFF) + (sum1 >> 8);
+   sum2 = (sum2 & 0xFF) + (sum2 >> 8);
+
+   return(sum2 << 8 | sum1);
+}
+
+static int t4_read_write_register(struct hid_device *hdev, u32 address,
+   u8 *read_val, u8 write_val, bool read_flag)
+{
+   int ret;
+   u16 check_sum;
+   u8 *input;
+   u8 *readbuf;
+
+   input = kzalloc(T4_FEATURE_REPORT_LEN, GFP_KERNEL);
+   if (!input)
+   return -ENOMEM;
+
+   input[0] = T4_FEATURE_REPORT_ID;
+   if (read_flag) {
+   input[1] = T4_CMD_REGISTER_READ;
+   input[8] = 0x00;
+   } else {
+   input[1] = T4_CMD_REGISTER_WRITE;
+   input[8] = write_val;
+   }
+   put_unaligned_le32(address, input + 2);
+   input[6] = 1;
+   input[7] = 0;
+
+   /* Calculate the checksum */
+   check_sum = t4_calc_check_sum(input, 1, 8);
+   input[9] = (u8)check_sum;
+   input[10] = (u8)(check_sum >> 8);
+   input[11] = 0;
+
+   ret = hid_hw_raw_request(hdev, T4_FEATURE_REPORT_ID, input,
+   T4_FEATURE_REPORT_LEN,
+   HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+   if (ret < 0) {
+   dev_err(>dev, "failed to read command (%d)\n", ret);
+   goto exit;
+   }
+
+   readbuf = kzalloc(T4_FEATURE_REPORT_LEN, GFP_KERNEL);
+   if (read_flag) {
+   if 

[PATCH 5/7] Support Alps T4 Touchpad device

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Define T4 device specification value for support T4 device.
-Create "t4_contact_data" and "t4_input_report" structure for decode T4 data 
and store it.
-Create "t4_calc_check_sum()" function for calculate checksum value to send the 
device. T4 needs to send this value when read/write device address value.
-Create "t4_read_write_register()" function for read/write device address value.
-Create "t4_raw_event()" function for decode device XYZ data, palm and button 
data.
-Replace "MAX_TOUCHES" fixed variable to "max_fingers" variable.
-Add T4 devuce product ID. (0x120C)
-T4 device is used on HP EliteBook 1000 series and Zbook Stduio

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 339 ++---
 drivers/hid/hid-core.c |   3 +-
 drivers/hid/hid-ids.h  |   1 +
 3 files changed, 322 insertions(+), 21 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index 4c323b58e009..5ae2cba8fe76 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -52,8 +52,30 @@
 #define ADDRESS_U1_PAD_BTN 0x00800052
 #define ADDRESS_U1_SP_BTN  0x0080009F
 
+#define T4_INPUT_REPORT_LENsizeof(struct t4_input_report)
+#define T4_FEATURE_REPORT_LEN  T4_INPUT_REPORT_LEN
+#define T4_FEATURE_REPORT_ID   7
+#define T4_CMD_REGISTER_READ   0x08
+#define T4_CMD_REGISTER_WRITE  0x07
+
+#define T4_ADDRESS_BASE0xC2C0
+#define PRM_SYS_CONFIG_1   (T4_ADDRESS_BASE + 0x0002)
+#define T4_PRM_FEED_CONFIG_1   (T4_ADDRESS_BASE + 0x0004)
+#define T4_PRM_FEED_CONFIG_4   (T4_ADDRESS_BASE + 0x001A)
+#define T4_PRM_ID_CONFIG_3 (T4_ADDRESS_BASE + 0x00B0)
+
+
+#define T4_FEEDCFG4_ADVANCED_ABS_ENABLE0x01
+#define T4_I2C_ABS 0x78
+
+#define T4_COUNT_PER_ELECTRODE 256
 #define MAX_TOUCHES5
 
+enum dev_num {
+   U1,
+   T4,
+   UNKNOWN,
+};
 /**
  * struct u1_data
  *
@@ -74,11 +96,12 @@
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
  */
-struct u1_dev {
+struct alps_dev {
struct input_dev *input;
struct input_dev *input2;
struct hid_device *hdev;
 
+   enum dev_num dev_type;
u8  max_fingers;
u8  has_sp;
u8  sp_btn_info;
@@ -92,6 +115,141 @@ struct u1_dev {
u32 sp_btn_cnt;
 };
 
+struct t4_contact_data {
+   u8  palm;
+   u8  x_lo;
+   u8  x_hi;
+   u8  y_lo;
+   u8  y_hi;
+};
+
+struct t4_input_report {
+   u8  reportID;
+   u8  numContacts;
+   struct t4_contact_data contact[5];
+   u8  button;
+   u8  track[5];
+   u8  zx[5], zy[5];
+   u8  palmTime[5];
+   u8  kilroy;
+   u16 timeStamp;
+};
+
+static u16 t4_calc_check_sum(u8 *buffer,
+   unsigned long offset, unsigned long length)
+{
+   u16 sum1 = 0xFF, sum2 = 0xFF;
+   unsigned long i = 0;
+
+   if (offset + length >= 50)
+   return 0;
+
+   while (length > 0) {
+   u32 tlen = length > 20 ? 20 : length;
+
+   length -= tlen;
+
+   do {
+   sum1 += buffer[offset + i];
+   sum2 += sum1;
+   i++;
+   } while (--tlen > 0);
+
+   sum1 = (sum1 & 0xFF) + (sum1 >> 8);
+   sum2 = (sum2 & 0xFF) + (sum2 >> 8);
+   }
+
+   sum1 = (sum1 & 0xFF) + (sum1 >> 8);
+   sum2 = (sum2 & 0xFF) + (sum2 >> 8);
+
+   return(sum2 << 8 | sum1);
+}
+
+static int t4_read_write_register(struct hid_device *hdev, u32 address,
+   u8 *read_val, u8 write_val, bool read_flag)
+{
+   int ret;
+   u16 check_sum;
+   u8 *input;
+   u8 *readbuf;
+
+   input = kzalloc(T4_FEATURE_REPORT_LEN, GFP_KERNEL);
+   if (!input)
+   return -ENOMEM;
+
+   input[0] = T4_FEATURE_REPORT_ID;
+   if (read_flag) {
+   input[1] = T4_CMD_REGISTER_READ;
+   input[8] = 0x00;
+   } else {
+   input[1] = T4_CMD_REGISTER_WRITE;
+   input[8] = write_val;
+   }
+   put_unaligned_le32(address, input + 2);
+   input[6] = 1;
+   input[7] = 0;
+
+   /* Calculate the checksum */
+   check_sum = t4_calc_check_sum(input, 1, 8);
+   input[9] = (u8)check_sum;
+   input[10] = (u8)(check_sum >> 8);
+   input[11] = 0;
+
+   ret = hid_hw_raw_request(hdev, T4_FEATURE_REPORT_ID, input,
+   T4_FEATURE_REPORT_LEN,
+   HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+   if (ret < 0) {
+   dev_err(>dev, "failed to read command (%d)\n", ret);
+   goto exit;
+   }
+
+   readbuf = kzalloc(T4_FEATURE_REPORT_LEN, GFP_KERNEL);
+   if (read_flag) {
+   if (!readbuf) {
+   ret = 

[PATCH 3/7] Add some variables

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Create x_min, y_min and max_fingers variables for set correct XY minimum value 
and the number of max finger on each devices.
-Move the Button pad checking code to U1 init function, because this checking 
code is for U1 device.

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 38 --
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index c4ea5c6c9be9..201fe175cba3 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -73,9 +73,12 @@
  * @y_active_len_mm: active area length of Y (mm)
  * @x_max: maximum x coordinate value
  * @y_max: maximum y coordinate value
+ * @x_min: minimum x coordinate value
+ * @y_min: minimum y coordinate value
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
  * @has_sp: boolean of sp existense
+ * @max_fingers: total number of fingers
  */
 struct u1_dev {
struct input_dev *input;
@@ -95,9 +98,12 @@ struct u1_dev {
u32 y_active_len_mm;
u32 x_max;
u32 y_max;
+   u32 x_min;
+   u32 y_min;
u32 btn_cnt;
u32 sp_btn_cnt;
u8  has_sp;
+   u8  max_fingers;
 };
 
 static int u1_read_write_register(struct hid_device *hdev, u32 address,
@@ -319,8 +325,10 @@ static int u1_init(struct hid_device *hdev, struct u1_dev 
*pri_data)
 
pri_data->x_max =
(pri_data->resolution << 2) * (pri_data->sen_line_num_x - 1);
+   pri_data->x_min = 1;
pri_data->y_max =
(pri_data->resolution << 2) * (pri_data->sen_line_num_y - 1);
+   pri_data->y_min = 1;
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
_data->btn_info, 0, true);
@@ -328,6 +336,12 @@ static int u1_init(struct hid_device *hdev, struct u1_dev 
*pri_data)
dev_err(>dev, "failed U1_PAD_BTN (%d)\n", ret);
goto exit;
}
+   if ((pri_data->btn_info & 0x0F) == (pri_data->btn_info & 0xF0) >> 4) {
+   pri_data->btn_cnt = (pri_data->btn_info & 0x0F);
+   } else {
+   /* Button pad */
+   pri_data->btn_cnt = 1;
+   }
 
pri_data->has_sp = 0;
/* Check StickPointer device */
@@ -355,7 +369,7 @@ static int u1_init(struct hid_device *hdev, struct u1_dev 
*pri_data)
}
pri_data->has_sp = 1;
}
-
+   pri_data->max_fingers = 5;
 exit:
return ret;
 }
@@ -383,8 +397,10 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
goto exit;
 
__set_bit(EV_ABS, input->evbit);
-   input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->x_max, 0, 0);
-   input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->y_max, 0, 0);
+   input_set_abs_params(input, ABS_MT_POSITION_X,
+   data->x_min, data->x_max, 0, 0);
+   input_set_abs_params(input, ABS_MT_POSITION_Y,
+   data->y_min, data->y_max, 0, 0);
 
if (data->x_active_len_mm && data->y_active_len_mm) {
res_x = (data->x_max - 1) / data->x_active_len_mm;
@@ -396,26 +412,21 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 64, 0, 0);
 
-   input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_POINTER);
+   input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
 
__set_bit(EV_KEY, input->evbit);
-   if ((data->btn_info & 0x0F) == (data->btn_info & 0xF0) >> 4) {
-   data->btn_cnt = (data->btn_info & 0x0F);
-   } else {
-   /* Button pad */
-   data->btn_cnt = 1;
+
+   if (data->btn_cnt == 1)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
-   }
 
for (i = 0; i < data->btn_cnt; i++)
__set_bit(BTN_LEFT + i, input->keybit);
 
-
/* Stick device initialization */
if (data->has_sp) {
input2 = input_allocate_device();
if (!input2) {
-   ret = -ENOMEM;
+   input_free_device(input2);
goto exit;
}
 
@@ -439,8 +450,7 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
__set_bit(INPUT_PROP_POINTER, input2->propbit);
__set_bit(INPUT_PROP_POINTING_STICK, input2->propbit);
 
-   ret = input_register_device(data->input2);
-   if (ret) {
+   if (input_register_device(data->input2)) {
input_free_device(input2);
goto exit;
}
-- 
2.11.0



[PATCH 7/7] Support Alps U1 USB Touchpad device

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Add T4 USB device Product ID. (0x1216)
-Separate T4 USB device initialization code from T4 Standard device code. 
-T4 USB device is used on HP Elite x2 series

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 35 +--
 drivers/hid/hid-core.c |  1 +
 drivers/hid/hid-ids.h  |  1 +
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index b1eeb4839bfc..939ae8255805 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -440,6 +440,7 @@ static int alps_raw_event(struct hid_device *hdev,
 
switch (hdev->product) {
case HID_PRODUCT_ID_T4_BTNLESS:
+   case HID_DEVICE_ID_ALPS_T4_USB:
ret = t4_raw_event(hdata, data, size);
break;
default:
@@ -594,13 +595,29 @@ static int T4_init(struct hid_device *hdev, struct 
alps_dev *pri_data)
int ret;
u8 tmp, sen_line_num_x, sen_line_num_y;
 
-   ret = t4_read_write_register(hdev, T4_PRM_ID_CONFIG_3, , 0, true);
-   if (ret < 0) {
-   dev_err(>dev, "failed T4_PRM_ID_CONFIG_3 (%d)\n", ret);
+   if (hdev->product == HID_DEVICE_ID_ALPS_T4_BTNLESS) {
+   ret = t4_read_write_register(hdev,
+   T4_PRM_ID_CONFIG_3, , 0, true);
+   if (ret < 0) {
+   dev_err(>dev,
+   "failed T4_PRM_ID_CONFIG_3 (%d)\n", ret);
goto exit;
+   }
+   sen_line_num_x = 16 + ((tmp & 0x0F)  | (tmp & 0x08 ? 0xF0 : 0));
+   sen_line_num_y =
+   12 + (((tmp & 0xF0) >> 4)  | (tmp & 0x80 ? 0xF0 : 0));
+
+   ret = t4_read_write_register(hdev,
+   PRM_SYS_CONFIG_1, , 0, true);
+   if (ret < 0) {
+   dev_err(>dev,
+   "failed PRM_SYS_CONFIG_1 (%d)\n", ret);
+   goto exit;
+   }
+   } else {
+   sen_line_num_x = 20;
+   sen_line_num_y = 12;
}
-   sen_line_num_x = 16 + ((tmp & 0x0F)  | (tmp & 0x08 ? 0xF0 : 0));
-   sen_line_num_y = 12 + (((tmp & 0xF0) >> 4)  | (tmp & 0x80 ? 0xF0 : 0));
 
pri_data->x_max = sen_line_num_x * T4_COUNT_PER_ELECTRODE;
pri_data->x_min = T4_COUNT_PER_ELECTRODE;
@@ -609,11 +626,6 @@ static int T4_init(struct hid_device *hdev, struct 
alps_dev *pri_data)
pri_data->x_active_len_mm = pri_data->y_active_len_mm = 0;
pri_data->btn_cnt = 1;
 
-   ret = t4_read_write_register(hdev, PRM_SYS_CONFIG_1, , 0, true);
-   if (ret < 0) {
-   dev_err(>dev, "failed PRM_SYS_CONFIG_1 (%d)\n", ret);
-   goto exit;
-   }
tmp |= 0x02;
ret = t4_read_write_register(hdev, PRM_SYS_CONFIG_1, NULL, tmp, false);
if (ret < 0) {
@@ -764,6 +776,7 @@ static int alps_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 
switch (hdev->product) {
case HID_DEVICE_ID_ALPS_T4_BTNLESS:
+   case HID_DEVICE_ID_ALPS_T4_USB:
data->dev_type = T4;
break;
case HID_DEVICE_ID_ALPS_U1_DUAL:
@@ -795,6 +808,8 @@ static const struct hid_device_id alps_id[] = {
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) },
+   { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
+   USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_USB) },
{ }
 };
 MODULE_DEVICE_TABLE(hid, alps_id);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 779e26cb3ba9..13ded460885e 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1777,6 +1777,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) 
},
+   { HID_USB_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_USB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) 
},
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 
USB_DEVICE_ID_APPLE_MAGICMOUSE) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 
USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 2b50d12b993e..71c2a021e296 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -76,6 +76,7 @@
 #define USB_VENDOR_ID_ALPS_JP  0x044E
 #define HID_DEVICE_ID_ALPS_U1_DUAL 0x120B
 #define HID_DEVICE_ID_ALPS_U1  0x1215
+#define HID_DEVICE_ID_ALPS_T4_USB  0x1216
 #define HID_DEVICE_ID_ALPS_T4_BTNLESS  0x120C
 
 #define USB_VENDOR_ID_AMI  0x046b
-- 

[PATCH 7/7] Support Alps U1 USB Touchpad device

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Add T4 USB device Product ID. (0x1216)
-Separate T4 USB device initialization code from T4 Standard device code. 
-T4 USB device is used on HP Elite x2 series

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 35 +--
 drivers/hid/hid-core.c |  1 +
 drivers/hid/hid-ids.h  |  1 +
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index b1eeb4839bfc..939ae8255805 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -440,6 +440,7 @@ static int alps_raw_event(struct hid_device *hdev,
 
switch (hdev->product) {
case HID_PRODUCT_ID_T4_BTNLESS:
+   case HID_DEVICE_ID_ALPS_T4_USB:
ret = t4_raw_event(hdata, data, size);
break;
default:
@@ -594,13 +595,29 @@ static int T4_init(struct hid_device *hdev, struct 
alps_dev *pri_data)
int ret;
u8 tmp, sen_line_num_x, sen_line_num_y;
 
-   ret = t4_read_write_register(hdev, T4_PRM_ID_CONFIG_3, , 0, true);
-   if (ret < 0) {
-   dev_err(>dev, "failed T4_PRM_ID_CONFIG_3 (%d)\n", ret);
+   if (hdev->product == HID_DEVICE_ID_ALPS_T4_BTNLESS) {
+   ret = t4_read_write_register(hdev,
+   T4_PRM_ID_CONFIG_3, , 0, true);
+   if (ret < 0) {
+   dev_err(>dev,
+   "failed T4_PRM_ID_CONFIG_3 (%d)\n", ret);
goto exit;
+   }
+   sen_line_num_x = 16 + ((tmp & 0x0F)  | (tmp & 0x08 ? 0xF0 : 0));
+   sen_line_num_y =
+   12 + (((tmp & 0xF0) >> 4)  | (tmp & 0x80 ? 0xF0 : 0));
+
+   ret = t4_read_write_register(hdev,
+   PRM_SYS_CONFIG_1, , 0, true);
+   if (ret < 0) {
+   dev_err(>dev,
+   "failed PRM_SYS_CONFIG_1 (%d)\n", ret);
+   goto exit;
+   }
+   } else {
+   sen_line_num_x = 20;
+   sen_line_num_y = 12;
}
-   sen_line_num_x = 16 + ((tmp & 0x0F)  | (tmp & 0x08 ? 0xF0 : 0));
-   sen_line_num_y = 12 + (((tmp & 0xF0) >> 4)  | (tmp & 0x80 ? 0xF0 : 0));
 
pri_data->x_max = sen_line_num_x * T4_COUNT_PER_ELECTRODE;
pri_data->x_min = T4_COUNT_PER_ELECTRODE;
@@ -609,11 +626,6 @@ static int T4_init(struct hid_device *hdev, struct 
alps_dev *pri_data)
pri_data->x_active_len_mm = pri_data->y_active_len_mm = 0;
pri_data->btn_cnt = 1;
 
-   ret = t4_read_write_register(hdev, PRM_SYS_CONFIG_1, , 0, true);
-   if (ret < 0) {
-   dev_err(>dev, "failed PRM_SYS_CONFIG_1 (%d)\n", ret);
-   goto exit;
-   }
tmp |= 0x02;
ret = t4_read_write_register(hdev, PRM_SYS_CONFIG_1, NULL, tmp, false);
if (ret < 0) {
@@ -764,6 +776,7 @@ static int alps_probe(struct hid_device *hdev, const struct 
hid_device_id *id)
 
switch (hdev->product) {
case HID_DEVICE_ID_ALPS_T4_BTNLESS:
+   case HID_DEVICE_ID_ALPS_T4_USB:
data->dev_type = T4;
break;
case HID_DEVICE_ID_ALPS_U1_DUAL:
@@ -795,6 +808,8 @@ static const struct hid_device_id alps_id[] = {
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) },
+   { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
+   USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_USB) },
{ }
 };
 MODULE_DEVICE_TABLE(hid, alps_id);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 779e26cb3ba9..13ded460885e 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1777,6 +1777,7 @@ static const struct hid_device_id 
hid_have_special_driver[] = {
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) 
},
+   { HID_USB_DEVICE(USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_USB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) 
},
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 
USB_DEVICE_ID_APPLE_MAGICMOUSE) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 
USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 2b50d12b993e..71c2a021e296 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -76,6 +76,7 @@
 #define USB_VENDOR_ID_ALPS_JP  0x044E
 #define HID_DEVICE_ID_ALPS_U1_DUAL 0x120B
 #define HID_DEVICE_ID_ALPS_U1  0x1215
+#define HID_DEVICE_ID_ALPS_T4_USB  0x1216
 #define HID_DEVICE_ID_ALPS_T4_BTNLESS  0x120C
 
 #define USB_VENDOR_ID_AMI  0x046b
-- 
2.11.0



[PATCH 3/7] Add some variables

2017-10-05 Thread Masaki Ota
From: Masaki Ota 
-Create x_min, y_min and max_fingers variables for set correct XY minimum value 
and the number of max finger on each devices.
-Move the Button pad checking code to U1 init function, because this checking 
code is for U1 device.

Signed-off-by: Masaki Ota 
---
 drivers/hid/hid-alps.c | 38 --
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index c4ea5c6c9be9..201fe175cba3 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -73,9 +73,12 @@
  * @y_active_len_mm: active area length of Y (mm)
  * @x_max: maximum x coordinate value
  * @y_max: maximum y coordinate value
+ * @x_min: minimum x coordinate value
+ * @y_min: minimum y coordinate value
  * @btn_cnt: number of buttons
  * @sp_btn_cnt: number of stick buttons
  * @has_sp: boolean of sp existense
+ * @max_fingers: total number of fingers
  */
 struct u1_dev {
struct input_dev *input;
@@ -95,9 +98,12 @@ struct u1_dev {
u32 y_active_len_mm;
u32 x_max;
u32 y_max;
+   u32 x_min;
+   u32 y_min;
u32 btn_cnt;
u32 sp_btn_cnt;
u8  has_sp;
+   u8  max_fingers;
 };
 
 static int u1_read_write_register(struct hid_device *hdev, u32 address,
@@ -319,8 +325,10 @@ static int u1_init(struct hid_device *hdev, struct u1_dev 
*pri_data)
 
pri_data->x_max =
(pri_data->resolution << 2) * (pri_data->sen_line_num_x - 1);
+   pri_data->x_min = 1;
pri_data->y_max =
(pri_data->resolution << 2) * (pri_data->sen_line_num_y - 1);
+   pri_data->y_min = 1;
 
ret = u1_read_write_register(hdev, ADDRESS_U1_PAD_BTN,
_data->btn_info, 0, true);
@@ -328,6 +336,12 @@ static int u1_init(struct hid_device *hdev, struct u1_dev 
*pri_data)
dev_err(>dev, "failed U1_PAD_BTN (%d)\n", ret);
goto exit;
}
+   if ((pri_data->btn_info & 0x0F) == (pri_data->btn_info & 0xF0) >> 4) {
+   pri_data->btn_cnt = (pri_data->btn_info & 0x0F);
+   } else {
+   /* Button pad */
+   pri_data->btn_cnt = 1;
+   }
 
pri_data->has_sp = 0;
/* Check StickPointer device */
@@ -355,7 +369,7 @@ static int u1_init(struct hid_device *hdev, struct u1_dev 
*pri_data)
}
pri_data->has_sp = 1;
}
-
+   pri_data->max_fingers = 5;
 exit:
return ret;
 }
@@ -383,8 +397,10 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
goto exit;
 
__set_bit(EV_ABS, input->evbit);
-   input_set_abs_params(input, ABS_MT_POSITION_X, 1, data->x_max, 0, 0);
-   input_set_abs_params(input, ABS_MT_POSITION_Y, 1, data->y_max, 0, 0);
+   input_set_abs_params(input, ABS_MT_POSITION_X,
+   data->x_min, data->x_max, 0, 0);
+   input_set_abs_params(input, ABS_MT_POSITION_Y,
+   data->y_min, data->y_max, 0, 0);
 
if (data->x_active_len_mm && data->y_active_len_mm) {
res_x = (data->x_max - 1) / data->x_active_len_mm;
@@ -396,26 +412,21 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
 
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 64, 0, 0);
 
-   input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_POINTER);
+   input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
 
__set_bit(EV_KEY, input->evbit);
-   if ((data->btn_info & 0x0F) == (data->btn_info & 0xF0) >> 4) {
-   data->btn_cnt = (data->btn_info & 0x0F);
-   } else {
-   /* Button pad */
-   data->btn_cnt = 1;
+
+   if (data->btn_cnt == 1)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
-   }
 
for (i = 0; i < data->btn_cnt; i++)
__set_bit(BTN_LEFT + i, input->keybit);
 
-
/* Stick device initialization */
if (data->has_sp) {
input2 = input_allocate_device();
if (!input2) {
-   ret = -ENOMEM;
+   input_free_device(input2);
goto exit;
}
 
@@ -439,8 +450,7 @@ static int alps_input_configured(struct hid_device *hdev, 
struct hid_input *hi)
__set_bit(INPUT_PROP_POINTER, input2->propbit);
__set_bit(INPUT_PROP_POINTING_STICK, input2->propbit);
 
-   ret = input_register_device(data->input2);
-   if (ret) {
+   if (input_register_device(data->input2)) {
input_free_device(input2);
goto exit;
}
-- 
2.11.0



[PATCH v5 4/5] cramfs: add mmap support

2017-10-05 Thread Nicolas Pitre
When cramfs_physmem is used then we have the opportunity to map files
directly from ROM, directly into user space, saving on RAM usage.
This gives us Execute-In-Place (XIP) support.

For a file to be mmap()-able, the map area has to correspond to a range
of uncompressed and contiguous blocks, and in the MMU case it also has
to be page aligned. A version of mkcramfs with appropriate support is
necessary to create such a filesystem image.

In the MMU case it may happen for a vma structure to extend beyond the
actual file size. This is notably the case in binfmt_elf.c:elf_map().
Or the file's last block is shared with other files and cannot be mapped
as is. Rather than refusing to mmap it, we do a "mixed" map and let the
regular fault handler populate the unmapped area with RAM-backed pages.
In practice the unmapped area is seldom accessed so page faults might
never occur before this area is discarded.

In the non-MMU case it is the get_unmapped_area method that is responsible
for providing the address where the actual data can be found. No mapping
is necessary of course.

Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 fs/cramfs/inode.c | 194 ++
 1 file changed, 194 insertions(+)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 6aa1d94ed8..071ce1eb58 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -15,7 +15,10 @@
 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -49,6 +52,7 @@ static inline struct cramfs_sb_info *CRAMFS_SB(struct 
super_block *sb)
 static const struct super_operations cramfs_ops;
 static const struct inode_operations cramfs_dir_inode_operations;
 static const struct file_operations cramfs_directory_operations;
+static const struct file_operations cramfs_physmem_fops;
 static const struct address_space_operations cramfs_aops;
 
 static DEFINE_MUTEX(read_mutex);
@@ -96,6 +100,10 @@ static struct inode *get_cramfs_inode(struct super_block 
*sb,
case S_IFREG:
inode->i_fop = _ro_fops;
inode->i_data.a_ops = _aops;
+   if (IS_ENABLED(CONFIG_CRAMFS_PHYSMEM) &&
+   CRAMFS_SB(sb)->flags & CRAMFS_FLAG_EXT_BLOCK_POINTERS &&
+   CRAMFS_SB(sb)->linear_phys_addr)
+   inode->i_fop = _physmem_fops;
break;
case S_IFDIR:
inode->i_op = _dir_inode_operations;
@@ -277,6 +285,192 @@ static void *cramfs_read(struct super_block *sb, unsigned 
int offset,
return NULL;
 }
 
+/*
+ * For a mapping to be possible, we need a range of uncompressed and
+ * contiguous blocks. Return the offset for the first block and number of
+ * valid blocks for which that is true, or zero otherwise.
+ */
+static u32 cramfs_get_block_range(struct inode *inode, u32 pgoff, u32 *pages)
+{
+   struct super_block *sb = inode->i_sb;
+   struct cramfs_sb_info *sbi = CRAMFS_SB(sb);
+   int i;
+   u32 *blockptrs, first_block_addr;
+
+   /*
+* We can dereference memory directly here as this code may be
+* reached only when there is a direct filesystem image mapping
+* available in memory.
+*/
+   blockptrs = (u32 *)(sbi->linear_virt_addr + OFFSET(inode) + pgoff * 4);
+   first_block_addr = blockptrs[0] & ~CRAMFS_BLK_FLAGS;
+   i = 0;
+   do {
+   u32 block_off = i * (PAGE_SIZE >> CRAMFS_BLK_DIRECT_PTR_SHIFT);
+   u32 expect = (first_block_addr + block_off) |
+CRAMFS_BLK_FLAG_DIRECT_PTR |
+CRAMFS_BLK_FLAG_UNCOMPRESSED;
+   if (blockptrs[i] != expect) {
+   pr_debug("range: block %d/%d got %#x expects %#x\n",
+pgoff+i, pgoff + *pages - 1,
+blockptrs[i], expect);
+   if (i == 0)
+   return 0;
+   break;
+   }
+   } while (++i < *pages);
+
+   *pages = i;
+   return first_block_addr << CRAMFS_BLK_DIRECT_PTR_SHIFT;
+}
+
+#ifdef CONFIG_MMU
+
+static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+   struct inode *inode = file_inode(file);
+   struct super_block *sb = inode->i_sb;
+   struct cramfs_sb_info *sbi = CRAMFS_SB(sb);
+   unsigned int pages, max_pages, offset;
+   unsigned long address, pgoff = vma->vm_pgoff;
+   char *bailout_reason;
+   int ret;
+
+   if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
+   return -EINVAL;
+
+   /* Could COW work here? */
+   bailout_reason = "vma is writable";
+   if (vma->vm_flags & VM_WRITE)
+   goto bailout;
+
+   max_pages = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+   bailout_reason = "beyond file limit";
+   if 

[PATCH v5 4/5] cramfs: add mmap support

2017-10-05 Thread Nicolas Pitre
When cramfs_physmem is used then we have the opportunity to map files
directly from ROM, directly into user space, saving on RAM usage.
This gives us Execute-In-Place (XIP) support.

For a file to be mmap()-able, the map area has to correspond to a range
of uncompressed and contiguous blocks, and in the MMU case it also has
to be page aligned. A version of mkcramfs with appropriate support is
necessary to create such a filesystem image.

In the MMU case it may happen for a vma structure to extend beyond the
actual file size. This is notably the case in binfmt_elf.c:elf_map().
Or the file's last block is shared with other files and cannot be mapped
as is. Rather than refusing to mmap it, we do a "mixed" map and let the
regular fault handler populate the unmapped area with RAM-backed pages.
In practice the unmapped area is seldom accessed so page faults might
never occur before this area is discarded.

In the non-MMU case it is the get_unmapped_area method that is responsible
for providing the address where the actual data can be found. No mapping
is necessary of course.

Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 fs/cramfs/inode.c | 194 ++
 1 file changed, 194 insertions(+)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 6aa1d94ed8..071ce1eb58 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -15,7 +15,10 @@
 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -49,6 +52,7 @@ static inline struct cramfs_sb_info *CRAMFS_SB(struct 
super_block *sb)
 static const struct super_operations cramfs_ops;
 static const struct inode_operations cramfs_dir_inode_operations;
 static const struct file_operations cramfs_directory_operations;
+static const struct file_operations cramfs_physmem_fops;
 static const struct address_space_operations cramfs_aops;
 
 static DEFINE_MUTEX(read_mutex);
@@ -96,6 +100,10 @@ static struct inode *get_cramfs_inode(struct super_block 
*sb,
case S_IFREG:
inode->i_fop = _ro_fops;
inode->i_data.a_ops = _aops;
+   if (IS_ENABLED(CONFIG_CRAMFS_PHYSMEM) &&
+   CRAMFS_SB(sb)->flags & CRAMFS_FLAG_EXT_BLOCK_POINTERS &&
+   CRAMFS_SB(sb)->linear_phys_addr)
+   inode->i_fop = _physmem_fops;
break;
case S_IFDIR:
inode->i_op = _dir_inode_operations;
@@ -277,6 +285,192 @@ static void *cramfs_read(struct super_block *sb, unsigned 
int offset,
return NULL;
 }
 
+/*
+ * For a mapping to be possible, we need a range of uncompressed and
+ * contiguous blocks. Return the offset for the first block and number of
+ * valid blocks for which that is true, or zero otherwise.
+ */
+static u32 cramfs_get_block_range(struct inode *inode, u32 pgoff, u32 *pages)
+{
+   struct super_block *sb = inode->i_sb;
+   struct cramfs_sb_info *sbi = CRAMFS_SB(sb);
+   int i;
+   u32 *blockptrs, first_block_addr;
+
+   /*
+* We can dereference memory directly here as this code may be
+* reached only when there is a direct filesystem image mapping
+* available in memory.
+*/
+   blockptrs = (u32 *)(sbi->linear_virt_addr + OFFSET(inode) + pgoff * 4);
+   first_block_addr = blockptrs[0] & ~CRAMFS_BLK_FLAGS;
+   i = 0;
+   do {
+   u32 block_off = i * (PAGE_SIZE >> CRAMFS_BLK_DIRECT_PTR_SHIFT);
+   u32 expect = (first_block_addr + block_off) |
+CRAMFS_BLK_FLAG_DIRECT_PTR |
+CRAMFS_BLK_FLAG_UNCOMPRESSED;
+   if (blockptrs[i] != expect) {
+   pr_debug("range: block %d/%d got %#x expects %#x\n",
+pgoff+i, pgoff + *pages - 1,
+blockptrs[i], expect);
+   if (i == 0)
+   return 0;
+   break;
+   }
+   } while (++i < *pages);
+
+   *pages = i;
+   return first_block_addr << CRAMFS_BLK_DIRECT_PTR_SHIFT;
+}
+
+#ifdef CONFIG_MMU
+
+static int cramfs_physmem_mmap(struct file *file, struct vm_area_struct *vma)
+{
+   struct inode *inode = file_inode(file);
+   struct super_block *sb = inode->i_sb;
+   struct cramfs_sb_info *sbi = CRAMFS_SB(sb);
+   unsigned int pages, max_pages, offset;
+   unsigned long address, pgoff = vma->vm_pgoff;
+   char *bailout_reason;
+   int ret;
+
+   if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
+   return -EINVAL;
+
+   /* Could COW work here? */
+   bailout_reason = "vma is writable";
+   if (vma->vm_flags & VM_WRITE)
+   goto bailout;
+
+   max_pages = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+   bailout_reason = "beyond file limit";
+   if (pgoff >= max_pages)
+   goto 

[PATCH v5 3/5] cramfs: implement uncompressed and arbitrary data block positioning

2017-10-05 Thread Nicolas Pitre
Two new capabilities are introduced here:

- The ability to store some blocks uncompressed.

- The ability to locate blocks anywhere.

Those capabilities can be used independently, but the combination
opens the possibility for execute-in-place (XIP) of program text segments
that must remain uncompressed, and in the MMU case, must have a specific
alignment.  It is even possible to still have the writable data segments
from the same file compressed as they have to be copied into RAM anyway.

This is achieved by giving special meanings to some unused block pointer
bits while remaining compatible with legacy cramfs images.

Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 fs/cramfs/README   | 31 ++-
 fs/cramfs/inode.c  | 90 +-
 include/uapi/linux/cramfs_fs.h | 26 +++-
 3 files changed, 126 insertions(+), 21 deletions(-)

diff --git a/fs/cramfs/README b/fs/cramfs/README
index 9d4e7ea311..d71b27e0ff 100644
--- a/fs/cramfs/README
+++ b/fs/cramfs/README
@@ -49,17 +49,46 @@ same as the start of the (i+1)'th  if there is one). 
 The first
  immediately follows the last  for the file.
 s are each 32 bits long.
 
+When the CRAMFS_FLAG_EXT_BLOCK_POINTERS capability bit is set, each
+'s top bits may contain special flags as follows:
+
+CRAMFS_BLK_FLAG_UNCOMPRESSED (bit 31):
+   The block data is not compressed and should be copied verbatim.
+
+CRAMFS_BLK_FLAG_DIRECT_PTR (bit 30):
+   The  stores the actual block start offset and not
+   its end, shifted right by 2 bits. The block must therefore be
+   aligned to a 4-byte boundary. The block size is either blksize
+   if CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified, otherwise
+   the compressed data length is included in the first 2 bytes of
+   the block data. This is used to allow discontiguous data layout
+   and specific data block alignments e.g. for XIP applications.
+
+
 The order of 's is a depth-first descent of the directory
 tree, i.e. the same order as `find -size +0 \( -type f -o -type l \)
 -print'.
 
 
 : The i'th  is the output of zlib's compress function
-applied to the i'th blksize-sized chunk of the input data.
+applied to the i'th blksize-sized chunk of the input data if the
+corresponding CRAMFS_BLK_FLAG_UNCOMPRESSED  bit is not set,
+otherwise it is the input data directly.
 (For the last  of the file, the input may of course be smaller.)
 Each  may be a different size.  (See  above.)
+
 s are merely byte-aligned, not generally u32-aligned.
 
+When CRAMFS_BLK_FLAG_DIRECT_PTR is specified then the corresponding
+ may be located anywhere and not necessarily contiguous with
+the previous/next blocks. In that case it is minimally u32-aligned.
+If CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified then the size is always
+blksize except for the last block which is limited by the file length.
+If CRAMFS_BLK_FLAG_DIRECT_PTR is set and CRAMFS_BLK_FLAG_UNCOMPRESSED
+is not set then the first 2 bytes of the block contains the size of the
+remaining block data as this cannot be determined from the placement of
+logically adjacent blocks.
+
 
 Holes
 -
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 89bce89c05..6aa1d94ed8 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -640,34 +640,86 @@ static int cramfs_readpage(struct file *file, struct page 
*page)
 
if (page->index < maxblock) {
struct super_block *sb = inode->i_sb;
-   u32 blkptr_offset = OFFSET(inode) + page->index*4;
-   u32 start_offset, compr_len;
+   u32 blkptr_offset = OFFSET(inode) + page->index * 4;
+   u32 block_ptr, block_start, block_len;
+   bool uncompressed, direct;
 
-   start_offset = OFFSET(inode) + maxblock*4;
mutex_lock(_mutex);
-   if (page->index)
-   start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4,
-   4);
-   compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) -
-   start_offset);
-   mutex_unlock(_mutex);
+   block_ptr = *(u32 *) cramfs_read(sb, blkptr_offset, 4);
+   uncompressed = (block_ptr & CRAMFS_BLK_FLAG_UNCOMPRESSED);
+   direct = (block_ptr & CRAMFS_BLK_FLAG_DIRECT_PTR);
+   block_ptr &= ~CRAMFS_BLK_FLAGS;
+
+   if (direct) {
+   /*
+* The block pointer is an absolute start pointer,
+* shifted by 2 bits. The size is included in the
+* first 2 bytes of the data block when compressed,
+* or PAGE_SIZE otherwise.
+*/
+   block_start = block_ptr << CRAMFS_BLK_DIRECT_PTR_SHIFT;
+   if (uncompressed) {
+  

[PATCH v5 3/5] cramfs: implement uncompressed and arbitrary data block positioning

2017-10-05 Thread Nicolas Pitre
Two new capabilities are introduced here:

- The ability to store some blocks uncompressed.

- The ability to locate blocks anywhere.

Those capabilities can be used independently, but the combination
opens the possibility for execute-in-place (XIP) of program text segments
that must remain uncompressed, and in the MMU case, must have a specific
alignment.  It is even possible to still have the writable data segments
from the same file compressed as they have to be copied into RAM anyway.

This is achieved by giving special meanings to some unused block pointer
bits while remaining compatible with legacy cramfs images.

Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 fs/cramfs/README   | 31 ++-
 fs/cramfs/inode.c  | 90 +-
 include/uapi/linux/cramfs_fs.h | 26 +++-
 3 files changed, 126 insertions(+), 21 deletions(-)

diff --git a/fs/cramfs/README b/fs/cramfs/README
index 9d4e7ea311..d71b27e0ff 100644
--- a/fs/cramfs/README
+++ b/fs/cramfs/README
@@ -49,17 +49,46 @@ same as the start of the (i+1)'th  if there is one). 
 The first
  immediately follows the last  for the file.
 s are each 32 bits long.
 
+When the CRAMFS_FLAG_EXT_BLOCK_POINTERS capability bit is set, each
+'s top bits may contain special flags as follows:
+
+CRAMFS_BLK_FLAG_UNCOMPRESSED (bit 31):
+   The block data is not compressed and should be copied verbatim.
+
+CRAMFS_BLK_FLAG_DIRECT_PTR (bit 30):
+   The  stores the actual block start offset and not
+   its end, shifted right by 2 bits. The block must therefore be
+   aligned to a 4-byte boundary. The block size is either blksize
+   if CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified, otherwise
+   the compressed data length is included in the first 2 bytes of
+   the block data. This is used to allow discontiguous data layout
+   and specific data block alignments e.g. for XIP applications.
+
+
 The order of 's is a depth-first descent of the directory
 tree, i.e. the same order as `find -size +0 \( -type f -o -type l \)
 -print'.
 
 
 : The i'th  is the output of zlib's compress function
-applied to the i'th blksize-sized chunk of the input data.
+applied to the i'th blksize-sized chunk of the input data if the
+corresponding CRAMFS_BLK_FLAG_UNCOMPRESSED  bit is not set,
+otherwise it is the input data directly.
 (For the last  of the file, the input may of course be smaller.)
 Each  may be a different size.  (See  above.)
+
 s are merely byte-aligned, not generally u32-aligned.
 
+When CRAMFS_BLK_FLAG_DIRECT_PTR is specified then the corresponding
+ may be located anywhere and not necessarily contiguous with
+the previous/next blocks. In that case it is minimally u32-aligned.
+If CRAMFS_BLK_FLAG_UNCOMPRESSED is also specified then the size is always
+blksize except for the last block which is limited by the file length.
+If CRAMFS_BLK_FLAG_DIRECT_PTR is set and CRAMFS_BLK_FLAG_UNCOMPRESSED
+is not set then the first 2 bytes of the block contains the size of the
+remaining block data as this cannot be determined from the placement of
+logically adjacent blocks.
+
 
 Holes
 -
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 89bce89c05..6aa1d94ed8 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -640,34 +640,86 @@ static int cramfs_readpage(struct file *file, struct page 
*page)
 
if (page->index < maxblock) {
struct super_block *sb = inode->i_sb;
-   u32 blkptr_offset = OFFSET(inode) + page->index*4;
-   u32 start_offset, compr_len;
+   u32 blkptr_offset = OFFSET(inode) + page->index * 4;
+   u32 block_ptr, block_start, block_len;
+   bool uncompressed, direct;
 
-   start_offset = OFFSET(inode) + maxblock*4;
mutex_lock(_mutex);
-   if (page->index)
-   start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4,
-   4);
-   compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) -
-   start_offset);
-   mutex_unlock(_mutex);
+   block_ptr = *(u32 *) cramfs_read(sb, blkptr_offset, 4);
+   uncompressed = (block_ptr & CRAMFS_BLK_FLAG_UNCOMPRESSED);
+   direct = (block_ptr & CRAMFS_BLK_FLAG_DIRECT_PTR);
+   block_ptr &= ~CRAMFS_BLK_FLAGS;
+
+   if (direct) {
+   /*
+* The block pointer is an absolute start pointer,
+* shifted by 2 bits. The size is included in the
+* first 2 bytes of the data block when compressed,
+* or PAGE_SIZE otherwise.
+*/
+   block_start = block_ptr << CRAMFS_BLK_DIRECT_PTR_SHIFT;
+   if (uncompressed) {
+   block_len = PAGE_SIZE;
+  

[PATCH v5 0/5] cramfs refresh for embedded usage

2017-10-05 Thread Nicolas Pitre
This series brings a nice refresh to the cramfs filesystem, adding the
following capabilities:

- Direct memory access, bypassing the block and/or MTD layers entirely.

- Ability to store individual data blocks uncompressed.

- Ability to locate individual data blocks anywhere in the filesystem.

The end result is a very tight filesystem that can be accessed directly
from ROM without any other subsystem underneath. This also allows for
user space XIP which is a very important feature for tiny embedded
systems.

This series is also available based on v4.13 via git here:

  http://git.linaro.org/people/nicolas.pitre/linux xipcramfs

Why cramfs?

  Because cramfs is very simple and small. With CONFIG_CRAMFS_BLOCK=n and
  CONFIG_CRAMFS_PHYSMEM=y the cramfs driver may use as little as 3704 bytes
  of code. That's many times smaller than squashfs. And the runtime memory
  usage is also much less with cramfs than squashfs. It packs very tightly
  already compared to romfs which has no compression support. And the cramfs
  format was simple to extend, allowing for both compressed and uncompressed
  blocks within the same file.

Why not accessing ROM via MTD?

  The MTD layer is nice and flexible. It also represents a huge overhead
  considering its core with no other enabled options weights 19KB.
  That's many times the size of the cramfs code for something that
  essentially boils down to a glorified argument parser and a call to
  memremap() in this case.  And if someone still wants to use cramfs via
  MTD then it is already possible with mtdblock.

Why not using DAX?

  DAX stands for "Direct Access" and is a generic kernel layer helping
  with the necessary tasks involved with XIP. It is tailored for large
  writable filesystems and relies on the presence of an MMU. It also has
  the following shortcoming: "The DAX code does not work correctly on
  architectures which have virtually mapped caches such as ARM, MIPS and
  SPARC." That makes it unsuitable for a large portion of the intended
  targets for this series. And due to the read-only nature of cramfs, it is
  possible to achieve the intended result with a much simpler approach making
  DAX somewhat overkill in this context.

The maximum size of a cramfs image can't exceed 272MB. In practice it is
likely to be much much less. Given this series is concerned with small
memory systems, even in the MMU case there is always plenty of vmalloc
space left to map it all and even a 272MB memremap() wouldn't be a
problem. If it is then maybe your system is big enough with large
resources to manage already and you're pretty unlikely to be using cramfs
in the first place.

Of course, while this cramfs remains backward compatible with existing
filesystem images, a newer mkcramfs version is necessary to take advantage
of the extended data layout. I created a version of mkcramfs that
detects ELF files and marks text+rodata segments for XIP and compresses the
rest of those ELF files automatically.

So here it is. I'm also willing to step up as cramfs maintainer given
that no sign of any maintenance activities appeared for years.


Changes from v4:

- Remove fault handler with vma splitting in favor of VM_MIXEDMAP at mmap
  time for much simpler code. Thanks to Christoph Hellwig for review and
  suggestion.
- Additional code cleanups, mostly from Christoph's suggestions.

Changes from v3:

- Rebased on v4.13.
- Made direct access depend on cramfs not being modular due to unexported
  vma handling functions.
- Solicit comments from mm people explicitly.

Changes from v2:

- Plugged a few races in cramfs_vmasplit_fault(). Thanks to Al Viro for
  highlighting them.
- Fixed some checkpatch warnings

Changes from v1:

- Improved mmap() support by adding the ability to partially populate a
  mapping and lazily split the non directly mapable pages to a separate
  vma at fault time (thanks to Chris Brandt for testing).
- Clarified the documentation some more.


diffstat:

 Documentation/filesystems/cramfs.txt |  42 +++
 MAINTAINERS  |   4 +-
 fs/cramfs/Kconfig|  38 +-
 fs/cramfs/README |  31 +-
 fs/cramfs/inode.c| 554 +
 include/uapi/linux/cramfs_fs.h   |  26 +-
 init/do_mounts.c |   8 +
 7 files changed, 625 insertions(+), 78 deletions(-)



[PATCH v5 1/5] cramfs: direct memory access support

2017-10-05 Thread Nicolas Pitre
Small embedded systems typically execute the kernel code in place (XIP)
directly from flash to save on precious RAM usage. This adds the ability
to consume filesystem data directly from flash to the cramfs filesystem
as well. Cramfs is particularly well suited to this feature as it is
very simple and its RAM usage is already very low, and with this feature
it is possible to use it with no block device support and even lower RAM
usage.

This patch was inspired by a similar patch from Shane Nay dated 17 years
ago that used to be very popular in embedded circles but never made it
into mainline. This is a cleaned-up implementation that uses far fewer
memory address at run time when both methods are configured in. In the
context of small IoT deployments, this functionality has become relevant
and useful again.

To distinguish between both access types, the cramfs_physmem filesystem
type must be specified when using a memory accessible cramfs image, and
the physaddr argument must provide the actual filesystem image's physical
memory location.

Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 fs/cramfs/Kconfig |  29 +-
 fs/cramfs/inode.c | 270 +++---
 2 files changed, 247 insertions(+), 52 deletions(-)

diff --git a/fs/cramfs/Kconfig b/fs/cramfs/Kconfig
index 11b29d491b..5b4e0b7e13 100644
--- a/fs/cramfs/Kconfig
+++ b/fs/cramfs/Kconfig
@@ -1,6 +1,5 @@
 config CRAMFS
tristate "Compressed ROM file system support (cramfs) (OBSOLETE)"
-   depends on BLOCK
select ZLIB_INFLATE
help
  Saying Y here includes support for CramFs (Compressed ROM File
@@ -20,3 +19,31 @@ config CRAMFS
  in terms of performance and features.
 
  If unsure, say N.
+
+config CRAMFS_BLOCKDEV
+   bool "Support CramFs image over a regular block device" if EXPERT
+   depends on CRAMFS && BLOCK
+   default y
+   help
+ This option allows the CramFs driver to load data from a regular
+ block device such a disk partition or a ramdisk.
+
+config CRAMFS_PHYSMEM
+   bool "Support CramFs image directly mapped in physical memory"
+   depends on CRAMFS
+   default y if !CRAMFS_BLOCKDEV
+   help
+ This option allows the CramFs driver to load data directly from
+ a linear adressed memory range (usually non volatile memory
+ like flash) instead of going through the block device layer.
+ This saves some memory since no intermediate buffering is
+ necessary.
+
+ The filesystem type for this feature is "cramfs_physmem".
+ The location of the CramFs image in memory is board
+ dependent. Therefore, if you say Y, you must know the proper
+ physical address where to store the CramFs image and specify
+ it using the physaddr=0x mount option (for example:
+ "mount -t cramfs_physmem -o physaddr=0x10 none /mnt").
+
+ If unsure, say N.
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 7919967488..89bce89c05 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "internal.h"
 
@@ -36,6 +37,8 @@ struct cramfs_sb_info {
unsigned long blocks;
unsigned long files;
unsigned long flags;
+   void *linear_virt_addr;
+   phys_addr_t linear_phys_addr;
 };
 
 static inline struct cramfs_sb_info *CRAMFS_SB(struct super_block *sb)
@@ -140,6 +143,9 @@ static struct inode *get_cramfs_inode(struct super_block 
*sb,
  * BLKS_PER_BUF*PAGE_SIZE, so that the caller doesn't need to
  * worry about end-of-buffer issues even when decompressing a full
  * page cache.
+ *
+ * Note: This is all optimized away at compile time when
+ *   CONFIG_CRAMFS_BLOCKDEV=n.
  */
 #define READ_BUFFERS (2)
 /* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
@@ -160,10 +166,10 @@ static struct super_block *buffer_dev[READ_BUFFERS];
 static int next_buffer;
 
 /*
- * Returns a pointer to a buffer containing at least LEN bytes of
- * filesystem starting at byte offset OFFSET into the filesystem.
+ * Populate our block cache and return a pointer from it.
  */
-static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned 
int len)
+static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset,
+   unsigned int len)
 {
struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
struct page *pages[BLKS_PER_BUF];
@@ -239,7 +245,39 @@ static void *cramfs_read(struct super_block *sb, unsigned 
int offset, unsigned i
return read_buffers[buffer] + offset;
 }
 
-static void cramfs_kill_sb(struct super_block *sb)
+/*
+ * Return a pointer to the linearly addressed cramfs image in memory.
+ */
+static void *cramfs_direct_read(struct super_block *sb, unsigned int offset,
+   unsigned int 

[PATCH v5 2/5] cramfs: make cramfs_physmem usable as root fs

2017-10-05 Thread Nicolas Pitre
Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 init/do_mounts.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/init/do_mounts.c b/init/do_mounts.c
index c2de5104aa..43b5817f60 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -556,6 +556,14 @@ void __init prepare_namespace(void)
ssleep(root_delay);
}
 
+   if (IS_ENABLED(CONFIG_CRAMFS_PHYSMEM) && root_fs_names &&
+   !strcmp(root_fs_names, "cramfs_physmem")) {
+   int err = do_mount_root("cramfs", "cramfs_physmem",
+   root_mountflags, root_mount_data);
+   if (!err)
+   goto out;
+   }
+
/*
 * wait for the known devices to complete their probing
 *
-- 
2.9.5



[PATCH v5 2/5] cramfs: make cramfs_physmem usable as root fs

2017-10-05 Thread Nicolas Pitre
Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 init/do_mounts.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/init/do_mounts.c b/init/do_mounts.c
index c2de5104aa..43b5817f60 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -556,6 +556,14 @@ void __init prepare_namespace(void)
ssleep(root_delay);
}
 
+   if (IS_ENABLED(CONFIG_CRAMFS_PHYSMEM) && root_fs_names &&
+   !strcmp(root_fs_names, "cramfs_physmem")) {
+   int err = do_mount_root("cramfs", "cramfs_physmem",
+   root_mountflags, root_mount_data);
+   if (!err)
+   goto out;
+   }
+
/*
 * wait for the known devices to complete their probing
 *
-- 
2.9.5



[PATCH v5 0/5] cramfs refresh for embedded usage

2017-10-05 Thread Nicolas Pitre
This series brings a nice refresh to the cramfs filesystem, adding the
following capabilities:

- Direct memory access, bypassing the block and/or MTD layers entirely.

- Ability to store individual data blocks uncompressed.

- Ability to locate individual data blocks anywhere in the filesystem.

The end result is a very tight filesystem that can be accessed directly
from ROM without any other subsystem underneath. This also allows for
user space XIP which is a very important feature for tiny embedded
systems.

This series is also available based on v4.13 via git here:

  http://git.linaro.org/people/nicolas.pitre/linux xipcramfs

Why cramfs?

  Because cramfs is very simple and small. With CONFIG_CRAMFS_BLOCK=n and
  CONFIG_CRAMFS_PHYSMEM=y the cramfs driver may use as little as 3704 bytes
  of code. That's many times smaller than squashfs. And the runtime memory
  usage is also much less with cramfs than squashfs. It packs very tightly
  already compared to romfs which has no compression support. And the cramfs
  format was simple to extend, allowing for both compressed and uncompressed
  blocks within the same file.

Why not accessing ROM via MTD?

  The MTD layer is nice and flexible. It also represents a huge overhead
  considering its core with no other enabled options weights 19KB.
  That's many times the size of the cramfs code for something that
  essentially boils down to a glorified argument parser and a call to
  memremap() in this case.  And if someone still wants to use cramfs via
  MTD then it is already possible with mtdblock.

Why not using DAX?

  DAX stands for "Direct Access" and is a generic kernel layer helping
  with the necessary tasks involved with XIP. It is tailored for large
  writable filesystems and relies on the presence of an MMU. It also has
  the following shortcoming: "The DAX code does not work correctly on
  architectures which have virtually mapped caches such as ARM, MIPS and
  SPARC." That makes it unsuitable for a large portion of the intended
  targets for this series. And due to the read-only nature of cramfs, it is
  possible to achieve the intended result with a much simpler approach making
  DAX somewhat overkill in this context.

The maximum size of a cramfs image can't exceed 272MB. In practice it is
likely to be much much less. Given this series is concerned with small
memory systems, even in the MMU case there is always plenty of vmalloc
space left to map it all and even a 272MB memremap() wouldn't be a
problem. If it is then maybe your system is big enough with large
resources to manage already and you're pretty unlikely to be using cramfs
in the first place.

Of course, while this cramfs remains backward compatible with existing
filesystem images, a newer mkcramfs version is necessary to take advantage
of the extended data layout. I created a version of mkcramfs that
detects ELF files and marks text+rodata segments for XIP and compresses the
rest of those ELF files automatically.

So here it is. I'm also willing to step up as cramfs maintainer given
that no sign of any maintenance activities appeared for years.


Changes from v4:

- Remove fault handler with vma splitting in favor of VM_MIXEDMAP at mmap
  time for much simpler code. Thanks to Christoph Hellwig for review and
  suggestion.
- Additional code cleanups, mostly from Christoph's suggestions.

Changes from v3:

- Rebased on v4.13.
- Made direct access depend on cramfs not being modular due to unexported
  vma handling functions.
- Solicit comments from mm people explicitly.

Changes from v2:

- Plugged a few races in cramfs_vmasplit_fault(). Thanks to Al Viro for
  highlighting them.
- Fixed some checkpatch warnings

Changes from v1:

- Improved mmap() support by adding the ability to partially populate a
  mapping and lazily split the non directly mapable pages to a separate
  vma at fault time (thanks to Chris Brandt for testing).
- Clarified the documentation some more.


diffstat:

 Documentation/filesystems/cramfs.txt |  42 +++
 MAINTAINERS  |   4 +-
 fs/cramfs/Kconfig|  38 +-
 fs/cramfs/README |  31 +-
 fs/cramfs/inode.c| 554 +
 include/uapi/linux/cramfs_fs.h   |  26 +-
 init/do_mounts.c |   8 +
 7 files changed, 625 insertions(+), 78 deletions(-)



[PATCH v5 1/5] cramfs: direct memory access support

2017-10-05 Thread Nicolas Pitre
Small embedded systems typically execute the kernel code in place (XIP)
directly from flash to save on precious RAM usage. This adds the ability
to consume filesystem data directly from flash to the cramfs filesystem
as well. Cramfs is particularly well suited to this feature as it is
very simple and its RAM usage is already very low, and with this feature
it is possible to use it with no block device support and even lower RAM
usage.

This patch was inspired by a similar patch from Shane Nay dated 17 years
ago that used to be very popular in embedded circles but never made it
into mainline. This is a cleaned-up implementation that uses far fewer
memory address at run time when both methods are configured in. In the
context of small IoT deployments, this functionality has become relevant
and useful again.

To distinguish between both access types, the cramfs_physmem filesystem
type must be specified when using a memory accessible cramfs image, and
the physaddr argument must provide the actual filesystem image's physical
memory location.

Signed-off-by: Nicolas Pitre 
Tested-by: Chris Brandt 
---
 fs/cramfs/Kconfig |  29 +-
 fs/cramfs/inode.c | 270 +++---
 2 files changed, 247 insertions(+), 52 deletions(-)

diff --git a/fs/cramfs/Kconfig b/fs/cramfs/Kconfig
index 11b29d491b..5b4e0b7e13 100644
--- a/fs/cramfs/Kconfig
+++ b/fs/cramfs/Kconfig
@@ -1,6 +1,5 @@
 config CRAMFS
tristate "Compressed ROM file system support (cramfs) (OBSOLETE)"
-   depends on BLOCK
select ZLIB_INFLATE
help
  Saying Y here includes support for CramFs (Compressed ROM File
@@ -20,3 +19,31 @@ config CRAMFS
  in terms of performance and features.
 
  If unsure, say N.
+
+config CRAMFS_BLOCKDEV
+   bool "Support CramFs image over a regular block device" if EXPERT
+   depends on CRAMFS && BLOCK
+   default y
+   help
+ This option allows the CramFs driver to load data from a regular
+ block device such a disk partition or a ramdisk.
+
+config CRAMFS_PHYSMEM
+   bool "Support CramFs image directly mapped in physical memory"
+   depends on CRAMFS
+   default y if !CRAMFS_BLOCKDEV
+   help
+ This option allows the CramFs driver to load data directly from
+ a linear adressed memory range (usually non volatile memory
+ like flash) instead of going through the block device layer.
+ This saves some memory since no intermediate buffering is
+ necessary.
+
+ The filesystem type for this feature is "cramfs_physmem".
+ The location of the CramFs image in memory is board
+ dependent. Therefore, if you say Y, you must know the proper
+ physical address where to store the CramFs image and specify
+ it using the physaddr=0x mount option (for example:
+ "mount -t cramfs_physmem -o physaddr=0x10 none /mnt").
+
+ If unsure, say N.
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 7919967488..89bce89c05 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "internal.h"
 
@@ -36,6 +37,8 @@ struct cramfs_sb_info {
unsigned long blocks;
unsigned long files;
unsigned long flags;
+   void *linear_virt_addr;
+   phys_addr_t linear_phys_addr;
 };
 
 static inline struct cramfs_sb_info *CRAMFS_SB(struct super_block *sb)
@@ -140,6 +143,9 @@ static struct inode *get_cramfs_inode(struct super_block 
*sb,
  * BLKS_PER_BUF*PAGE_SIZE, so that the caller doesn't need to
  * worry about end-of-buffer issues even when decompressing a full
  * page cache.
+ *
+ * Note: This is all optimized away at compile time when
+ *   CONFIG_CRAMFS_BLOCKDEV=n.
  */
 #define READ_BUFFERS (2)
 /* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
@@ -160,10 +166,10 @@ static struct super_block *buffer_dev[READ_BUFFERS];
 static int next_buffer;
 
 /*
- * Returns a pointer to a buffer containing at least LEN bytes of
- * filesystem starting at byte offset OFFSET into the filesystem.
+ * Populate our block cache and return a pointer from it.
  */
-static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned 
int len)
+static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset,
+   unsigned int len)
 {
struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
struct page *pages[BLKS_PER_BUF];
@@ -239,7 +245,39 @@ static void *cramfs_read(struct super_block *sb, unsigned 
int offset, unsigned i
return read_buffers[buffer] + offset;
 }
 
-static void cramfs_kill_sb(struct super_block *sb)
+/*
+ * Return a pointer to the linearly addressed cramfs image in memory.
+ */
+static void *cramfs_direct_read(struct super_block *sb, unsigned int offset,
+   unsigned int len)
+{
+   struct cramfs_sb_info *sbi = 

  1   2   3   4   5   6   7   8   9   10   >