Re: [PATCH v2 1/2] i2c: aspeed: added driver for Aspeed I2C

2016-09-19 Thread Brendan Higgins
Gentle ping

On Fri, Sep 9, 2016 at 6:55 PM, Brendan Higgins
 wrote:
> Added initial master and slave support for Aspeed I2C controller.
> Supports fourteen busses present in ast24xx and ast25xx BMC SoCs by
> Aspeed.
>
> Signed-off-by: Brendan Higgins 
> ---
> Changes for v2:
>   - Added single module_init (multiple was breaking some builds).
> ---
>  drivers/i2c/busses/Kconfig  |  10 +
>  drivers/i2c/busses/Makefile |   1 +
>  drivers/i2c/busses/i2c-aspeed.c | 831 
> 
>  3 files changed, 842 insertions(+)
>  create mode 100644 drivers/i2c/busses/i2c-aspeed.c
>
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 5c3993b..0178c6c 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -998,6 +998,16 @@ config I2C_RCAR
>   This driver can also be built as a module.  If so, the module
>   will be called i2c-rcar.
>
> +config I2C_ASPEED
> +   tristate "Aspeed AST2xxx SoC I2C Controller"
> +   depends on (ARCH_ASPEED || COMPILE_TEST) && OF
> +   help
> + If you say yes to this option, support will be included for the
> + Aspeed AST2xxx SoC I2C controller.
> +
> + This driver can also be built as a module.  If so, the module
> + will be called i2c-aspeed.
> +
>  comment "External I2C/SMBus adapter drivers"
>
>  config I2C_DIOLAN_U2C
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 37f2819..49631cd 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -96,6 +96,7 @@ obj-$(CONFIG_I2C_XILINX)  += i2c-xiic.o
>  obj-$(CONFIG_I2C_XLR)  += i2c-xlr.o
>  obj-$(CONFIG_I2C_XLP9XX)   += i2c-xlp9xx.o
>  obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
> +obj-$(CONFIG_I2C_ASPEED)   += i2c-aspeed.o
>
>  # External I2C/SMBus adapter drivers
>  obj-$(CONFIG_I2C_DIOLAN_U2C)   += i2c-diolan-u2c.o
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> new file mode 100644
> index 000..b19f13c
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -0,0 +1,831 @@
> +/*
> + *  I2C adapter for the ASPEED I2C bus.
> + *
> + *  Copyright (C) 2012-2020  ASPEED Technology Inc.
> + *  Copyright 2016 IBM Corporation
> + *  Copyright 2016 Google, 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.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +/* I2C Register */
> +#define ASPEED_I2C_FUN_CTRL_REG0x00
> +#define ASPEED_I2C_AC_TIMING_REG1  0x04
> +#define ASPEED_I2C_AC_TIMING_REG2  0x08
> +#define ASPEED_I2C_INTR_CTRL_REG   0x0c
> +#define ASPEED_I2C_INTR_STS_REG0x10
> +#define ASPEED_I2C_CMD_REG 0x14
> +#define ASPEED_I2C_DEV_ADDR_REG0x18
> +#define ASPEED_I2C_BYTE_BUF_REG0x20
> +
> +#define ASPEED_I2C_NUM_BUS 14
> +
> +/* Global Register Definition */
> +/* 0x00 : I2C Interrupt Status Register  */
> +/* 0x08 : I2C Interrupt Target Assignment  */
> +
> +/* Device Register Definition */
> +/* 0x00 : I2CD Function Control Register  */
> +#define ASPEED_I2CD_MULTI_MASTER_DIS   BIT(15)
> +#define ASPEED_I2CD_SDA_DRIVE_1T_ENBIT(8)
> +#define ASPEED_I2CD_M_SDA_DRIVE_1T_EN  BIT(7)
> +#define ASPEED_I2CD_M_HIGH_SPEED_ENBIT(6)
> +#define ASPEED_I2CD_SLAVE_EN   BIT(1)
> +#define ASPEED_I2CD_MASTER_EN  BIT(0)
> +
> +/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
> +#define ASPEED_NO_TIMEOUT_CTRL 0
> +
> +
> +/* 0x0c : I2CD Interrupt Control Register &
> + * 0x10 : I2CD Interrupt Status Register
> + *
> + * These share bit definitions, so use the same values for the enable &
> + * status bits.
> + */
> +#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUTBIT(14)
> +#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE  BIT(13)
> +#define ASPEED_I2CD_INTR_SLAVE_MATCH   BIT(7)
> +#define ASPEED_I2CD_INTR_SCL_TIMEOUT   BIT(6)
> +#define ASPEED_I

[PATCH v3 1/2] i2c: aspeed: added driver for Aspeed I2C

2016-09-19 Thread Brendan Higgins
Added initial master and slave support for Aspeed I2C controller.
Supports fourteen busses present in ast24xx and ast25xx BMC SoCs by
Aspeed.

Signed-off-by: Brendan Higgins 
---
Changes for v2:
  - Added single module_init (multiple was breaking some builds).
Changes for v3:
  - Removed "bus" device tree param; now extracted from bus address offset
---
 drivers/i2c/busses/Kconfig  |  10 +
 drivers/i2c/busses/Makefile |   1 +
 drivers/i2c/busses/i2c-aspeed.c | 846 
 3 files changed, 857 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-aspeed.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 5c3993b..0178c6c 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -998,6 +998,16 @@ config I2C_RCAR
  This driver can also be built as a module.  If so, the module
  will be called i2c-rcar.
 
+config I2C_ASPEED
+   tristate "Aspeed AST2xxx SoC I2C Controller"
+   depends on (ARCH_ASPEED || COMPILE_TEST) && OF
+   help
+ If you say yes to this option, support will be included for the
+ Aspeed AST2xxx SoC I2C controller.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-aspeed.
+
 comment "External I2C/SMBus adapter drivers"
 
 config I2C_DIOLAN_U2C
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 37f2819..49631cd 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -96,6 +96,7 @@ obj-$(CONFIG_I2C_XILINX)  += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)  += i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)   += i2c-xlp9xx.o
 obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o
+obj-$(CONFIG_I2C_ASPEED)   += i2c-aspeed.o
 
 # External I2C/SMBus adapter drivers
 obj-$(CONFIG_I2C_DIOLAN_U2C)   += i2c-diolan-u2c.o
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
new file mode 100644
index 000..207533e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -0,0 +1,846 @@
+/*
+ *  I2C adapter for the ASPEED I2C bus.
+ *
+ *  Copyright (C) 2012-2020  ASPEED Technology Inc.
+ *  Copyright 2016 IBM Corporation
+ *  Copyright 2016 Google, 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* I2C Register */
+#define ASPEED_I2C_FUN_CTRL_REG0x00
+#define ASPEED_I2C_AC_TIMING_REG1  0x04
+#define ASPEED_I2C_AC_TIMING_REG2  0x08
+#define ASPEED_I2C_INTR_CTRL_REG   0x0c
+#define ASPEED_I2C_INTR_STS_REG0x10
+#define ASPEED_I2C_CMD_REG 0x14
+#define ASPEED_I2C_DEV_ADDR_REG0x18
+#define ASPEED_I2C_BYTE_BUF_REG0x20
+#define ASPEED_I2C_OFFSET_START0x40
+#define ASPEED_I2C_OFFSET_INCREMENT0x40
+
+#define ASPEED_I2C_NUM_BUS 14
+
+/* Global Register Definition */
+/* 0x00 : I2C Interrupt Status Register  */
+/* 0x08 : I2C Interrupt Target Assignment  */
+
+/* Device Register Definition */
+/* 0x00 : I2CD Function Control Register  */
+#define ASPEED_I2CD_MULTI_MASTER_DIS   BIT(15)
+#define ASPEED_I2CD_SDA_DRIVE_1T_ENBIT(8)
+#define ASPEED_I2CD_M_SDA_DRIVE_1T_EN  BIT(7)
+#define ASPEED_I2CD_M_HIGH_SPEED_ENBIT(6)
+#define ASPEED_I2CD_SLAVE_EN   BIT(1)
+#define ASPEED_I2CD_MASTER_EN  BIT(0)
+
+/* 0x08 : I2CD Clock and AC Timing Control Register #2 */
+#define ASPEED_NO_TIMEOUT_CTRL 0
+
+
+/* 0x0c : I2CD Interrupt Control Register &
+ * 0x10 : I2CD Interrupt Status Register
+ *
+ * These share bit definitions, so use the same values for the enable &
+ * status bits.
+ */
+#define ASPEED_I2CD_INTR_SDA_DL_TIMEOUTBIT(14)
+#define ASPEED_I2CD_INTR_BUS_RECOVER_DONE  BIT(13)
+#define ASPEED_I2CD_INTR_SLAVE_MATCH   BIT(7)
+#define ASPEED_I2CD_INTR_SCL_TIMEOUT   BIT(6)
+#define ASPEED_I2CD_INTR_ABNORMAL  BIT(5)
+#define ASPEED_I2CD_INTR_NORMAL_STOP   BIT(4)
+#define ASPEED_I2CD_INTR_ARBIT_LOSSBIT(3)
+#define ASPEED_I2CD_INTR_RX_DONE   BIT(2)
+#define ASPEED_I2CD_INTR_TX_NAKBIT(1)
+#define ASPEED_I2CD_INTR_TX_ACKBIT(0)
+
+/* 0x14 : I2CD Command/Status Register   */
+#define ASPEED_I2CD_SCL_L

[PATCH v3 2/2] i2c: aspeed: added documentation for Aspeed I2C driver

2016-09-19 Thread Brendan Higgins
Added device tree binding documentation for Aspeed I2C controller and
busses.

Signed-off-by: Brendan Higgins 
---
Changes for v2:
  - None
Changes for v3:
  - Removed reference to "bus" device tree param
---
 .../devicetree/bindings/i2c/i2c-aspeed.txt | 61 ++
 1 file changed, 61 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-aspeed.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt 
b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
new file mode 100644
index 000..dd11a97
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
@@ -0,0 +1,61 @@
+Device tree configuration for the I2C controller and busses on the AST24XX
+and AST25XX SoCs.
+
+Controller:
+
+   Required Properties:
+   - #address-cells: should be 1
+   - #size-cells   : should be 1
+   - #interrupt-cells  : should be 1
+   - compatible: should be "aspeed,ast2400-i2c-controller"
+ or "aspeed,ast2500-i2c-controller"
+   - reg   : address start and range of controller
+   - ranges: defines address offset and range for busses
+   - interrupts: interrupt number
+   - clocks: root clock of bus, should reference the APB
+ clock
+   - clock-ranges  : specifies that child busses can inherit clocks
+   - interrupt-controller  : denotes that the controller receives and fires
+ new interrupts for child busses
+
+Bus:
+
+   Required Properties:
+   - #address-cells: should be 1
+   - #size-cells   : should be 0
+   - reg   : address offset and range of bus
+   - compatible: should be "aspeed,ast2400-i2c-bus"
+ or "aspeed,ast2500-i2c-bus"
+   - interrupts: interrupt number
+
+   Optional Properties:
+   - clock-frequency   : frequency of the bus clock in Hz
+ defaults to 100 kHz when not specified
+
+Example:
+
+i2c: i2c@1e78a000 {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   #interrupt-cells = <1>;
+
+   compatible = "aspeed,ast2400-i2c-controller";
+   reg = <0x1e78a000 0x40>;
+   ranges = <0 0x1e78a000 0x1000>;
+   interrupts = <12>;
+   clocks = <&clk_apb>;
+   clock-ranges;
+   interrupt-controller;
+
+   i2c0: i2c-bus@40 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0x40 0x40>;
+   compatible = "aspeed,ast2400-i2c-bus";
+   clock-frequency = <10>;
+   status = "disabled";
+   interrupts = <0>;
+   interrupt-parent = <&i2c>;
+   };
+};
+
-- 
2.8.0.rc3.226.g39d4020



Re: [PATCH v2 2/2] i2c: aspeed: added documentation for Aspeed I2C driver

2016-09-19 Thread Brendan Higgins
Addressed in v3.

Thanks!

On Mon, Sep 19, 2016 at 2:35 PM, Rob Herring  wrote:
> On Fri, Sep 09, 2016 at 06:55:51PM -0700, Brendan Higgins wrote:
>> Added device tree binding documentation for Aspeed I2C controller and
>> busses.
>>
>> Signed-off-by: Brendan Higgins 
>> ---
>> Changes for v2:
>>   - None
>> ---
>>  .../devicetree/bindings/i2c/i2c-aspeed.txt | 63 
>> ++
>>  1 file changed, 63 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>>
>> diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt 
>> b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>> new file mode 100644
>> index 000..df68f2a
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>> @@ -0,0 +1,63 @@
>> +Device tree configuration for the I2C controller and busses on the AST24XX
>> +and AST25XX SoCs.
>> +
>> +Controller:
>> +
>> + Required Properties:
>> + - #address-cells: should be 1
>> + - #size-cells   : should be 1
>> + - #interrupt-cells  : should be 1
>> + - compatible: should be "aspeed,ast2400-i2c-controller"
>> +   or "aspeed,ast2500-i2c-controller"
>> + - reg   : address start and range of controller
>> + - ranges: defines address offset and range for busses
>> + - interrupts: interrupt number
>> + - clocks: root clock of bus, should reference the APB
>> +   clock
>> + - clock-ranges  : specifies that child busses can inherit 
>> clocks
>> + - interrupt-controller  : denotes that the controller receives and 
>> fires
>> +   new interrupts for child busses
>> +
>> +Bus:
>> +
>> + Required Properties:
>> + - #address-cells: should be 1
>> + - #size-cells   : should be 0
>> + - reg   : address offset and range of bus
>> + - compatible: should be "aspeed,ast2400-i2c-bus"
>> +   or "aspeed,ast2500-i2c-bus"
>> + - bus   : the bus's number
>
> Don't use indexes. The reg property is enough to id which bus is which.


Re: [PATCH v2 2/2] i2c: aspeed: added documentation for Aspeed I2C driver

2016-09-20 Thread Brendan Higgins
(sorry if you get a duplicate, I forgot to send plain text)

First off, someone pointed out to me that the mapping that I used
between addresses and bus numbers is not actually valid for busses
8-14.

This could be fixed by checking the offset, but I am wondering if that
is the right way to do it. It seems like this is not completely
trivial so maybe this should be specified in the device tree? If that
is the case, should I do this as another reg entry or go back to the
way I was doing it before?

On Mon, Sep 19, 2016 at 4:26 PM, Brendan Higgins
 wrote:
> Addressed in v3.
>
> Thanks!
>
> On Mon, Sep 19, 2016 at 2:35 PM, Rob Herring  wrote:
>> On Fri, Sep 09, 2016 at 06:55:51PM -0700, Brendan Higgins wrote:
>>> Added device tree binding documentation for Aspeed I2C controller and
>>> busses.
>>>
>>> Signed-off-by: Brendan Higgins 
>>> ---
>>> Changes for v2:
>>>   - None
>>> ---
>>>  .../devicetree/bindings/i2c/i2c-aspeed.txt | 63 
>>> ++
>>>  1 file changed, 63 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>>>
>>> diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt 
>>> b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>>> new file mode 100644
>>> index 000..df68f2a
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>>> @@ -0,0 +1,63 @@
>>> +Device tree configuration for the I2C controller and busses on the AST24XX
>>> +and AST25XX SoCs.
>>> +
>>> +Controller:
>>> +
>>> + Required Properties:
>>> + - #address-cells: should be 1
>>> + - #size-cells   : should be 1
>>> + - #interrupt-cells  : should be 1
>>> + - compatible: should be "aspeed,ast2400-i2c-controller"
>>> +   or "aspeed,ast2500-i2c-controller"
>>> + - reg   : address start and range of controller
>>> + - ranges: defines address offset and range for busses
>>> + - interrupts: interrupt number
>>> + - clocks: root clock of bus, should reference the APB
>>> +   clock
>>> + - clock-ranges  : specifies that child busses can inherit 
>>> clocks
>>> + - interrupt-controller  : denotes that the controller receives and 
>>> fires
>>> +   new interrupts for child busses
>>> +
>>> +Bus:
>>> +
>>> + Required Properties:
>>> + - #address-cells: should be 1
>>> + - #size-cells   : should be 0
>>> + - reg   : address offset and range of bus
>>> + - compatible: should be "aspeed,ast2400-i2c-bus"
>>> +   or "aspeed,ast2500-i2c-bus"
>>> + - bus   : the bus's number
>>
>> Don't use indexes. The reg property is enough to id which bus is which.


Re: [PATCH v2 2/2] i2c: aspeed: added documentation for Aspeed I2C driver

2016-09-20 Thread Brendan Higgins
To be clear, these bus numbers are defined as part of the hardware
specification. I am not sure if that was clear before.

On Tue, Sep 20, 2016 at 11:08 AM, Brendan Higgins
 wrote:
> (sorry if you get a duplicate, I forgot to send plain text)
>
> First off, someone pointed out to me that the mapping that I used
> between addresses and bus numbers is not actually valid for busses
> 8-14.
>
> This could be fixed by checking the offset, but I am wondering if that
> is the right way to do it. It seems like this is not completely
> trivial so maybe this should be specified in the device tree? If that
> is the case, should I do this as another reg entry or go back to the
> way I was doing it before?
>
> On Mon, Sep 19, 2016 at 4:26 PM, Brendan Higgins
>  wrote:
>> Addressed in v3.
>>
>> Thanks!
>>
>> On Mon, Sep 19, 2016 at 2:35 PM, Rob Herring  wrote:
>>> On Fri, Sep 09, 2016 at 06:55:51PM -0700, Brendan Higgins wrote:
>>>> Added device tree binding documentation for Aspeed I2C controller and
>>>> busses.
>>>>
>>>> Signed-off-by: Brendan Higgins 
>>>> ---
>>>> Changes for v2:
>>>>   - None
>>>> ---
>>>>  .../devicetree/bindings/i2c/i2c-aspeed.txt | 63 
>>>> ++
>>>>  1 file changed, 63 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt 
>>>> b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>>>> new file mode 100644
>>>> index 000..df68f2a
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
>>>> @@ -0,0 +1,63 @@
>>>> +Device tree configuration for the I2C controller and busses on the AST24XX
>>>> +and AST25XX SoCs.
>>>> +
>>>> +Controller:
>>>> +
>>>> + Required Properties:
>>>> + - #address-cells: should be 1
>>>> + - #size-cells   : should be 1
>>>> + - #interrupt-cells  : should be 1
>>>> + - compatible: should be "aspeed,ast2400-i2c-controller"
>>>> +   or "aspeed,ast2500-i2c-controller"
>>>> + - reg   : address start and range of controller
>>>> + - ranges: defines address offset and range for busses
>>>> + - interrupts: interrupt number
>>>> + - clocks: root clock of bus, should reference the APB
>>>> +   clock
>>>> + - clock-ranges  : specifies that child busses can inherit 
>>>> clocks
>>>> + - interrupt-controller  : denotes that the controller receives and 
>>>> fires
>>>> +   new interrupts for child busses
>>>> +
>>>> +Bus:
>>>> +
>>>> + Required Properties:
>>>> + - #address-cells: should be 1
>>>> + - #size-cells   : should be 0
>>>> + - reg   : address offset and range of bus
>>>> + - compatible: should be "aspeed,ast2400-i2c-bus"
>>>> +   or "aspeed,ast2500-i2c-bus"
>>>> + - bus   : the bus's number
>>>
>>> Don't use indexes. The reg property is enough to id which bus is which.


Re: [PATCH] i2c: aspeed: Retain delay/setup/hold values when configuring bus frequency

2017-08-15 Thread Brendan Higgins
On Tue, Aug 15, 2017 at 10:21 AM, Andrew Jeffery  wrote:
> In addition to the base, low and high clock configuration, the AC timing
> register #1 on the AST2400 houses fields controlling:
>
> 1. tBUF: Minimum delay between Stop and Start conditions
> 2. tHDSTA: Hold time for the Start condition
> 3. tACST: Setup time for Start and Stop conditions, and hold time for the
>Repeated Start condition
>
> These values are defined in hardware on the AST2500 and therefore don't
> need to be set.
>
> aspeed_i2c_init_clk() was performing a direct write of the generated
> clock values rather than a read/mask/modify/update sequence to retain
> tBUF, tHDSTA and tACST, and therefore cleared the tBUF, tHDSTA and tACST
> fields on the AST2400. This resulted in a delay/setup/hold time of 1
> base clock, which in some configurations is not enough for some devices
> (e.g. the MAX31785 fan controller, with an APB of 48MHz and a desired
> bus speed of 100kHz).
>
> Signed-off-by: Andrew Jeffery 
> ---
>  drivers/i2c/busses/i2c-aspeed.c | 9 -
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index ee76e6dddc4b..284f8670dbeb 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -53,6 +53,9 @@
>  #define ASPEED_I2CD_MASTER_EN  BIT(0)
>
>  /* 0x04 : I2CD Clock and AC Timing Control Register #1 */
> +#define ASPEED_I2CD_TIME_TBUF_MASK GENMASK(31, 28)
> +#define ASPEED_I2CD_TIME_THDSTA_MASK   GENMASK(27, 24)
> +#define ASPEED_I2CD_TIME_TACST_MASKGENMASK(23, 20)
>  #define ASPEED_I2CD_TIME_SCL_HIGH_SHIFT16
>  #define ASPEED_I2CD_TIME_SCL_HIGH_MASK GENMASK(19, 16)
>  #define ASPEED_I2CD_TIME_SCL_LOW_SHIFT 12
> @@ -744,7 +747,11 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus 
> *bus)
> u32 divisor, clk_reg_val;
>
> divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency);
> -   clk_reg_val = bus->get_clk_reg_val(divisor);
> +   clk_reg_val = readl(bus->base + ASPEED_I2C_AC_TIMING_REG1);
> +   clk_reg_val &= (ASPEED_I2CD_TIME_TBUF_MASK |
> +   ASPEED_I2CD_TIME_THDSTA_MASK |
> +   ASPEED_I2CD_TIME_TACST_MASK);
> +   clk_reg_val |= bus->get_clk_reg_val(divisor);
> writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1);
> writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2);
>
> --
> 2.11.0
>

Awesome! I think this might fix an issue we saw on one of our boards.
I am out of the country right now, so I cannot test this myself, until Monday.


Re: [PATCH v10 4/5] i2c: aspeed: added driver for Aspeed I2C

2017-06-19 Thread Brendan Higgins
I thought all of the comments made sense and will be addressed in my
next revision,
except the following:

>> +static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
>> +{
>> + unsigned long time_left, flags;
>> + int ret = 0;
>> + u32 command;
>> +
>> + spin_lock_irqsave(&bus->lock, flags);
>> + command = readl(bus->base + ASPEED_I2C_CMD_REG);
>> +
>> + if (command & ASPEED_I2CD_SDA_LINE_STS) {
>> + /* Bus is idle: no recovery needed. */
>> + if (command & ASPEED_I2CD_SCL_LINE_STS)
>> + goto out;
>> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
>> + command);
>> +
>> + reinit_completion(&bus->cmd_complete);
>> + writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
>> + spin_unlock_irqrestore(&bus->lock, flags);
>> +
>> + time_left = wait_for_completion_timeout(
>> + &bus->cmd_complete, bus->adap.timeout);
>> +
>> + spin_lock_irqsave(&bus->lock, flags);
>> + if (time_left == 0)
>> + goto reset_out;
>> + else if (bus->cmd_err)
>> + goto reset_out;
>> + /* Recovery failed. */
>> + else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
>> +ASPEED_I2CD_SCL_LINE_STS))
>> + goto reset_out;
>> + /* Bus error. */
>> + } else {
>> + dev_dbg(bus->dev, "bus hung (state %x), attempting recovery\n",
>> + command);
>
> Same dbg message as in the condition? Move it out of the 'if'?

Message is the same; that's true; however, I only want to print this
if I am actually doing
the recovery. There is a case in the first condition where we actually
don't attempt recovery.
(See both SDA and SCL high). Nevertheless, now that I am looking at
this. I think it might
make sense to make the dbg statements different since I can explain
what type of recovery
I am attempting.

>
>> +
>> + reinit_completion(&bus->cmd_complete);
>> + writel(ASPEED_I2CD_BUS_RECOVER_CMD,
>> +bus->base + ASPEED_I2C_CMD_REG);
>
> Out of interest: What does the RECOVER_CMD do?

According to the documentation, it attempts to create 1 to 8 SCL
cycles to force any stuck
device to let go of the SDA line. It then puts the hardware in a sane
state once it detects
that the bus has been recovered. I will put a comment to this effect.

>
>> + spin_unlock_irqrestore(&bus->lock, flags);
>> +
>> + time_left = wait_for_completion_timeout(
>> + &bus->cmd_complete, bus->adap.timeout);
>> +
>> + spin_lock_irqsave(&bus->lock, flags);
>> + if (time_left == 0)
>> + goto reset_out;
>> + else if (bus->cmd_err)
>> + goto reset_out;
>> + /* Recovery failed. */
>> + else if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
>> +ASPEED_I2CD_SDA_LINE_STS))
>> + goto reset_out;
>> + }
>> +
>> +out:
>> + spin_unlock_irqrestore(&bus->lock, flags);
>> +
>> + return ret;
>> +
>> +reset_out:
>> + spin_unlock_irqrestore(&bus->lock, flags);
>> +
>> + return aspeed_i2c_reset(bus);
>> +}

Cheers!


[PATCH v11 0/4] i2c: aspeed: added driver for Aspeed I2C

2017-06-20 Thread Brendan Higgins
Addressed comments from:
  - Wolfram in: http://www.spinics.net/lists/devicetree/msg182142.html
and http://www.spinics.net/lists/devicetree/msg182144.html

Changes since previous update:
  - MAINTAINERS: Added MAINTAINERS entry for Aspeed I2C driver and friends
  - I2C driver: Added support for COMPILE_TEST
  - I2C driver: Fixed i2c fault codes in interrupt handler
  - I2C driver: Use i2c_{get|set}_adapdata instead of adapter->algo_data
  - I2C driver: Fixed some other stylistic issues

As the Aspeed I2C interrupt controller changes were already accepted by the
irqchip maintainers, this patchset no longer contains them.

As before, tested on Aspeed 2500 evaluation board and a real platform with an
Aspeed 2520.


[PATCH v11 3/4] i2c: aspeed: added driver for Aspeed I2C

2017-06-20 Thread Brendan Higgins
Added initial master support for Aspeed I2C controller. Supports
fourteen busses present in AST24XX and AST25XX BMC SoCs by Aspeed.

Signed-off-by: Brendan Higgins 
---
hanges for v2:
  - Added single module_init (multiple was breaking some builds).
Changes for v3:
  - Removed "bus" device tree param; now extracted from bus address offset
Changes for v4:
  - I2C adapter number is now generated dynamically unless specified in alias.
Changes for v5:
  - Removed irq_chip used to multiplex IRQ and replaced it with dummy_irq_chip
along with some other IRQ cleanup.
  - Addressed comments from Cedric, and Vladimir, mostly stylistic things and
using devm managed resources.
  - Increased max clock frequency before the bus is put in HighSpeed mode, as
per Kachalov's comment.
Changes for v6:
  - No longer arbitrarily restrict bus to be slave xor master.
  - Pulled out "struct aspeed_i2c_controller" as a interrupt controller.
  - Pulled out slave support into its own commit.
  - Rewrote code that sets clock divider register because the original version
set it incorrectly.
  - Rewrote the aspeed_i2c_master_irq handler because the old method of
completing a completion in between restarts was too slow causing devices to
misbehave.
  - Added support for I2C_M_RECV_LEN which I had incorrectly said was supported
before.
  - Addressed other comments from Vladimir.
Changes for v7:
  - Changed clock-frequency to bus-frequency
  - Made some fixes to clock divider code
  - Added hardware reset function
  - Marked functions that need to be called with the lock held as "unlocked"
  - Did a bunch of clean up
Changes for v8:
  - ACK IRQ status bits before doing anything else
  - Added multi-master device tree property
  - Do not send STOP commands after interrupt errors
  - Fix SMBUS_QUICK emulation handling
  - Removed highspeed clock code (I will do it in a later patch set)
  - Use the platform_device name for the adapter name
  - Reset for all failed recoveries
  - Removed the "__" prefix from all of the non-thread safe functions
Changes for v9:
  - No longer debug log after every address NACK
  - Clear errors after reset
  - No longer access clock while holding lock
  - Ack all interrupts durring bus reset and initialization
Changes for v10:
  - Added master_xfer_result field to struct aspeed_i2c_bus
Changes for v11:
  - Added support for COMPILE_TEST
  - Fixed i2c fault codes in interrupt handler
  - Use i2c_{get|set}_adapdata instead of adapter->algo_data
  - Fixed some other stylistic issues
---
 drivers/i2c/busses/Kconfig  |  10 +
 drivers/i2c/busses/Makefile |   1 +
 drivers/i2c/busses/i2c-aspeed.c | 690 
 3 files changed, 701 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-aspeed.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 144cbadc7c72..6cb893a0911b 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -326,6 +326,16 @@ config I2C_POWERMAC
 
 comment "I2C system bus drivers (mostly embedded / system-on-chip)"
 
+config I2C_ASPEED
+   tristate "Aspeed I2C Controller"
+   depends on ARCH_ASPEED || COMPILE_TEST
+   help
+ If you say yes to this option, support will be included for the
+ Aspeed I2C controller.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-aspeed.
+
 config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on ARCH_AT91
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 30b60855fbcd..e84604b9bf3b 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_I2C_HYDRA)   += i2c-hydra.o
 obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
 
 # Embedded system I2C/SMBus host controller drivers
+obj-$(CONFIG_I2C_ASPEED)   += i2c-aspeed.o
 obj-$(CONFIG_I2C_AT91) += i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)   += i2c-au1550.o
 obj-$(CONFIG_I2C_AXXIA)+= i2c-axxia.o
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
new file mode 100644
index ..55f241f2cfcc
--- /dev/null
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -0,0 +1,690 @@
+/*
+ *  Aspeed 24XX/25XX I2C Controller.
+ *
+ *  Copyright (C) 2012-2017 ASPEED Technology Inc.
+ *  Copyright 2017 IBM Corporation
+ *  Copyright 2017 Google, 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* I2C Register */
+#define ASPEED_I2C_FUN_C

[PATCH v11 4/4] i2c: aspeed: added slave support for Aspeed I2C driver

2017-06-20 Thread Brendan Higgins
Added slave support for Aspeed I2C controller. Supports fourteen busses
present in AST24XX and AST25XX BMC SoCs by Aspeed.

Signed-off-by: Brendan Higgins 
---
Added in v6:
  - Pulled slave support out of initial driver commit into its own commit.
  - No longer arbitrarily restrict bus to be slave xor master.
Changes for v7:
  - Added hardware reset function
  - Marked functions that need to be called with the lock held as "unlocked"
  - Did some cleanup
Changes for v8:
  - None
Changes for v9:
  - None
Changes for v10:
  - None
Changes for v11:
  - Use i2c_{get|set}_adapdata instead of adapter->algo_data
---
 drivers/i2c/busses/i2c-aspeed.c | 201 
 1 file changed, 201 insertions(+)

diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 55f241f2cfcc..f19348328a71 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -49,6 +49,7 @@
 #define ASPEED_I2CD_SDA_DRIVE_1T_ENBIT(8)
 #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN  BIT(7)
 #define ASPEED_I2CD_M_HIGH_SPEED_ENBIT(6)
+#define ASPEED_I2CD_SLAVE_EN   BIT(1)
 #define ASPEED_I2CD_MASTER_EN  BIT(0)
 
 /* 0x04 : I2CD Clock and AC Timing Control Register #1 */
@@ -69,6 +70,7 @@
  */
 #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUTBIT(14)
 #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE  BIT(13)
+#define ASPEED_I2CD_INTR_SLAVE_MATCH   BIT(7)
 #define ASPEED_I2CD_INTR_SCL_TIMEOUT   BIT(6)
 #define ASPEED_I2CD_INTR_ABNORMAL  BIT(5)
 #define ASPEED_I2CD_INTR_NORMAL_STOP   BIT(4)
@@ -101,6 +103,9 @@
 #define ASPEED_I2CD_M_TX_CMD   BIT(1)
 #define ASPEED_I2CD_M_START_CMDBIT(0)
 
+/* 0x18 : I2CD Slave Device Address Register   */
+#define ASPEED_I2CD_DEV_ADDR_MASK  GENMASK(6, 0)
+
 enum aspeed_i2c_master_state {
ASPEED_I2C_MASTER_START,
ASPEED_I2C_MASTER_TX_FIRST,
@@ -111,6 +116,15 @@ enum aspeed_i2c_master_state {
ASPEED_I2C_MASTER_INACTIVE,
 };
 
+enum aspeed_i2c_slave_state {
+   ASPEED_I2C_SLAVE_START,
+   ASPEED_I2C_SLAVE_READ_REQUESTED,
+   ASPEED_I2C_SLAVE_READ_PROCESSED,
+   ASPEED_I2C_SLAVE_WRITE_REQUESTED,
+   ASPEED_I2C_SLAVE_WRITE_RECEIVED,
+   ASPEED_I2C_SLAVE_STOP,
+};
+
 struct aspeed_i2c_bus {
struct i2c_adapter  adap;
struct device   *dev;
@@ -130,6 +144,10 @@ struct aspeed_i2c_bus {
int cmd_err;
/* Protected only by i2c_lock_bus */
int master_xfer_result;
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+   struct i2c_client   *slave;
+   enum aspeed_i2c_slave_state slave_state;
+#endif /* CONFIG_I2C_SLAVE */
 };
 
 static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
@@ -202,6 +220,110 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus 
*bus)
return aspeed_i2c_reset(bus);
 }
 
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
+{
+   u32 command, irq_status, status_ack = 0;
+   struct i2c_client *slave = bus->slave;
+   bool irq_handled = true;
+   u8 value;
+
+   spin_lock(&bus->lock);
+   if (!slave) {
+   irq_handled = false;
+   goto out;
+   }
+
+   command = readl(bus->base + ASPEED_I2C_CMD_REG);
+   irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+
+   /* Slave was requested, restart state machine. */
+   if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
+   status_ack |= ASPEED_I2CD_INTR_SLAVE_MATCH;
+   bus->slave_state = ASPEED_I2C_SLAVE_START;
+   }
+
+   /* Slave is not currently active, irq was for someone else. */
+   if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
+   irq_handled = false;
+   goto out;
+   }
+
+   dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
+   irq_status, command);
+
+   /* Slave was sent something. */
+   if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
+   value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
+   /* Handle address frame. */
+   if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
+   if (value & 0x1)
+   bus->slave_state =
+   ASPEED_I2C_SLAVE_READ_REQUESTED;
+   else
+   bus->slave_state =
+   
ASPEED_I2C_SLAVE_WRITE_REQUESTED;
+   }
+   status_ack |= ASPEED_I2CD_INTR_RX_DONE;
+   }
+
+   /* Sla

[PATCH v11 2/4] i2c: aspeed: added documentation for Aspeed I2C driver

2017-06-20 Thread Brendan Higgins
Added device tree binding documentation for Aspeed I2C busses.

Signed-off-by: Brendan Higgins 
Acked-by: Rob Herring 
---
hanges for v2:
  - None
Changes for v3:
  - Removed reference to "bus" device tree param
Changes for v4:
  - None
Changes for v5:
  - None
Changes for v6:
  - Replaced the controller property with and interrupt controller, leaving only
the busses in the I2C documentation.
Changes for v7:
  - Changed clock-frequency to bus-frequency in device tree
Changes for v8:
  - Added multi-master property to device tree
Changes for v9:
  - None
Changes for v10:
  - None
Changes for v11:
  - None
---
 .../devicetree/bindings/i2c/i2c-aspeed.txt | 48 ++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/i2c-aspeed.txt

diff --git a/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt 
b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
new file mode 100644
index ..bd6480b19535
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
@@ -0,0 +1,48 @@
+Device tree configuration for the I2C busses on the AST24XX and AST25XX SoCs.
+
+Required Properties:
+- #address-cells   : should be 1
+- #size-cells  : should be 0
+- reg  : address offset and range of bus
+- compatible   : should be "aspeed,ast2400-i2c-bus"
+ or "aspeed,ast2500-i2c-bus"
+- clocks   : root clock of bus, should reference the APB
+ clock
+- interrupts   : interrupt number
+- interrupt-parent : interrupt controller for bus, should reference a
+ aspeed,ast2400-i2c-ic or aspeed,ast2500-i2c-ic
+ interrupt controller
+
+Optional Properties:
+- bus-frequency: frequency of the bus clock in Hz defaults to 100 kHz 
when not
+ specified
+- multi-master : states that there is another master active on this bus.
+
+Example:
+
+i2c {
+   compatible = "simple-bus";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0 0x1e78a000 0x1000>;
+
+   i2c_ic: interrupt-controller@0 {
+   #interrupt-cells = <1>;
+   compatible = "aspeed,ast2400-i2c-ic";
+   reg = <0x0 0x40>;
+   interrupts = <12>;
+   interrupt-controller;
+   };
+
+   i2c0: i2c-bus@40 {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   #interrupt-cells = <1>;
+   reg = <0x40 0x40>;
+   compatible = "aspeed,ast2400-i2c-bus";
+   clocks = <&clk_apb>;
+   bus-frequency = <10>;
+   interrupts = <0>;
+   interrupt-parent = <&i2c_ic>;
+   };
+};
-- 
2.13.1.611.g7e3b11ae1-goog



[PATCH v11 1/4] MAINTAINERS: add entry for Aspeed I2C driver

2017-06-20 Thread Brendan Higgins
Added myself as maintainer of the Aspeed I2C driver and the associated
I2C interrupt controller and added Joel Stanley and Benjamin
Herrenschmidt as reviewers.

Signed-off-by: Brendan Higgins 
---
Added in v11:
  - Added MAINTAINERS entry for Aspeed I2C driver and friends
---
 MAINTAINERS | 12 
 1 file changed, 12 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 053c3bdd1fe5..2bb541549cc1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1123,6 +1123,18 @@ F:   arch/arm/mach-aspeed/
 F: arch/arm/boot/dts/aspeed-*
 F: drivers/*/*aspeed*
 
+ARM/ASPEED I2C DRIVER
+M: Brendan Higgins 
+R: Benjamin Herrenschmidt 
+R: Joel Stanley 
+L: linux-...@vger.kernel.org
+L: open...@lists.ozlabs.org
+S: Maintained
+F: drivers/irqchip/irq-aspeed-i2c-ic.c
+F: drivers/i2c/busses/i2c-aspeed.c
+F: 
Documentation/devicetree/bindings/interrupt-controller/aspeed,ast2400-i2c-ic.txt
+F: Documentation/devicetree/bindings/i2c/i2c-aspeed.txt
+
 ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
 M: Nicolas Ferre 
 M: Alexandre Belloni 
-- 
2.13.1.611.g7e3b11ae1-goog



Re: [PATCH v2 0/2] clocksource: npcm: add NPCM7xx timer driver

2017-11-03 Thread Brendan Higgins
On Wed, Nov 1, 2017 at 5:16 AM, Tomer Maimon  wrote:
> Addressed comments from:
>  - Daniel Lezcano: https://www.spinics.net/lists/devicetree/msg196683.html
>
> Changes since version 1:
>  - Rename driver name
>  - Removing unnecessary dependencies in configuration
>  - Adding prefix to the macros
>  - No changes to dt-binding documentation since v1
>
> Asked Brendon to modify NPCM7xx device tree for support NPCM7xx timer driver
> https://www.spinics.net/lists/arm-kernel/msg614424.html

Rob Herring asks that we keep the device tree binding the same as I have it.
Unless, there is some part of the conversation that I am missing.

>
> Changes have been tested on the NPCM750 evaluation board.
>
> Tomer Maimon (2):
>   clocksource: npcm: add NPCM7xx timer driver
>   dt-binding: timer: document NPCM7xx timer DT bindings
>
>  .../bindings/timer/nuvoton,npcm7xx-timer.txt   |  25 +++
>  drivers/clocksource/Kconfig|   8 +
>  drivers/clocksource/Makefile   |   1 +
>  drivers/clocksource/npcm7xx-timer.c| 224 
> +
>  4 files changed, 258 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.txt
>  create mode 100644 drivers/clocksource/npcm7xx-timer.c
>
> --
> 2.14.1
>


Re: [PATCH v2 1/2] clocksource: npcm: add NPCM7xx timer driver

2017-11-03 Thread Brendan Higgins
Looks like you missed a couple of comments from Daniel:
https://www.spinics.net/lists/devicetree/msg196683.html

Also, I think the binding documentation is supposed to come before the driver.

On Wed, Nov 1, 2017 at 5:16 AM, Tomer Maimon  wrote:
> Add Nuvoton BMC NPCM7xx timer driver.
>
> the clocksource Enable 24-bit TIMER0 and TIMER1 counters,
> while TIMER0 serves as clockevent and TIMER1 serves as clocksource.
>
> Signed-off-by: Tomer Maimon 
> ---
>  drivers/clocksource/Kconfig |   8 ++
>  drivers/clocksource/Makefile|   1 +
>  drivers/clocksource/npcm7xx-timer.c | 224 
> 
>  3 files changed, 233 insertions(+)
>  create mode 100644 drivers/clocksource/npcm7xx-timer.c

Looks like you forgot to rename the driver.

>
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index cc6062049170..46184af75d6c 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -140,6 +140,14 @@ config VT8500_TIMER
> help
>   Enables support for the VT8500 driver.
>
> +config NPCM7XX_TIMER
> +   bool "NPCM7xx timer driver" if COMPILE_TEST
> +   depends on HAS_IOMEM
> +   select CLKSRC_MMIO
> +   help
> + Enable 24-bit TIMER0 and TIMER1 counters in the NPCM7xx arcithcture,
> + While TIMER0 serves as clockevent and TIMER1 serves as clocksource.
> +
>  config CADENCE_TTC_TIMER
> bool "Cadence TTC timer driver" if COMPILE_TEST
> depends on COMMON_CLK
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index dbc1ad14515e..f2a9318a1eec 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -53,6 +53,7 @@ obj-$(CONFIG_CLKSRC_TI_32K)   += timer-ti-32k.o
>  obj-$(CONFIG_CLKSRC_NPS)   += timer-nps.o
>  obj-$(CONFIG_OXNAS_RPS_TIMER)  += timer-oxnas-rps.o
>  obj-$(CONFIG_OWL_TIMER)+= owl-timer.o
> +obj-$(CONFIG_NPCM7XX_TIMER)+= npcm7xx-timer.o
>
>  obj-$(CONFIG_ARC_TIMERS)   += arc_timer.o
>  obj-$(CONFIG_ARM_ARCH_TIMER)   += arm_arch_timer.o
> diff --git a/drivers/clocksource/npcm7xx-timer.c 
> b/drivers/clocksource/npcm7xx-timer.c
> new file mode 100644
> index ..d1ea5c183a69
> --- /dev/null
> +++ b/drivers/clocksource/npcm7xx-timer.c
> @@ -0,0 +1,224 @@
> +
> +/*
> + * Copyright (c) 2017 Nuvoton Technology corporation.
> + * Copyright 2017 Google, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation;version 2 of the License.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +struct npcm7xx_clockevent_data {
> +   struct clock_event_device cvd;
> +   void __iomem *timer_base;
> +   unsigned int rate;
> +};
> +
> +/* Timers registers */
> +#define NPCM7XX_REG_TCSR0  0x0 /* Timer 0 Control and Status Register */
> +#define NPCM7XX_REG_TICR0  0x8 /* Timer 0 Initial Count Register */
> +#define NPCM7XX_REG_TCSR1  0x4 /* Timer 1 Control and Status Register */
> +#define NPCM7XX_REG_TICR1  0xc /* Timer 1 Initial Count Register */
> +#define NPCM7XX_REG_TDR1   0x14 /* Timer 1 Data Register */
> +#define NPCM7XX_REG_TISR   0x18 /* Timer Interrupt Status Register */
> +
> +/* Timers control */
> +#define NPCM7XX_Tx_RESETINT0x1f
> +#define NPCM7XX_Tx_PERIOD  BIT(27)
> +#define NPCM7XX_Tx_INTEN   BIT(29)
> +#define NPCM7XX_Tx_COUNTEN BIT(30)
> +#define NPCM7XX_Tx_ONESHOT 0x0
> +#define NPCM7XX_Tx_OPERGENMASK(3, 27)
> +#define NPCM7XX_Tx_MIN_PRESCALE0x1
> +#define NPCM7XX_Tx_TDR_MASK_BITS   24
> +#define NPCM7XX_Tx_MAX_CNT 0xFF
> +#define NPCM7XX_T0_CLR_INT 0x1
> +#define NPCM7XX_Tx_CLR_CSR 0x0
> +
> +/* Timers operating mode */
> +#define NPCM7XX_START_PERIODIC_Tx (NPCM7XX_Tx_PERIOD | NPCM7XX_Tx_COUNTEN | \
> +   NPCM7XX_Tx_INTEN | \
> +   NPCM7XX_Tx_MIN_PRESCALE)
> +
> +#define NPCM7XX_START_ONESHOT_Tx (NPCM7XX_Tx_ONESHOT | NPCM7XX_Tx_COUNTEN | \
> +   NPCM7XX_Tx_INTEN | \
> +   NPCM7XX_Tx_MIN_PRESCALE)
> +#define NPCM7XX_START_Tx (NPCM7XX_Tx_COUNTEN | NPCM7XX_Tx_PERIOD | \
> +   NPCM7XX_Tx_MIN_PRESCALE)
> +
> +static int npcm7xx_timer_oneshot(struct clock_event_device *evt)
> +{
> +   u32 val;
> +   struct npcm7xx_clockevent_data *cevtd =
> +   container_of(evt, struct npcm7xx_clockevent_data, cvd);
> +
> +   val = readl(cevtd->timer_base + NPCM7XX_REG_TCSR0);
> +   val &= ~NPCM7XX_Tx_OPER;
> +
> +   val = readl(cevtd->timer_base + NPCM7XX_REG_TCSR0);
> + 

Re: [PATCH v7 1/3] arm: npcm: add basic support for Nuvoton BMCs

2017-11-03 Thread Brendan Higgins
On Thu, Oct 26, 2017 at 4:45 AM, Tomer Maimon  wrote:
> Hi Brendan,
>
> Sorry for the delay,
>
> On 21 October 2017 at 00:08, Russell King - ARM Linux
>  wrote:
>> On Fri, Oct 20, 2017 at 01:57:47PM -0700, Brendan Higgins wrote:
>>> On Fri, Oct 20, 2017 at 3:48 AM, Russell King - ARM Linux
>>>  wrote:
>>> > On Thu, Oct 19, 2017 at 03:50:48PM -0700, Brendan Higgins wrote:
>>> >> Adds basic support for the Nuvoton NPCM750 BMC.
>>> >>
>>> >> Signed-off-by: Brendan Higgins 
>>> >> Reviewed-by: Tomer Maimon 
>>> >> Reviewed-by: Avi Fishman 
>>> >> Tested-by: Tomer Maimon 
>>> >> Tested-by: Avi Fishman 
>>> >> ---
>>> >>  arch/arm/Kconfig |  2 +
>>> >>  arch/arm/Makefile|  1 +
>>> >>  arch/arm/mach-npcm/Kconfig   | 48 
>>> >>  arch/arm/mach-npcm/Makefile  |  3 ++
>>> >>  arch/arm/mach-npcm/headsmp.S | 17 +
>>> >>  arch/arm/mach-npcm/npcm7xx.c | 34 +
>>> >>  arch/arm/mach-npcm/platsmp.c | 88 
>>> >> 
>>> >>  7 files changed, 193 insertions(+)
>>> >>  create mode 100644 arch/arm/mach-npcm/Kconfig
>>> >>  create mode 100644 arch/arm/mach-npcm/Makefile
>>> >>  create mode 100644 arch/arm/mach-npcm/headsmp.S
>>> >>  create mode 100644 arch/arm/mach-npcm/npcm7xx.c
>>> >>  create mode 100644 arch/arm/mach-npcm/platsmp.c
>>> >>
>>> >> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
>>> >> index 61a0cb15067e..05543f1cfbde 100644
>>> >> --- a/arch/arm/Kconfig
>>> >> +++ b/arch/arm/Kconfig
>>> >> @@ -782,6 +782,8 @@ source "arch/arm/mach-netx/Kconfig"
>>> >>
>>> >>  source "arch/arm/mach-nomadik/Kconfig"
>>> >>
>>> >> +source "arch/arm/mach-npcm/Kconfig"
>>> >> +
>>> >>  source "arch/arm/mach-nspire/Kconfig"
>>> >>
>>> >>  source "arch/arm/plat-omap/Kconfig"
>>> >> diff --git a/arch/arm/Makefile b/arch/arm/Makefile
>>> >> index 47d3a1ab08d2..60ca50c7d762 100644
>>> >> --- a/arch/arm/Makefile
>>> >> +++ b/arch/arm/Makefile
>>> >> @@ -191,6 +191,7 @@ machine-$(CONFIG_ARCH_MEDIATEK)   += mediatek
>>> >>  machine-$(CONFIG_ARCH_MXS)   += mxs
>>> >>  machine-$(CONFIG_ARCH_NETX)  += netx
>>> >>  machine-$(CONFIG_ARCH_NOMADIK)   += nomadik
>>> >> +machine-$(CONFIG_ARCH_NPCM)  += npcm
>>> >>  machine-$(CONFIG_ARCH_NSPIRE)+= nspire
>>> >>  machine-$(CONFIG_ARCH_OXNAS) += oxnas
>>> >>  machine-$(CONFIG_ARCH_OMAP1) += omap1
>>> >> diff --git a/arch/arm/mach-npcm/Kconfig b/arch/arm/mach-npcm/Kconfig
>>> >> new file mode 100644
>>> >> index ..21dfa8ce828f
>>> >> --- /dev/null
>>> >> +++ b/arch/arm/mach-npcm/Kconfig
>>> >> @@ -0,0 +1,48 @@
>>> >> +menuconfig ARCH_NPCM
>>> >> + bool "Nuvoton NPCM Architecture"
>>> >> + select ARCH_REQUIRE_GPIOLIB
>>> >> + select USE_OF
>>> >> + select PINCTRL
>>> >> + select PINCTRL_NPCM7XX
>>> >> +
>>> >> +if ARCH_NPCM
>>> >> +
>>> >> +comment "NPCMX50 CPU type"
>>> >> +
>>> >> +config CPU_NPCM750
>
> I started the upstream process of NPCM7xx clocksource driver, I got
> the following comment
> https://www.spinics.net/lists/devicetree/msg197916.html
>
> Is it possible to modify the the architecture configuration name to
> ARCH_NPCM7XX.

You mean the CPU config: CPU_NPCM7XX?

I think the ARCH_NPCM is right, since that corresponds to this directory
which is for all ARM Nuvoton BMCs.

>
>>> >> + depends on ARCH_NPCM && ARCH_MULTI_V7
>>> >> + bool "Support for NPCM750 BMC CPU (Poleg)"
>>> >> + select CACHE_L2X0
>>> >> + select CPU_V7
>>> >> + select ARM_GIC
>>> >> + select HAVE_SMP
>>> >> + select SMP
>>> >> + select SMP_ON_UP
>>> >> + select HAVE_ARM_SCU
>>> >> +  

Re: [PATCH v2] i2c: aspeed: Deassert reset in probe

2017-10-18 Thread Brendan Higgins
On Wed, Oct 18, 2017 at 7:29 AM, Joel Stanley  wrote:
> In order to use i2c from a cold boot, the i2c peripheral must be taken
> out of reset. We request a shared reset controller each time a bus
> driver is loaded, as the reset is shared between the 14 i2c buses.
>
> On remove the reset is asserted, which only touches the hardware once
> the last i2c bus is removed.
>
> The request is optional, so if a device tree does not specify a reset
> controller (or the driver is not built in), the driver continues to
> probe.
>
> Signed-off-by: Joel Stanley 
> ---
> v2: Sort the headers
>
>  drivers/i2c/busses/i2c-aspeed.c | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index 284f8670dbeb..a2006376322f 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -12,6 +12,7 @@
>
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -27,6 +28,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>
>  /* I2C Register */
> @@ -132,6 +134,7 @@ struct aspeed_i2c_bus {
> struct i2c_adapter  adap;
> struct device   *dev;
> void __iomem*base;
> +   struct reset_control*rst;
> /* Synchronizes I/O mem access to base. */
> spinlock_t  lock;
> struct completion   cmd_complete;
> @@ -847,6 +850,9 @@ static int aspeed_i2c_probe_bus(struct platform_device 
> *pdev)
> /* We just need the clock rate, we don't actually use the clk object. 
> */
> devm_clk_put(&pdev->dev, parent_clk);
>
> +   bus->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
> +   reset_control_deassert(bus->rst);
> +
> ret = of_property_read_u32(pdev->dev.of_node,
>"bus-frequency", &bus->bus_frequency);
> if (ret < 0) {
> @@ -919,6 +925,8 @@ static int aspeed_i2c_remove_bus(struct platform_device 
> *pdev)
>
> i2c_del_adapter(&bus->adap);
>
> +   reset_control_assert(bus->rst);
> +
> return 0;
>  }
>
> --
> 2.14.1
>
Reviewed-by: Brendan Higgins 


Re: [PATCH v6 2/3] arm: dts: add Nuvoton NPCM750 device tree

2017-10-19 Thread Brendan Higgins
Sorry for the delay. A couple questions:

On Wed, Sep 27, 2017 at 2:42 PM, Rob Herring  wrote:
> On Tue, Sep 19, 2017 at 03:40:00PM -0700, Brendan Higgins wrote:
>> Add a common device tree for all Nuvoton NPCM750 BMCs and a board
>> specific device tree for the NPCM750 (Poleg) evaluation board.
>>
>> Signed-off-by: Brendan Higgins 
>> Reviewed-by: Tomer Maimon 
>> Reviewed-by: Avi Fishman 
>> Reviewed-by: Joel Stanley 
>> Tested-by: Tomer Maimon 
>> Tested-by: Avi Fishman 
>> ---
>>  .../arm/cpu-enable-method/nuvoton,npcm7xx-smp  |  42 
>>  .../devicetree/bindings/arm/npcm/npcm.txt  |   6 +
>>  arch/arm/boot/dts/nuvoton-npcm750-evb.dts  |  48 +
>>  arch/arm/boot/dts/nuvoton-npcm750.dtsi | 211 
>> +
>>  include/dt-bindings/clock/nuvoton,npcm7xx-clks.h   |  39 
>>  5 files changed, 346 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp
>>  create mode 100644 Documentation/devicetree/bindings/arm/npcm/npcm.txt
>>  create mode 100644 arch/arm/boot/dts/nuvoton-npcm750-evb.dts
>>  create mode 100644 arch/arm/boot/dts/nuvoton-npcm750.dtsi
>>  create mode 100644 include/dt-bindings/clock/nuvoton,npcm7xx-clks.h
>>
>> diff --git 
>> a/Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp
>>  
>> b/Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp
>> new file mode 100644
>> index ..e81f85b400cf
>> --- /dev/null
>> +++ 
>> b/Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp
>> @@ -0,0 +1,42 @@
>> +=
>> +Secondary CPU enable-method "nuvoton,npcm7xx-smp" binding
>> +=
>> +
>> +To apply to all CPUs, a single "nuvoton,npcm7xx-smp" enable method should be
>> +defined in the "cpus" node.
>> +
>> +Enable method name:  "nuvoton,npcm7xx-smp"
>> +Compatible machines: "nuvoton,npcm750"
>> +Compatible CPUs: "arm,cortex-a9"
>> +Related properties:  (none)
>> +
>> +Note:
>> +This enable method needs valid nodes compatible with "arm,cortex-a9-scu" and
>> +"nuvoton,npcm750-gcr".
>> +
>> +Example:
>> +
>> + cpus {
>> + #address-cells = <1>;
>> + #size-cells = <0>;
>> + enable-method = "nuvoton,npcm7xx-smp";
>> +
>> + cpu@0 {
>> + device_type = "cpu";
>> + compatible = "arm,cortex-a9";
>> + clocks = <&clk NPCM7XX_CLK_CPU>;
>> + clock-names = "clk_cpu";
>> + reg = <0>;
>> + next-level-cache = <&L2>;
>> + };
>> +
>> + cpu@1 {
>> + device_type = "cpu";
>> + compatible = "arm,cortex-a9";
>> + clocks = <&clk NPCM7XX_CLK_CPU>;
>> + clock-names = "clk_cpu";
>> + reg = <1>;
>> + next-level-cache = <&L2>;
>> + };
>> + };
>> +
>> diff --git a/Documentation/devicetree/bindings/arm/npcm/npcm.txt 
>> b/Documentation/devicetree/bindings/arm/npcm/npcm.txt
>> new file mode 100644
>> index ..2d87d9ecea85
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/npcm/npcm.txt
>> @@ -0,0 +1,6 @@
>> +NPCM Platforms Device Tree Bindings
>> +---
>> +NPCM750 SoC
>> +Required root node properties:
>> + - compatible = "nuvoton,npcm750";
>> +
>> diff --git a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts 
>> b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
>> new file mode 100644
>> index ..a0675e584125
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
>> @@ -0,0 +1,48 @@
>> +/*
>> + * DTS file for all NPCM750 SoCs
>> + *
>> + * Copyright 2012 Tomer Maimon 
>> + *
>> + * The code contained herein is licensed under the GNU General Public
>> + * License. You may obtain a copy of the GNU General Public License
>> + * Version 2 or later at the following locations:
>> + *
>> + * http://www.op

[PATCH v7 0/3] arm: npcm: add basic support for Nuvoton BMCs

2017-10-19 Thread Brendan Higgins
Addressed comments from:
  - Rob: http://www.spinics.net/lists/devicetree/msg196376.html

Changes since previous update:
  - Moved all memory mapped nodes to busses.
  - Map ranges starting at 0
  - Moved external clocks to root
  - No changes to mach-npcm since v5
  - No changes to MAINTAINERS since v5

Changes have been tested on the NPCM750 evaluation board.


[PATCH v7 3/3] MAINTAINERS: Add entry for the Nuvoton NPCM architecture

2017-10-19 Thread Brendan Higgins
Add maintainers and reviewers for the Nuvoton NPCM architecture.

Signed-off-by: Brendan Higgins 
Reviewed-by: Tomer Maimon 
Reviewed-by: Avi Fishman 
---
 MAINTAINERS | 13 +
 1 file changed, 13 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 44cb004c765d..ec0d35384a16 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1598,6 +1598,19 @@ F:   drivers/pinctrl/nomadik/
 F: drivers/i2c/busses/i2c-nomadik.c
 T: git 
git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git
 
+ARM/NUVOTON NPCM ARCHITECTURE
+M: Avi Fishman 
+M: Tomer Maimon 
+R: Brendan Higgins 
+R: Rick Altherr 
+L: open...@lists.ozlabs.org (moderated for non-subscribers)
+S: Supported
+F: arch/arm/mach-npcm/
+F: arch/arm/boot/dts/nuvoton-npcm*
+F: include/dt-bindings/clock/nuvoton,npcm7xx-clks.h
+F: drivers/*/*npcm*
+F: Documentation/*/*npcm*
+
 ARM/NUVOTON W90X900 ARM ARCHITECTURE
 M: Wan ZongShun 
 L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers)
-- 
2.15.0.rc0.271.g36b669edcc-goog



[PATCH v7 1/3] arm: npcm: add basic support for Nuvoton BMCs

2017-10-19 Thread Brendan Higgins
Adds basic support for the Nuvoton NPCM750 BMC.

Signed-off-by: Brendan Higgins 
Reviewed-by: Tomer Maimon 
Reviewed-by: Avi Fishman 
Tested-by: Tomer Maimon 
Tested-by: Avi Fishman 
---
 arch/arm/Kconfig |  2 +
 arch/arm/Makefile|  1 +
 arch/arm/mach-npcm/Kconfig   | 48 
 arch/arm/mach-npcm/Makefile  |  3 ++
 arch/arm/mach-npcm/headsmp.S | 17 +
 arch/arm/mach-npcm/npcm7xx.c | 34 +
 arch/arm/mach-npcm/platsmp.c | 88 
 7 files changed, 193 insertions(+)
 create mode 100644 arch/arm/mach-npcm/Kconfig
 create mode 100644 arch/arm/mach-npcm/Makefile
 create mode 100644 arch/arm/mach-npcm/headsmp.S
 create mode 100644 arch/arm/mach-npcm/npcm7xx.c
 create mode 100644 arch/arm/mach-npcm/platsmp.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 61a0cb15067e..05543f1cfbde 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -782,6 +782,8 @@ source "arch/arm/mach-netx/Kconfig"
 
 source "arch/arm/mach-nomadik/Kconfig"
 
+source "arch/arm/mach-npcm/Kconfig"
+
 source "arch/arm/mach-nspire/Kconfig"
 
 source "arch/arm/plat-omap/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 47d3a1ab08d2..60ca50c7d762 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -191,6 +191,7 @@ machine-$(CONFIG_ARCH_MEDIATEK) += mediatek
 machine-$(CONFIG_ARCH_MXS) += mxs
 machine-$(CONFIG_ARCH_NETX)+= netx
 machine-$(CONFIG_ARCH_NOMADIK) += nomadik
+machine-$(CONFIG_ARCH_NPCM)+= npcm
 machine-$(CONFIG_ARCH_NSPIRE)  += nspire
 machine-$(CONFIG_ARCH_OXNAS)   += oxnas
 machine-$(CONFIG_ARCH_OMAP1)   += omap1
diff --git a/arch/arm/mach-npcm/Kconfig b/arch/arm/mach-npcm/Kconfig
new file mode 100644
index ..21dfa8ce828f
--- /dev/null
+++ b/arch/arm/mach-npcm/Kconfig
@@ -0,0 +1,48 @@
+menuconfig ARCH_NPCM
+   bool "Nuvoton NPCM Architecture"
+   select ARCH_REQUIRE_GPIOLIB
+   select USE_OF
+   select PINCTRL
+   select PINCTRL_NPCM7XX
+
+if ARCH_NPCM
+
+comment "NPCMX50 CPU type"
+
+config CPU_NPCM750
+   depends on ARCH_NPCM && ARCH_MULTI_V7
+   bool "Support for NPCM750 BMC CPU (Poleg)"
+   select CACHE_L2X0
+   select CPU_V7
+   select ARM_GIC
+   select HAVE_SMP
+   select SMP
+   select SMP_ON_UP
+   select HAVE_ARM_SCU
+   select HAVE_ARM_TWD if SMP
+   select ARM_ERRATA_720789
+   select ARM_ERRATA_754322
+   select ARM_ERRATA_764369
+   select ARM_ERRATA_794072
+   select PL310_ERRATA_588369
+   select PL310_ERRATA_727915
+   select USB_EHCI_ROOT_HUB_TT
+   select USB_ARCH_HAS_HCD
+   select USB_ARCH_HAS_EHCI
+   select USB_EHCI_HCD
+   select USB_ARCH_HAS_OHCI
+   select USB_OHCI_HCD
+   select USB
+   select FIQ
+   select CPU_USE_DOMAINS
+   select GENERIC_CLOCKEVENTS
+   select CLKDEV_LOOKUP
+   select COMMON_CLK if OF
+   select NPCM750_TIMER
+   select MFD_SYSCON
+   help
+ Support for NPCM750 BMC CPU (Poleg).
+
+ Nuvoton NPCM750 BMC based on the Cortex A9.
+
+endif
diff --git a/arch/arm/mach-npcm/Makefile b/arch/arm/mach-npcm/Makefile
new file mode 100644
index ..78416055b854
--- /dev/null
+++ b/arch/arm/mach-npcm/Makefile
@@ -0,0 +1,3 @@
+AFLAGS_headsmp.o   += -march=armv7-a
+
+obj-$(CONFIG_CPU_NPCM750)  += npcm7xx.o platsmp.o headsmp.o
diff --git a/arch/arm/mach-npcm/headsmp.S b/arch/arm/mach-npcm/headsmp.S
new file mode 100644
index ..9fccbbd49ed4
--- /dev/null
+++ b/arch/arm/mach-npcm/headsmp.S
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2017 Google, 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.
+ */
+
+#include 
+#include 
+#include 
+
+ENTRY(npcm7xx_secondary_startup)
+   safe_svcmode_maskall r0
+
+   b   secondary_startup
+ENDPROC(npcm7xx_secondary_startup)
diff --git a/arch/arm/mach-npcm/npcm7xx.c b/arch/arm/mach-npcm/npcm7xx.c
new file mode 100644
index ..132e9d587857
--- /dev/null
+++ b/arch/arm/mach-npcm/npcm7xx.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Nuvoton Technology corporation.
+ * Copyright 2017 Google, 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NPCM7XX_AUX_VAL (L310_AUX_CTRL_INSTR_PREFETCH |
   \
+L310_AUX_CTRL_DATA_PREFETCH | \
+L310_AUX_CTRL_NS_LOCKDO

[PATCH v7 2/3] arm: dts: add Nuvoton NPCM750 device tree

2017-10-19 Thread Brendan Higgins
Add a common device tree for all Nuvoton NPCM750 BMCs and a board
specific device tree for the NPCM750 (Poleg) evaluation board.

Signed-off-by: Brendan Higgins 
Reviewed-by: Tomer Maimon 
Reviewed-by: Avi Fishman 
Reviewed-by: Joel Stanley 
Tested-by: Tomer Maimon 
Tested-by: Avi Fishman 
---
 .../arm/cpu-enable-method/nuvoton,npcm7xx-smp  |  42 +
 .../devicetree/bindings/arm/npcm/npcm.txt  |   6 +
 arch/arm/boot/dts/nuvoton-npcm750-evb.dts  |  48 +
 arch/arm/boot/dts/nuvoton-npcm750.dtsi | 198 +
 include/dt-bindings/clock/nuvoton,npcm7xx-clks.h   |  39 
 5 files changed, 333 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp
 create mode 100644 Documentation/devicetree/bindings/arm/npcm/npcm.txt
 create mode 100644 arch/arm/boot/dts/nuvoton-npcm750-evb.dts
 create mode 100644 arch/arm/boot/dts/nuvoton-npcm750.dtsi
 create mode 100644 include/dt-bindings/clock/nuvoton,npcm7xx-clks.h

diff --git 
a/Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp 
b/Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp
new file mode 100644
index ..e81f85b400cf
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/arm/cpu-enable-method/nuvoton,npcm7xx-smp
@@ -0,0 +1,42 @@
+=
+Secondary CPU enable-method "nuvoton,npcm7xx-smp" binding
+=
+
+To apply to all CPUs, a single "nuvoton,npcm7xx-smp" enable method should be
+defined in the "cpus" node.
+
+Enable method name:"nuvoton,npcm7xx-smp"
+Compatible machines:   "nuvoton,npcm750"
+Compatible CPUs:   "arm,cortex-a9"
+Related properties:(none)
+
+Note:
+This enable method needs valid nodes compatible with "arm,cortex-a9-scu" and
+"nuvoton,npcm750-gcr".
+
+Example:
+
+   cpus {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   enable-method = "nuvoton,npcm7xx-smp";
+
+   cpu@0 {
+   device_type = "cpu";
+   compatible = "arm,cortex-a9";
+   clocks = <&clk NPCM7XX_CLK_CPU>;
+   clock-names = "clk_cpu";
+   reg = <0>;
+   next-level-cache = <&L2>;
+   };
+
+   cpu@1 {
+   device_type = "cpu";
+   compatible = "arm,cortex-a9";
+   clocks = <&clk NPCM7XX_CLK_CPU>;
+   clock-names = "clk_cpu";
+   reg = <1>;
+   next-level-cache = <&L2>;
+   };
+   };
+
diff --git a/Documentation/devicetree/bindings/arm/npcm/npcm.txt 
b/Documentation/devicetree/bindings/arm/npcm/npcm.txt
new file mode 100644
index ..2d87d9ecea85
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/npcm/npcm.txt
@@ -0,0 +1,6 @@
+NPCM Platforms Device Tree Bindings
+---
+NPCM750 SoC
+Required root node properties:
+   - compatible = "nuvoton,npcm750";
+
diff --git a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts 
b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
new file mode 100644
index ..a0675e584125
--- /dev/null
+++ b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
@@ -0,0 +1,48 @@
+/*
+ * DTS file for all NPCM750 SoCs
+ *
+ * Copyright 2012 Tomer Maimon 
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "nuvoton-npcm750.dtsi"
+
+/ {
+   model = "Nuvoton npcm750 Development Board (Device Tree)";
+   compatible = "nuvoton,npcm750";
+
+   chosen {
+   stdout-path = &serial3;
+   };
+
+   memory {
+   reg = <0 0x4000>;
+   };
+};
+
+&watchdog1 {
+   status = "okay";
+};
+
+&serial0 {
+   status = "okay";
+};
+
+&serial1 {
+   status = "okay";
+};
+
+&serial2 {
+   status = "okay";
+};
+
+&serial3 {
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/nuvoton-npcm750.dtsi 
b/arch/arm/boot/dts/nuvoton-npcm750.dtsi
new file mode 100644
index ..85506b3cdd39
--- /dev/null
+++ b/arch/arm/boot/dts/nuvoton-npcm750.dtsi
@@ -0,0 +1,198 @@
+/*
+ * DTSi file for the NPCM750 SoC
+ *
+ * Copyright 2012 Tomer Maimon 
+ *
+ * The code contained herein is licensed under 

Re: [PATCH i2c-next v4] i2c: aspeed: Handle master/slave combined irq events properly

2018-08-22 Thread Brendan Higgins
   "master failed to STOP irq_status:0x%x\n",
> +   irq_status);
> bus->cmd_err = -EIO;
> /* Do not STOP as we have already tried. */
> } else {
> @@ -540,33 +542,51 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus 
> *bus)
> bus->master_xfer_result = bus->msgs_index + 1;
> complete(&bus->cmd_complete);
>  out_no_complete:
> -   if (irq_status != status_ack)
> -   dev_err(bus->dev,
> -   "irq handled != irq. expected 0x%08x, but was 
> 0x%08x\n",
> -   irq_status, status_ack);
> -   return !!irq_status;
> +   return status_ack;
>  }
>
>  static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
>  {
> struct aspeed_i2c_bus *bus = dev_id;
> -   bool ret;
> +   u32 irq_received, irq_status, irq_acked;
>
> spin_lock(&bus->lock);
> +   irq_received = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
> +   irq_status = irq_received;
>
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> -   if (aspeed_i2c_slave_irq(bus)) {
> -   dev_dbg(bus->dev, "irq handled by slave.\n");
> -   ret = true;
> -   goto out;
> +   /*
> +* In most cases, interrupt bits will be set one by one, although
> +* multiple interrupt bits could be set at the same time. It's also
> +* possible that master interrupt bits could be set along with slave
> +* interrupt bits. Each case needs to be handled using corresponding
> +* handlers depending on the current state.
> +*/
> +   if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) {
> +   irq_acked = aspeed_i2c_master_irq(bus, irq_status);
> +   irq_status &= ~irq_acked;
> +   if (irq_status)
> +   irq_acked = aspeed_i2c_slave_irq(bus, irq_status);
> +   } else {
> +   irq_acked = aspeed_i2c_slave_irq(bus, irq_status);
> +   irq_status &= ~irq_acked;
> +   if (irq_status)
> +   irq_acked = aspeed_i2c_master_irq(bus, irq_status);
> }
> +#else
> +   irq_acked = aspeed_i2c_master_irq(bus, irq_status);
>  #endif /* CONFIG_I2C_SLAVE */
>
> -   ret = aspeed_i2c_master_irq(bus);
> +   irq_status &= ~irq_acked;
> +   if (irq_status)
> +   dev_err(bus->dev,
> +   "irq handled != irq. expected 0x%08x, but was 
> 0x%08x\n",
> +   irq_received, irq_received ^ irq_status);

I think you want to use `irq_acked` here.

>
> -out:
> +   /* Ack all interrupt bits. */
> +   writel(irq_received, bus->base + ASPEED_I2C_INTR_STS_REG);
> spin_unlock(&bus->lock);
> -   return ret ? IRQ_HANDLED : IRQ_NONE;
> +   return irq_status ? IRQ_NONE : IRQ_HANDLED;
>  }
>
>  static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
> --
> 2.18.0
>

One minor issue and then I think we are good to go!

Also, sorry about not reviewing your last patch. I missed it apparently.

Feel free to mark the next patch "Reviewed-by: Brendan Higgins
"

Cheers


Re: [PATCH i2c-next v5] i2c: aspeed: Handle master/slave combined irq events properly

2018-08-23 Thread Brendan Higgins
On Thu, Aug 23, 2018 at 1:56 PM Jae Hyun Yoo
 wrote:
>
> In most of cases, interrupt bits are set one by one but there are
> also a lot of other cases that Aspeed I2C IP sends multiple
> interrupt bits with combining master and slave events using a
> single interrupt call. It happens much more in multi-master
> environment than single-master. For an example, when master is
> waiting for a NORMAL_STOP interrupt in its MASTER_STOP state,
> SLAVE_MATCH and RX_DONE interrupts could come along with the
> NORMAL_STOP in case of an another master immediately sends data
> just after acquiring the bus. In this case, the NORMAL_STOP
> interrupt should be handled by master_irq and the SLAVE_MATCH and
> RX_DONE interrupts should be handled by slave_irq. This commit
> modifies irq hadling logic to handle the master/slave combined
> events properly.
>
> Signed-off-by: Jae Hyun Yoo 
> Reviewed-by: Brendan Higgins 
> ---
> Changes since v4:
> - Fixed an error printing message that handlers didn't handle all interrupts.
>
> Changes since v3:
> - Fixed typos in a comment.
>
> Changes since v2:
> - Changed the name of ASPEED_I2CD_INTR_ERRORS to 
> ASPEED_I2CD_INTR_MASTER_ERRORS
> - Removed a member irq_status from the struct aspeed_i2c_bus and changed
>   master_irq and slave_irq handlers to make them return status_ack.
> - Added a comment to explain why it needs to try both irq handlers.
>
> Changes since v1:
> - Fixed a grammar issue in commit message.
> - Added a missing line feed character into a message printing.
>
>  drivers/i2c/busses/i2c-aspeed.c | 115 +++-
>  1 file changed, 70 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index a4f956c6d567..8341e384f4f1 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -82,6 +82,11 @@
>  #define ASPEED_I2CD_INTR_RX_DONE   BIT(2)
>  #define ASPEED_I2CD_INTR_TX_NAKBIT(1)
>  #define ASPEED_I2CD_INTR_TX_ACKBIT(0)
> +#define ASPEED_I2CD_INTR_MASTER_ERRORS   
>  \
> +   (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
>  \
> +ASPEED_I2CD_INTR_SCL_TIMEOUT |   
>  \
> +ASPEED_I2CD_INTR_ABNORMAL |  
>  \
> +ASPEED_I2CD_INTR_ARBIT_LOSS)
>  #define ASPEED_I2CD_INTR_ALL 
>  \
> (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
>  \
>  ASPEED_I2CD_INTR_BUS_RECOVER_DONE |  
>  \
> @@ -227,20 +232,16 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus 
> *bus)
>  }
>
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> -static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
> +static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
>  {
> -   u32 command, irq_status, status_ack = 0;
> +   u32 command, status_ack = 0;
> struct i2c_client *slave = bus->slave;
> -   bool irq_handled = true;
> u8 value;
>
> -   if (!slave) {
> -   irq_handled = false;
> -   goto out;
> -   }
> +   if (!slave)
> +   return 0;
>
> command = readl(bus->base + ASPEED_I2C_CMD_REG);
> -   irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
>
> /* Slave was requested, restart state machine. */
> if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
> @@ -249,10 +250,8 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus 
> *bus)
> }
>
> /* Slave is not currently active, irq was for someone else. */
> -   if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
> -   irq_handled = false;
> -   goto out;
> -   }
> +   if (bus->slave_state == ASPEED_I2C_SLAVE_STOP)
> +   return status_ack;
>
> dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
> irq_status, command);
> @@ -281,19 +280,19 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus 
> *bus)
> status_ack |= ASPEED_I2CD_INTR_TX_NAK;
> bus->slave_state = ASPEED_I2C_SLAVE_STOP;
> }
> +   if (irq_status & ASPEED_I2CD_INTR_TX_ACK)
> +   status_ack |= ASPEED_I2CD_INTR_TX_ACK;
>
> switch (bus->slave_state) {
> case ASPEED_I2C_SLAVE_READ_REQUESTED:
> if (irq_status & ASPEED_I2CD_INTR_TX_

Re: [PATCH] i2c: aspeed: Improve driver to support multi-master use cases stably

2018-07-19 Thread Brendan Higgins
On Tue, Jul 17, 2018 at 9:18 AM Jae Hyun Yoo
 wrote:
>
>
> On 7/15/2018 8:05 PM, Gary Hsu wrote:
> > Hi Jae,
> >
> > In originally, we reserved these register bits for debug purpose. But for 
> > some error handling case, we found it is also useful to help to clarify 
> > some error conditions. So driver also can use these fields information to 
> > check something.
> > As for how driver use these information in their code, I have no comment. I 
> > don’t understand the driver. But these information is the real controller 
> > state, it had no problem to use information.
> >
>
> Thanks Gary!
>
> Hi Brendan,
> Is it acceptable now if I add this as a comment like below?

Yep, that's fine. I didn't mean to hold you up. I was just curious.

>
> Thanks,
> Jae
>
> > Best Regards,
> >
> > 許馥疇 Gary Hsu
> >
> > 信驊科技股份有限公司
> > ASPEED Technology Inc.
> >
> > 2F,No.15,Industry East Road 4.,Hsinchu Science Park, Hsinchu City 30077, 
> > Taiwan
> > 新竹科學園區工業東四路 15 號 2F
> >
> > Tel : 886-3-5789568 ext:807
> > Fax : 886-3-5789586
> > Web : http://www.aspeedtech.com
> >
> > * Email Confidentiality Notice 
> > 免責聲明:
> > 因應個人資料保護法施行,本信件(或其附件)可能包含機密資訊,並受法律保護。如 台端非指定之收件者,請以電子郵件通知本電子郵件之發送者, 
> > 並請立即刪除本電子郵件及其附件和銷毀所有複印件。謝謝您的合作!
> >
> > DISCLAIMER:
> > This message (and any attachments) may contain legally privileged and/or 
> > other confidential information. If you have received it in error, please 
> > notify the sender by reply e-mail and immediately delete the e-mail and any 
> > attachments without copying or disclosing the contents. Thank you.
> >
> > -Original Message-
> > From: Jae Hyun Yoo [mailto:jae.hyun@linux.intel.com]
> > Sent: Saturday, July 14, 2018 2:54 AM
> > To: Brendan Higgins 
> > Cc: Benjamin Herrenschmidt ; Joel Stanley 
> > ; Andrew Jeffery ; 
> > linux-...@vger.kernel.org; OpenBMC Maillist ; 
> > Linux ARM ; 
> > linux-asp...@lists.ozlabs.org; Linux Kernel Mailing List 
> > ; james.fe...@linux.intel.com; 
> > vernon.mau...@linux.intel.com; Benjamin Fair ; 
> > Patrick Venture ; Gary Hsu ; 
> > Ryan Chen 
> > Subject: Re: [PATCH] i2c: aspeed: Improve driver to support multi-master 
> > use cases stably
> >
> > On 7/13/2018 11:12 AM, Brendan Higgins wrote:
> >> On Fri, Jul 13, 2018 at 10:22 AM Jae Hyun Yoo
> >>  wrote:
> >>>
> >>> On 7/12/2018 11:21 AM, Jae Hyun Yoo wrote:
> >>>> On 7/12/2018 2:33 AM, Brendan Higgins wrote:
> >>>>> On Wed, Jun 27, 2018 at 10:55 AM Jae Hyun Yoo
> >>>>>  wrote:
> >> 
> >>>>> 
> >>>>>>>> +   for (;;) {
> >>>>>>>> +   if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> >>>>>>>> + (ASPEED_I2CD_BUS_BUSY_STS |
> >>>>>>>> +  ASPEED_I2CD_XFER_MODE_STS_MASK)))
> >>>>>>>
> >>>>>>> Is using the Transfer Mode State Machine bits necessary? The
> >>>>>>> documentation marks it as "for debugging purpose only," so
> >>>>>>> relying on it makes me nervous.
> >>>>>>>
> >>>>>>
> >>>>>> As you said, the documentation marks it as "for debugging purpose 
> >>>>>> only."
> >>>>>> but ASPEED also uses this way in their SDK code because it's the
> >>>>>> best way for checking bus busy status which can cover both single
> >>>>>> and multi-master use cases.
> >>>>>>
> >>>>>
> >>>>> Well, it would also be really nice to have access to this bit if
> >>>>> someone wants to implement MCTP. Could we maybe check with Aspeed
> >>>>> what them meant by "for debugging purposes only" and document it
> >>>>> here? It makes me nervous to rely on debugging functionality for
> >>>>> normal usage.
> >>>>>
> >>>>
> >>>> Okay, I'll check it with Aspeed. Will let you know their response.
> >>>>
> >>>
> >>> I've checked it with Gary Hsu  and he
> >>> confirmed that the bits reflect real information and good to be used
> >>> in practical code.
> >>
> >> Huh. For my own edification, could you ask them why they said "for
> >> debugging purpose only" in the documentation? I am just really curious
> >> what they meant by that. I would be satisfied if you just CC'ed me on
> >> your email thread with Gary, and I can ask him myself.
> >>
> >
> > I've already CC'ed Gary and Ryan in this thread.
> >
> > Hi Gary,
> >
> > Can you explain why the documentation says that the bit field is 'for 
> > debugging purpose only'? Any plan to change the description?
> >
> > Thanks,
> >
> > Jae
> >
> >>>
> >>> I'll add a comment like below:
> >>>
> >>> /*
> >>> * This is marked as 'for debugging purpose only' in datasheet but
> >>> * ASPEED confirmed that this reflects real information and good
> >>> * to be used in practical code.
> >>> */
> >>>
> >>> Is it acceptable then?
> >>
> >> Yeah, that's fine.
> >>
> >> 
> >>
> >> Cheers
> >>


Re: [PATCH] i2c: aspeed: Improve driver to support multi-master use cases stably

2018-07-19 Thread Brendan Higgins
On Sun, Jul 15, 2018 at 8:05 PM Gary Hsu  wrote:
>
> Hi Jae,
>
> In originally, we reserved these register bits for debug purpose. But for 
> some error handling case, we found it is also useful to help to clarify some 
> error conditions. So driver also can use these fields information to check 
> something.
> As for how driver use these information in their code, I have no comment. I 
> don’t understand the driver. But these information is the real controller 
> state, it had no problem to use information.

Okay, so it was originally only intended for debugging, but then showed itself
to be useful, got it. Just out of curiosity, why did you mark it that way in
the documentation? It seems as though you are trying to discourage people from
using it.

>
> Best Regards,
>
> 許馥疇 Gary Hsu
>
> 信驊科技股份有限公司
> ASPEED Technology Inc.
>
> 2F,No.15,Industry East Road 4.,Hsinchu Science Park, Hsinchu City 30077, 
> Taiwan
> 新竹科學園區工業東四路 15 號 2F
>
> Tel : 886-3-5789568 ext:807
> Fax : 886-3-5789586
> Web : http://www.aspeedtech.com
>
> * Email Confidentiality Notice 
> 免責聲明:
> 因應個人資料保護法施行,本信件(或其附件)可能包含機密資訊,並受法律保護。如 台端非指定之收件者,請以電子郵件通知本電子郵件之發送者, 
> 並請立即刪除本電子郵件及其附件和銷毀所有複印件。謝謝您的合作!
>
> DISCLAIMER:
> This message (and any attachments) may contain legally privileged and/or 
> other confidential information. If you have received it in error, please 
> notify the sender by reply e-mail and immediately delete the e-mail and any 
> attachments without copying or disclosing the contents. Thank you.
>
> -Original Message-
> From: Jae Hyun Yoo [mailto:jae.hyun@linux.intel.com]
> Sent: Saturday, July 14, 2018 2:54 AM
> To: Brendan Higgins 
> Cc: Benjamin Herrenschmidt ; Joel Stanley 
> ; Andrew Jeffery ; 
> linux-...@vger.kernel.org; OpenBMC Maillist ; Linux 
> ARM ; linux-asp...@lists.ozlabs.org; 
> Linux Kernel Mailing List ; 
> james.fe...@linux.intel.com; vernon.mau...@linux.intel.com; Benjamin Fair 
> ; Patrick Venture ; Gary Hsu 
> ; Ryan Chen 
> Subject: Re: [PATCH] i2c: aspeed: Improve driver to support multi-master use 
> cases stably
>
> On 7/13/2018 11:12 AM, Brendan Higgins wrote:
> > On Fri, Jul 13, 2018 at 10:22 AM Jae Hyun Yoo
> >  wrote:
> >>
> >> On 7/12/2018 11:21 AM, Jae Hyun Yoo wrote:
> >>> On 7/12/2018 2:33 AM, Brendan Higgins wrote:
> >>>> On Wed, Jun 27, 2018 at 10:55 AM Jae Hyun Yoo
> >>>>  wrote:
> > 
> >>>> 
> >>>>>>> +   for (;;) {
> >>>>>>> +   if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> >>>>>>> + (ASPEED_I2CD_BUS_BUSY_STS |
> >>>>>>> +  ASPEED_I2CD_XFER_MODE_STS_MASK)))
> >>>>>>
> >>>>>> Is using the Transfer Mode State Machine bits necessary? The
> >>>>>> documentation marks it as "for debugging purpose only," so
> >>>>>> relying on it makes me nervous.
> >>>>>>
> >>>>>
> >>>>> As you said, the documentation marks it as "for debugging purpose only."
> >>>>> but ASPEED also uses this way in their SDK code because it's the
> >>>>> best way for checking bus busy status which can cover both single
> >>>>> and multi-master use cases.
> >>>>>
> >>>>
> >>>> Well, it would also be really nice to have access to this bit if
> >>>> someone wants to implement MCTP. Could we maybe check with Aspeed
> >>>> what them meant by "for debugging purposes only" and document it
> >>>> here? It makes me nervous to rely on debugging functionality for
> >>>> normal usage.
> >>>>
> >>>
> >>> Okay, I'll check it with Aspeed. Will let you know their response.
> >>>
> >>
> >> I've checked it with Gary Hsu  and he
> >> confirmed that the bits reflect real information and good to be used
> >> in practical code.
> >
> > Huh. For my own edification, could you ask them why they said "for
> > debugging purpose only" in the documentation? I am just really curious
> > what they meant by that. I would be satisfied if you just CC'ed me on
> > your email thread with Gary, and I can ask him myself.
> >
>
> I've already CC'ed Gary and Ryan in this thread.
>
> Hi Gary,
>
> Can you explain why the documentation says that the bit field is 'for 
> debugging purpose only'? Any plan to change the description?
>
> Thanks,
>
> Jae
>
> >>
> >> I'll add a comment like below:
> >>
> >> /*
> >>* This is marked as 'for debugging purpose only' in datasheet but
> >>* ASPEED confirmed that this reflects real information and good
> >>* to be used in practical code.
> >>*/
> >>
> >> Is it acceptable then?
> >
> > Yeah, that's fine.
> >
> > 
> >
> > Cheers
> >


Re: [PATCH v2] i2c: aspeed: Handle master/slave combined irq events properly

2018-07-31 Thread Brendan Higgins
On Tue, Jul 24, 2018 at 10:31 AM Jae Hyun Yoo
 wrote:
>
> In most of cases, interrupt bits are set one by one but there are
> also a lot of other cases that Aspeed I2C IP sends multiple
> interrupt bits with combining master and slave events using a
> single interrupt call. It happens much more in multi-master
> environment than single-master. For an example, when master is
> waiting for a NORMAL_STOP interrupt in its MASTER_STOP state,
> SLAVE_MATCH and RX_DONE interrupts could come along with the
> NORMAL_STOP in case of an another master immediately sends data
> just after acquiring the bus. In this case, the NORMAL_STOP
> interrupt should be handled by master_irq and the SLAVE_MATCH and
> RX_DONE interrupts should be handled by slave_irq. This commit
> modifies irq hadling logic to handle the master/slave combined
> events properly.
>
> Changes since v1:
> - Fixed a grammer issue in commit message.
> - Added a missing line feed character into a message printing.

This should not go in the commit log. Please move this to the comment section.

>
> Signed-off-by: Jae Hyun Yoo 
> ---
>  drivers/i2c/busses/i2c-aspeed.c | 135 ++--
>  1 file changed, 75 insertions(+), 60 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index efb89422d496..75431e305073 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -82,6 +82,11 @@
>  #define ASPEED_I2CD_INTR_RX_DONE   BIT(2)
>  #define ASPEED_I2CD_INTR_TX_NAKBIT(1)
>  #define ASPEED_I2CD_INTR_TX_ACKBIT(0)
> +#define ASPEED_I2CD_INTR_ERRORS  
>  \
> +   (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
>  \
> +ASPEED_I2CD_INTR_SCL_TIMEOUT |   
>  \
> +ASPEED_I2CD_INTR_ABNORMAL |  
>  \
> +ASPEED_I2CD_INTR_ARBIT_LOSS)
>  #define ASPEED_I2CD_INTR_ALL 
>  \
> (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
>  \
>  ASPEED_I2CD_INTR_BUS_RECOVER_DONE |  
>  \
> @@ -150,6 +155,7 @@ struct aspeed_i2c_bus {
> int cmd_err;
> /* Protected only by i2c_lock_bus */
> int master_xfer_result;
> +   u32 irq_status;
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> struct i2c_client   *slave;
> enum aspeed_i2c_slave_state slave_state;
> @@ -229,36 +235,30 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus 
> *bus)
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
>  static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)

I think it will be cleaner if both this and aspeed_i2c_master_irq return the
status_ack; that way you will not have to add the irq_status field to the
struct.

>  {
> -   u32 command, irq_status, status_ack = 0;
> +   u32 command, status_ack = 0;
> struct i2c_client *slave = bus->slave;
> -   bool irq_handled = true;
> u8 value;
>
> -   if (!slave) {
> -   irq_handled = false;
> -   goto out;
> -   }
> +   if (!slave)
> +   return false;
>
> command = readl(bus->base + ASPEED_I2C_CMD_REG);
> -   irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
>
> /* Slave was requested, restart state machine. */
> -   if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
> +   if (bus->irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
> status_ack |= ASPEED_I2CD_INTR_SLAVE_MATCH;
> bus->slave_state = ASPEED_I2C_SLAVE_START;
> }
>
> /* Slave is not currently active, irq was for someone else. */
> -   if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
> -   irq_handled = false;
> -   goto out;
> -   }
> +   if (bus->slave_state == ASPEED_I2C_SLAVE_STOP)
> +   return false;
>
> dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
> -   irq_status, command);
> +   bus->irq_status, command);
>
> /* Slave was sent something. */
> -   if (irq_status & ASPEED_I2CD_INTR_RX_DONE) {
> +   if (bus->irq_status & ASPEED_I2CD_INTR_RX_DONE) {
> value = readl(bus->base + ASPEED_I2C_BYTE_BUF_REG) >> 8;
> /* Handle address frame. */
> if (bus->slave_state == ASPEED_I2C_SLAVE_START) {
> @@ -273,28 +273,29 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus 
> *bus)
> }
>
> /* Slave was asked to stop. */
> -   if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
> +   if (bus->irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
> status_ack |= ASPEED_I2CD_INT

Re: [PATCH i2c-next v2] i2c: aspeed: Add an explicit type casting for *get_clk_reg_val

2018-07-31 Thread Brendan Higgins
On Tue, Jul 24, 2018 at 1:39 PM Jae Hyun Yoo
 wrote:
>
> This commit fixes this sparse warning:
> drivers/i2c/busses/i2c-aspeed.c:875:38: warning: incorrect type in assignment 
> (different modifiers)
> drivers/i2c/busses/i2c-aspeed.c:875:38:expected unsigned int ( 
> *get_clk_reg_val )( ... )
> drivers/i2c/busses/i2c-aspeed.c:875:38:got void const *const data
>
> Signed-off-by: Jae Hyun Yoo 
> ---
> Changes since v1:
> - Fixed title and added Reported-by tag.
>
>  drivers/i2c/busses/i2c-aspeed.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index efb89422d496..a4f956c6d567 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -872,7 +872,7 @@ static int aspeed_i2c_probe_bus(struct platform_device 
> *pdev)
> if (!match)
> bus->get_clk_reg_val = aspeed_i2c_24xx_get_clk_reg_val;
> else
> -   bus->get_clk_reg_val = match->data;
> +   bus->get_clk_reg_val = (u32 (*)(u32))match->data;
>
> /* Initialize the I2C adapter */
> spin_lock_init(&bus->lock);
> --
> 2.18.0
>

Reviewed-by: Brendan Higgins 


Re: [PATCH] i2c: aspeed: Add newline characters into message printings.

2018-07-12 Thread Brendan Higgins
On Wed, Jul 11, 2018 at 10:10 AM Joe Perches  wrote:
>
> On Wed, 2018-07-11 at 09:53 -0700, Jae Hyun Yoo wrote:
> > On 7/10/2018 10:42 PM, Brendan Higgins wrote:
> > > On Mon, Jul 2, 2018 at 2:14 PM Jae Hyun Yoo 
> > >  wrote:
> > > > There are some log printing without a newline character. This
> > > > patch adds the missing newline characters.
> []
> > > > diff --git a/drivers/i2c/busses/i2c-aspeed.c 
> > > > b/drivers/i2c/busses/i2c-aspeed.c
> []
> > > > @@ -431,7 +431,7 @@ static bool aspeed_i2c_master_irq(struct 
> > > > aspeed_i2c_bus *bus)
> > > >   */
> > > >  if (bus->master_state == ASPEED_I2C_MASTER_START) {
> > > >  if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) 
> > > > {
> > > > -   pr_devel("no slave present at %02x", msg->addr);
> > > > +   pr_devel("no slave present at %02x\n", 
> > > > msg->addr);
> > >
> > > Unless something changed in the last couple versions of the kernel, this 
> > > is the
> > > only line that actually changes anything. dev_* inserts a newline for 
> > > every
> > > call.
>
> Not true.
>
> Any printk without KERN_CONT inserts a newline
> if the last character
> emitted is not a newline.
>
> dev_ uses can also be followed by pr_cont.
>
> So this patch does reduce the possibility of
> interleaved messages from multiple processes.

My mistake. Thanks for pointing that out.

Jae, forget what I said earlier. This looks good to me.


Re: [PATCH] i2c: aspeed: Adjust spinlock scope in the irq handler

2018-07-12 Thread Brendan Higgins
On Mon, Jul 2, 2018 at 2:40 PM Jae Hyun Yoo
 wrote:
>
> This patch adjusts spinlock scope to make it wrap the whole irq
> handler using a single lock/unlock which covers both master and
> slave handlers.
>
> Signed-off-by: Jae Hyun Yoo 
> ---
>  drivers/i2c/busses/i2c-aspeed.c | 16 ++--
>  1 file changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index 60e4d0e939a3..9f02aa959a3e 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -234,7 +234,6 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus 
> *bus)
> bool irq_handled = true;
> u8 value;
>
> -   spin_lock(&bus->lock);
> if (!slave) {
> irq_handled = false;
> goto out;
> @@ -325,7 +324,6 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus 
> *bus)
> writel(status_ack, bus->base + ASPEED_I2C_INTR_STS_REG);
>
>  out:
> -   spin_unlock(&bus->lock);
> return irq_handled;
>  }
>  #endif /* CONFIG_I2C_SLAVE */
> @@ -389,7 +387,6 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus 
> *bus)
> u8 recv_byte;
> int ret;
>
> -   spin_lock(&bus->lock);
> irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
> /* Ack all interrupt bits. */
> writel(irq_status, bus->base + ASPEED_I2C_INTR_STS_REG);
> @@ -547,22 +544,29 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus 
> *bus)
> dev_err(bus->dev,
> "irq handled != irq. expected 0x%08x, but was 
> 0x%08x\n",
> irq_status, status_ack);
> -   spin_unlock(&bus->lock);
> return !!irq_status;
>  }
>
>  static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
>  {
> struct aspeed_i2c_bus *bus = dev_id;
> +   bool ret;
> +
> +   spin_lock(&bus->lock);
>
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> if (aspeed_i2c_slave_irq(bus)) {
> dev_dbg(bus->dev, "irq handled by slave.\n");
> -   return IRQ_HANDLED;
> +   ret = true;
> +   goto out;
> }
>  #endif /* CONFIG_I2C_SLAVE */
>
> -   return aspeed_i2c_master_irq(bus) ? IRQ_HANDLED : IRQ_NONE;
> +   ret = aspeed_i2c_master_irq(bus);
> +
> +out:
> +   spin_unlock(&bus->lock);
> +   return ret ? IRQ_HANDLED : IRQ_NONE;
>  }
>
>  static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
> --
> 2.17.1
>

Reviewed-by: Brendan Higgins 

Thanks!


Re: [PATCH] i2c: aspeed: Improve driver to support multi-master use cases stably

2018-07-12 Thread Brendan Higgins
On Wed, Jun 27, 2018 at 10:55 AM Jae Hyun Yoo
 wrote:
>

> >> +/* Timeout for bus busy checking */
> >> +#define BUS_BUSY_CHECK_TIMEOUT 25 /* 250ms */
> >> +#define BUS_BUSY_CHECK_INTERVAL1  /* 
> >> 10ms */
> >
> > Could you add a comment on where you got these values from?
> >
>
> These are coming from ASPEED SDK code. Actually, they use 100ms for
> timeout and 10ms for interval but I increased the timeout value to
> 250ms so that it covers a various range of bus speed. I think, it
> should be computed at run time based on the current bus speed, or
> we could add these as device tree settings. How do you think about it?
>

This should definitely be a device tree setting. If one of the busses is being
used as a regular I2C bus, it could hold the bus for an unlimited amount of
time before sending a STOP. As for a default, 100ms is probably fine given
that, a) the limit will only apply to multi-master mode, and b) multi-master
mode will probably almost always be used with IPMB, or MCTP (MCTP actually
recommends a 100ms timeout for this purpose, see
https://www.dmtf.org/sites/default/files/standards/documents/DSP0237_1.1.0.pdf,
symbol PT2a). That being said, if you actually want to implement IPMB, or MCTP
arbitration logic, it is much more complicated.

>  >

> >>   #if IS_ENABLED(CONFIG_I2C_SLAVE)
> >> -   if (aspeed_i2c_slave_irq(bus)) {
> >> -   dev_dbg(bus->dev, "irq handled by slave.\n");
> >> -   return IRQ_HANDLED;
> >> +   if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) {
> >> +   if (!aspeed_i2c_master_irq(bus))
> >
> > Why do you check the slave if master fails (or vice versa)? I
> > understand that there are some status bits that have not been handled,
> > but it doesn't seem reasonable to assume that there is state that the
> > other should do something with; the only way this would happen is if
> > the state that you think you are in does not match the status bits you
> > have been given, but if this is the case, you are already hosed; I
> > don't think trying the other handler is likely to make things better,
> > unless there is something that I am missing.
> >
>
> In most of cases, interrupt bits are set one by one but there are also a
> lot of other cases that ASPEED I2C H/W sends multiple interrupt bits
> with combining master and slave events using a single interrupt call. It
> happens much in multi-master environment than single-master. For
> example, when master is waiting for a NORMAL_STOP interrupt in its
> MASTER_STOP state, SLAVE_MATCH and RX_DONE interrupts could come along
> with the NORMAL_STOP in case of an another master immediately sends data
> just after acquiring the bus - it happens a lot in BMC-ME connection
> practically. In this case, the NORMAL_STOP interrupt should be handled
> by master_irq and the SLAVE_MATCH and RX_DONE interrupts should be
> handled by slave_irq so it's the reason why this code is added.

That sucks. Well, it sounds like there are only a handful of cases in which
this can happen. Maybe enumerate these cases and error out or at least warn if
it is not one of them?

>

> >> +   for (;;) {
> >> +   if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> >> + (ASPEED_I2CD_BUS_BUSY_STS |
> >> +  ASPEED_I2CD_XFER_MODE_STS_MASK)))
> >
> > Is using the Transfer Mode State Machine bits necessary? The
> > documentation marks it as "for debugging purpose only," so relying on
> > it makes me nervous.
> >
>
> As you said, the documentation marks it as "for debugging purpose only."
> but ASPEED also uses this way in their SDK code because it's the best
> way for checking bus busy status which can cover both single and
> multi-master use cases.
>

Well, it would also be really nice to have access to this bit if someone wants
to implement MCTP. Could we maybe check with Aspeed what them meant by "for
debugging purposes only" and document it here? It makes me nervous to rely on
debugging functionality for normal usage.

> >> +   return 0;
> >> +   if (ktime_compare(ktime_get(), timeout) > 0)
> >> +   break;
> >> +   usleep_range((BUS_BUSY_CHECK_INTERVAL >> 2) + 1,
> >
> > Where did you get this minimum value?
> >
>
> No source for the minimum value. ASPEED uses mdelay(10) in their SDK
> but I changed that code using usleep_range and the range value was set
> with considering time stretching of usleep_range.
> regmap_read_poll_timeout was a reference for this code.

What protocol are you trying to implement on top of this? You mentioned BMC-ME
above; that's IPMB, right? For most use cases, this should work, but if you
need arbitration, you will need to do quite a bit more work.

>
> Thanks,
>
> Jae


Cheers


Re: [PATCH] i2c: aspeed: Improve driver to support multi-master use cases stably

2018-07-13 Thread Brendan Higgins
On Thu, Jul 12, 2018 at 11:21 AM Jae Hyun Yoo
 wrote:
>
> On 7/12/2018 2:33 AM, Brendan Higgins wrote:
> > On Wed, Jun 27, 2018 at 10:55 AM Jae Hyun Yoo
> >  wrote:
> >>
> > 
> >>>> +/* Timeout for bus busy checking */
> >>>> +#define BUS_BUSY_CHECK_TIMEOUT 25 /* 250ms 
> >>>> */
> >>>> +#define BUS_BUSY_CHECK_INTERVAL1  
> >>>> /* 10ms */
> >>>
> >>> Could you add a comment on where you got these values from?
> >>>
> >>
> >> These are coming from ASPEED SDK code. Actually, they use 100ms for
> >> timeout and 10ms for interval but I increased the timeout value to
> >> 250ms so that it covers a various range of bus speed. I think, it
> >> should be computed at run time based on the current bus speed, or
> >> we could add these as device tree settings. How do you think about it?
> >>
> >
> > This should definitely be a device tree setting. If one of the busses is 
> > being
> > used as a regular I2C bus, it could hold the bus for an unlimited amount of
> > time before sending a STOP. As for a default, 100ms is probably fine given
> > that, a) the limit will only apply to multi-master mode, and b) multi-master
> > mode will probably almost always be used with IPMB, or MCTP (MCTP actually
> > recommends a 100ms timeout for this purpose, see
> > https://www.dmtf.org/sites/default/files/standards/documents/DSP0237_1.1.0.pdf,
> > symbol PT2a). That being said, if you actually want to implement IPMB, or 
> > MCTP
> > arbitration logic, it is much more complicated.
> >
>
> Okay then, I think, we can fix the timeout value to 100ms and enable the
> bus busy checking logic only when 'multi-master' is set in device tree.
> My thought is, no additional arbitration logic is needed because
> arbitration is performed in H/W level and H/W reports
> ASPEED_I2CD_INTR_ARBIT_LOSS when it fails acquiring a bus. The
> ARBIT_LOSS event is already being handled well by this driver code you
> implemented.

I still think it would be best to provide an option to specify the timeout value
it in the device tree regardless of master mode or not. Also, I am talking about
fairness arbitration not the physical level arbitration provided by the I2C
spec. The physical arbitration that Aspeed provides just allows multiple masters
to operate on the same bus according to the specification; this bus arbitration
does not guarantee forward progress or even guarentee that the actual message
will be sent, which is what you are trying to do here.

Since you are planning on implementing IPMB, you will probably need to implement
fairness arbitration. I am not familiar with your BMC-ME channel. It sounds like
it pre-dates MCTP, so it must implement its own fairness arbitration on top of
the IPMB layer (more like you bake in some assumptions about what the possible
state is at anytime that guarentee fairness).

Are you using the Aspeed BMC on both sides of the connection? If so, you might
be further ahead to implement MCTP fairness arbitration which can be used in
conjunction with IPMB. This will require a bit of work to do, but everyone will
be much happier in the long term (assuming MCTP does eventually become a thing).

>
> >>   >
> > 
> >>>>#if IS_ENABLED(CONFIG_I2C_SLAVE)
> >>>> -   if (aspeed_i2c_slave_irq(bus)) {
> >>>> -   dev_dbg(bus->dev, "irq handled by slave.\n");
> >>>> -   return IRQ_HANDLED;
> >>>> +   if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) {
> >>>> +   if (!aspeed_i2c_master_irq(bus))
> >>>
> >>> Why do you check the slave if master fails (or vice versa)? I
> >>> understand that there are some status bits that have not been handled,
> >>> but it doesn't seem reasonable to assume that there is state that the
> >>> other should do something with; the only way this would happen is if
> >>> the state that you think you are in does not match the status bits you
> >>> have been given, but if this is the case, you are already hosed; I
> >>> don't think trying the other handler is likely to make things better,
> >>> unless there is something that I am missing.
> >>>
> >>
> >> In most of cases, interrupt bits are set one by one but there are also a
> >> lot of other cases that ASPEED I2C H/W sends multiple interrupt bits
> >> with combining master and slave events using a single interrupt call. It
> >> happens muc

Re: [PATCH] i2c: aspeed: Improve driver to support multi-master use cases stably

2018-07-13 Thread Brendan Higgins
On Fri, Jul 13, 2018 at 10:22 AM Jae Hyun Yoo
 wrote:
>
> On 7/12/2018 11:21 AM, Jae Hyun Yoo wrote:
> > On 7/12/2018 2:33 AM, Brendan Higgins wrote:
> >> On Wed, Jun 27, 2018 at 10:55 AM Jae Hyun Yoo
> >>  wrote:

> >> 
> >>>>> +   for (;;) {
> >>>>> +   if (!(readl(bus->base + ASPEED_I2C_CMD_REG) &
> >>>>> + (ASPEED_I2CD_BUS_BUSY_STS |
> >>>>> +  ASPEED_I2CD_XFER_MODE_STS_MASK)))
> >>>>
> >>>> Is using the Transfer Mode State Machine bits necessary? The
> >>>> documentation marks it as "for debugging purpose only," so relying on
> >>>> it makes me nervous.
> >>>>
> >>>
> >>> As you said, the documentation marks it as "for debugging purpose only."
> >>> but ASPEED also uses this way in their SDK code because it's the best
> >>> way for checking bus busy status which can cover both single and
> >>> multi-master use cases.
> >>>
> >>
> >> Well, it would also be really nice to have access to this bit if
> >> someone wants
> >> to implement MCTP. Could we maybe check with Aspeed what them meant by
> >> "for
> >> debugging purposes only" and document it here? It makes me nervous to
> >> rely on
> >> debugging functionality for normal usage.
> >>
> >
> > Okay, I'll check it with Aspeed. Will let you know their response.
> >
>
> I've checked it with Gary Hsu  and he confirmed
> that the bits reflect real information and good to be used in practical
> code.

Huh. For my own edification, could you ask them why they said "for debugging
purpose only" in the documentation? I am just really curious what they meant by
that. I would be satisfied if you just CC'ed me on your email thread with Gary,
and I can ask him myself.

>
> I'll add a comment like below:
>
> /*
>   * This is marked as 'for debugging purpose only' in datasheet but
>   * ASPEED confirmed that this reflects real information and good
>   * to be used in practical code.
>   */
>
> Is it acceptable then?

Yeah, that's fine.



Cheers


Re: [PATCH 1/2] ARM: npcm: add CONFIG_ARCH_MULTI_V7 dependency

2018-03-08 Thread Brendan Higgins
On Wed, Mar 7, 2018 at 8:24 AM Arnd Bergmann  wrote:

> The top-level CONFIG_ARCH_NPCM symbol is not guarded with a
> dependency, and can be selected for builds of traditional
> (non-multiplatform) builds as well, where it causes a build
> failure:

> arch/arm/boot/Makefile:17: arch/arm/mach-npcm//Makefile.boot: No such
file or directory

> This moves the dependency to avoid that particular condition.

> Signed-off-by: Arnd Bergmann 
> ---
>   arch/arm/mach-npcm/Kconfig | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)

> diff --git a/arch/arm/mach-npcm/Kconfig b/arch/arm/mach-npcm/Kconfig
> index 6ff9df2636be..2bc6697c8d97 100644
> --- a/arch/arm/mach-npcm/Kconfig
> +++ b/arch/arm/mach-npcm/Kconfig
> @@ -1,5 +1,5 @@
>   menuconfig ARCH_NPCM
> -   bool "Nuvoton NPCM Architecture"
> +   bool "Nuvoton NPCM Architecture" if ARCH_MULTI_V7
>  select ARCH_REQUIRE_GPIOLIB
>  select USE_OF
>  select PINCTRL
> @@ -10,7 +10,7 @@ if ARCH_NPCM
>   comment "NPCM7XX CPU type"

>   config ARCH_NPCM750
> -   depends on ARCH_NPCM && ARCH_MULTI_V7
> +   depends on ARCH_NPCM
>  bool "Support for NPCM750 BMC CPU (Poleg)"
>  select CACHE_L2X0
>  select CPU_V7
> --
> 2.9.0


Reviewed-by: Brendan Higgins 

Thanks!


Re: Bad MAINTAINERS pattern in section 'ARM/NUVOTON NPCM ARCHITECTURE'

2018-09-28 Thread Brendan Higgins
On Fri, Sep 28, 2018 at 2:51 PM Joe Perches  wrote:
>
> Please fix this defect appropriately.
>
> linux-next MAINTAINERS section:
>
> 1781ARM/NUVOTON NPCM ARCHITECTURE
> 1782M:  Avi Fishman 
> 1783M:  Tomer Maimon 
> 1784R:  Patrick Venture 
> 1785R:  Nancy Yuen 
>     1786R:  Brendan Higgins 
> 1787L:  open...@lists.ozlabs.org (moderated for 
> non-subscribers)
> 1788S:  Supported
> 1789F:  arch/arm/mach-npcm/
> 1790F:  arch/arm/boot/dts/nuvoton-npcm*
> --> 1791F:  include/dt-bindings/clock/nuvoton,npcm7xx-clks.h
> 1792F:  drivers/*/*npcm*
> 1793F:  Documentation/devicetree/bindings/*/*npcm*
> 1794F:  Documentation/devicetree/bindings/*/*/*npcm*
>
> Commit that introduced this:
>
> commit 6a498e06ba22872d3a27cc0dae77b9314b1de48b
>  Author: Brendan Higgins 
>  Date:   Thu Aug 17 09:44:32 2017 -0700
>
>  MAINTAINERS: Add entry for the Nuvoton NPCM architecture
>
>  Add maintainers and reviewers for the Nuvoton NPCM architecture.
>
>  Signed-off-by: Brendan Higgins 
>  Reviewed-by: Tomer Maimon 
>  Reviewed-by: Avi Fishman 
>  Signed-off-by: Arnd Bergmann 
>
>   MAINTAINERS | 14 ++
>   1 file changed, 14 insertions(+)
>
> No commit with include/dt-bindings/clock/nuvoton,npcm7xx-clks.h found

Ah, looks like it should actually be
include/dt-bindings/clock/nuvoton,npcm7xx-clock.h. We probably changed
it in one of the revisions and forgot to update it.

>


Re: [RFC v3 08/19] arch: um: add shim to trap to allow installing a fault catcher for tests

2018-12-03 Thread Brendan Higgins
On Thu, Nov 29, 2018 at 7:34 PM Luis Chamberlain  wrote:
>
> On Wed, Nov 28, 2018 at 11:36:25AM -0800, Brendan Higgins wrote:
> > diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
> > index cced829460427..bf90e678b3d71 100644
> > --- a/arch/um/kernel/trap.c
> > +++ b/arch/um/kernel/trap.c
> > @@ -201,6 +201,12 @@ void segv_handler(int sig, struct siginfo *unused_si, 
> > struct uml_pt_regs *regs)
> >   segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
> >  }
> >
> > +static void segv_run_catcher(jmp_buf *catcher, void *fault_addr)
> > +{
> > + current->thread.fault_addr = fault_addr;
> > + UML_LONGJMP(catcher, 1);
> > +}
> > +
> >  /*
> >   * We give a *copy* of the faultinfo in the regs to segv.
> >   * This must be done, since nesting SEGVs could overwrite
> > @@ -219,7 +225,10 @@ unsigned long segv(struct faultinfo fi, unsigned long 
> > ip, int is_user,
> >   if (!is_user && regs)
> >   current->thread.segv_regs = container_of(regs, struct 
> > pt_regs, regs);
> >
> > - if (!is_user && (address >= start_vm) && (address < end_vm)) {
> > + catcher = current->thread.fault_catcher;
>
> This and..
>
> > + if (catcher && current->thread.is_running_test)
> > + segv_run_catcher(catcher, (void *) address);
> > + else if (!is_user && (address >= start_vm) && (address < end_vm)) {
> >   flush_tlb_kernel_vm();
> >   goto out;
> >   }
>
> *not this*

I don't understand. Are you saying the previous block of code is good
and this one is bad?

>
> > @@ -246,12 +255,10 @@ unsigned long segv(struct faultinfo fi, unsigned long 
> > ip, int is_user,
> >   address = 0;
> >   }
> >
> > - catcher = current->thread.fault_catcher;
> >   if (!err)
> >   goto out;
> >   else if (catcher != NULL) {
> > - current->thread.fault_addr = (void *) address;
> > - UML_LONGJMP(catcher, 1);
> > + segv_run_catcher(catcher, (void *) address);
> >   }
> >   else if (current->thread.fault_addr != NULL)
> >   panic("fault_addr set but no fault catcher");
>
> But with this seems one atomic change which should be submitted
> separately, its just a helper. Think it would make the actual
> change needed easier to review, ie, your needed changes would
> be smaller and clearer for what you need.

Are you suggesting that I pull out the bits needed to implement abort
in the next patch and squash it into this one?


Re: [PATCH] i2c: aspeed: Add newline characters into message printings.

2018-07-10 Thread Brendan Higgins
  "master received interrupt 0x%08x, but is inactive\n",
> irq_status);
> bus->cmd_err = -EIO;
> /* Do not STOP as we should be inactive. */
> @@ -851,7 +851,7 @@ static int aspeed_i2c_probe_bus(struct platform_device 
> *pdev)
> bus->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
> if (IS_ERR(bus->rst)) {
> dev_err(&pdev->dev,
> -   "missing or invalid reset controller device tree 
> entry");
> +   "missing or invalid reset controller device tree 
> entry\n");
> return PTR_ERR(bus->rst);
> }
> reset_control_deassert(bus->rst);
> --
> 2.17.1
>

Reviewed-by: Brendan Higgins 


Re: [PATCH] i2c: aspeed: Fix initial values of master and slave state

2018-07-10 Thread Brendan Higgins
On Mon, Jul 2, 2018 at 2:20 PM Jae Hyun Yoo
 wrote:
>
> This patch changes the order of enum aspeed_i2c_master_state and
> enum aspeed_i2c_slave_state defines to make their initial value to
> ASPEED_I2C_MASTER_INACTIVE and ASPEED_I2C_SLAVE_STOP respectively.
> In case of multi-master use, if a slave data comes ahead of the
> first master xfer, master_state starts from an invalid state so
> this change fixes the issue.
>
> Signed-off-by: Jae Hyun Yoo 
> ---
>  drivers/i2c/busses/i2c-aspeed.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index 60e4d0e939a3..2714c7fbe7c9 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -111,22 +111,22 @@
>  #define ASPEED_I2CD_DEV_ADDR_MASK  GENMASK(6, 0)
>
>  enum aspeed_i2c_master_state {
> +   ASPEED_I2C_MASTER_INACTIVE,
> ASPEED_I2C_MASTER_START,
> ASPEED_I2C_MASTER_TX_FIRST,
> ASPEED_I2C_MASTER_TX,
> ASPEED_I2C_MASTER_RX_FIRST,
> ASPEED_I2C_MASTER_RX,
> ASPEED_I2C_MASTER_STOP,
> -   ASPEED_I2C_MASTER_INACTIVE,
>  };
>
>  enum aspeed_i2c_slave_state {
> +   ASPEED_I2C_SLAVE_STOP,
> ASPEED_I2C_SLAVE_START,
> ASPEED_I2C_SLAVE_READ_REQUESTED,
> ASPEED_I2C_SLAVE_READ_PROCESSED,
> ASPEED_I2C_SLAVE_WRITE_REQUESTED,
> ASPEED_I2C_SLAVE_WRITE_RECEIVED,
> -   ASPEED_I2C_SLAVE_STOP,
>  };
>
>  struct aspeed_i2c_bus {
> --
> 2.17.1
>

Reviewed-by: Brendan Higgins 

Thanks!

BTW, sorry for the delay, just got back from vacation. I will review
the rest tomorrow.


Re: [PATCH] i2c: aspeed: Improve driver to support multi-master use cases stably

2018-06-27 Thread Brendan Higgins
On Tue, Jun 26, 2018 at 9:58 AM Jae Hyun Yoo
 wrote:
>
> BMC firmware should support some multi-master use cases such as multi-node,
> IPMB, BMC-ME link and so on but the current ASPEED I2C driver is a bit
> unstable for the multi-master use case. So this patch improves ASPEED I2C
> driver to support the multi-master use case stably.
>
> Changes:
> * Added XFER_MODE status register checking logic into
>   aspeed_i2c_master_xfer to improve the current bus busy checking logic.
> * Changed the order of enum aspeed_i2c_master_state and
>   enum aspeed_i2c_slave_state defines to make their initial values set to
>   ASPEED_I2C_MASTER_INACTIVE and ASPEED_I2C_SLAVE_STOP respectively.
>   In case of multi-master use with previous code, if a slave data comes
>   ahead of the first master xfer, master_state starts from an invalid
>   state. This change fixed the issue.
> * Adjusted spin_lock scope to make it wrap the whole irq handler using
>   a single lock and unlock pair covers both master and slave handlers.
> * Added irq_status variable as a member of the struct aspeed_i2c_bus to
>   collect handled interrupt bits throughout the master and the slave irq
>   handlers.
> * Added control logic to put an order on calling the master and the slave
>   irq handlers based on their current states.
>
> Signed-off-by: Jae Hyun Yoo 
> ---
>  drivers/i2c/busses/i2c-aspeed.c | 200 +++-
>  1 file changed, 118 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index 60e4d0e939a3..ac3e17d9a365 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -4,6 +4,7 @@
>   *  Copyright (C) 2012-2017 ASPEED Technology Inc.
>   *  Copyright 2017 IBM Corporation
>   *  Copyright 2017 Google, Inc.
> + *  Copyright (c) 2018 Intel Corporation
>   *
>   *  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
> @@ -12,6 +13,7 @@
>
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -82,6 +84,11 @@
>  #define ASPEED_I2CD_INTR_RX_DONE   BIT(2)
>  #define ASPEED_I2CD_INTR_TX_NAKBIT(1)
>  #define ASPEED_I2CD_INTR_TX_ACKBIT(0)
> +#define ASPEED_I2CD_INTR_ERRORS  
>  \
> +   (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
>  \
> +ASPEED_I2CD_INTR_SCL_TIMEOUT |   
>  \
> +ASPEED_I2CD_INTR_ABNORMAL |  
>  \
> +ASPEED_I2CD_INTR_ARBIT_LOSS)
>  #define ASPEED_I2CD_INTR_ALL 
>  \
> (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT |
>  \
>  ASPEED_I2CD_INTR_BUS_RECOVER_DONE |  
>  \
> @@ -94,6 +101,7 @@
>  ASPEED_I2CD_INTR_TX_ACK)
>
>  /* 0x14 : I2CD Command/Status Register   */
> +#define ASPEED_I2CD_XFER_MODE_STS_MASK GENMASK(22, 19)
>  #define ASPEED_I2CD_SCL_LINE_STS   BIT(18)
>  #define ASPEED_I2CD_SDA_LINE_STS   BIT(17)
>  #define ASPEED_I2CD_BUS_BUSY_STS   BIT(16)
> @@ -110,23 +118,27 @@
>  /* 0x18 : I2CD Slave Device Address Register   */
>  #define ASPEED_I2CD_DEV_ADDR_MASK  GENMASK(6, 0)
>
> +/* Timeout for bus busy checking */
> +#define BUS_BUSY_CHECK_TIMEOUT 25 /* 250ms */
> +#define BUS_BUSY_CHECK_INTERVAL1  /* 
> 10ms */

Could you add a comment on where you got these values from?

Also, please use the same naming pattern as above.

> +
>  enum aspeed_i2c_master_state {
> +   ASPEED_I2C_MASTER_INACTIVE,
> ASPEED_I2C_MASTER_START,
> ASPEED_I2C_MASTER_TX_FIRST,
> ASPEED_I2C_MASTER_TX,
> ASPEED_I2C_MASTER_RX_FIRST,
> ASPEED_I2C_MASTER_RX,
> ASPEED_I2C_MASTER_STOP,
> -   ASPEED_I2C_MASTER_INACTIVE,
>  };
>
>  enum aspeed_i2c_slave_state {
> +   ASPEED_I2C_SLAVE_STOP,
> ASPEED_I2C_SLAVE_START,
> ASPEED_I2C_SLAVE_READ_REQUESTED,
> ASPEED_I2C_SLAVE_READ_PROCESSED,
> ASPEED_I2C_SLAVE_WRITE_REQUESTED,
> ASPEED_I2C_SLAVE_WRITE_RECEIVED,
> -   ASPEED_I2C_SLAVE_STOP,
>  };
>
>  struct aspeed_i2c_bus {
> @@ -150,6 +162,7 @@ struct aspeed_i2c_bus {
> int cmd_err;
> /* Protected only by i2c_lock_bus */
> int master_xfer_result;
> +   u32 irq_status;
>  #if IS_ENABLED(CONFIG_I2C_SLAVE)
> struct i2c_client   *slave;
> enum aspeed_i2c_slave_state slave_state;
> @@ -229,37 +242,30 @@ static int aspeed_i2c_recover_bus(stru

Re: [PATCH 5/7] [stable-4.19] i2c: aspeed: fix build warning

2018-12-14 Thread Brendan Higgins
On Fri, Dec 14, 2018 at 2:12 PM Arnd Bergmann  wrote:
>
> Upstream commit 3e9efc3299dd ("i2c: aspeed: Handle master/slave combined irq 
> events
> properly") reworked the interrupt handling and fixed a warning in the process:
>
> drivers/i2c/busses/i2c-aspeed.c: In function 'aspeed_i2c_bus_irq':
> drivers/i2c/busses/i2c-aspeed.c:567:1: error: label 'out' defined but not 
> used [-Werror=unused-label]
>
> The warning is still present in v4.19.8 and can be fixed either by applying
> that original patch, or by adding a simple #ifdef.
>
> Here, I choose the second simpler option as the original patch seems too
> invasive for a stable backport.
>
> Signed-off-by: Arnd Bergmann 

Thanks!

Reviewed-by: Brendan Higgins 


Re: [PATCH i2c-next v7 3/5] dt-bindings: i2c: aspeed: Add 'bus-timeout-ms' property as an optional property

2018-10-09 Thread Brendan Higgins
On Fri, Oct 5, 2018 at 2:45 PM Jae Hyun Yoo
 wrote:
>
> This commit adds 'bus-timeout-ms' property as an optional property
> which can be used for setting the bus timeout value of an adapter.
> With this patch, the bus timeout value can be set through this
> property at the probing time of this module. Still the bus timeout
> value can be set by an I2C_TIMEOUT ioctl on cdev at runtime too.
>
> Signed-off-by: Jae Hyun Yoo 

Reviewed-by: Brendan Higgins 

Thanks for putting all the work in to do it this way!


Re: [PATCH i2c-next v7 4/5] i2c: aspeed: Remove hard-coded bus timeout value setting

2018-10-09 Thread Brendan Higgins
On Fri, Oct 5, 2018 at 2:45 PM Jae Hyun Yoo
 wrote:
>
> This commit removes hard-coded bus timeout value setting so that
> it can be set by i2c-core-base.
>
> Signed-off-by: Jae Hyun Yoo 
> Reviewed-by: Joel Stanley 

Reviewed-by: Brendan Higgins 


Re: [PATCH i2c-next v7 5/5] i2c: aspeed: Add bus idle waiting logic for multi-master use cases

2018-10-09 Thread Brendan Higgins
On Fri, Oct 5, 2018 at 2:45 PM Jae Hyun Yoo
 wrote:
>
> In multi-master environment, this driver's master cannot know
> exactly when peer master sends data to this driver's slave so a
> case can be happened that this master tries to send data through
> the master_xfer function but slave data from peer master is still
> being processed by this driver.
>
> To prevent any state corruption in the case, this patch adds
> checking code if any slave operation is ongoing and it waits up to
> the bus timeout duration before starting a master_xfer operation.
>
> Signed-off-by: Jae Hyun Yoo 

Reviewed-by: Brendan Higgins 


[RFC v1 00/31] kunit: Introducing KUnit, the Linux kernel unit testing framework

2018-10-16 Thread Brendan Higgins
This patch set proposes KUnit, a lightweight unit testing and mocking
framework for the Linux kernel.

Unlike Autotest and kselftest, KUnit is a true unit testing framework;
it does not require installing the kernel on a test machine or in a VM
and does not require tests to be written in userspace running on a host
kernel. Additionally, KUnit is fast: From invocation to completion KUnit
can run several dozen tests in under a second. Currently, the entire
KUnit test suite for KUnit runs in under a second from the initial
invocation (build time excluded).

KUnit is heavily inspired by JUnit, Python's unittest.mock, and
Googletest/Googlemock for C++. KUnit provides facilities for defining
unit test cases, grouping related test cases into test suites, providing
common infrastructure for running tests, mocking, spying, and much more.

## What's so special about unit testing?

A unit test is supposed to test a single unit of code in isolation,
hence the name. There should be no dependencies outside the control of
the test; this means no external dependencies, which makes tests orders
of magnitudes faster. Likewise, since there are no external dependencies,
there are no hoops to jump through to run the tests. Additionally, this
makes unit tests deterministic: a failing unit test always indicates a
problem. Finally, because unit tests necessarily have finer granularity,
they are able to test all code paths easily solving the classic problem
of difficulty in exercising error handling code.

## Is KUnit trying to replace other testing frameworks for the kernel?

No. Most existing tests for the Linux kernel are end-to-end tests, which
have their place. A well tested system has lots of unit tests, a
reasonable number of integration tests, and some end-to-end tests. KUnit
is just trying to address the unit test space which is currently not
being addressed.

## More information on KUnit

There is a bunch of documentation near the end of this patch set that
describes how to use KUnit and best practices for writing unit tests.
For convenience I am hosting the compiled docs here:
https://google.github.io/kunit-docs/third_party/kernel/docs/

-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 02/31] kunit: test: adds KUnit test runner core

2018-10-16 Thread Brendan Higgins
Adds the KUnit core, which allows test cases to be defined and
associated with common initialization and cleanup logic.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 165 ++
 kunit/Makefile   |   2 +-
 kunit/test.c | 168 +++
 3 files changed, 334 insertions(+), 1 deletion(-)
 create mode 100644 include/kunit/test.h
 create mode 100644 kunit/test.c

diff --git a/include/kunit/test.h b/include/kunit/test.h
new file mode 100644
index 0..e0b14b227ac44
--- /dev/null
+++ b/include/kunit/test.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Base unit test (KUnit) API.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_TEST_H
+#define _KUNIT_TEST_H
+
+#include 
+#include 
+
+struct test;
+
+/**
+ * struct test_case - represents an individual test case.
+ * @run_case: the function representing the actual test case.
+ * @name: the name of the test case.
+ *
+ * A test case is a function with the signature, ``void (*)(struct test *)``
+ * that makes expectations (see TEST_EXPECT_TRUE()) about code under test. Each
+ * test case is associated with a &struct test_module and will be run after the
+ * module's init function and followed by the module's exit function.
+ *
+ * A test case should be static and should only be created with the TEST_CASE()
+ * macro; additionally, every array of test cases should be terminated with an
+ * empty test case.
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * void add_test_basic(struct test *test)
+ * {
+ * TEST_EXPECT_EQ(test, 1, add(1, 0));
+ * TEST_EXPECT_EQ(test, 2, add(1, 1));
+ * TEST_EXPECT_EQ(test, 0, add(-1, 1));
+ * TEST_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX));
+ * TEST_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN));
+ * }
+ *
+ * static struct test_case example_test_cases[] = {
+ * TEST_CASE(add_test_basic),
+ * {},
+ * };
+ *
+ */
+struct test_case {
+   void (*run_case)(struct test *test);
+   const char name[256];
+
+   /* private: internal use only. */
+   bool success;
+};
+
+/**
+ * TEST_CASE - A helper for creating a &struct test_case
+ * @test_name: a reference to a test case function.
+ *
+ * Takes a symbol for a function representing a test case and creates a &struct
+ * test_case object from it. See the documentation for &struct test_case for an
+ * example on how to use it.
+ */
+#define TEST_CASE(test_name) { .run_case = test_name, .name = #test_name }
+
+/**
+ * struct test_module - describes a related collection of &struct test_case s.
+ * @name: the name of the test. Purely informational.
+ * @init: called before every test case.
+ * @exit: called after every test case.
+ * @test_cases: a null terminated array of test cases.
+ *
+ * A test_module is a collection of related &struct test_case s, such that
+ * @init is called before every test case and @exit is called after every test
+ * case, similar to the notion of a *test fixture* or a *test class* in other
+ * unit testing frameworks like JUnit or Googletest.
+ *
+ * Every &struct test_case must be associated with a test_module for KUnit to
+ * run it.
+ */
+struct test_module {
+   const char name[256];
+   int (*init)(struct test *test);
+   void (*exit)(struct test *test);
+   struct test_case *test_cases;
+};
+
+/**
+ * struct test - represents a running instance of a test.
+ * @priv: for user to store arbitrary data. Commonly used to pass data created
+ * in the init function (see &struct test_module).
+ *
+ * Used to store information about the current context under which the test is
+ * running. Most of this data is private and should only be accessed indirectly
+ * via public functions; the one exception is @priv which can be used by the
+ * test writer to store arbitrary data.
+ */
+struct test {
+   void *priv;
+
+   /* private: internal use only. */
+   const char *name; /* Read only after initialization! */
+   spinlock_t lock; /* Gaurds all mutable test state. */
+   bool success; /* Protected by lock. */
+   void (*vprintk)(const struct test *test,
+   const char *level,
+   struct va_format *vaf);
+};
+
+int test_init_test(struct test *test, const char *name);
+
+int test_run_tests(struct test_module *module);
+
+/**
+ * module_test() - used to register a &struct test_module with KUnit.
+ * @module: a statically allocated &struct test_module.
+ *
+ * Registers @module with the test framework. See &struct test_module for more
+ * information.
+ */
+#define module_test(module) \
+   static int module_test_init##module(void) \
+   { \
+   return test_run_tests(&module); \
+   } \
+   lat

[RFC v1 01/31] kunit: test: added string_stream a std::stream like string builder

2018-10-16 Thread Brendan Higgins
A number of test features need to do pretty complicated string printing
where it may not be possible to rely on a single preallocated string
with parameters.

This provides a library for constructing the string as you go similar to
C++'s std::string.

Signed-off-by: Brendan Higgins 
---
 include/kunit/string-stream.h |  44 ++
 kunit/Kconfig |  16 
 kunit/Makefile|   1 +
 kunit/string-stream.c | 149 ++
 4 files changed, 210 insertions(+)
 create mode 100644 include/kunit/string-stream.h
 create mode 100644 kunit/Kconfig
 create mode 100644 kunit/Makefile
 create mode 100644 kunit/string-stream.c

diff --git a/include/kunit/string-stream.h b/include/kunit/string-stream.h
new file mode 100644
index 0..933ed5740cf07
--- /dev/null
+++ b/include/kunit/string-stream.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * C++ stream style string builder used in KUnit for building messages.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_STRING_STREAM_H
+#define _KUNIT_STRING_STREAM_H
+
+#include 
+#include 
+#include 
+#include 
+
+struct string_stream_fragment {
+   struct list_head node;
+   char *fragment;
+};
+
+struct string_stream {
+   size_t length;
+   struct list_head fragments;
+
+   /* length and fragments are protected by this lock */
+   spinlock_t lock;
+   struct kref refcount;
+   int (*add)(struct string_stream *this, const char *fmt, ...);
+   int (*vadd)(struct string_stream *this, const char *fmt, va_list args);
+   char *(*get_string)(struct string_stream *this);
+   void (*clear)(struct string_stream *this);
+   bool (*is_empty)(struct string_stream *this);
+};
+
+struct string_stream *new_string_stream(void);
+
+void destroy_string_stream(struct string_stream *stream);
+
+void string_stream_get(struct string_stream *stream);
+
+int string_stream_put(struct string_stream *stream);
+
+#endif /* _KUNIT_STRING_STREAM_H */
diff --git a/kunit/Kconfig b/kunit/Kconfig
new file mode 100644
index 0..64480092b2c24
--- /dev/null
+++ b/kunit/Kconfig
@@ -0,0 +1,16 @@
+#
+# KUnit base configuration
+#
+
+menu "KUnit support"
+
+config KUNIT
+   bool "Enable support for unit tests (KUnit)"
+   help
+ Enables support for kernel unit tests (KUnit), a lightweight unit
+ testing and mocking framework for the Linux kernel. These tests are
+ able to be run locally on a developer's workstation without a VM or
+ special hardware. For more information, please see
+ Documentation/kunit/
+
+endmenu
diff --git a/kunit/Makefile b/kunit/Makefile
new file mode 100644
index 0..de16cce9d6a27
--- /dev/null
+++ b/kunit/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_KUNIT)+= string-stream.o
diff --git a/kunit/string-stream.c b/kunit/string-stream.c
new file mode 100644
index 0..1e7efa630cc35
--- /dev/null
+++ b/kunit/string-stream.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * C++ stream style string builder used in KUnit for building messages.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+#include 
+
+static int string_stream_vadd(struct string_stream *this,
+  const char *fmt,
+  va_list args)
+{
+   struct string_stream_fragment *fragment;
+   int len;
+   va_list args_for_counting;
+   unsigned long flags;
+
+   /* Make a copy because `vsnprintf` could change it */
+   va_copy(args_for_counting, args);
+
+   /* Need space for null byte. */
+   len = vsnprintf(NULL, 0, fmt, args_for_counting) + 1;
+
+   va_end(args_for_counting);
+
+   fragment = kmalloc(sizeof(*fragment), GFP_KERNEL);
+   if (!fragment)
+   return -ENOMEM;
+
+   fragment->fragment = kmalloc(len, GFP_KERNEL);
+   if (!fragment->fragment) {
+   kfree(fragment);
+   return -ENOMEM;
+   }
+
+   len = vsnprintf(fragment->fragment, len, fmt, args);
+   spin_lock_irqsave(&this->lock, flags);
+   this->length += len;
+   list_add_tail(&fragment->node, &this->fragments);
+   spin_unlock_irqrestore(&this->lock, flags);
+   return 0;
+}
+
+static int string_stream_add(struct string_stream *this, const char *fmt, ...)
+{
+   va_list args;
+   int result;
+
+   va_start(args, fmt);
+   result = string_stream_vadd(this, fmt, args);
+   va_end(args);
+   return result;
+}
+
+static void string_stream_clear(struct string_stream *this)
+{
+   struct string_stream_fragment *fragment, *fragment_safe;
+   unsigned long flags;
+
+   spin_lock_irqsave(&this->lock, flags);
+   list_for_each_entry_safe(fragment,
+   

[RFC v1 08/31] arch: um: added shim to trap to allow installing a fault catcher for tests

2018-10-16 Thread Brendan Higgins
Added context to current thread that allows a test to specify that it
wants to skip the normal checks to run an installed fault catcher.

Signed-off-by: Brendan Higgins 
---
 arch/um/include/asm/processor-generic.h |  4 +++-
 arch/um/kernel/trap.c   | 15 +++
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/arch/um/include/asm/processor-generic.h 
b/arch/um/include/asm/processor-generic.h
index b58b746d3f2ca..d566cd416ff02 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -27,6 +27,7 @@ struct thread_struct {
struct task_struct *prev_sched;
struct arch_thread arch;
jmp_buf switch_buf;
+   bool is_running_test;
struct {
int op;
union {
@@ -51,7 +52,8 @@ struct thread_struct {
.fault_addr = NULL, \
.prev_sched = NULL, \
.arch   = INIT_ARCH_THREAD, \
-   .request= { 0 } \
+   .request= { 0 }, \
+   .is_running_test= false, \
 }
 
 static inline void release_thread(struct task_struct *task)
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index ec9a42c14c565..9b97712daf14f 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -201,6 +201,12 @@ void segv_handler(int sig, struct siginfo *unused_si, 
struct uml_pt_regs *regs)
segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
 }
 
+static void segv_run_catcher(jmp_buf *catcher, void *fault_addr)
+{
+   current->thread.fault_addr = fault_addr;
+   UML_LONGJMP(catcher, 1);
+}
+
 /*
  * We give a *copy* of the faultinfo in the regs to segv.
  * This must be done, since nesting SEGVs could overwrite
@@ -219,7 +225,10 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, 
int is_user,
if (!is_user && regs)
current->thread.segv_regs = container_of(regs, struct pt_regs, 
regs);
 
-   if (!is_user && (address >= start_vm) && (address < end_vm)) {
+   catcher = current->thread.fault_catcher;
+   if (catcher && current->thread.is_running_test)
+   segv_run_catcher(catcher, (void *) address);
+   else if (!is_user && (address >= start_vm) && (address < end_vm)) {
flush_tlb_kernel_vm();
goto out;
}
@@ -246,12 +255,10 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, 
int is_user,
address = 0;
}
 
-   catcher = current->thread.fault_catcher;
if (!err)
goto out;
else if (catcher != NULL) {
-   current->thread.fault_addr = (void *) address;
-   UML_LONGJMP(catcher, 1);
+   segv_run_catcher(catcher, (void *) address);
}
else if (current->thread.fault_addr != NULL)
panic("fault_addr set but no fault catcher");
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 07/31] kunit: test: added initial tests

2018-10-16 Thread Brendan Higgins
Added a test for string stream along with a more simple example.

Signed-off-by: Brendan Higgins 
---
 kunit/Kconfig  | 12 ++
 kunit/Makefile |  2 +
 kunit/example-test.c   | 88 ++
 kunit/string-stream-test.c | 61 ++
 4 files changed, 163 insertions(+)
 create mode 100644 kunit/example-test.c
 create mode 100644 kunit/string-stream-test.c

diff --git a/kunit/Kconfig b/kunit/Kconfig
index 64480092b2c24..5cb500355c873 100644
--- a/kunit/Kconfig
+++ b/kunit/Kconfig
@@ -13,4 +13,16 @@ config KUNIT
  special hardware. For more information, please see
  Documentation/kunit/
 
+config KUNIT_TEST
+   bool "KUnit test for KUnit"
+   depends on KUNIT
+   help
+ Enables KUnit test to test KUnit.
+
+config KUNIT_EXAMPLE_TEST
+   bool "Example test for KUnit"
+   depends on KUNIT
+   help
+ Enables example KUnit test to demo features of KUnit.
+
 endmenu
diff --git a/kunit/Makefile b/kunit/Makefile
index 5b4562ea7f322..319eb9dc8be0e 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -1 +1,3 @@
 obj-$(CONFIG_KUNIT)+= test.o string-stream.o test-stream.o
+obj-$(CONFIG_KUNIT_TEST)   += string-stream-test.o
+obj-$(CONFIG_EXAMPLE_TEST) += example-test.o
diff --git a/kunit/example-test.c b/kunit/example-test.c
new file mode 100644
index 0..e9bd2b41c5fd2
--- /dev/null
+++ b/kunit/example-test.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Example KUnit test to show how to use KUnit.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+
+/*
+ * This is the most fundamental element of KUnit, the test case. A test case
+ * makes a set EXPECTATIONs and ASSERTIONs about the behavior of some code; if
+ * any expectations or assertions are not met, the test fails; otherwise, the
+ * test passes.
+ *
+ * In KUnit, a test case is just a function with the signature
+ * `void (*)(struct test *)`. `struct test` is a context object that stores
+ * information about the current test.
+ */
+static void example_simple_test(struct test *test)
+{
+   /*
+* This is an EXPECTATION; it is how KUnit tests things. When you want
+* to test a piece of code, you set some expectations about what the
+* code should do. KUnit then runs the test and verifies that the code's
+* behavior matched what was expected.
+*/
+   TEST_EXPECT_EQ(test, 1 + 1, 2);
+}
+
+/*
+ * This is run once before each test case, see the comment on
+ * example_test_module for more information.
+ */
+static int example_test_init(struct test *test)
+{
+   test_info(test, "initializing");
+
+   return 0;
+}
+
+/*
+ * Here we make a list of all the test cases we want to add to the test module
+ * below.
+ */
+static struct test_case example_test_cases[] = {
+   /*
+* This is a helper to create a test case object from a test case
+* function; its exact function is not important to understand how to
+* use KUnit, just know that this is how you associate test cases with a
+* test module.
+*/
+   TEST_CASE(example_simple_test),
+   {},
+};
+
+/*
+ * This defines a suite or grouping of tests.
+ *
+ * Test cases are defined as belonging to the suite by adding them to
+ * `test_cases`.
+ *
+ * Often it is desirable to run some function which will set up things which
+ * will be used by every test; this is accomplished with an `init` function
+ * which runs before each test case is invoked. Similarly, an `exit` function
+ * may be specified which runs after every test case and can be used to for
+ * cleanup. For clarity, running tests in a test module would behave as 
follows:
+ *
+ * module.init(test);
+ * module.test_case[0](test);
+ * module.exit(test);
+ * module.init(test);
+ * module.test_case[1](test);
+ * module.exit(test);
+ * ...;
+ */
+static struct test_module example_test_module = {
+   .name = "example",
+   .init = example_test_init,
+   .test_cases = example_test_cases,
+};
+
+/*
+ * This registers the above test module telling KUnit that this is a suite of
+ * tests that need to be run.
+ */
+module_test(example_test_module);
diff --git a/kunit/string-stream-test.c b/kunit/string-stream-test.c
new file mode 100644
index 0..07c626cbfffbf
--- /dev/null
+++ b/kunit/string-stream-test.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit test for struct string_stream.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+#include 
+
+static void string_stream_test_get_string(struct test *test)
+{
+   struct string_stream *stream = new_string_stream();
+   char *output;
+
+   stream->add(stream, "Foo");
+   stream->add(stream, " %s", "bar");
+
+   outp

[RFC v1 03/31] kunit: test: added test resource management API

2018-10-16 Thread Brendan Higgins
This creates a common API for test managed resources like memory and
test objects.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 109 +++
 kunit/test.c |  95 +
 2 files changed, 204 insertions(+)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index e0b14b227ac44..1c116a20063da 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -12,6 +12,69 @@
 #include 
 #include 
 
+struct test_resource;
+
+typedef int (*test_resource_init_t)(struct test_resource *, void *);
+typedef void (*test_resource_free_t)(struct test_resource *);
+
+/**
+ * struct test_resource - represents a *test managed resource*
+ * @allocation: for the user to store arbitrary data.
+ * @free: a user supplied function to free the resource. Populated by
+ * test_alloc_resource().
+ *
+ * Represents a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case.
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * struct test_kmalloc_params {
+ * size_t size;
+ * gfp_t gfp;
+ * };
+ *
+ * static int test_kmalloc_init(struct test_resource *res, void *context)
+ * {
+ * struct test_kmalloc_params *params = context;
+ * res->allocation = kmalloc(params->size, params->gfp);
+ *
+ * if (!res->allocation)
+ * return -ENOMEM;
+ *
+ * return 0;
+ * }
+ *
+ * static void test_kmalloc_free(struct test_resource *res)
+ * {
+ * kfree(res->allocation);
+ * }
+ *
+ * void *test_kmalloc(struct test *test, size_t size, gfp_t gfp)
+ * {
+ * struct test_kmalloc_params params;
+ * struct test_resource *res;
+ *
+ * params.size = size;
+ * params.gfp = gfp;
+ *
+ * res = test_alloc_resource(test, test_kmalloc_init,
+ * test_kmalloc_free, ¶ms);
+ * if (res)
+ * return res->allocation;
+ * else
+ * return NULL;
+ * }
+ */
+struct test_resource {
+   void *allocation;
+   test_resource_free_t free;
+
+   /* private: internal use only. */
+   struct list_head node;
+};
+
 struct test;
 
 /**
@@ -104,6 +167,7 @@ struct test {
const char *name; /* Read only after initialization! */
spinlock_t lock; /* Gaurds all mutable test state. */
bool success; /* Protected by lock. */
+   struct list_head resources; /* Protected by lock. */
void (*vprintk)(const struct test *test,
const char *level,
struct va_format *vaf);
@@ -127,6 +191,51 @@ int test_run_tests(struct test_module *module);
} \
late_initcall(module_test_init##module)
 
+/**
+ * test_alloc_resource() - Allocates a *test managed resource*.
+ * @test: The test context object.
+ * @init: a user supplied function to initialize the resource.
+ * @free: a user supplied function to free the resource.
+ * @context: for the user to pass in arbitrary data.
+ *
+ * Allocates a *test managed resource*, a resource which will automatically be
+ * cleaned up at the end of a test case. See &struct test_resource for an
+ * example.
+ */
+struct test_resource *test_alloc_resource(struct test *test,
+ test_resource_init_t init,
+ test_resource_free_t free,
+ void *context);
+
+void test_free_resource(struct test *test, struct test_resource *res);
+
+/**
+ * test_kmalloc() - Just like kmalloc() except the allocation is *test 
managed*.
+ * @test: The test context object.
+ * @size: The size in bytes of the desired memory.
+ * @gfp: flags passed to underlying kmalloc().
+ *
+ * Just like `kmalloc(...)`, except the allocation is managed by the test case
+ * and is automatically cleaned up after the test case concludes. See &struct
+ * test_resource for more information.
+ */
+void *test_kmalloc(struct test *test, size_t size, gfp_t gfp);
+
+/**
+ * test_kzalloc() - Just like test_kmalloc(), but zeroes the allocation.
+ * @test: The test context object.
+ * @size: The size in bytes of the desired memory.
+ * @gfp: flags passed to underlying kmalloc().
+ *
+ * See kzalloc() and test_kmalloc() for more information.
+ */
+static inline void *test_kzalloc(struct test *test, size_t size, gfp_t gfp)
+{
+   return test_kmalloc(test, size, gfp | __GFP_ZERO);
+}
+
+void test_cleanup(struct test *test);
+
 void __printf(3, 4) test_printk(const char *level,
const struct test *test,
const char *fmt, ...);
diff --git a/kunit/test.c b/kunit/test.c
index 4732e5f0d7575..fd0a51245215e 100644
--- a/kunit/test.c
+++ b/kunit/test.c
@@ -66,6 +66,7 @@ static void test_vprin

[RFC v1 10/31] kunit: test: added concept of initcalls

2018-10-16 Thread Brendan Higgins
Added a way to add plugins that require a test module to be loaded
during initialization.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 19 +++
 kunit/test.c | 29 +
 2 files changed, 48 insertions(+)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 49a9d6e43992c..58dbe2aee423f 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -152,6 +152,12 @@ struct test_module {
struct test_case *test_cases;
 };
 
+struct test_initcall {
+   struct list_head node;
+   int (*init)(struct test_initcall *this, struct test *test);
+   void (*exit)(struct test_initcall *this);
+};
+
 /**
  * struct test - represents a running instance of a test.
  * @priv: for user to store arbitrary data. Commonly used to pass data created
@@ -183,6 +189,19 @@ int test_init_test(struct test *test, const char *name);
 
 int test_run_tests(struct test_module *module);
 
+void test_install_initcall(struct test_initcall *initcall);
+
+#define test_pure_initcall(fn) postcore_initcall(fn)
+
+#define test_register_initcall(initcall) \
+   static int register_test_initcall_##initcall(void) \
+   { \
+   test_install_initcall(&initcall); \
+   \
+   return 0; \
+   } \
+   test_pure_initcall(register_test_initcall_##initcall)
+
 /**
  * module_test() - used to register a &struct test_module with KUnit.
  * @module: a statically allocated &struct test_module.
diff --git a/kunit/test.c b/kunit/test.c
index f89cfaaf5eb79..9737465fb0568 100644
--- a/kunit/test.c
+++ b/kunit/test.c
@@ -53,6 +53,19 @@ static void test_set_death_test(struct test *test, bool 
death_test)
spin_unlock_irqrestore(&test->lock, flags);
 }
 
+struct test_global_context {
+   struct list_head initcalls;
+};
+
+static struct test_global_context test_global_context = {
+   .initcalls = LIST_HEAD_INIT(test_global_context.initcalls),
+};
+
+void test_install_initcall(struct test_initcall *initcall)
+{
+   list_add_tail(&initcall->node, &test_global_context.initcalls);
+}
+
 static int test_vprintk_emit(const struct test *test,
 int level,
 const char *fmt,
@@ -130,8 +143,18 @@ static void test_run_case_internal(struct test *test,
   struct test_module *module,
   struct test_case *test_case)
 {
+   struct test_initcall *initcall;
int ret;
 
+   list_for_each_entry(initcall, &test_global_context.initcalls, node) {
+   ret = initcall->init(initcall, test);
+   if (ret) {
+   test_err(test, "failed to initialize: %d", ret);
+   test->success = false;
+   return;
+   }
+   }
+
if (module->init) {
ret = module->init(test);
if (ret) {
@@ -146,6 +169,12 @@ static void test_run_case_internal(struct test *test,
 
 static void test_case_internal_cleanup(struct test *test)
 {
+   struct test_initcall *initcall;
+
+   list_for_each_entry(initcall, &test_global_context.initcalls, node) {
+   initcall->exit(initcall);
+   }
+
test_cleanup(test);
 }
 
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 13/31] kunit: mock: added parameter list minipulation macros

2018-10-16 Thread Brendan Higgins
Adds macros for parsing and manipulating parameter lists needed for
generating mocks.

Signed-off-by: Brendan Higgins 
---
 include/kunit/params.h  | 305 
 kunit/Makefile  |   2 +-
 kunit/mock-macro-test.c | 149 
 3 files changed, 455 insertions(+), 1 deletion(-)
 create mode 100644 include/kunit/params.h
 create mode 100644 kunit/mock-macro-test.c

diff --git a/include/kunit/params.h b/include/kunit/params.h
new file mode 100644
index 0..f9692d3cd703f
--- /dev/null
+++ b/include/kunit/params.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Macros for parsing and manipulating parameter lists needed for generating
+ * mocks.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_PARAMS_H
+#define _KUNIT_PARAMS_H
+
+#define NUM_VA_ARGS_IMPL(__dummy, \
+__1,  \
+__2,  \
+__3,  \
+__4,  \
+__5,  \
+__6,  \
+__7,  \
+__8,  \
+__9,  \
+__10, \
+__11, \
+__12, \
+__13, \
+__14, \
+__15, \
+__16, \
+__nargs, args...) __nargs
+
+#define NUM_VA_ARGS(args...) NUM_VA_ARGS_IMPL(__dummy, ##args,\
+ 16,  \
+ 15,  \
+ 14,  \
+ 13,  \
+ 12,  \
+ 11,  \
+ 10,  \
+ 9,   \
+ 8,   \
+ 7,   \
+ 6,   \
+ 5,   \
+ 4,   \
+ 3,   \
+ 2,   \
+ 1,   \
+ 0)
+
+#define CONCAT_INTERNAL(left, right) left##right
+#define CONCAT(left, right) CONCAT_INTERNAL(left, right)
+
+#define EMPTY()
+
+/*
+ * Takes the name of a function style macro such as FOO() and prevents it from
+ * being evaluated on the current pass.
+ *
+ * This is useful when you need to write a "recursive" macro since a macro name
+ * becomes painted after it is pasted. If a different macro is pasted, this
+ * different macro won't be pasted; if we then defer the evaluation of the this
+ * "indirection macro", we can prevent the original definition from getting
+ * painted.
+ *
+ * Example:
+ *   #define EXAMPLE EXPAND(FOO()) // FOO() is evaluated on 1st pass.
+ *   #define EXAMPLE EXPAND(DEFER(FOO)()) // FOO() is evaluated on the second
+ *   // pass.
+ */
+#define DEFER(macro_id) macro_id EMPTY()
+
+/*
+ * Takes the name of a function style macro such as FOO() and prevents it from
+ * being evaluated on the current or following pass.
+ *
+ * This is useful when you need to DEFER inside an operation which causes an
+ * extra pass, like IF.
+ *
+ * Example:
+ *   #define EXAMPLE EXPAND(FOO()) // FOO() is evaluated on 1st pass.
+ *   #define EXAMPLE EXPAND(DEFER(FOO)()) // FOO() i

[RFC v1 11/31] kunit: test: added concept of post conditions

2018-10-16 Thread Brendan Higgins
Adds a way to specify that certain conditions must be met at the end of
a test case.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h |  6 ++
 kunit/test.c | 13 -
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 58dbe2aee423f..be2b7d1de 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -158,6 +158,11 @@ struct test_initcall {
void (*exit)(struct test_initcall *this);
 };
 
+struct test_post_condition {
+   struct list_head node;
+   void (*validate)(struct test_post_condition *condition);
+};
+
 /**
  * struct test - represents a running instance of a test.
  * @priv: for user to store arbitrary data. Commonly used to pass data created
@@ -177,6 +182,7 @@ struct test {
bool success; /* Protected by lock. */
bool death_test; /* Protected by lock. */
struct list_head resources; /* Protected by lock. */
+   struct list_head post_conditions;
void (*set_death_test)(struct test *test, bool death_test);
void (*vprintk)(const struct test *test,
const char *level,
diff --git a/kunit/test.c b/kunit/test.c
index 9737465fb0568..6ea60059b4918 100644
--- a/kunit/test.c
+++ b/kunit/test.c
@@ -125,8 +125,9 @@ static void __noreturn test_abort(struct test *test)
 
 int test_init_test(struct test *test, const char *name)
 {
-   spin_lock_init(&test->lock);
INIT_LIST_HEAD(&test->resources);
+   INIT_LIST_HEAD(&test->post_conditions);
+   spin_lock_init(&test->lock);
test->name = name;
test->set_death_test = test_set_death_test;
test->vprintk = test_vprintk;
@@ -186,6 +187,16 @@ static void test_run_case_cleanup(struct test *test,
  struct test_module *module,
  struct test_case *test_case)
 {
+   struct test_post_condition *condition, *condition_safe;
+
+   list_for_each_entry_safe(condition,
+condition_safe,
+&test->post_conditions,
+node) {
+   condition->validate(condition);
+   list_del(&condition->node);
+   }
+
if (module->exit)
module->exit(test);
 
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 05/31] kunit: test: added the concept of expectations

2018-10-16 Thread Brendan Higgins
Added support for expectations, which allow properties to be specified
and then verified in tests.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 259 +++
 1 file changed, 259 insertions(+)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 68320fa2452de..d652825d7296f 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -273,4 +273,263 @@ void __printf(3, 4) test_printk(const char *level,
 #define test_err(test, fmt, ...) \
test_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
 
+static inline struct test_stream *test_expect_start(struct test *test,
+   const char *file,
+   const char *line)
+{
+   struct test_stream *stream = test_new_stream(test);
+
+   stream->add(stream, "EXPECTATION FAILED at %s:%s\n\t", file, line);
+
+   return stream;
+}
+
+static inline void test_expect_end(struct test *test,
+  bool success,
+  struct test_stream *stream)
+{
+   if (!success)
+   test->fail(test, stream);
+   else
+   stream->clear(stream);
+}
+
+#define TEST_EXPECT_START(test) \
+   test_expect_start(test, __FILE__, __stringify(__LINE__))
+
+#define TEST_EXPECT_END(test, success, stream) \
+   test_expect_end(test, success, stream)
+
+#define TEST_EXPECT(test, success, message) do {  \
+   struct test_stream *__stream = TEST_EXPECT_START(test);\
+  \
+   __stream->add(__stream, message);  \
+   TEST_EXPECT_END(test, success, __stream);  \
+} while (0)
+
+/**
+ * TEST_SUCCEED() - A no-op expectation. Only exists for code clarity.
+ * @test: The test context object.
+ *
+ * The opposite of TEST_FAIL(), it is an expectation that cannot fail. In other
+ * words, it does nothing and only exists for code clarity. See
+ * TEST_EXPECT_TRUE() for more information.
+ */
+#define TEST_SUCCEED(test) do {} while (0)
+
+/**
+ * TEST_FAIL() - Always causes a test to fail when evaluated.
+ * @test: The test context object.
+ * @message: an informational message to be printed when the assertion is made.
+ *
+ * The opposite of TEST_SUCCEED(), it is an expectation that always fails. In
+ * other words, it always results in a failed expectation, and consequently
+ * always causes the test case to fail when evaluated. See TEST_EXPECT_TRUE()
+ * for more information.
+ */
+#define TEST_FAIL(test, message) TEST_EXPECT(test, false, message)
+
+/**
+ * TEST_EXPECT_TRUE() - Causes a test failure when the expression is not true.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails when this does
+ * not evaluate to true.
+ *
+ * This and expectations of the form `TEST_EXPECT_*` will cause the test case 
to
+ * fail when the specified condition is not met; however, it will not prevent
+ * the test case from continuing to run; this is otherwise known as an
+ * *expectation failure*.
+ */
+#define TEST_EXPECT_TRUE(test, condition) \
+   TEST_EXPECT(test, (condition), \
+  "Expected " #condition " is true, but is false.")
+
+/**
+ * TEST_EXPECT_FALSE() - Causes a test failure when the expression is not 
false.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails when this does
+ * not evaluate to false.
+ *
+ * Sets an expectation that @condition evaluates to false. See
+ * TEST_EXPECT_TRUE() for more information.
+ */
+#define TEST_EXPECT_FALSE(test, condition)\
+   TEST_EXPECT(test, !(condition),\
+  "Expected " #condition " is false, but is true.")
+
+static inline void test_expect_binary(struct test *test,
+ long long left, const char *left_name,
+ long long right, const char *right_name,
+ bool compare_result,
+ const char *compare_name,
+ const char *file,
+ const char *line)
+{
+   struct test_stream *stream = test_expect_start(test, file, line);
+
+   stream->add(stream,
+   "Expected %s %s %s, but\n",
+   left_name, compare_name, right_name);
+   stream->add(stream, "\t\t%s == %lld\n", left_name, left);
+   stream->add(stream, "\t\t%s == %lld", right_name, right);
+
+   test_exp

[RFC v1 19/31] kunit: mock: implemented nice, strict and naggy mock distinctions

2018-10-16 Thread Brendan Higgins
Nice mocks only fail when there is an expectation on a method, but none
match a given call. Strict mocks only pass when there is a matching
expectation for every call. Naggy mocks have the same pass/fail behavior
as nice, but report a warning in any case a strict mock would fail.

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h |  63 +
 kunit/mock-test.c| 192 ++-
 kunit/mock.c |  10 +-
 kunit/test-stream-test.c |   6 +-
 4 files changed, 265 insertions(+), 6 deletions(-)

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index 4f85b39d628d0..8d155b27a257a 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -95,10 +95,17 @@ struct mock_method {
struct list_head expectations;
 };
 
+enum mock_type {
+   MOCK_TYPE_NICE,
+   MOCK_TYPE_NAGGY,
+   MOCK_TYPE_STRICT
+};
+
 struct mock {
struct test_post_condition parent;
struct test *test;
struct list_head methods;
+   enum mock_type type;
/* TODO(brendanhigg...@google.com): add locking to do_expect. */
const void *(*do_expect)(struct mock *mock,
 const char *method_name,
@@ -108,6 +115,8 @@ struct mock {
 int len);
 };
 
+#define DEFAULT_MOCK_TYPE MOCK_TYPE_NAGGY
+
 void mock_init_ctrl(struct test *test, struct mock *mock);
 
 void mock_validate_expectations(struct mock *mock);
@@ -137,6 +146,60 @@ void mock_unregister_formatter(struct mock_param_formatter 
*formatter);
 
 #define MOCK(name) name##_mock
 
+/**
+ * STRICT_MOCK() - sets the mock to be strict and returns the mock
+ * @mock: the mock
+ *
+ * For an example, see ``The Nice, the Strict, and the Naggy`` under
+ * ``Using KUnit``.
+ */
+#define STRICT_MOCK(mock) \
+({ \
+   mock_get_ctrl(mock)->type = MOCK_TYPE_STRICT; \
+   mock; \
+})
+
+static inline bool is_strict_mock(struct mock *mock)
+{
+   return mock->type == MOCK_TYPE_STRICT;
+}
+
+/**
+ * NICE_MOCK() - sets the mock to be nice and returns the mock
+ * @mock: the mock
+ *
+ * For an example, see ``The Nice, the Strict, and the Naggy`` under
+ * ``Using KUnit``.
+ */
+#define NICE_MOCK(mock) \
+({ \
+   mock_get_ctrl(mock)->type = MOCK_TYPE_NICE; \
+   mock; \
+})
+
+static inline bool is_nice_mock(struct mock *mock)
+{
+   return mock->type == MOCK_TYPE_NICE;
+}
+
+/**
+ * NAGGY_MOCK() - sets the mock to be naggy and returns the mock
+ * @mock: the mock
+ *
+ * For an example, see ``The Nice, the Strict, and the Naggy`` under
+ * ``Using KUnit``.
+ */
+#define NAGGY_MOCK(mock) \
+({ \
+   mock_get_ctrl(mock)->type = MOCK_TYPE_NAGGY; \
+   mock; \
+})
+
+static inline bool is_naggy_mock(struct mock *mock)
+{
+   return mock->type == MOCK_TYPE_NAGGY;
+}
+
 /**
  * TEST_EXPECT_CALL() - Declares a *call expectation* on a mock function.
  * @expectation_call: a mocked method or function with parameters replaced with
diff --git a/kunit/mock-test.c b/kunit/mock-test.c
index 77b16ad754424..675387743ada4 100644
--- a/kunit/mock-test.c
+++ b/kunit/mock-test.c
@@ -150,7 +150,7 @@ static void mock_test_failed_expect_call_fails_test(struct 
test *test)
 static void mock_test_do_expect_default_return(struct test *test)
 {
struct mock_test_context *ctx = test->priv;
-   struct MOCK(test) *mock_test = ctx->mock_test;
+   struct MOCK(test) *mock_test = NICE_MOCK(ctx->mock_test);
struct test *trgt = mock_get_trgt(mock_test);
struct mock *mock = ctx->mock;
int param0 = 5, param1 = -5;
@@ -187,6 +187,49 @@ static void mock_test_do_expect_default_return(struct test 
*test)
TEST_EXPECT_EQ(test, 0, expectation->times_called);
 }
 
+/**
+ * DOC: Testing the failure condition of different mock types.
+ *
+ * The following tests will test the behaviour of expectations under different
+ * conditions. For example, what happens when an expectation:
+ * - is not satisfied at the end of the test
+ * - is fulfilled but the expected function is called again
+ * - a function is called without expectations set on it
+ *
+ * For each of these conditions, there may be variations between the different
+ * types of mocks: nice mocks, naggy mocks (the default) and strict mocks.
+ *
+ * More information about these mocks can be found in the kernel documentation
+ * under Documentation/test/api/class-and-function-mocking
+ */
+
+/* Method called on strict mock with no expectations will fail */
+static void mock_test_strict_no_expectations_will_fail(struct test *test)
+{
+   struct mock_test_context *ctx = test->priv;
+   struct MOCK(test) *mock_test = ctx->mock_test;
+   struct test *trgt = mock_get_trgt(mock_test);
+   struct mock *mock = ctx->mock;
+   int param0 = 5, param1 = -5;
+   static const char * const two_param_types[] = {"int", "int"};
+   const vo

[RFC v1 20/31] kunit: mock: add ability to mock functions with void context

2018-10-16 Thread Brendan Higgins
Adds ability to mock functions with a void* context object.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h| 53 +
 kunit/mock-macro-test.c | 30 +++
 kunit/mock.c|  9 +++
 3 files changed, 92 insertions(+)

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index 8d155b27a257a..89e95b3fcf09e 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -381,6 +381,24 @@ static inline bool is_naggy_mock(struct mock *mock)
struct MOCK(struct_name) *MOCK_INIT_ID(struct_name)(   \
struct test *test)
 
+#define DECLARE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name,   \
+ handle_index,\
+ return_type, \
+ param_types...)  \
+   DECLARE_MOCK_COMMON(name,  \
+   handle_index,  \
+   return_type,   \
+   param_types)
+
+#define DECLARE_VOID_CLASS_MOCK_HANDLE_INDEX(name,\
+handle_index, \
+return_type,  \
+param_types...)   \
+   DECLARE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name,\
+ handle_index,\
+ return_type, \
+ param_types)
+
 /**
  * CONSTRUCT_MOCK()
  * @struct_name: name of the class
@@ -631,6 +649,41 @@ static inline bool is_naggy_mock(struct mock *mock)
return mock_obj;   \
}
 
+struct MOCK(void) {
+   struct mock ctrl;
+   void*trgt;
+};
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
+static inline struct mock *from_void_ptr_to_mock(const void *ptr)
+{
+   struct MOCK(void) *mock_void_ptr = ptr;
+
+   return mock_get_ctrl(mock_void_ptr);
+}
+#pragma GCC diagnostic pop
+
+#define DEFINE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name,\
+handle_index, \
+return_type,  \
+param_types...)   \
+   DEFINE_MOCK_COMMON(name,   \
+  handle_index,   \
+  from_void_ptr_to_mock,  \
+  return_type,\
+  param_types)
+#define DEFINE_VOID_CLASS_MOCK_HANDLE_INDEX(name, \
+   handle_index,  \
+   return_type,   \
+   param_types...)\
+   DEFINE_VOID_CLASS_MOCK_HANDLE_INDEX_INTERNAL(name, \
+handle_index, \
+return_type,  \
+param_types)
+
+DECLARE_STRUCT_CLASS_MOCK_INIT(void);
+
 #define CONVERT_TO_ACTUAL_TYPE(type, ptr) (*((type *) ptr))
 
 /**
diff --git a/kunit/mock-macro-test.c b/kunit/mock-macro-test.c
index 84d9d3f484366..0f95105ec032a 100644
--- a/kunit/mock-macro-test.c
+++ b/kunit/mock-macro-test.c
@@ -48,8 +48,19 @@ static int test_struct_init(struct MOCK(test_struct) 
*mock_test_struct)
 
 DEFINE_STRUCT_CLASS_MOCK_INIT(test_struct, test_struct_init);
 
+DECLARE_VOID_CLASS_MOCK_HANDLE_INDEX(METHOD(test_void_ptr_func),
+HANDLE_INDEX(0),
+RETURNS(int),
+PARAMS(void*, int));
+
+DEFINE_VOID_CLASS_MOCK_HANDLE_INDEX(METHOD(test_void_ptr_func),
+   HANDLE_INDEX(0),
+   RETURNS(int),
+   PARAMS(void*, int));
+
 struct mock_macro_context {
struct MOCK(test_struct) *mock_test_struct;
+   struct MOCK(void) *mock_void_ptr;
 };
 
 #define TO_STR_INTERNAL(...) #__VA_ARGS__
@@ -195,6 +206,20 @@ s

[RFC v1 24/31] kunit: improved sigsegv stack trace printing

2018-10-16 Thread Brendan Higgins
Sacrificed the control of printing stack trace within the crash handler
in the test runner for getting a better stack trace; this is still not
ideal, but much better than before.

Signed-off-by: Brendan Higgins 
---
 arch/um/kernel/trap.c | 11 ++-
 kunit/test.c  | 13 +
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 9b97712daf14f..c3ff8346800c4 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -226,8 +226,17 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, 
int is_user,
current->thread.segv_regs = container_of(regs, struct pt_regs, 
regs);
 
catcher = current->thread.fault_catcher;
-   if (catcher && current->thread.is_running_test)
+   if (catcher && current->thread.is_running_test) {
+   /*
+* TODO(b/77223210): Right now we don't have a way to store a
+* copy of the stack, or a copy of information from the stack,
+* so we need to print it now; otherwise, the stack will be
+* destroyed by segv_run_catcher which works by popping off
+* stack frames.
+*/
+   show_stack(NULL, NULL);
segv_run_catcher(catcher, (void *) address);
+   }
else if (!is_user && (address >= start_vm) && (address < end_vm)) {
flush_tlb_kernel_vm();
goto out;
diff --git a/kunit/test.c b/kunit/test.c
index 6ea60059b4918..5d78f76b421af 100644
--- a/kunit/test.c
+++ b/kunit/test.c
@@ -210,12 +210,17 @@ static void test_handle_test_crash(struct test *test,
   struct test_module *module,
   struct test_case *test_case)
 {
-   test_err(test, "%s crashed", test_case->name);
/*
-* TODO(brendanhigg...@google.com): This prints the stack trace up
-* through this frame, not up to the frame that caused the crash.
+* TODO(brendanhigg...@google.com): Right now we don't have a way to
+* store a copy of the stack, or a copy of information from the stack,
+* so we need to print it in the "trap" handler; otherwise, the stack
+* will be destroyed when it returns to us by popping off the
+* appropriate stack frames (see longjmp).
+*
+* Ideally we would print the stack trace here, but we do not have the
+* ability to do so with meaningful information at this time.
 */
-   show_stack(NULL, NULL);
+   test_err(test, "%s crashed", test_case->name);
 
test_case_internal_cleanup(test);
 }
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 04/31] kunit: test: added test_stream a std::stream like logger

2018-10-16 Thread Brendan Higgins
Adds a C++ style log library for for logging test results.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test-stream.h |  49 
 include/kunit/test.h|   2 +
 kunit/Makefile  |   2 +-
 kunit/test-stream.c | 153 
 kunit/test.c|   8 ++
 5 files changed, 213 insertions(+), 1 deletion(-)
 create mode 100644 include/kunit/test-stream.h
 create mode 100644 kunit/test-stream.c

diff --git a/include/kunit/test-stream.h b/include/kunit/test-stream.h
new file mode 100644
index 0..c5dfd95ef21bb
--- /dev/null
+++ b/include/kunit/test-stream.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * C++ stream style string formatter and printer used in KUnit for outputting
+ * KUnit messages.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_TEST_STREAM_H
+#define _KUNIT_TEST_STREAM_H
+
+#include 
+#include 
+
+struct test;
+
+/**
+ * struct test_stream - a std::stream style string builder.
+ * @set_level: sets the level that this string should be printed at.
+ * @add: adds the formatted input to the internal buffer.
+ * @commit: prints out the internal buffer to the user.
+ * @clear: clears the internal buffer.
+ *
+ * A std::stream style string builder. Allows messages to be built up and
+ * printed all at once.
+ */
+struct test_stream {
+   void (*set_level)(struct test_stream *this, const char *level);
+   void (*add)(struct test_stream *this, const char *fmt, ...);
+   void (*append)(struct test_stream *this, struct test_stream *other);
+   void (*commit)(struct test_stream *this);
+   void (*clear)(struct test_stream *this);
+   /* private: internal use only. */
+   struct test *test;
+   spinlock_t lock; /* Guards level. */
+   const char *level;
+   struct string_stream *internal_stream;
+};
+
+/**
+ * test_new_stream() - constructs a new &struct test_stream.
+ * @test: The test context object.
+ *
+ * Constructs a new test managed &struct test_stream.
+ */
+struct test_stream *test_new_stream(struct test *test);
+
+#endif /* _KUNIT_TEST_STREAM_H */
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 1c116a20063da..68320fa2452de 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -11,6 +11,7 @@
 
 #include 
 #include 
+#include 
 
 struct test_resource;
 
@@ -171,6 +172,7 @@ struct test {
void (*vprintk)(const struct test *test,
const char *level,
struct va_format *vaf);
+   void (*fail)(struct test *test, struct test_stream *stream);
 };
 
 int test_init_test(struct test *test, const char *name);
diff --git a/kunit/Makefile b/kunit/Makefile
index 7fc613a9b383b..5b4562ea7f322 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_KUNIT)+= test.o string-stream.o
+obj-$(CONFIG_KUNIT)+= test.o string-stream.o test-stream.o
diff --git a/kunit/test-stream.c b/kunit/test-stream.c
new file mode 100644
index 0..392966864a708
--- /dev/null
+++ b/kunit/test-stream.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * C++ stream style string formatter and printer used in KUnit for outputting
+ * KUnit messages.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+#include 
+
+static const char *test_stream_get_level(struct test_stream *this)
+{
+   unsigned long flags;
+   const char *level;
+
+   spin_lock_irqsave(&this->lock, flags);
+   level = this->level;
+   spin_unlock_irqrestore(&this->lock, flags);
+
+   return level;
+}
+
+static void test_stream_set_level(struct test_stream *this, const char *level)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&this->lock, flags);
+   this->level = level;
+   spin_unlock_irqrestore(&this->lock, flags);
+}
+
+static void test_stream_add(struct test_stream *this, const char *fmt, ...)
+{
+   va_list args;
+   struct string_stream *stream = this->internal_stream;
+
+   va_start(args, fmt);
+   if (stream->vadd(stream, fmt, args) < 0)
+   test_err(this->test, "Failed to allocate fragment: %s", fmt);
+
+   va_end(args);
+}
+
+static void test_stream_append(struct test_stream *this,
+  struct test_stream *other)
+{
+   struct string_stream *other_stream = other->internal_stream;
+   const char *other_content;
+
+   other_content = other_stream->get_string(other_stream);
+
+   if (!other_content) {
+   test_err(this->test,
+"Failed to get string from second argument for 
appending.");
+   return;
+   }
+
+   this->add(this, other_content);
+}
+
+static void test_stream_clear(struct test_stream *this)
+{
+   this->internal_stre

[RFC v1 18/31] kunit: mock: added parameter formatters

2018-10-16 Thread Brendan Higgins
Added parameter formatters which provide string formatting for
parameters that have no matchers to be matched against.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h |  49 +++
 kunit/common-mocks.c | 132 +++
 kunit/mock.c |  48 --
 kunit/test-stream-test.c |  28 +
 4 files changed, 252 insertions(+), 5 deletions(-)

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index daf965cf954e6..4f85b39d628d0 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -123,6 +123,18 @@ struct mock_expectation *mock_add_matcher(struct mock 
*mock,
  struct mock_param_matcher *matchers[],
  int len);
 
+struct mock_param_formatter {
+   struct list_head node;
+   const char *type_name;
+   void (*format)(struct mock_param_formatter *formatter,
+  struct test_stream *stream,
+  const void *param);
+};
+
+void mock_register_formatter(struct mock_param_formatter *formatter);
+
+void mock_unregister_formatter(struct mock_param_formatter *formatter);
+
 #define MOCK(name) name##_mock
 
 /**
@@ -834,4 +846,41 @@ struct mock_param_matcher *test_struct_cmp(
const char *struct_name,
struct mock_struct_matcher_entry *entries);
 
+struct mock_struct_formatter_entry {
+   size_t member_offset;
+   struct mock_param_formatter *formatter;
+};
+
+static inline void init_mock_struct_formatter_entry_internal(
+   struct mock_struct_formatter_entry *entry,
+   size_t offset,
+   struct mock_param_formatter *formatter)
+{
+   entry->member_offset = offset;
+   entry->formatter = formatter;
+}
+
+#define INIT_MOCK_STRUCT_FORMATTER_ENTRY(entry, type, member, formatter)   
\
+   init_mock_struct_formatter_entry_internal(entry,   \
+ offsetof(type,   \
+  member),\
+  formatter)
+
+static inline void INIT_MOCK_STRUCT_FORMATTER_ENTRY_LAST(
+   struct mock_struct_formatter_entry *entry)
+{
+   entry->formatter = NULL;
+}
+
+struct mock_param_formatter *mock_struct_formatter(
+   struct test *test,
+   const char *struct_name,
+   struct mock_struct_formatter_entry *entries);
+
+struct mock_param_formatter *mock_find_formatter(const char *type_name);
+
+#define FORMATTER_FROM_TYPE(type) mock_find_formatter(#type)
+
+extern struct mock_param_formatter unknown_formatter[];
+
 #endif /* _KUNIT_MOCK_H */
diff --git a/kunit/common-mocks.c b/kunit/common-mocks.c
index ef88f8b8acda3..1c52522808cab 100644
--- a/kunit/common-mocks.c
+++ b/kunit/common-mocks.c
@@ -386,3 +386,135 @@ DEFINE_RETURN_ACTION_WITH_TYPENAME(longlong, long long);
 DEFINE_RETURN_ACTION_WITH_TYPENAME(ulonglong, unsigned long long);
 DEFINE_RETURN_ACTION_WITH_TYPENAME(ptr, void *);
 
+struct mock_param_integer_formatter {
+   struct mock_param_formatter formatter;
+   const char *fmt_str;
+};
+
+static void mock_format_integer(struct mock_param_formatter *pformatter,
+   struct test_stream *stream,
+   const void *pparam)
+{
+   struct mock_param_integer_formatter *formatter =
+   container_of(pformatter,
+struct mock_param_integer_formatter,
+formatter);
+   long long param = CONVERT_TO_ACTUAL_TYPE(long long, pparam);
+
+   stream->add(stream, formatter->fmt_str, param);
+}
+
+#define INTEGER_FORMATTER_INIT(type, fmt) { \
+   .formatter = { \
+   .type_name = #type, \
+   .format = mock_format_integer, \
+   }, \
+   .fmt_str = fmt, \
+}
+
+static struct mock_param_integer_formatter integer_formatters[] = {
+   INTEGER_FORMATTER_INIT(u8, "%PRIu8"),
+   INTEGER_FORMATTER_INIT(u16, "%PRIu16"),
+   INTEGER_FORMATTER_INIT(u32, "%PRIu32"),
+   INTEGER_FORMATTER_INIT(u64, "%PRIu64"),
+   INTEGER_FORMATTER_INIT(char, "%c"),
+   INTEGER_FORMATTER_INIT(unsigned char, "%hhu"),
+   INTEGER_FORMATTER_INIT(signed char, "%hhd"),
+   INTEGER_FORMATTER_INIT(short, "%hd"),
+   INTEGER_FORMATTER_INIT(unsigned short, "%hu"),
+   INTEGER_FORMATTER_INIT(int, "%d"),
+   INTEGER_FORMATTER_INIT(unsigned int, "%u"),
+   INTEGER_FORMATTER_INIT(long, "%ld"),
+   INTEGER_FORMATTER_INIT(unsigned long, "%lu"),
+   INTEGER_FORMATTER_INIT(long long, "%lld"),
+   INTEGER_FORMATTER_IN

[RFC v1 15/31] kunit: mock: added basic matchers and actions

2018-10-16 Thread Brendan Higgins
Added basic matchers and actions needed for any kind of mocking to be
useful; these matchers and actions are how expectations for mocks are
described: what calls the mocks are expected to receive, and what the
mock should do under those circumstances.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h | 222 +++
 kunit/Makefile   |   3 +-
 kunit/common-mocks.c | 272 +++
 3 files changed, 496 insertions(+), 1 deletion(-)
 create mode 100644 kunit/common-mocks.c

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index 1a35c5702cb15..62e8afcaeab55 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -122,4 +122,226 @@ struct mock_expectation *mock_add_matcher(struct mock 
*mock,
  struct mock_param_matcher *matchers[],
  int len);
 
+#define CONVERT_TO_ACTUAL_TYPE(type, ptr) (*((type *) ptr))
+
+/**
+ * DOC: Built In Matchers
+ *
+ * These are the matchers that can be used when matching arguments in
+ * :c:func:`EXPECT_CALL` (more can be defined manually).
+ *
+ * For example, there's a matcher that matches any arguments:
+ *
+ * .. code-block:: c
+ *
+ *struct mock_param_matcher *any(struct test *test);
+ *
+ * There are matchers for integers based on the binary condition:
+ *
+ * * eq: equals to
+ * * ne: not equal to
+ * * lt: less than
+ * * le: less than or equal to
+ * * gt: greater than
+ * * ge: greater than or equal to
+ *
+ * .. code-block:: c
+ *
+ *struct mock_param_matcher *test_int_eq(struct test *test, int expected);
+ *struct mock_param_matcher *test_int_ne(struct test *test, int expected);
+ *struct mock_param_matcher *test_int_lt(struct test *test, int expected);
+ *struct mock_param_matcher *test_int_le(struct test *test, int expected);
+ *struct mock_param_matcher *test_int_gt(struct test *test, int expected);
+ *struct mock_param_matcher *test_int_ge(struct test *test, int expected);
+ *
+ * For a detailed list, please see
+ * ``include/linux/mock.h``.
+ */
+
+/* Matches any argument */
+struct mock_param_matcher *test_any(struct test *test);
+
+/*
+ * Matches different types of integers, the argument is compared to the
+ * `expected` field, based on the comparison defined.
+ */
+struct mock_param_matcher *test_u8_eq(struct test *test, u8 expected);
+struct mock_param_matcher *test_u8_ne(struct test *test, u8 expected);
+struct mock_param_matcher *test_u8_le(struct test *test, u8 expected);
+struct mock_param_matcher *test_u8_lt(struct test *test, u8 expected);
+struct mock_param_matcher *test_u8_ge(struct test *test, u8 expected);
+struct mock_param_matcher *test_u8_gt(struct test *test, u8 expected);
+
+struct mock_param_matcher *test_u16_eq(struct test *test, u16 expected);
+struct mock_param_matcher *test_u16_ne(struct test *test, u16 expected);
+struct mock_param_matcher *test_u16_le(struct test *test, u16 expected);
+struct mock_param_matcher *test_u16_lt(struct test *test, u16 expected);
+struct mock_param_matcher *test_u16_ge(struct test *test, u16 expected);
+struct mock_param_matcher *test_u16_gt(struct test *test, u16 expected);
+
+struct mock_param_matcher *test_u32_eq(struct test *test, u32 expected);
+struct mock_param_matcher *test_u32_ne(struct test *test, u32 expected);
+struct mock_param_matcher *test_u32_le(struct test *test, u32 expected);
+struct mock_param_matcher *test_u32_lt(struct test *test, u32 expected);
+struct mock_param_matcher *test_u32_ge(struct test *test, u32 expected);
+struct mock_param_matcher *test_u32_gt(struct test *test, u32 expected);
+
+struct mock_param_matcher *test_u64_eq(struct test *test, u64 expected);
+struct mock_param_matcher *test_u64_ne(struct test *test, u64 expected);
+struct mock_param_matcher *test_u64_le(struct test *test, u64 expected);
+struct mock_param_matcher *test_u64_lt(struct test *test, u64 expected);
+struct mock_param_matcher *test_u64_ge(struct test *test, u64 expected);
+struct mock_param_matcher *test_u64_gt(struct test *test, u64 expected);
+
+struct mock_param_matcher *test_char_eq(struct test *test, char expected);
+struct mock_param_matcher *test_char_ne(struct test *test, char expected);
+struct mock_param_matcher *test_char_le(struct test *test, char expected);
+struct mock_param_matcher *test_char_lt(struct test *test, char expected);
+struct mock_param_matcher *test_char_ge(struct test *test, char expected);
+struct mock_param_matcher *test_char_gt(struct test *test, char expected);
+
+struct mock_param_matcher *test_uchar_eq(struct test *test,
+unsigned char expected);
+struct mock_param_matcher *test_uchar_ne(struct test *test,
+unsigned char expected);
+struct mock_param_matcher *test_uchar_le(struct test *test,
+unsigned char expected);
+struct mock_param_matcher *test_uch

[RFC v1 14/31] kunit: mock: added internal mock infrastructure

2018-10-16 Thread Brendan Higgins
Adds the core internal mechanisms that mocks are implemented with; in
particular, this adds the mechanisms by which expectation on mocks are
validated and by which actions may be supplied and then executed when
mocks are called.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h | 125 +++
 kunit/Makefile   |   5 +-
 kunit/mock.c | 359 +++
 3 files changed, 487 insertions(+), 2 deletions(-)
 create mode 100644 include/kunit/mock.h
 create mode 100644 kunit/mock.c

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
new file mode 100644
index 0..1a35c5702cb15
--- /dev/null
+++ b/include/kunit/mock.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Mocking API for KUnit.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_MOCK_H
+#define _KUNIT_MOCK_H
+
+#include 
+#include  /* For PARAMS(...) */
+#include 
+#include 
+#include 
+
+/**
+ * struct mock_param_matcher - represents a matcher used in a *call 
expectation*
+ * @match: the function that performs the matching
+ *
+ * The matching function takes a couple of parameters:
+ *
+ * - ``this``: refers to the parent struct
+ * - ``stream``: a &test_stream to which a detailed message should be added as
+ *   to why the parameter matches or not
+ * - ``param``: a pointer to the parameter to check for a match
+ *
+ * The matching function should return whether or not the passed parameter
+ * matches.
+ */
+struct mock_param_matcher {
+   bool (*match)(struct mock_param_matcher *this,
+ struct test_stream *stream,
+ const void *param);
+};
+
+#define MOCK_MAX_PARAMS 255
+
+struct mock_matcher {
+   struct mock_param_matcher *matchers[MOCK_MAX_PARAMS];
+   int num;
+};
+
+/**
+ * struct mock_action - Represents an action that a mock performs when
+ *  expectation is matched
+ * @do_action: the action to perform
+ *
+ * The action function is given some parameters:
+ *
+ * - ``this``: refers to the parent struct
+ * - ``params``: an array of pointers to the params passed into the mocked
+ *   method or function. **The class argument is excluded for a mocked class
+ *   method.**
+ * - ``len``: size of ``params``
+ *
+ * The action function returns a pointer to the value that the mocked method
+ * or function should be returning.
+ */
+struct mock_action {
+   void *(*do_action)(struct mock_action *this,
+  const void **params,
+  int len);
+};
+
+/**
+ * struct mock_expectation - represents a *call expectation* on a function.
+ * @action: A &struct mock_action to perform when the function is called.
+ * @max_calls_expected: maximum number of times an expectation may be called.
+ * @min_calls_expected: minimum number of times an expectation may be called.
+ * @retire_on_saturation: no longer match once ``max_calls_expected`` is
+ *   reached.
+ *
+ * Represents a *call expectation* on a function created with EXPECT_CALL().
+ */
+struct mock_expectation {
+   struct mock_action *action;
+   int max_calls_expected;
+   int min_calls_expected;
+   bool retire_on_saturation;
+   /* private: internal use only. */
+   const char *expectation_name;
+   struct list_head node;
+   struct mock_matcher *matcher;
+   int times_called;
+};
+
+struct mock_method {
+   struct list_head node;
+   const char *method_name;
+   const void *method_ptr;
+   struct mock_action *default_action;
+   struct list_head expectations;
+};
+
+struct mock {
+   struct test_post_condition parent;
+   struct test *test;
+   struct list_head methods;
+   /* TODO(brendanhigg...@google.com): add locking to do_expect. */
+   const void *(*do_expect)(struct mock *mock,
+const char *method_name,
+const void *method_ptr,
+const char * const *param_types,
+const void **params,
+int len);
+};
+
+void mock_init_ctrl(struct test *test, struct mock *mock);
+
+void mock_validate_expectations(struct mock *mock);
+
+int mock_set_default_action(struct mock *mock,
+   const char *method_name,
+   const void *method_ptr,
+   struct mock_action *action);
+
+struct mock_expectation *mock_add_matcher(struct mock *mock,
+ const char *method_name,
+ const void *method_ptr,
+ struct mock_param_matcher *matchers[],
+ int len);
+
+#endif /* _KUNIT_MOCK_H */
diff --git a/kunit/Makefile b/kunit/Makefile
index f72a02cb9f23d..ad58110de695c 100644
--- a/kunit/Makefile
+++

[RFC v1 16/31] kunit: mock: added class mocking support

2018-10-16 Thread Brendan Higgins
Introduces basic class mocking, the ability to automatically generate a
Linux C-style class implementation whose behavior is controlled by test
cases, which can also set expectations on when and how mocks are called.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h| 438 +++-
 kunit/Makefile  |   2 +-
 kunit/example-test.c|  90 +
 kunit/mock-macro-test.c |  82 
 kunit/mock-test.c   | 276 +
 kunit/test-mock.c   |  39 
 kunit/test-mock.h   |  23 +++
 7 files changed, 947 insertions(+), 3 deletions(-)
 create mode 100644 kunit/mock-test.c
 create mode 100644 kunit/test-mock.c
 create mode 100644 kunit/test-mock.h

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index 62e8afcaeab55..1b7485e2cedb8 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -72,7 +72,8 @@ struct mock_action {
  * @retire_on_saturation: no longer match once ``max_calls_expected`` is
  *   reached.
  *
- * Represents a *call expectation* on a function created with EXPECT_CALL().
+ * Represents a *call expectation* on a function created with
+ * TEST_EXPECT_CALL().
  */
 struct mock_expectation {
struct mock_action *action;
@@ -122,13 +123,446 @@ struct mock_expectation *mock_add_matcher(struct mock 
*mock,
  struct mock_param_matcher *matchers[],
  int len);
 
+#define MOCK(name) name##_mock
+
+/**
+ * TEST_EXPECT_CALL() - Declares a *call expectation* on a mock function.
+ * @expectation_call: a mocked method or function with parameters replaced with
+ *matchers.
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * // Class to mock.
+ * struct example {
+ * int (*foo)(struct example *, int);
+ * };
+ *
+ * // Define the mock.
+ * DECLARE_STRUCT_CLASS_MOCK_PREREQS(example);
+ *
+ * DEFINE_STRUCT_CLASS_MOCK(METHOD(foo), CLASS(example),
+ *  RETURNS(int),
+ *  PARAMS(struct example *, int));
+ *
+ * static int example_init(struct MOCK(example) *mock_example)
+ * {
+ * struct example *example = mock_get_trgt(mock_example);
+ *
+ * example->foo = foo;
+ * return 0;
+ * }
+ *
+ * DEFINE_STRUCT_CLASS_MOCK_INIT(example, example_init);
+ *
+ * static void foo_example_test_success(struct test *test)
+ * {
+ * struct MOCK(example) *mock_example;
+ * struct example *example = mock_get_trgt(mock_example);
+ * struct mock_expectation *handle;
+ *
+ * mock_example = CONSTRUCT_MOCK(example, test);
+ *
+ * handle = TEST_EXPECT_CALL(foo(mock_get_ctrl(mock_example),
+ *  test_int_eq(test, 5)));
+ * handle->action = int_return(test, 2);
+ *
+ * EXPECT_EQ(test, 2, example_bar(example, 5));
+ * }
+ *
+ * Return:
+ * A &struct mock_expectation representing the call expectation.
+ * allowing additional conditions and actions to be specified.
+ */
+#define TEST_EXPECT_CALL(expectation_call) mock_master_##expectation_call
+
+#define mock_get_ctrl_internal(mock_object) (&(mock_object)->ctrl)
+#define mock_get_ctrl(mock_object) mock_get_ctrl_internal(mock_object)
+
+#define mock_get_trgt_internal(mock_object) (&(mock_object)->trgt)
+#define mock_get_trgt(mock_object) mock_get_trgt_internal(mock_object)
+
+#define mock_get_test(mock_object) (mock_get_ctrl(mock_object)->test)
+
+#define CLASS(struct_name) struct_name
+#define HANDLE_INDEX(index) index
+#define METHOD(method_name) method_name
+#define RETURNS(return_type) return_type
+/* #define PARAMS(...) __VA_ARGS__ included by linux/tracepoint.h */
+
+#define MOCK_INIT_ID(struct_name) struct_name##mock_init
+#define REAL_ID(func_name) __real__##func_name
+#define INVOKE_ID(func_name) __invoke__##func_name
+
+#define DECLARE_MOCK_CLIENT(name, return_type, param_types...) \
+   return_type name(PARAM_LIST_FROM_TYPES(param_types))
+
+#define DECLARE_MOCK_MASTER(name, ctrl_index, param_types...) \
+   struct mock_expectation *mock_master_##name(   \
+   MATCHER_PARAM_LIST_FROM_TYPES(ctrl_index,  \
+ param_types));
+
+#define DECLARE_MOCK_COMMON(name, handle_index, return_type, param_types...)   
\
+   DECLARE_MOCK_CLIENT(name, return_type, param_types);   \
+   DECLARE_MOCK_MASTER(name, handle_index, param_types)
+
+#define DECLARE_STRUCT_CLASS_MOCK_STRUCT(struct_name) \
+   struct MOCK(struct_name) { \
+   struct mock ctrl;  \
+   s

[RFC v1 06/31] arch: um: enabled running kunit from User Mode Linux

2018-10-16 Thread Brendan Higgins
Makes minimum number of changes outside of the KUnit directories for
KUnit to build and run using UML.

Signed-off-by: Brendan Higgins 
---
 Makefile | 2 +-
 arch/um/Kconfig.rest | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 863f58503beed..c8e659468ed49 100644
--- a/Makefile
+++ b/Makefile
@@ -944,7 +944,7 @@ endif
 
 
 ifeq ($(KBUILD_EXTMOD),)
-core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
+core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ kunit/
 
 vmlinux-dirs   := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
diff --git a/arch/um/Kconfig.rest b/arch/um/Kconfig.rest
index 08327b9c0cbea..484c4cfcad1ef 100644
--- a/arch/um/Kconfig.rest
+++ b/arch/um/Kconfig.rest
@@ -1,4 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
+
+source "kunit/Kconfig"
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 31/31] MAINTAINERS: add entry for KUnit the unit testing framework

2018-10-16 Thread Brendan Higgins
Added myself as maintainer of KUnit, the Linux kernel's unit testing
framework.

Signed-off-by: Brendan Higgins 
---
 MAINTAINERS | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 544cac829cf44..9c3d34f0062ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7801,6 +7801,21 @@ S:   Maintained
 F: tools/testing/selftests/
 F: Documentation/dev-tools/kselftest*
 
+KERNEL UNIT TESTING FRAMEWORK (KUnit)
+M: Brendan Higgins 
+L: kunit-...@googlegroups.com
+W: https://google.github.io/kunit-docs/third_party/kernel/docs/
+S: Maintained
+F: Documentation/kunit/
+F: arch/um/include/asm/io-mock-shared.h
+F: arch/um/include/asm/io-mock.h
+F: arch/um/kernel/io-mock.c
+F: drivers/base/platform-mock.c
+F: include/linux/platform_device_mock.h
+F: include/kunit/
+F: kunit/
+F: tools/testing/kunit/
+
 KERNEL USERMODE HELPER
 M: "Luis R. Rodriguez" 
 L: linux-kernel@vger.kernel.org
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 30/31] kunit.py: improved output from python wrapper

2018-10-16 Thread Brendan Higgins
- added colors to displayed output
- added timing and summary

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 tools/testing/kunit/kunit.py| 20 ++-
 tools/testing/kunit/kunit_parser.py | 93 -
 2 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 1356be404996b..b36c7b7924567 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -6,6 +6,7 @@
 import argparse
 import sys
 import os
+import time
 
 import kunit_config
 import kunit_kernel
@@ -24,17 +25,32 @@ parser.add_argument('--timeout', help='maximum number of 
seconds to allow for '
 cli_args = parser.parse_args()
 linux = kunit_kernel.LinuxSourceTree()
 
+config_start = time.time()
 success = linux.build_reconfig()
+config_end = time.time()
 if not success:
quit()
 
-print('Building KUnit Kernel ...')
+kunit_parser.print_with_timestamp('Building KUnit Kernel ...')
+
+build_start = time.time()
 success = linux.build_um_kernel()
+build_end = time.time()
 if not success:
quit()
 
-print('Starting KUnit Kernel ...')
+kunit_parser.print_with_timestamp('Starting KUnit Kernel ...')
+test_start = time.time()
+
 if cli_args.raw_output:
kunit_parser.raw_output(linux.run_kernel(timeout=cli_args.timeout))
 else:
kunit_parser.parse_run_tests(linux.run_kernel(timeout=cli_args.timeout))
+
+test_end = time.time()
+
+kunit_parser.print_with_timestamp((
+   "Elapsed time: %.3fs total, %.3fs configuring, %.3fs " +
+   "building, %.3fs running.\n") % (test_end - config_start,
+   config_end - config_start, build_end - build_start,
+   test_end - test_start))
diff --git a/tools/testing/kunit/kunit_parser.py 
b/tools/testing/kunit/kunit_parser.py
index 1dff3adb73bd3..d9051e407d5a7 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 import re
+from datetime import datetime
 
 kunit_start_re = re.compile('console .* enabled')
 kunit_end_re = re.compile('List of all partitions:')
@@ -19,6 +20,94 @@ def raw_output(kernel_output):
for line in kernel_output:
print(line)
 
+DIVIDER = "=" * 30
+
+RESET = '\033[0;0m'
+
+def red(text):
+   return '\033[1;31m' + text + RESET
+
+def yellow(text):
+   return '\033[1;33m' + text + RESET
+
+def green(text):
+   return '\033[1;32m' + text + RESET
+
+def print_with_timestamp(message):
+   print('[%s] %s' % (datetime.now().strftime('%H:%M:%S'), message))
+
+def print_log(log):
+   for m in log:
+   print_with_timestamp(m)
+
 def parse_run_tests(kernel_output):
-   for output in isolate_kunit_output(kernel_output):
-   print(output)
+   test_case_output = re.compile('^kunit .*?: (.*)$')
+
+   test_module_success = re.compile('^kunit .*: all tests passed')
+   test_module_fail = re.compile('^kunit .*: one or more tests failed')
+
+   test_case_success = re.compile('^kunit (.*): (.*) passed')
+   test_case_fail = re.compile('^kunit (.*): (.*) failed')
+   test_case_crash = re.compile('^kunit (.*): (.*) crashed')
+
+   total_tests = set()
+   failed_tests = set()
+   crashed_tests = set()
+
+   def get_test_name(match):
+   return match.group(1) + ":" + match.group(2)
+
+   current_case_log = []
+   def end_one_test(match, log):
+   log.clear()
+   total_tests.add(get_test_name(match))
+
+   print_with_timestamp(DIVIDER)
+   for line in isolate_kunit_output(kernel_output):
+   # Ignore module output:
+   if (test_module_success.match(line) or
+   test_module_fail.match(line)):
+   print_with_timestamp(DIVIDER)
+   continue
+
+   match = re.match(test_case_success, line)
+   if match:
+   print_with_timestamp(green("[PASSED] ") +
+get_test_name(match))
+   end_one_test(match, current_case_log)
+   continue
+
+   match = re.match(test_case_fail, line)
+   # Crashed tests will report as both failed and crashed. We only
+   # want to show and count it once.
+   if match and get_test_name(match) not in crashed_tests:
+   failed_tests.add(get_test_name(match))
+   print_with_timestamp(red("[FAILED] " +
+get_test_name(match)))
+   print_log(map(yellow, current_case_log))
+

[RFC v1 28/31] kunit: added Python libraries for handing KUnit config and kernel

2018-10-16 Thread Brendan Higgins
kunit_config.py:
  - parses .config and Kconfig files

kunit_kernel.py: provides helper functions to:
  - configure the kernel using kunitconfig
  - builds the kernel with the correct architecture
  - provides function to invoke the kernel and stream the output back

The kernel invocation is wrapped in a subprocess call within the module
because regular invocation of the kernel (./linux) may modify TTY
settings.

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 tools/testing/kunit/.gitignore  |   3 +
 tools/testing/kunit/kunit_config.py |  60 ++
 tools/testing/kunit/kunit_kernel.py | 123 
 3 files changed, 186 insertions(+)
 create mode 100644 tools/testing/kunit/.gitignore
 create mode 100644 tools/testing/kunit/kunit_config.py
 create mode 100644 tools/testing/kunit/kunit_kernel.py

diff --git a/tools/testing/kunit/.gitignore b/tools/testing/kunit/.gitignore
new file mode 100644
index 0..c791ff59a37a9
--- /dev/null
+++ b/tools/testing/kunit/.gitignore
@@ -0,0 +1,3 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
\ No newline at end of file
diff --git a/tools/testing/kunit/kunit_config.py 
b/tools/testing/kunit/kunit_config.py
new file mode 100644
index 0..183bd5e758762
--- /dev/null
+++ b/tools/testing/kunit/kunit_config.py
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0
+
+import collections
+import re
+
+CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_\w+ is not set$'
+CONFIG_PATTERN = r'^CONFIG_\w+=\S+$'
+
+KconfigEntryBase = collections.namedtuple('KconfigEntry', ['raw_entry'])
+
+
+class KconfigEntry(KconfigEntryBase):
+
+   def __str__(self) -> str:
+   return self.raw_entry
+
+
+class KconfigParseError(Exception):
+   """Error parsing Kconfig defconfig or .config."""
+
+
+class Kconfig(object):
+   """Represents defconfig or .config specified using the Kconfig 
language."""
+
+   def __init__(self):
+   self._entries = []
+
+   def entries(self):
+   return set(self._entries)
+
+   def add_entry(self, entry: KconfigEntry) -> None:
+   self._entries.append(entry)
+
+   def is_subset_of(self, other: "Kconfig") -> bool:
+   return self.entries().issubset(other.entries())
+
+   def write_to_file(self, path: str) -> None:
+   with open(path, 'w') as f:
+   for entry in self.entries():
+   f.write(str(entry) + '\n')
+
+   def parse_from_string(self, blob: str) -> None:
+   """Parses a string containing KconfigEntrys and populates this 
Kconfig."""
+   self._entries = []
+   is_not_set_matcher = re.compile(CONFIG_IS_NOT_SET_PATTERN)
+   config_matcher = re.compile(CONFIG_PATTERN)
+   for line in blob.split('\n'):
+   line = line.strip()
+   if not line:
+   continue
+   elif config_matcher.match(line) or 
is_not_set_matcher.match(line):
+   self._entries.append(KconfigEntry(line))
+   elif line[0] == '#':
+   continue
+   else:
+   raise KconfigParseError('Failed to parse: ' + 
line)
+
+   def read_from_file(self, path: str) -> None:
+   with open(path, 'r') as f:
+   self.parse_from_string(f.read())
diff --git a/tools/testing/kunit/kunit_kernel.py 
b/tools/testing/kunit/kunit_kernel.py
new file mode 100644
index 0..87abaede50513
--- /dev/null
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: GPL-2.0
+
+import logging
+import subprocess
+import os
+
+import kunit_config
+
+KCONFIG_PATH = '.config'
+
+class ConfigError(Exception):
+   """Represents an error trying to configure the Linux kernel."""
+
+
+class BuildError(Exception):
+   """Represents an error trying to build the Linux kernel."""
+
+
+class LinuxSourceTreeOperations(object):
+   """An abstraction over command line operations performed on a source 
tree."""
+
+   def make_mrproper(self):
+   try:
+   subprocess.check_output(['make', 'mrproper'])
+   except OSError as e:
+   raise ConfigError('Could not call make command: ' + e)
+   except subprocess.CalledProcessError as e:
+   raise ConfigError(e.output)
+
+   def make_olddefconfig(self):
+   try:
+ 

[RFC v1 29/31] kunit: added KUnit wrapper script and simple output parser

2018-10-16 Thread Brendan Higgins
The KUnit wrapper script interfaces with the two modules
(kunit_config.py and kunit_kernel.py) and provides a command line
interface for running KUnit tests. This interface allows the caller to
specify options like test timeouts. The script handles configuring,
building and running the kernel and tests.

The output parser (kunit_parser.py) simply strips out all the output
from the kernel that is outputted as part of it's initialization
sequence. This ensures that only the output from KUnit is displayed
on the screen.

A full version of the output is written to test.log, or can be seen by
passing --raw_output to the wrapper script.

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 tools/testing/kunit/kunit.py| 40 +
 tools/testing/kunit/kunit_kernel.py |  3 +--
 tools/testing/kunit/kunit_parser.py | 24 +
 3 files changed, 65 insertions(+), 2 deletions(-)
 create mode 100755 tools/testing/kunit/kunit.py
 create mode 100644 tools/testing/kunit/kunit_parser.py

diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
new file mode 100755
index 0..1356be404996b
--- /dev/null
+++ b/tools/testing/kunit/kunit.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: GPL-2.0
+
+# A thin wrapper on top of the KUnit Kernel
+
+import argparse
+import sys
+import os
+
+import kunit_config
+import kunit_kernel
+import kunit_parser
+
+parser = argparse.ArgumentParser(description='Runs KUnit tests.')
+
+parser.add_argument('--raw_output', help='don\'t format output from kernel',
+   action='store_true')
+
+parser.add_argument('--timeout', help='maximum number of seconds to allow for '
+   'all tests to run. This does not include time taken to '
+   'build the tests.', type=int, default=300,
+   metavar='timeout')
+
+cli_args = parser.parse_args()
+linux = kunit_kernel.LinuxSourceTree()
+
+success = linux.build_reconfig()
+if not success:
+   quit()
+
+print('Building KUnit Kernel ...')
+success = linux.build_um_kernel()
+if not success:
+   quit()
+
+print('Starting KUnit Kernel ...')
+if cli_args.raw_output:
+   kunit_parser.raw_output(linux.run_kernel(timeout=cli_args.timeout))
+else:
+   kunit_parser.parse_run_tests(linux.run_kernel(timeout=cli_args.timeout))
diff --git a/tools/testing/kunit/kunit_kernel.py 
b/tools/testing/kunit/kunit_kernel.py
index 87abaede50513..c1259b174f7d4 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -113,8 +113,7 @@ class LinuxSourceTree(object):
return False
return True
 
-   def run_kernel(self, args=[]):
-   timeout = None
+   def run_kernel(self, args=[], timeout=None):
args.extend(['mem=256M'])
process = self._ops.linux_bin(args, timeout)
with open('test.log', 'w') as f:
diff --git a/tools/testing/kunit/kunit_parser.py 
b/tools/testing/kunit/kunit_parser.py
new file mode 100644
index 0..1dff3adb73bd3
--- /dev/null
+++ b/tools/testing/kunit/kunit_parser.py
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0
+
+import re
+
+kunit_start_re = re.compile('console .* enabled')
+kunit_end_re = re.compile('List of all partitions:')
+
+def isolate_kunit_output(kernel_output):
+   started = False
+   for line in kernel_output:
+   if kunit_start_re.match(line):
+   started = True
+   elif kunit_end_re.match(line):
+   break
+   elif started:
+   yield line
+
+def raw_output(kernel_output):
+   for line in kernel_output:
+   print(line)
+
+def parse_run_tests(kernel_output):
+   for output in isolate_kunit_output(kernel_output):
+   print(output)
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 22/31] kunit: mock: add the concept of spyable functions

2018-10-16 Thread Brendan Higgins
Adds the concept of spying like in Mockito
(http://static.javadoc.io/org.mockito/mockito-core/2.20.0/org/mockito/Mockito.html#spy-T-).
This allows a function declaration to be labled as spyable which allows
the function to be mocked *and* to allow the mock to invoke the original
function definition.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h | 123 ++-
 kunit/common-mocks.c |  36 +
 2 files changed, 158 insertions(+), 1 deletion(-)

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index b58e30ba02ce2..c3615e80d96ee 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -284,6 +284,13 @@ static inline bool is_naggy_mock(struct mock *mock)
DECLARE_MOCK_CLIENT(name, return_type, param_types);   \
DECLARE_MOCK_MASTER(name, handle_index, param_types)
 
+#define DECLARE_SPYABLE(name, return_type, param_types...)\
+   return_type REAL_ID(name)(param_types);\
+   return_type name(param_types); \
+   void *INVOKE_ID(name)(struct test *test,   \
+ const void *params[],\
+ int len)
+
 #define DECLARE_MOCK_FUNC_CLIENT(name, return_type, param_types...) \
DECLARE_MOCK_CLIENT(name, return_type, param_types)
 
@@ -465,6 +472,100 @@ static inline bool is_naggy_mock(struct mock *mock)
RETURN(return_type, retval);   \
}
 
+#if IS_ENABLED(CONFIG_KUNIT)
+#define DEFINE_INVOKABLE(name, return_type, RETURN_ASSIGN, param_types...) 
\
+   void *INVOKE_ID(name)(struct test *test,   \
+ const void *params[],\
+ int len) {   \
+   return_type *retval;   \
+  \
+   TEST_ASSERT_EQ(test, NUM_VA_ARGS(param_types), len);   \
+   retval = test_kzalloc(test,\
+ sizeof(*retval), \
+ GFP_KERNEL); \
+   TEST_ASSERT_NOT_ERR_OR_NULL(test, retval); \
+   RETURN_ASSIGN() REAL_ID(name)( \
+   ARRAY_ACCESSORS_FROM_TYPES(\
+   param_types)); \
+   return retval; \
+   }
+#else
+#define DEFINE_INVOKABLE(name, return_type, RETURN_ASSIGN, param_types...)
+#endif
+
+#define DEFINE_SPYABLE_COMMON(name,   \
+ return_type, \
+ RETURN_ASSIGN,   \
+ param_types...)  \
+   return_type REAL_ID(name)(param_types);\
+   return_type name(param_types) __mockable_alias(REAL_ID(name)); \
+   DEFINE_INVOKABLE(name, return_type, RETURN_ASSIGN, param_types);
+
+#define ASSIGN() *retval =
+
+/**
+ * DEFINE_SPYABLE()
+ * @name: name of the function
+ * @return_type: return type of the function
+ * @param_types: parameter types of the function
+ *
+ * Used to define a function which is *redirect-mockable*, which allows the
+ * function to be mocked and refer to the original definition via
+ * INVOKE_REAL().
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * DEFINE_SPYABLE(i2c_add_adapter,
+ *RETURNS(int), PARAMS(struct i2c_adapter *));
+ * int REAL_ID(i2c_add_adapter)(struct i2c_adapter *adapter)
+ * {
+ * ...
+ * }
+ *
+ * static int aspeed_i2c_test_init(struct test *test)
+ * {
+ * struct mock_param_capturer *adap_capturer;
+ * struct mock_expectation *handle;
+ * struct aspeed_i2c_test *ctx;
+ * int ret;
+ *
+ * ctx = test_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
+ * if (!ctx)
+ * return -ENOMEM;
+ * test->priv = ctx;
+ *
+ * handle = TEST_EXPECT_CALL(
+ * i2c_add_adapter(capturer_to_matcher(
+ * adap_capturer)));
+ * handle->action = INVOKE_REAL(test, i2c_add_adapter);
+ * ret = of_fake_probe_platform_by_name(test,
+ *  "asp

[RFC v1 26/31] arch: um: added stubs for mock iomem for KUnit

2018-10-16 Thread Brendan Higgins
This mocks out some iomem functions (functions like readl and writel),
for mocking hardware interfaces.

Signed-off-by: Brendan Higgins 
---
 arch/um/Kconfig.common   |  8 +-
 arch/um/Kconfig.um   |  5 
 arch/um/include/asm/Kbuild   |  1 -
 arch/um/include/asm/io-mock-shared.h | 33 +
 arch/um/include/asm/io-mock.h| 43 
 arch/um/include/asm/io.h |  8 ++
 arch/um/kernel/Makefile  |  1 +
 arch/um/kernel/io-mock.c | 40 ++
 kunit/Kconfig|  1 +
 9 files changed, 138 insertions(+), 2 deletions(-)
 create mode 100644 arch/um/include/asm/io-mock-shared.h
 create mode 100644 arch/um/include/asm/io-mock.h
 create mode 100644 arch/um/kernel/io-mock.c

diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index 07f84c842cc31..72e7efb74f7fd 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -19,7 +19,13 @@ config MMU
default y
 
 config NO_IOMEM
-   def_bool y
+   bool
+   default y if !KUNIT
+
+config HAS_IOMEM
+   bool "Turns on fake IOMEM support for KUnit"
+   depends on KUNIT
+   select MOCK_IOMEM
 
 config ISA
bool
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index 20da5a8ca9490..8d35e0e2c23d1 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -122,3 +122,8 @@ config SECCOMP
  defined by each seccomp mode.
 
  If unsure, say Y.
+
+config PLATFORM_MOCK
+   bool "Enable a mock architecture used for unit testing."
+   depends on KUNIT && OF
+   default n
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index b10dde6cb793b..9fd2827ab76d1 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -12,7 +12,6 @@ generic-y += ftrace.h
 generic-y += futex.h
 generic-y += hardirq.h
 generic-y += hw_irq.h
-generic-y += io.h
 generic-y += irq_regs.h
 generic-y += irq_work.h
 generic-y += kdebug.h
diff --git a/arch/um/include/asm/io-mock-shared.h 
b/arch/um/include/asm/io-mock-shared.h
new file mode 100644
index 0..6baf59cb17a58
--- /dev/null
+++ b/arch/um/include/asm/io-mock-shared.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_UM_IO_MOCK_SHARED_H
+#define _ASM_UM_IO_MOCK_SHARED_H
+
+#define readb readb
+u8 readb(const volatile void __iomem *);
+
+#define readw readw
+u16 readw(const volatile void __iomem *);
+
+#define readl readl
+u32 readl(const volatile void __iomem *);
+
+#ifdef CONFIG_64BIT
+#define readq readq
+u64 readq(const volatile void __iomem *);
+#endif /* CONFIG_64BIT */
+
+#define writeb writeb
+void writeb(u8, const volatile void __iomem *);
+
+#define writew writew
+void writew(u16, const volatile void __iomem *);
+
+#define writel writel
+void writel(u32, const volatile void __iomem *);
+
+#ifdef CONFIG_64BIT
+#define writeq writeq
+void writeq(u64, const volatile void __iomem *);
+#endif /* CONFIG_64BIT */
+
+#endif /* _ASM_UM_IO_MOCK_SHARED_H */
diff --git a/arch/um/include/asm/io-mock.h b/arch/um/include/asm/io-mock.h
new file mode 100644
index 0..bdc5cd1d4e33c
--- /dev/null
+++ b/arch/um/include/asm/io-mock.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Mock IO functions.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _ASM_UM_IO_MOCK_H
+#define _ASM_UM_IO_MOCK_H
+
+#include 
+#include 
+
+DECLARE_FUNCTION_MOCK(readb,
+ RETURNS(u8), PARAMS(const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK(readw,
+ RETURNS(u16), PARAMS(const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK(readl,
+ RETURNS(u32), PARAMS(const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DECLARE_FUNCTION_MOCK(readq,
+ RETURNS(u64), PARAMS(const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(writeb,
+ PARAMS(u8, const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(writew,
+ PARAMS(u16, const volatile void __iomem *));
+
+DECLARE_FUNCTION_MOCK_VOID_RETURN(writel,
+ PARAMS(u32, const volatile void __iomem *));
+
+#ifdef CONFIG_64BIT
+DECLARE_FUNCTION_MOCK_VOID_RETURN(writeq,
+ PARAMS(u64, const volatile void __iomem *));
+#endif /* CONFIG_64BIT */
+
+#endif /* _ASM_UM_IO_MOCK_H */
diff --git a/arch/um/include/asm/io.h b/arch/um/include/asm/io.h
index 96f77b5232aaf..a7f61cf963756 100644
--- a/arch/um/include/asm/io.h
+++ b/arch/um/include/asm/io.h
@@ -2,11 +2,19 @@
 #ifndef _ASM_UM_IO_H
 #define _ASM_UM_IO_H
 
+#include 
+#include 
+
+#if IS_ENABLED(CONFIG_PLATFORM_MOCK)
+#include 
+#endif
+
 #define ioremap ioremap
 static inline void __iomem *ioremap(phys_addr_t offset, size_t size)
 {
retu

[RFC v1 25/31] kunit: added concept of platform mocking

2018-10-16 Thread Brendan Higgins
Platform mocking is the mocking of all platform specific functions that
interact directly with hardware. In effect, this provides the ability to
mock any hardware behavior.

Signed-off-by: Brendan Higgins 
---
 drivers/base/Makefile|  1 +
 drivers/base/platform-mock.c | 65 
 include/linux/platform_device_mock.h | 64 +++
 3 files changed, 130 insertions(+)
 create mode 100644 drivers/base/platform-mock.c
 create mode 100644 include/linux/platform_device_mock.h

diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 704f442958103..77cc599daa020 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o
 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o
 obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o
 obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o
+obj-$(CONFIG_PLATFORM_MOCK) += platform-mock.o
 
 obj-y  += test/
 
diff --git a/drivers/base/platform-mock.c b/drivers/base/platform-mock.c
new file mode 100644
index 0..3df9f1b0bb50f
--- /dev/null
+++ b/drivers/base/platform-mock.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Fake platform device API for unit testing platform drivers.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+
+struct device_node *of_fake_node(struct test *test, const char *name)
+{
+   struct device_node *node;
+
+   node = test_kzalloc(test, sizeof(*node), GFP_KERNEL);
+   if (!node)
+   return NULL;
+
+   of_node_init(node);
+
+   return node;
+}
+
+struct platform_device *
+of_fake_probe_platform(struct test *test,
+  const struct platform_driver *driver,
+  const char *node_name)
+{
+   struct platform_device *pdev;
+   struct device_node *of_node;
+   int ret;
+
+   of_node = of_fake_node(test, node_name);
+   if (!of_node)
+   return ERR_PTR(-ENOMEM);
+
+   test_info(test, "Creating device");
+   pdev = of_platform_device_create(of_node, node_name, NULL);
+   if (!pdev)
+   return ERR_PTR(-ENODEV);
+
+   test_info(test, "Probing");
+   ret = driver->probe(pdev);
+   if (ret)
+   return ERR_PTR(ret);
+
+   return pdev;
+}
+
+struct platform_device *of_fake_probe_platform_by_name(struct test *test,
+  const char *driver_name,
+  const char *node_name)
+{
+   const struct device_driver *driver;
+
+   test_info(test, "Locating driver by name");
+   driver = driver_find(driver_name, &platform_bus_type);
+   if (!driver)
+   return ERR_PTR(-ENODEV);
+
+   return of_fake_probe_platform(test,
+ to_platform_driver(driver),
+ node_name);
+}
diff --git a/include/linux/platform_device_mock.h 
b/include/linux/platform_device_mock.h
new file mode 100644
index 0..898539d166f66
--- /dev/null
+++ b/include/linux/platform_device_mock.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Fake platform device API for unit testing platform drivers.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#include 
+#include 
+
+static inline struct platform_driver *platform_driver_find(const char *name)
+{
+   struct device_driver *driver;
+
+   driver = driver_find(name, &platform_bus_type);
+   if (!driver)
+   return NULL;
+
+   return to_platform_driver(driver);
+}
+
+/**
+ * of_fake_node()
+ * @test: the test to associate node with
+ * @name: name of the node
+ *
+ * The &struct device_node returned is allocated as a root node with the given
+ * name and otherwise behaves as a real &struct device_node.
+ *
+ * Returns: the faked &struct device_node
+ */
+struct device_node *of_fake_node(struct test *test, const char *name);
+
+/**
+ * of_fake_probe_platform()
+ * @test: the test to associate the fake platform device with
+ * @driver: driver to probe
+ * @node_name: name of the device node created
+ *
+ * Creates a &struct platform_device and an associated &struct device_node,
+ * probes the provided &struct platform_driver with the &struct 
platform_device.
+ *
+ * Returns: the &struct platform_device that was created
+ */
+struct platform_device *
+of_fake_probe_platform(struct test *test,
+  const struct platform_driver *driver,
+  const char *node_name);
+
+/**
+ * of_fake_probe_platform_by_name()
+ * @test: the test to associate the fake platform device with
+ * @driver_name: name of the driver to probe
+ * @node_name: name of the device node created
+ *
+ * Same as of_fake_probe_platform() but looks up t

[RFC v1 27/31] Documentation: kunit: adds complete documentation for KUnit

2018-10-16 Thread Brendan Higgins
- Added intro and usage guide for KUnit
- Added API reference

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 Documentation/index.rst   |   1 +
 .../kunit/api/class-and-function-mocking.rst  |  68 ++
 Documentation/kunit/api/index.rst |  21 +
 Documentation/kunit/api/platform-mocking.rst  |  36 +
 Documentation/kunit/api/test.rst  |  15 +
 Documentation/kunit/faq.rst   |  46 +
 Documentation/kunit/index.rst |  84 ++
 Documentation/kunit/start.rst | 185 
 Documentation/kunit/usage.rst | 876 ++
 9 files changed, 1332 insertions(+)
 create mode 100644 Documentation/kunit/api/class-and-function-mocking.rst
 create mode 100644 Documentation/kunit/api/index.rst
 create mode 100644 Documentation/kunit/api/platform-mocking.rst
 create mode 100644 Documentation/kunit/api/test.rst
 create mode 100644 Documentation/kunit/faq.rst
 create mode 100644 Documentation/kunit/index.rst
 create mode 100644 Documentation/kunit/start.rst
 create mode 100644 Documentation/kunit/usage.rst

diff --git a/Documentation/index.rst b/Documentation/index.rst
index fdc585703498e..9415b6536d04b 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -66,6 +66,7 @@ merged much easier.
kernel-hacking/index
trace/index
maintainer/index
+   kunit/index
 
 Kernel API documentation
 
diff --git a/Documentation/kunit/api/class-and-function-mocking.rst 
b/Documentation/kunit/api/class-and-function-mocking.rst
new file mode 100644
index 0..3e53291145f1f
--- /dev/null
+++ b/Documentation/kunit/api/class-and-function-mocking.rst
@@ -0,0 +1,68 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==
+Class and Function Mocking
+==
+
+This file documents class and function mocking features.
+
+.. note::
+   If possible, prefer class mocking over arbitrary function mocking. Class
+   mocking has a much more limited scope and provides more control.
+   This file documents class mocking and most mocking features that do not
+   depend on function or platform mocking.
+
+Readability Macros
+--
+When defining and declaring mock stubs, use these readability macros.
+
+.. code-block:: c
+
+#define CLASS(struct_name) struct_name
+#define HANDLE_INDEX(index) index
+#define METHOD(method_name) method_name
+#define RETURNS(return_type) return_type
+#define PARAMS(...) __VA_ARGS__
+
+Consider a ``struct Foo`` with a member function
+``int add(struct Foo*, int a, int b);``
+
+When generating a mock stub with :c:func:`DEFINE_STRUCT_CLASS_MOCK`, which
+takes a method name, struct name, return type, and method parameters, the
+arguments should be passed in with the readability macros.
+
+.. code-block:: c
+
+DEFINE_STRUCT_CLASS_MOCK(
+METHOD(add),
+CLASS(Foo),
+RETURNS(int),
+PARAMS(struct Foo *, int, int)
+);
+
+For a more detailed example of this, take a look at the example in
+:doc:`../start`
+
+These macros should only be used in the context of the mock stub generators.
+
+
+Built in Matchers
+-
+
+.. kernel-doc:: include/kunit/mock.h
+   :doc: Built In Matchers
+
+Mock Returns
+
+These functions can be used to specify a value to be returned (``ret``) when a
+mocked function is intercepted via :c:func:`EXPECT_CALL`.
+
+.. code-block:: c
+
+struct mock_action *int_return(struct test *test, int ret);
+struct mock_action *u32_return(struct test *test, u32 ret);
+
+API
+---
+.. kernel-doc:: include/kunit/mock.h
+   :internal:
diff --git a/Documentation/kunit/api/index.rst 
b/Documentation/kunit/api/index.rst
new file mode 100644
index 0..a4fdc35b32c5c
--- /dev/null
+++ b/Documentation/kunit/api/index.rst
@@ -0,0 +1,21 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=
+API Reference
+=
+.. toctree::
+
+   test
+   class-and-function-mocking
+   platform-mocking
+
+This section documents the KUnit kernel testing API. It is divided into 3
+sections:
+
+= 
==
+:doc:`test`   documents all of the standard testing API
+  excluding mocking or mocking related 
features.
+:doc:`class-and-function-mocking` documents class and function mocking 
features.
+:doc:`platform-mocking`   documents mocking libraries that mock out
+  platform specific features.
+= 
==
diff --git a/Documentation/kunit/api/platform-mocking.rst 
b/Documentation/kunit/api/platform-mocking.rst
new file mode 100644
index 0..72555eb5b1de1
--- /dev/null
+++ b/Documentation/kunit/api/platform-mocking.rst

[RFC v1 23/31] kunit: mock: add parameter capturers

2018-10-16 Thread Brendan Higgins
Adds the concept of an argument capturer which, when used with a matcher
in an EXPECT_CALL(...), will capture the value of the matching argument.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h | 83 
 kunit/common-mocks.c | 78 +
 2 files changed, 161 insertions(+)

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index c3615e80d96ee..0e1aa568709a1 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -1172,6 +1172,89 @@ struct mock_param_matcher *test_struct_cmp(
const char *struct_name,
struct mock_struct_matcher_entry *entries);
 
+/**
+ * struct mock_param_capturer - used to capture parameter when matching
+ *
+ * Use the associated helper macros to access relevant fields.
+ * Example:
+ *
+ * .. code-block::c
+ *
+ * static int some_test(struct test *test)
+ * {
+ * // imagine a mocked function: int add(int a, int b)
+ * struct mock_param_capturer *capturer =
+ * mock_int_capturer_create(test, any(test));
+ * TEST_EXPECT_CALL(add(any(test), capturer_to_matcher(capturer)));
+ * TEST_ASSERT_PARAM_CAPTURED(test, capturer);
+ *
+ * int captured_value = mock_capturer_get(capturer, int);
+ * }
+ */
+struct mock_param_capturer {
+   /* private: internal use only. */
+   struct mock_param_matcher matcher;
+   struct mock_param_matcher *child_matcher;
+   void *(*capture_param)(struct test *test, const void *param);
+   void *captured_param;
+};
+
+struct mock_param_capturer *mock_param_capturer_create(
+   struct test *test,
+   struct mock_param_matcher *child_matcher,
+   void *(*capture_param)(struct test *, const void *));
+
+/**
+ * mock_int_capturer_create() - creates a int parameter capturer
+ * @test: associated test
+ * @child_matcher: matcher used to match the integer
+ *
+ * The capturer will capture the value if the matcher is satisfied.
+ */
+struct mock_param_capturer *mock_int_capturer_create(
+   struct test *test, struct mock_param_matcher *child_matcher);
+
+/**
+ * mock_int_capturer_create() - creates a generic pointer parameter capturer
+ * @test: associated test
+ * @child_matcher: matcher used to match the pointer
+ *
+ * The capturer will capture the value if the matcher is satisfied
+ */
+struct mock_param_capturer *mock_ptr_capturer_create(
+   struct test *test, struct mock_param_matcher *child_matcher);
+
+/**
+ * capturer_to_matcher()
+ * @capturer: the param capturer
+ *
+ * Use this function when passing a capturer into an EXPECT_CALL() where a
+ * matcher would be expected. See the example for &struct mock_param_capturer.
+ */
+#define capturer_to_matcher(capturer) (&(capturer)->matcher)
+
+/**
+ * TEST_ASSERT_PARAM_CAPTURED(): Asserts that a parameter has been captured.
+ * @test: the associated test
+ * @capturer: the param capturer
+ *
+ * See &struct mock_param_capturer for an example.
+ */
+#define TEST_ASSERT_PARAM_CAPTURED(test, capturer)\
+   TEST_ASSERT(test,  \
+  !IS_ERR_OR_NULL((capturer)->captured_param),\
+  "Asserted " #capturer " captured param, but did not.")
+
+/**
+ * mock_capturer_get(): Returns the value captured by ``capturer``
+ * @capturer: the param capturer
+ * @type: the type of the value
+ *
+ * See &struct mock_param_capturer for an example.
+ */
+#define mock_capturer_get(capturer, type) \
+   CONVERT_TO_ACTUAL_TYPE(type, (capturer)->captured_param)
+
 struct mock_action *invoke(struct test *test,
   void *(*invokable)(struct test *,
  const void *params[],
diff --git a/kunit/common-mocks.c b/kunit/common-mocks.c
index ce0159923814d..62528b7df83c6 100644
--- a/kunit/common-mocks.c
+++ b/kunit/common-mocks.c
@@ -323,6 +323,84 @@ struct mock_param_matcher *test_struct_cmp(
return &matcher->matcher;
 }
 
+static bool match_and_capture_param(struct mock_param_matcher *pmatcher,
+   struct test_stream *stream,
+   const void *param)
+{
+   struct mock_param_capturer *capturer =
+   container_of(pmatcher,
+struct mock_param_capturer,
+matcher);
+   struct mock_param_matcher *child_matcher = capturer->child_matcher;
+   bool matches;
+
+   matches = child_matcher->match(child_matcher, stream, param);
+   if (matches)
+   capturer->captured_param = capturer->capture_param(stream->test,
+ 

[RFC v1 21/31] kunit: mock: added support for arbitrary function mocking

2018-10-16 Thread Brendan Higgins
Up to this point KUnit only supported method style function mocking
where there was some type of class or context object and the function
was only accessed via a pointer.

This adds support for mocking any function via the __mockable attribute.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h| 107 
 kunit/mock-macro-test.c |  14 ++
 kunit/mock.c|  41 +++
 3 files changed, 162 insertions(+)

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index 89e95b3fcf09e..b58e30ba02ce2 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -144,6 +144,8 @@ void mock_register_formatter(struct mock_param_formatter 
*formatter);
 
 void mock_unregister_formatter(struct mock_param_formatter *formatter);
 
+struct mock *mock_get_global_mock(void);
+
 #define MOCK(name) name##_mock
 
 /**
@@ -282,6 +284,12 @@ static inline bool is_naggy_mock(struct mock *mock)
DECLARE_MOCK_CLIENT(name, return_type, param_types);   \
DECLARE_MOCK_MASTER(name, handle_index, param_types)
 
+#define DECLARE_MOCK_FUNC_CLIENT(name, return_type, param_types...) \
+   DECLARE_MOCK_CLIENT(name, return_type, param_types)
+
+#define DECLARE_MOCK_FUNC_MASTER(name, param_types...) \
+   DECLARE_MOCK_MASTER(name, MOCK_MAX_PARAMS, param_types)
+
 #define DECLARE_STRUCT_CLASS_MOCK_STRUCT(struct_name) \
struct MOCK(struct_name) { \
struct mock ctrl;  \
@@ -411,6 +419,16 @@ static inline bool is_naggy_mock(struct mock *mock)
  */
 #define CONSTRUCT_MOCK(struct_name, test) MOCK_INIT_ID(struct_name)(test)
 
+#define DECLARE_FUNCTION_MOCK_INTERNAL(name, return_type, param_types...)  
\
+   DECLARE_MOCK_FUNC_CLIENT(name, return_type, param_types);  \
+   DECLARE_MOCK_FUNC_MASTER(name, param_types);
+
+#define DECLARE_FUNCTION_MOCK(name, return_type, param_types...) \
+   DECLARE_FUNCTION_MOCK_INTERNAL(name, return_type, param_types)
+
+#define DECLARE_FUNCTION_MOCK_VOID_RETURN(name, param_types...) \
+   DECLARE_FUNCTION_MOCK(name, void, param_types)
+
 #define DEFINE_MOCK_CLIENT_COMMON(name,
   \
  handle_index,\
  MOCK_SOURCE, \
@@ -488,6 +506,31 @@ static inline bool is_naggy_mock(struct mock *mock)
 NO_RETURN,\
 param_types)
 
+#define FUNC_MOCK_SOURCE(ctx, handle_index) mock_get_global_mock()
+#define DEFINE_MOCK_FUNC_CLIENT_COMMON(name,  \
+  return_type,\
+  RETURN, \
+  param_types...) \
+   DEFINE_MOCK_CLIENT_COMMON(name,\
+ MOCK_MAX_PARAMS, \
+ FUNC_MOCK_SOURCE,\
+ name,\
+ return_type, \
+ RETURN,  \
+ param_types)
+
+#define DEFINE_MOCK_FUNC_CLIENT(name, return_type, param_types...)\
+   DEFINE_MOCK_FUNC_CLIENT_COMMON(name,   \
+  return_type,\
+  CAST_AND_RETURN,\
+  param_types)
+
+#define DEFINE_MOCK_FUNC_CLIENT_VOID_RETURN(name, param_types...) \
+   DEFINE_MOCK_FUNC_CLIENT_COMMON(name,   \
+  void,   \
+  NO_RETURN,  \
+  param_types)
+
 #define DEFINE_MOCK_MASTER_COMMON_INTERNAL(name,  \
   ctrl_index, \
   MOCK_SOURCE,\
@@ -522,6 +565,13 @@ static inline bool is_naggy_mock(struct mock *mock)
  CLASS_MOCK_MASTER_SOURCE,\
  param_types)
 
+#define FUNC_MOCK_CLIENT_SOURCE(ctrl_index) mock_get_global_mock()
+#define

[RFC v1 17/31] kunit: mock: added struct param matcher

2018-10-16 Thread Brendan Higgins
Added parameter matcher builder for matching struct values.

Signed-off-by: Brendan Higgins 
---
 include/kunit/mock.h |  56 +++
 kunit/Makefile   |   5 +-
 kunit/common-mocks.c | 116 ++
 kunit/mock-test.c|  43 +++
 kunit/test-stream-test.c | 150 +++
 5 files changed, 368 insertions(+), 2 deletions(-)
 create mode 100644 kunit/test-stream-test.c

diff --git a/include/kunit/mock.h b/include/kunit/mock.h
index 1b7485e2cedb8..daf965cf954e6 100644
--- a/include/kunit/mock.h
+++ b/include/kunit/mock.h
@@ -760,6 +760,14 @@ struct mock_param_matcher *test_memeq(struct test *test,
  size_t size);
 struct mock_param_matcher *test_streq(struct test *test, const char *str);
 
+struct mock_param_matcher *test_str_contains(struct test *test,
+const char *needle);
+
+/* Matches var-arg arguments. */
+struct mock_param_matcher *test_va_format_cmp(struct test *test,
+struct mock_param_matcher *fmt_matcher,
+struct mock_param_matcher *va_matcher);
+
 struct mock_action *test_u8_return(struct test *test, u8 ret);
 struct mock_action *test_u16_return(struct test *test, u16 ret);
 struct mock_action *test_u32_return(struct test *test, u32 ret);
@@ -778,4 +786,52 @@ struct mock_action *test_ulonglong_return(struct test 
*test,
  unsigned long long ret);
 struct mock_action *test_ptr_return(struct test *test, void *ret);
 
+/**
+ * struct mock_struct_matcher_entry - composed with other &struct
+ *mock_struct_matcher_entry to make a
+ *&struct struct_matcher
+ * @member_offset: offset of this member
+ * @matcher: matcher for this particular member
+ *
+ * This is used for struct_cmp() matchers.
+ */
+struct mock_struct_matcher_entry {
+   size_t member_offset;
+   struct mock_param_matcher *matcher;
+};
+
+static inline void init_mock_struct_matcher_entry_internal(
+   struct mock_struct_matcher_entry *entry,
+   size_t offset,
+   struct mock_param_matcher *matcher)
+{
+   entry->member_offset = offset;
+   entry->matcher = matcher;
+}
+
+/**
+ * INIT_MOCK_STRUCT_MATCHER_ENTRY()
+ * @entry: the &struct mock_struct_matcher_entry to initialize
+ * @type: the struct being matched
+ * @member: the member of the struct being matched, used to calculate the 
offset
+ * @matcher: matcher to match that member
+ *
+ * Initializes ``entry`` to match ``type->member`` with ``matcher``.
+ */
+#define INIT_MOCK_STRUCT_MATCHER_ENTRY(entry, type, member, matcher)  \
+   init_mock_struct_matcher_entry_internal(entry, \
+   offsetof(type, member),\
+   matcher)
+
+static inline void INIT_MOCK_STRUCT_MATCHER_ENTRY_LAST(
+   struct mock_struct_matcher_entry *entry)
+{
+   entry->matcher = NULL;
+}
+
+struct mock_param_matcher *test_struct_cmp(
+   struct test *test,
+   const char *struct_name,
+   struct mock_struct_matcher_entry *entries);
+
 #endif /* _KUNIT_MOCK_H */
diff --git a/kunit/Makefile b/kunit/Makefile
index 6fccfcdbc6f84..e05fbcae8bfb0 100644
--- a/kunit/Makefile
+++ b/kunit/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_KUNIT)+= test.o mock.o common-mocks.o string-stream.o 
\
   test-stream.o
-obj-$(CONFIG_KUNIT_TEST)   += \
-  test-test.o test-mock.o mock-macro-test.o mock-test.o string-stream-test.o
+obj-$(CONFIG_KUNIT_TEST)   += \
+  test-test.o test-mock.o mock-macro-test.o mock-test.o string-stream-test.o \
+  test-stream-test.o
 obj-$(CONFIG_EXAMPLE_TEST) += example-test.o
diff --git a/kunit/common-mocks.c b/kunit/common-mocks.c
index ecac9c1c29c0e..ef88f8b8acda3 100644
--- a/kunit/common-mocks.c
+++ b/kunit/common-mocks.c
@@ -207,6 +207,122 @@ struct mock_param_matcher *test_streq(struct test *test, 
const char *str)
return &matcher->matcher;
 }
 
+struct mock_str_contains_matcher {
+   struct mock_param_matcher matcher;
+   const char *needle;
+};
+
+static bool match_str_contains(struct mock_param_matcher *pmatcher,
+  struct test_stream *stream,
+  const void *phaystack)
+{
+   struct mock_str_contains_matcher *matcher =
+   container_of(pmatcher,
+struct mock_str_contains_matcher,
+matcher);
+   const char *haystack = CONVERT_TO_ACTUAL_TYPE(const char *, phaystack);
+   bool matches = strstr(haystack, matcher->needle);
+
+   if (matches)
+   stream->add(stream,
+

[RFC v1 12/31] checkpatch: added support for struct MOCK(foo) syntax

2018-10-16 Thread Brendan Higgins
This adds struct MOCK(foo) as a NonptrType so that it is recognized
correctly in declarations.

Signed-off-by: Brendan Higgins 
---
 scripts/checkpatch.pl | 4 
 1 file changed, 4 insertions(+)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 447857ffaf6be..9806f190796de 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -745,6 +745,10 @@ sub build_types {
(?:
(?:typeof|__typeof__)\s*\([^\)]*\)|
(?:$typeTypedefs\b)|
+   # Matching a \b breaks struct MOCK(foo) syntax,
+   # so we need to have it not lumped in with the
+   # types in @typeList.
+   (?:struct\s+MOCK\($Ident\))|
(?:${all}\b)
)
(?:\s+$Modifier|\s+const)*
-- 
2.19.1.331.ge82ca0e54c-goog



[RFC v1 09/31] kunit: test: added the concept of assertions

2018-10-16 Thread Brendan Higgins
Added support for assertions which are like expectations except the test
terminates if the assertion is not satisfied.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h   | 272 -
 kunit/Makefile |   2 +-
 kunit/string-stream-test.c |  12 +-
 kunit/test-test.c  |  37 +
 kunit/test.c   | 131 --
 5 files changed, 436 insertions(+), 18 deletions(-)
 create mode 100644 kunit/test-test.c

diff --git a/include/kunit/test.h b/include/kunit/test.h
index d652825d7296f..49a9d6e43992c 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -84,9 +84,10 @@ struct test;
  * @name: the name of the test case.
  *
  * A test case is a function with the signature, ``void (*)(struct test *)``
- * that makes expectations (see TEST_EXPECT_TRUE()) about code under test. Each
- * test case is associated with a &struct test_module and will be run after the
- * module's init function and followed by the module's exit function.
+ * that makes expectations and assertions (see TEST_EXPECT_TRUE() and
+ * TEST_ASSERT_TRUE()) about code under test. Each test case is associated with
+ * a &struct test_module and will be run after the module's init function and
+ * followed by the module's exit function.
  *
  * A test case should be static and should only be created with the TEST_CASE()
  * macro; additionally, every array of test cases should be terminated with an
@@ -168,11 +169,14 @@ struct test {
const char *name; /* Read only after initialization! */
spinlock_t lock; /* Gaurds all mutable test state. */
bool success; /* Protected by lock. */
+   bool death_test; /* Protected by lock. */
struct list_head resources; /* Protected by lock. */
+   void (*set_death_test)(struct test *test, bool death_test);
void (*vprintk)(const struct test *test,
const char *level,
struct va_format *vaf);
void (*fail)(struct test *test, struct test_stream *stream);
+   void (*abort)(struct test *test);
 };
 
 int test_init_test(struct test *test, const char *name);
@@ -532,4 +536,266 @@ static inline void test_expect_binary(struct test *test,
TEST_EXPECT_END(test, !IS_ERR_OR_NULL(__ptr), __stream);   \
 } while (0)
 
+static inline struct test_stream *test_assert_start(struct test *test,
+   const char *file,
+   const char *line)
+{
+   struct test_stream *stream = test_new_stream(test);
+
+   stream->add(stream, "ASSERTION FAILED at %s:%s\n\t", file, line);
+
+   return stream;
+}
+
+static inline void test_assert_end(struct test *test,
+  bool success,
+  struct test_stream *stream)
+{
+   if (!success) {
+   test->fail(test, stream);
+   test->abort(test);
+   } else {
+   stream->clear(stream);
+   }
+}
+
+#define TEST_ASSERT_START(test) \
+   test_assert_start(test, __FILE__, __stringify(__LINE__))
+
+#define TEST_ASSERT_END(test, success, stream) \
+   test_assert_end(test, success, stream)
+
+#define TEST_ASSERT(test, success, message) do {  \
+   struct test_stream *__stream = TEST_ASSERT_START(test);\
+  \
+   __stream->add(__stream, message);  \
+   TEST_ASSERT_END(test, success, __stream);  \
+} while (0)
+
+#define TEST_ASSERT_FAILURE(test, message) TEST_ASSERT(test, false, message)
+
+/**
+ * TEST_ASSERT_TRUE() - Causes an assertion failure when expression is not 
true.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails and aborts when
+ * this does not evaluate to true.
+ *
+ * This and assertions of the form `TEST_ASSERT_*` will cause the test case to
+ * fail *and immediately abort* when the specified condition is not met. Unlike
+ * an expectation failure, it will prevent the test case from continuing to 
run;
+ * this is otherwise known as an *assertion failure*.
+ */
+#define TEST_ASSERT_TRUE(test, condition) \
+   TEST_ASSERT(test, (condition), \
+  "Asserted " #condition " is true, but is false.")
+
+/**
+ * TEST_ASSERT_FALSE() - Sets an assertion that @condition is false.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression.
+ *
+ * Sets an assertion that the value that @condition evaluates to is false.  
This
+ * is the same as TEST_EXPECT_FALSE(), except it causes an assertion failure
+ * (see TEST_ASSERT_TR

Re: [RFC v1 12/31] checkpatch: added support for struct MOCK(foo) syntax

2018-10-16 Thread Brendan Higgins
On Tue, Oct 16, 2018 at 4:59 PM Joe Perches  wrote:
>
> On Tue, 2018-10-16 at 16:51 -0700, Brendan Higgins wrote:
> > This adds struct MOCK(foo) as a NonptrType so that it is recognized
> > correctly in declarations.
>
> I think this commit message is lacking context.

Oh sorry, you are right. We added macros for generating mocks from
types, so we decided to name the generated mock types struct MOCK(foo)
(where the base type is struct foo); this commit makes checkpatch not
complain at this new syntax.


Re: [RFC v1 06/31] arch: um: enabled running kunit from User Mode Linux

2018-10-17 Thread Brendan Higgins
On Wed, Oct 17, 2018 at 8:29 AM Kieran Bingham
 wrote:
>
> Hi Brendan,
>
> I very excitedly jumped on these patches to try them out, as this is
> essentially something I was trying to do a few weeks back.
>
> On 17/10/18 00:50, Brendan Higgins wrote:
> > Makes minimum number of changes outside of the KUnit directories for
> > KUnit to build and run using UML.
> >
> > Signed-off-by: Brendan Higgins 
> > ---
> >  Makefile | 2 +-
> >  arch/um/Kconfig.rest | 3 +++
>
> But this file isn't present on v4.19-rc8
>
> It looks like the file is removed at f163977d21a2 ("um: cleanup Kconfig
> files")

Whoops.

>
> What version have you currently based these patches on?

This patch set is based on 4.18, but I have versions for 4.4, 4.9,
4.14, 4.16, and 4.17.

I will rebase this patch set to 4.19-rc8 and send it out shortly.

> Do you expect to keep a branch somewhere that's easy to pull in?

I have one here: https://kunit-review.googlesource.com/c/linux/+/1030
(you can check it out with git fetch
https://kunit.googlesource.com/linux refs/changes/30/1030/4 && git
checkout FETCH_HEAD)

>
> Please add me to the CC list as an interested party on later versions :-)

Will do.


Re: [RFC v1 06/31] arch: um: enabled running kunit from User Mode Linux

2018-10-17 Thread Brendan Higgins
On Wed, Oct 17, 2018 at 10:52 AM  wrote:
> >
> > It might be of interest to the automated testing mailing list too ? (Tim?)
>
>  I think this is interesting to groups doing automated testing of the kernel
> (including myself) as another set of tests to run.  Right now I don't see it
> as having any special attributes related to automation.  But I could be wrong.

Pardon my ignorance, but by automated testing you mean a CI server
with presubmits, nightlys, and things of the sort?

If that's the case, KUnit could be helpful because of the low resource
cost in running them and the speed at which they run. There are some
other features we would like to add which would help with that goal as
well like test isolation. We actually have a presubmit server
internally for running KUnit tests that can usually respond to patches
with test results within a couple minutes. Would something like that
be interesting?


Re: [RFC v1 00/31] kunit: Introducing KUnit, the Linux kernel unit testing framework

2018-10-17 Thread Brendan Higgins
On Wed, Oct 17, 2018 at 10:49 AM  wrote:
>
> > -Original Message-
> > From: Brendan Higgins
> >
> > This patch set proposes KUnit, a lightweight unit testing and mocking
> > framework for the Linux kernel.
>
> I'm interested in this, and think the kernel might benefit from this,
> but I have lots of questions.
>
Awesome!

> > Unlike Autotest and kselftest, KUnit is a true unit testing framework;
> > it does not require installing the kernel on a test machine or in a VM
> > and does not require tests to be written in userspace running on a host
> > kernel.
>
>
> This is stated here and a few places in the documentation.  Just to clarify,
> KUnit works by compiling the unit under test, along with the test code
> itself, and then runs it on the machine where the compilation took
> place?  Is this right?  How does cross-compiling enter into the equation?
> If not what I described, then what exactly is happening?
>
Yep, that's exactly right!

The test and the code under test are linked together in the same
binary and are compiled under Kbuild. Right now I am linking
everything into a UML kernel, but I would ultimately like to make
tests compile into completely independent test binaries. So each test
file would get compiled into its own test binary and would link
against only the code needed to run the test, but we are a bit of a
ways off from that.

For now, tests compile as part of a UML kernel and a test script boots
the UML kernel, tests run as part of the boot process, and the script
extracts test results and reports them.

I intentionally made it so the KUnit test libraries could be
relatively easily ported to other architectures, but in the long term,
tests that depend on being built into a real kernel that boots on real
hardware would be a lot more difficult to maintain and we would never
be able to provide the kind of resources and infrastructure as we
could for tests that run as normal user space binaries.

Does that answer your question?

> Sorry - I haven't had time to look through the patches in detail.
>
> Another issue is, what requirements does this place on the tested
> code?  Is extra instrumentation required?  I didn't see any, but I
> didn't look exhaustively at the code.
>
Nope, no special instrumentation. As long as the code under tests can
be compiled under COMPILE_TEST for the host architecture, you should
be able to use KUnit.

> Are all unit tests stored separately from the unit-under-test, or are
> they expected to be in the same directory?  Who is expected to
> maintain the unit tests?  How often are they expected to change?
> (Would it be every time the unit-under-test changed?)
>
Tests are in the same directory as the code under test. For example,
if I have a driver drivers/i2c/busses/i2c-aspeed.c, I would write a
test drivers/i2c/busses/i2c-aspeed-test.c (that's my opinion anyway).

Unit tests should be the responsibility of the person who is
responsible for the code. So one way to do this would be that unit
tests should be the responsibility of the maintainer who would in turn
require that new tests are written for any new code added, and that
all tests should pass for every patch sent for review.

A well written unit test tests public interfaces (by public I just
mean functions exported outside of a .c file, so non-static functions
and functions which are shared as a member of a struct) so a unit test
should change at a slower rate than the code under test, but you would
likely have to change the test anytime the public interface changes
(intended behavior changes, function signature changes, new public
feature added, etc). More succinctly, if the contract that your code
provide changes your test should probably change, if the contract
doesn't change, your test probably shouldn't change. Does that make
sense?

> Does the test code require the same level of expertise to write
> and maintain as the unit-under-test code?  That is, could this be
> a new opportunity for additional developers (especially relative
> newcomers) to add value to the kernel by writing and maintaining
> test code, or does this add to the already large burden of code
> maintenance for our existing maintainers.

So a couple things, in order to write a unit test, the person who
writes the test must understand what the code they are testing is
supposed to do. To some extent that will probably require someone with
some expertise to ensure that the test makes sense, and indeed a
change that breaks a test should be accompanied by a update to the
test.

On the other hand, I think understanding what pre-existing code does
and is supposed to do is much easier than writing new code from
scratch, and probably doesn't require too much expertise. I actually
did a bit of an experiment internally on this: I had some people with

Re: [RFC v1 06/31] arch: um: enabled running kunit from User Mode Linux

2018-10-17 Thread Brendan Higgins
On Wed, Oct 17, 2018 at 2:18 PM  wrote:

> > There are some
> > other features we would like to add which would help with that goal as
> > well like test isolation. We actually have a presubmit server
> > internally for running KUnit tests that can usually respond to patches
> > with test results within a couple minutes. Would something like that
> > be interesting?
> I think the code and architecture of the software that handles presubmit,
> mail-list scanning, notifications, etc. would be of interest.  But KUnit 
> features
> themselves (macro definitions, mocking vs. faking, etc.) would not.
> I only say that in the context of CC-ing the automated testing list on the 
> patch set.
> Of course the KUnit features are interesting by themselves for testers doing
> unit testing.

Fair enough. Well, we will share what we have in that regard, but that
belongs on a separate thread.

BTW, what mailing list is that? I am also guessing your code isn't in
the kernel repo; where is it?


Re: [RFC v1 26/31] arch: um: added stubs for mock iomem for KUnit

2018-10-17 Thread Brendan Higgins
On Wed, Oct 17, 2018 at 3:28 PM Rob Herring  wrote:

> > diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
> > index 07f84c842cc31..72e7efb74f7fd 100644
> > --- a/arch/um/Kconfig.common
> > +++ b/arch/um/Kconfig.common
> > @@ -19,7 +19,13 @@ config MMU
> > default y
> >
> >  config NO_IOMEM
> > -   def_bool y
> > +   bool
> > +   default y if !KUNIT
> > +
> > +config HAS_IOMEM
>
> HAS_IOMEM is essentially a disable flag for lots of drivers on UML.
> Ignoring drivers, it doesn't really control a significant amount of
> code (albeit small amount of code you need for this series). As a
> driver disable, it does a poor job as lots of drivers aren't MMIO and
> aren't disabled. I think we should decouple these 2 things. Perhaps
> get rid of the driver disable part altogether. We already do 'depends
> on ARCH_FOO || COMPILE_TEST' for lots of drivers.
>
I think that makes sense. Any code that can build should be able to
build under KUnit, but we probably want to turn that on on a per
driver basis as we write tests for them.

> Also, I wouldn't be surprised if turning on HAS_IOMEM causes UML
> randconfig failures. Arnd does lots of randconfig testing and might be
> willing to help check.
>
It almost certainly would fail randconfig. As you point out below, I
don't implement everything that's required, just enough to show off
KUnit in a couple examples.

> > +   bool "Turns on fake IOMEM support for KUnit"
> > +   depends on KUNIT
> > +   select MOCK_IOMEM
> >
> >  config ISA
> > bool
> > diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
> > index 20da5a8ca9490..8d35e0e2c23d1 100644
> > --- a/arch/um/Kconfig.um
> > +++ b/arch/um/Kconfig.um
> > @@ -122,3 +122,8 @@ config SECCOMP
> >   defined by each seccomp mode.
> >
> >   If unsure, say Y.
> > +
> > +config PLATFORM_MOCK
> > +   bool "Enable a mock architecture used for unit testing."
> > +   depends on KUNIT && OF
> > +   default n
> > diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
> > index b10dde6cb793b..9fd2827ab76d1 100644
> > --- a/arch/um/include/asm/Kbuild
> > +++ b/arch/um/include/asm/Kbuild
> > @@ -12,7 +12,6 @@ generic-y += ftrace.h
> >  generic-y += futex.h
> >  generic-y += hardirq.h
> >  generic-y += hw_irq.h
> > -generic-y += io.h
> >  generic-y += irq_regs.h
> >  generic-y += irq_work.h
> >  generic-y += kdebug.h
> > diff --git a/arch/um/include/asm/io-mock-shared.h 
> > b/arch/um/include/asm/io-mock-shared.h
> > new file mode 100644
> > index 0..6baf59cb17a58
> > --- /dev/null
> > +++ b/arch/um/include/asm/io-mock-shared.h
> > @@ -0,0 +1,33 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef _ASM_UM_IO_MOCK_SHARED_H
> > +#define _ASM_UM_IO_MOCK_SHARED_H
> > +
> > +#define readb readb
> > +u8 readb(const volatile void __iomem *);
>
> What about all the other flavors of MMIO accessors like __raw_readb,
> readb_relaxed, etc.? readX/writeX is intended for PCI based drivers
> which doesn't seem to be what you are targeting in this series.
>
Those need to be done too. I just mostly wanted to illustrate that it
can be done, and what is needed to support mocking MMIO. I wasn't sure
how controversial my approach would be, so I didn't want to put any
more work than was necessary for illustration without getting some
feedback.

> I think it would be good if this capability was not just on UML. I
> could also imagine wanting to run tests on real h/w. Perhaps you just

I think that's reasonable.

> want to log and/or check i/o accesses. Or you need some dependencies
> in place rather than trying to fake everything (clocks, gpios, pinmux,
> irq, etc.). That being said, I'm not trying to add a bunch of things
> for you to do. Though maybe it makes sense to split this series some.

Almost definitely. I figured this patchset, as is, is a good
illustration of what I am trying to do, what is possible, and the kind
of work that is necessary to get there. If people like what I am doing
and want more of this type of thing, I think focussing on getting base
support in and then working on features separately is the way to go.

> How many of the patches are needed to convert the DT unittests for
> example?

At first glance, just you probably only need the stuff in the first 9
patches for that. You don't appear to be doing any IO of any sort, so
you don't need this stuff. You appear to depend only on some fake
data; everything else seems pretty self contained, so you don't need
any of the mocking support for that. So if I understand correctly you
just need the base support needed for bare bones unit tests, all that
stuff is in the first 9 patches.

Cheers


Re: [RFC v1 22/31] kunit: mock: add the concept of spyable functions

2018-10-17 Thread Brendan Higgins
On Wed, Oct 17, 2018 at 3:47 PM Rob Herring  wrote:
>
> On Tue, Oct 16, 2018 at 6:54 PM Brendan Higgins
>  wrote:
> >
> > Adds the concept of spying like in Mockito
> > (http://static.javadoc.io/org.mockito/mockito-core/2.20.0/org/mockito/Mockito.html#spy-T-).
> > This allows a function declaration to be labled as spyable which allows
> > the function to be mocked *and* to allow the mock to invoke the original
> > function definition.
>
> We can already hook into arbitrary functions ftrace. Wouldn't
> utilizing that simplify features like this and avoid having to touch
> existing code for testing? Not sure what it would take to enable
> ftrace on UML. It is at least partially compiler dependent.

Regardless of what we end up doing, this definitely needs more work.

After looking at include/linux/ftrace.h, it does look feasible to use
ftrace for spying. I totally agree that we don't want to reinvent this
wheel if we can avoid it, but I have no idea what getting it working
on UML would look like. Dependence on compiler features could be an
issue: pretty much anyone who can build the kernel should be able to
run our tests.


Re: [RFC v1 00/31] kunit: Introducing KUnit, the Linux kernel unit testing framework

2018-10-17 Thread Brendan Higgins
On Wed, Oct 17, 2018 at 4:12 PM Randy Dunlap  wrote:
>
> On 10/16/18 4:50 PM, Brendan Higgins wrote:
> > This patch set proposes KUnit, a lightweight unit testing and mocking
> > framework for the Linux kernel.
>
> Hi,
>
> Just a general comment:
>
> Documentation/process/submitting-patches.rst says:
> < instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
> to do frotz", as if you are giving orders to the codebase to change
> its behaviour.>>
>

Thanks! I will fix this in the next revision.


[PATCH] MAINTAINERS: fix bad pattern in ARM/NUVOTON NPCM

2018-10-05 Thread Brendan Higgins
In the process of upstreaming architecture support for ARM/NUVOTON NPCM
include/dt-bindings/clock/nuvoton,npcm7xx-clks.h was renamed
include/dt-bindings/clock/nuvoton,npcm7xx-clock.h without updating
MAINTAINERS. This updates the MAINTAINERS pattern to match the new name
of this file.

Fixes: 6a498e06ba22 ("MAINTAINERS: Add entry for the Nuvoton NPCM architecture")
Reported-by: Joe Perches 
Signed-off-by: Brendan Higgins 
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 544cac829cf4..771378e82de8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1730,7 +1730,7 @@ L:open...@lists.ozlabs.org (moderated for 
non-subscribers)
 S: Supported
 F: arch/arm/mach-npcm/
 F: arch/arm/boot/dts/nuvoton-npcm*
-F: include/dt-bindings/clock/nuvoton,npcm7xx-clks.h
+F: include/dt-bindings/clock/nuvoton,npcm7xx-clock.h
 F: drivers/*/*npcm*
 F: Documentation/devicetree/bindings/*/*npcm*
 F: Documentation/devicetree/bindings/*/*/*npcm*
-- 
2.19.0.605.g01d371f741-goog



[RFC v2 12/14] kunit.py: improve output from python wrapper

2018-10-23 Thread Brendan Higgins
- add colors to displayed output
- add timing and summary

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 tools/testing/kunit/kunit.py| 20 ++-
 tools/testing/kunit/kunit_parser.py | 93 -
 2 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/tools/testing/kunit/kunit.py b/tools/testing/kunit/kunit.py
index 1356be404996b..b36c7b7924567 100755
--- a/tools/testing/kunit/kunit.py
+++ b/tools/testing/kunit/kunit.py
@@ -6,6 +6,7 @@
 import argparse
 import sys
 import os
+import time
 
 import kunit_config
 import kunit_kernel
@@ -24,17 +25,32 @@ parser.add_argument('--timeout', help='maximum number of 
seconds to allow for '
 cli_args = parser.parse_args()
 linux = kunit_kernel.LinuxSourceTree()
 
+config_start = time.time()
 success = linux.build_reconfig()
+config_end = time.time()
 if not success:
quit()
 
-print('Building KUnit Kernel ...')
+kunit_parser.print_with_timestamp('Building KUnit Kernel ...')
+
+build_start = time.time()
 success = linux.build_um_kernel()
+build_end = time.time()
 if not success:
quit()
 
-print('Starting KUnit Kernel ...')
+kunit_parser.print_with_timestamp('Starting KUnit Kernel ...')
+test_start = time.time()
+
 if cli_args.raw_output:
kunit_parser.raw_output(linux.run_kernel(timeout=cli_args.timeout))
 else:
kunit_parser.parse_run_tests(linux.run_kernel(timeout=cli_args.timeout))
+
+test_end = time.time()
+
+kunit_parser.print_with_timestamp((
+   "Elapsed time: %.3fs total, %.3fs configuring, %.3fs " +
+   "building, %.3fs running.\n") % (test_end - config_start,
+   config_end - config_start, build_end - build_start,
+   test_end - test_start))
diff --git a/tools/testing/kunit/kunit_parser.py 
b/tools/testing/kunit/kunit_parser.py
index 1dff3adb73bd3..d9051e407d5a7 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 import re
+from datetime import datetime
 
 kunit_start_re = re.compile('console .* enabled')
 kunit_end_re = re.compile('List of all partitions:')
@@ -19,6 +20,94 @@ def raw_output(kernel_output):
for line in kernel_output:
print(line)
 
+DIVIDER = "=" * 30
+
+RESET = '\033[0;0m'
+
+def red(text):
+   return '\033[1;31m' + text + RESET
+
+def yellow(text):
+   return '\033[1;33m' + text + RESET
+
+def green(text):
+   return '\033[1;32m' + text + RESET
+
+def print_with_timestamp(message):
+   print('[%s] %s' % (datetime.now().strftime('%H:%M:%S'), message))
+
+def print_log(log):
+   for m in log:
+   print_with_timestamp(m)
+
 def parse_run_tests(kernel_output):
-   for output in isolate_kunit_output(kernel_output):
-   print(output)
+   test_case_output = re.compile('^kunit .*?: (.*)$')
+
+   test_module_success = re.compile('^kunit .*: all tests passed')
+   test_module_fail = re.compile('^kunit .*: one or more tests failed')
+
+   test_case_success = re.compile('^kunit (.*): (.*) passed')
+   test_case_fail = re.compile('^kunit (.*): (.*) failed')
+   test_case_crash = re.compile('^kunit (.*): (.*) crashed')
+
+   total_tests = set()
+   failed_tests = set()
+   crashed_tests = set()
+
+   def get_test_name(match):
+   return match.group(1) + ":" + match.group(2)
+
+   current_case_log = []
+   def end_one_test(match, log):
+   log.clear()
+   total_tests.add(get_test_name(match))
+
+   print_with_timestamp(DIVIDER)
+   for line in isolate_kunit_output(kernel_output):
+   # Ignore module output:
+   if (test_module_success.match(line) or
+   test_module_fail.match(line)):
+   print_with_timestamp(DIVIDER)
+   continue
+
+   match = re.match(test_case_success, line)
+   if match:
+   print_with_timestamp(green("[PASSED] ") +
+get_test_name(match))
+   end_one_test(match, current_case_log)
+   continue
+
+   match = re.match(test_case_fail, line)
+   # Crashed tests will report as both failed and crashed. We only
+   # want to show and count it once.
+   if match and get_test_name(match) not in crashed_tests:
+   failed_tests.add(get_test_name(match))
+   print_with_timestamp(red("[FAILED] " +
+get_test_name(match)))
+   print_log(map(yellow, current_case_log))
+

[RFC v2 01/14] kunit: test: add KUnit test runner core

2018-10-23 Thread Brendan Higgins
Add core facilities for defining unit tests; this provides a common way
to define test cases, functions that execute code which is under test
and determine whether the code under test behaves as expected; this also
provides a way to group together related test cases in test suites (here
we call them test_modules).

Just define test cases and how to execute them for now; setting
expectations on code will be defined later.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 165 ++
 kunit/Kconfig|  17 +
 kunit/Makefile   |   1 +
 kunit/test.c | 168 +++
 4 files changed, 351 insertions(+)
 create mode 100644 include/kunit/test.h
 create mode 100644 kunit/Kconfig
 create mode 100644 kunit/Makefile
 create mode 100644 kunit/test.c

diff --git a/include/kunit/test.h b/include/kunit/test.h
new file mode 100644
index 0..e0b14b227ac44
--- /dev/null
+++ b/include/kunit/test.h
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Base unit test (KUnit) API.
+ *
+ * Copyright (C) 2018, Google LLC.
+ * Author: Brendan Higgins 
+ */
+
+#ifndef _KUNIT_TEST_H
+#define _KUNIT_TEST_H
+
+#include 
+#include 
+
+struct test;
+
+/**
+ * struct test_case - represents an individual test case.
+ * @run_case: the function representing the actual test case.
+ * @name: the name of the test case.
+ *
+ * A test case is a function with the signature, ``void (*)(struct test *)``
+ * that makes expectations (see TEST_EXPECT_TRUE()) about code under test. Each
+ * test case is associated with a &struct test_module and will be run after the
+ * module's init function and followed by the module's exit function.
+ *
+ * A test case should be static and should only be created with the TEST_CASE()
+ * macro; additionally, every array of test cases should be terminated with an
+ * empty test case.
+ *
+ * Example:
+ *
+ * .. code-block:: c
+ *
+ * void add_test_basic(struct test *test)
+ * {
+ * TEST_EXPECT_EQ(test, 1, add(1, 0));
+ * TEST_EXPECT_EQ(test, 2, add(1, 1));
+ * TEST_EXPECT_EQ(test, 0, add(-1, 1));
+ * TEST_EXPECT_EQ(test, INT_MAX, add(0, INT_MAX));
+ * TEST_EXPECT_EQ(test, -1, add(INT_MAX, INT_MIN));
+ * }
+ *
+ * static struct test_case example_test_cases[] = {
+ * TEST_CASE(add_test_basic),
+ * {},
+ * };
+ *
+ */
+struct test_case {
+   void (*run_case)(struct test *test);
+   const char name[256];
+
+   /* private: internal use only. */
+   bool success;
+};
+
+/**
+ * TEST_CASE - A helper for creating a &struct test_case
+ * @test_name: a reference to a test case function.
+ *
+ * Takes a symbol for a function representing a test case and creates a &struct
+ * test_case object from it. See the documentation for &struct test_case for an
+ * example on how to use it.
+ */
+#define TEST_CASE(test_name) { .run_case = test_name, .name = #test_name }
+
+/**
+ * struct test_module - describes a related collection of &struct test_case s.
+ * @name: the name of the test. Purely informational.
+ * @init: called before every test case.
+ * @exit: called after every test case.
+ * @test_cases: a null terminated array of test cases.
+ *
+ * A test_module is a collection of related &struct test_case s, such that
+ * @init is called before every test case and @exit is called after every test
+ * case, similar to the notion of a *test fixture* or a *test class* in other
+ * unit testing frameworks like JUnit or Googletest.
+ *
+ * Every &struct test_case must be associated with a test_module for KUnit to
+ * run it.
+ */
+struct test_module {
+   const char name[256];
+   int (*init)(struct test *test);
+   void (*exit)(struct test *test);
+   struct test_case *test_cases;
+};
+
+/**
+ * struct test - represents a running instance of a test.
+ * @priv: for user to store arbitrary data. Commonly used to pass data created
+ * in the init function (see &struct test_module).
+ *
+ * Used to store information about the current context under which the test is
+ * running. Most of this data is private and should only be accessed indirectly
+ * via public functions; the one exception is @priv which can be used by the
+ * test writer to store arbitrary data.
+ */
+struct test {
+   void *priv;
+
+   /* private: internal use only. */
+   const char *name; /* Read only after initialization! */
+   spinlock_t lock; /* Gaurds all mutable test state. */
+   bool success; /* Protected by lock. */
+   void (*vprintk)(const struct test *test,
+   const char *level,
+   struct va_format *vaf);
+};
+
+int test_init_test(struct test *test, const char *name);
+
+int test_run_tests(struct test_module *module);
+
+/**
+ * module_test() - used to register a &struct test_module with KUni

[RFC v2 05/14] kunit: test: add the concept of expectations

2018-10-23 Thread Brendan Higgins
Add support for expectations, which allow properties to be specified and
then verified in tests.

Signed-off-by: Brendan Higgins 
---
 include/kunit/test.h | 259 +++
 1 file changed, 259 insertions(+)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 68320fa2452de..d652825d7296f 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -273,4 +273,263 @@ void __printf(3, 4) test_printk(const char *level,
 #define test_err(test, fmt, ...) \
test_printk(KERN_ERR, test, fmt, ##__VA_ARGS__)
 
+static inline struct test_stream *test_expect_start(struct test *test,
+   const char *file,
+   const char *line)
+{
+   struct test_stream *stream = test_new_stream(test);
+
+   stream->add(stream, "EXPECTATION FAILED at %s:%s\n\t", file, line);
+
+   return stream;
+}
+
+static inline void test_expect_end(struct test *test,
+  bool success,
+  struct test_stream *stream)
+{
+   if (!success)
+   test->fail(test, stream);
+   else
+   stream->clear(stream);
+}
+
+#define TEST_EXPECT_START(test) \
+   test_expect_start(test, __FILE__, __stringify(__LINE__))
+
+#define TEST_EXPECT_END(test, success, stream) \
+   test_expect_end(test, success, stream)
+
+#define TEST_EXPECT(test, success, message) do {  \
+   struct test_stream *__stream = TEST_EXPECT_START(test);\
+  \
+   __stream->add(__stream, message);  \
+   TEST_EXPECT_END(test, success, __stream);  \
+} while (0)
+
+/**
+ * TEST_SUCCEED() - A no-op expectation. Only exists for code clarity.
+ * @test: The test context object.
+ *
+ * The opposite of TEST_FAIL(), it is an expectation that cannot fail. In other
+ * words, it does nothing and only exists for code clarity. See
+ * TEST_EXPECT_TRUE() for more information.
+ */
+#define TEST_SUCCEED(test) do {} while (0)
+
+/**
+ * TEST_FAIL() - Always causes a test to fail when evaluated.
+ * @test: The test context object.
+ * @message: an informational message to be printed when the assertion is made.
+ *
+ * The opposite of TEST_SUCCEED(), it is an expectation that always fails. In
+ * other words, it always results in a failed expectation, and consequently
+ * always causes the test case to fail when evaluated. See TEST_EXPECT_TRUE()
+ * for more information.
+ */
+#define TEST_FAIL(test, message) TEST_EXPECT(test, false, message)
+
+/**
+ * TEST_EXPECT_TRUE() - Causes a test failure when the expression is not true.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails when this does
+ * not evaluate to true.
+ *
+ * This and expectations of the form `TEST_EXPECT_*` will cause the test case 
to
+ * fail when the specified condition is not met; however, it will not prevent
+ * the test case from continuing to run; this is otherwise known as an
+ * *expectation failure*.
+ */
+#define TEST_EXPECT_TRUE(test, condition) \
+   TEST_EXPECT(test, (condition), \
+  "Expected " #condition " is true, but is false.")
+
+/**
+ * TEST_EXPECT_FALSE() - Causes a test failure when the expression is not 
false.
+ * @test: The test context object.
+ * @condition: an arbitrary boolean expression. The test fails when this does
+ * not evaluate to false.
+ *
+ * Sets an expectation that @condition evaluates to false. See
+ * TEST_EXPECT_TRUE() for more information.
+ */
+#define TEST_EXPECT_FALSE(test, condition)\
+   TEST_EXPECT(test, !(condition),\
+  "Expected " #condition " is false, but is true.")
+
+static inline void test_expect_binary(struct test *test,
+ long long left, const char *left_name,
+ long long right, const char *right_name,
+ bool compare_result,
+ const char *compare_name,
+ const char *file,
+ const char *line)
+{
+   struct test_stream *stream = test_expect_start(test, file, line);
+
+   stream->add(stream,
+   "Expected %s %s %s, but\n",
+   left_name, compare_name, right_name);
+   stream->add(stream, "\t\t%s == %lld\n", left_name, left);
+   stream->add(stream, "\t\t%s == %lld", right_name, right);
+
+   test_exp

[RFC v2 10/14] kunit: add Python libraries for handing KUnit config and kernel

2018-10-23 Thread Brendan Higgins
The ultimate goal is to create minimal isolated test binaries; in the
meantime we are using UML to provide the infrastructure to run tests, so
define an abstract way to configure and run tests that allow us to
change the context in which tests are built without affecting the user.
This also makes pretty and dynamic error reporting, and a lot of other
nice features easier.

kunit_config.py:
  - parse .config and Kconfig files.

kunit_kernel.py: provides helper functions to:
  - configure the kernel using kunitconfig.
  - build the kernel with the appropriate configuration.
  - provide function to invoke the kernel and stream the output back.

Signed-off-by: Felix Guo 
Signed-off-by: Brendan Higgins 
---
 tools/testing/kunit/.gitignore  |   3 +
 tools/testing/kunit/kunit_config.py |  60 ++
 tools/testing/kunit/kunit_kernel.py | 123 
 3 files changed, 186 insertions(+)
 create mode 100644 tools/testing/kunit/.gitignore
 create mode 100644 tools/testing/kunit/kunit_config.py
 create mode 100644 tools/testing/kunit/kunit_kernel.py

diff --git a/tools/testing/kunit/.gitignore b/tools/testing/kunit/.gitignore
new file mode 100644
index 0..c791ff59a37a9
--- /dev/null
+++ b/tools/testing/kunit/.gitignore
@@ -0,0 +1,3 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
\ No newline at end of file
diff --git a/tools/testing/kunit/kunit_config.py 
b/tools/testing/kunit/kunit_config.py
new file mode 100644
index 0..183bd5e758762
--- /dev/null
+++ b/tools/testing/kunit/kunit_config.py
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0
+
+import collections
+import re
+
+CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_\w+ is not set$'
+CONFIG_PATTERN = r'^CONFIG_\w+=\S+$'
+
+KconfigEntryBase = collections.namedtuple('KconfigEntry', ['raw_entry'])
+
+
+class KconfigEntry(KconfigEntryBase):
+
+   def __str__(self) -> str:
+   return self.raw_entry
+
+
+class KconfigParseError(Exception):
+   """Error parsing Kconfig defconfig or .config."""
+
+
+class Kconfig(object):
+   """Represents defconfig or .config specified using the Kconfig 
language."""
+
+   def __init__(self):
+   self._entries = []
+
+   def entries(self):
+   return set(self._entries)
+
+   def add_entry(self, entry: KconfigEntry) -> None:
+   self._entries.append(entry)
+
+   def is_subset_of(self, other: "Kconfig") -> bool:
+   return self.entries().issubset(other.entries())
+
+   def write_to_file(self, path: str) -> None:
+   with open(path, 'w') as f:
+   for entry in self.entries():
+   f.write(str(entry) + '\n')
+
+   def parse_from_string(self, blob: str) -> None:
+   """Parses a string containing KconfigEntrys and populates this 
Kconfig."""
+   self._entries = []
+   is_not_set_matcher = re.compile(CONFIG_IS_NOT_SET_PATTERN)
+   config_matcher = re.compile(CONFIG_PATTERN)
+   for line in blob.split('\n'):
+   line = line.strip()
+   if not line:
+   continue
+   elif config_matcher.match(line) or 
is_not_set_matcher.match(line):
+   self._entries.append(KconfigEntry(line))
+   elif line[0] == '#':
+   continue
+   else:
+   raise KconfigParseError('Failed to parse: ' + 
line)
+
+   def read_from_file(self, path: str) -> None:
+   with open(path, 'r') as f:
+   self.parse_from_string(f.read())
diff --git a/tools/testing/kunit/kunit_kernel.py 
b/tools/testing/kunit/kunit_kernel.py
new file mode 100644
index 0..87abaede50513
--- /dev/null
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: GPL-2.0
+
+import logging
+import subprocess
+import os
+
+import kunit_config
+
+KCONFIG_PATH = '.config'
+
+class ConfigError(Exception):
+   """Represents an error trying to configure the Linux kernel."""
+
+
+class BuildError(Exception):
+   """Represents an error trying to build the Linux kernel."""
+
+
+class LinuxSourceTreeOperations(object):
+   """An abstraction over command line operations performed on a source 
tree."""
+
+   def make_mrproper(self):
+   try:
+   subprocess.check_output(['make', 'mrproper'])
+   except OSError as e:
+   raise Con

Re: [PATCH] i2c: aspeed: Acknowledge most interrupts early in interrupt handler

2018-09-17 Thread Brendan Higgins
On Mon, Sep 17, 2018 at 6:11 PM Joel Stanley  wrote:
>
> On Fri, 14 Sep 2018 at 13:00, Guenter Roeck  wrote:
> >
> > Commit 3e9efc3299dd ("i2c: aspeed: Handle master/slave combined irq events
> > properly") moved interrupt acknowledgment to the end of the interrupt
> > handler. In part this was done because the AST2500 datasheet says:
> >
> >  I2CD10 Interrupt Status Register
> >bit 2 Receive Done Interrupt status
> >  S/W needs to clear this status bit to allow next data receiving.
> >
> > Acknowledging Receive Done before receive data was handled resulted in
> > receive errors on high speed I2C busses.
> >
> > However, interrupt acknowledgment was not only moved to the end of the
> > interrupt handler for Receive Done Interrupt status, but for all interrupt
> > status bits. This could result in race conditions if a second interrupt was
> > received during interrupt handling and not handled but still acknowledged
> > at the end of the interrupt handler.
> >
> > Acknowledge only "Receive Done Interrupt status" late in the interrupt
> > handler to solve the problem.
> >
> > Fixes: 3e9efc3299dd ("i2c: aspeed: Handle master/slave combined irq events 
> > properly")
> > Cc: Jae Hyun Yoo 
> > Cc: Joel Stanley 
> > Signed-off-by: Guenter Roeck 
>
> Thanks for getting to the bottom of this Guenter. I gave it a spin on
> Romulus (ast2500) and Palmetto (ast2400) without issue.
>
> Tested-by: Joel Stanley 
>

Nice work! Thanks!

Acked-by: Brendan Higgins 


Re: [PATCH] Documentation: kunit: add tips for using current->kunit_test

2021-04-07 Thread Brendan Higgins
On Tue, Apr 6, 2021 at 3:51 PM Daniel Latypov  wrote:
>
> As of commit 359a376081d4 ("kunit: support failure from dynamic analysis
> tools"), we can use current->kunit_test to find the current kunit test.
>
> Mention this in tips.rst and give an example of how this can be used in
> conjunction with `test->priv` to pass around state and specifically
> implement something like mocking.
> There's a lot more we could go into on that topic, but given that
> example is already longer than every other "tip" on this page, we just
> point to the API docs and leave filling in the blanks as an exercise to
> the reader.
>
> Also give an example of kunit_fail_current_test().
>
> Signed-off-by: Daniel Latypov 

Reviewed-by: Brendan Higgins 


Re: [PATCH v3 1/2] kunit: add a KUnit test for SLUB debugging functionality

2021-04-09 Thread Brendan Higgins
On Thu, Apr 8, 2021 at 10:19 AM Daniel Latypov  wrote:
>
> On Thu, Apr 8, 2021 at 3:30 AM Marco Elver  wrote:
> >
> > On Tue, 6 Apr 2021 at 12:57, Vlastimil Babka  wrote:
> > >
> > >
> > > On 4/1/21 11:24 PM, Marco Elver wrote:
> > > > On Thu, 1 Apr 2021 at 21:04, Daniel Latypov  wrote:
> > > >> > }
> > > >> > #else
> > > >> > static inline bool slab_add_kunit_errors(void) { return 
> > > >> > false; }
> > > >> > #endif
> > > >> >
> > > >> > And anywhere you want to increase the error count, you'd call
> > > >> > slab_add_kunit_errors().
> > > >> >
> > > >> > Another benefit of this approach is that if KUnit is disabled, there 
> > > >> > is
> > > >> > zero overhead and no additional code generated (vs. the current
> > > >> > approach).
> > > >>
> > > >> The resource approach looks really good, but...
> > > >> You'd be picking up a dependency on
> > > >> https://lore.kernel.org/linux-kselftest/20210311152314.3814916-2-dlaty...@google.com/
> > > >> current->kunit_test will always be NULL unless CONFIG_KASAN=y &&
> > > >> CONFIG_KUNIT=y at the moment.
> > > >> My patch drops the CONFIG_KASAN requirement and opens it up to all 
> > > >> tests.
> > > >
> > > > Oh, that's a shame, but hopefully it'll be in -next soon.
> > > >
> > > >> At the moment, it's just waiting another look over from Brendan or 
> > > >> David.
> > > >> Any ETA on that, folks? :)
> > > >>
> > > >> So if you don't want to get blocked on that for now, I think it's fine 
> > > >> to add:
> > > >>   #ifdef CONFIG_SLUB_KUNIT_TEST
> > > >>   int errors;
> > > >>   #endif
> > > >
> > > > Until kunit fixes setting current->kunit_test, a cleaner workaround
> > > > that would allow to do the patch with kunit_resource, is to just have
> > > > an .init/.exit function that sets it ("current->kunit_test = test;").
> > > > And then perhaps add a note ("FIXME: ...") to remove it once the above
> > > > patch has landed.
> > > >
> > > > At least that way we get the least intrusive change for mm/slub.c, and
> > > > the test is the only thing that needs a 2-line patch to clean up
> > > > later.
> > >
> > > So when testing internally Oliver's new version with your suggestions 
> > > (thanks
> > > again for those), I got lockdep splats because slab_add_kunit_errors is 
> > > called
> > > also from irq disabled contexts, and kunit_find_named_resource will call
> > > spin_lock(&test->lock) that's not irq safe. Can we make the lock irq 
> > > safe? I
> > > tried the change below and it makde the problem go away. If you agree, the
> > > question is how to proceed - make it part of Oliver's patch series and let
> > > Andrew pick it all with eventually kunit team's acks on this patch, or 
> > > whatnot.
> >
> > From what I can tell it should be fine to make it irq safe (ack for
> > your patch below). Regarding patch logistics, I'd probably add it to
> > the series. If that ends up not working, we'll find out sooner or
> > later.
> >
> > (FYI, the prerequisite patch for current->kunit_test is in -next now.)
>
> Yep.
> There's also two follow-up patches in
> https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git/log/?h=kunit
>
> >
> > KUnit maintainers, do you have any preferences?
>
> Poked offline and Brendan and David seemed fine either way.
> So probably just include it in this patch series for convenience.
>
> Brendan also mentioned KUnit used to use spin_lock_irqsave/restore()
> but had been told to not use it until necessary.
> See 
> https://lore.kernel.org/linux-kselftest/20181016235120.138227-3-brendanhigg...@google.com/
> So I think there's no objections to the patch itself either.
>
> But I'd wait for Brendan to chime in to confirm.

That's correct. Before KUnit was accepted upstream, early versions of
the patchset used the irqsave/restore versions. I was asked to remove
them until they were necessary, and it looks like that time is now :-)

So yes, I would be happy to see this patch go in. Looks good to me the
way you have it below. Send it out as its own patch in your series and
I will give it a Reviewed-by.

Thanks!

> > > 8<
> > >
> > > commit ab28505477892e9824c57ac338c88aec2ec0abce
> > > Author: Vlastimil Babka 
> > > Date:   Tue Apr 6 12:28:07 2021 +0200
> > >
> > > kunit: make test->lock irq safe
> > >
> > > diff --git a/include/kunit/test.h b/include/kunit/test.h
> > > index 49601c4b98b8..524d4789af22 100644
> > > --- a/include/kunit/test.h
> > > +++ b/include/kunit/test.h
> > > @@ -515,8 +515,9 @@ kunit_find_resource(struct kunit *test,
> > > void *match_data)
> > >  {
> > > struct kunit_resource *res, *found = NULL;
> > > +   unsigned long flags;
> > >
> > > -   spin_lock(&test->lock);
> > > +   spin_lock_irqsave(&test->lock, flags);
> > >
> > > list_for_each_entry_reverse(res, &test->resources, node) {
> > > if (match(test, res, (void *)match_data)) {
> > > @@ -526,7 +527,7 @@ kunit_find_resource(struct kunit *test,
> >

Re: [RFC v3 17/19] of: unittest: migrate tests to run on KUnit

2019-02-27 Thread Brendan Higgins
On Mon, Feb 18, 2019 at 2:56 PM Frank Rowand  wrote:
>
> On 2/12/19 5:44 PM, Brendan Higgins wrote:
> > On Wed, Nov 28, 2018 at 12:56 PM Rob Herring  wrote:
> >>
> >> On Wed, Nov 28, 2018 at 1:38 PM Brendan Higgins
> >>  wrote:

> >>> ---
> >>>  drivers/of/Kconfig|1 +
> >>>  drivers/of/unittest.c | 1405 ++---
> >>>  2 files changed, 752 insertions(+), 654 deletions(-)
> >>>
> > 
> >>> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
> >>> index 41b49716ac75f..a5ef44730ffdb 100644
> >>> --- a/drivers/of/unittest.c
> >>> +++ b/drivers/of/unittest.c

> >>> +
> >>> +   KUNIT_EXPECT_EQ(test,
> >>> +   of_property_match_string(np,
> >>> +"phandle-list-names",
> >>> +"first"),
> >>> +   0);
> >>> +   KUNIT_EXPECT_EQ(test,
> >>> +   of_property_match_string(np,
> >>> +"phandle-list-names",
> >>> +"second"),
> >>> +   1);
> >>
> >> Fewer lines on these would be better even if we go over 80 chars.
>
> Agreed.  unittest.c already is a greater than 80 char file in general, and
> is a file that benefits from that.
>

Noted.

>
> > On the of_property_match_string(...), I have no opinion. I will do
> > whatever you like best.
> >
> > Nevertheless, as far as the KUNIT_EXPECT_*(...), I do have an opinion: I am
> > trying to establish a good, readable convention. Given an expect statement
> > structured as
> > ```
> > KUNIT_EXPECT_*(
> > test,
> > expect_arg_0, ..., expect_arg_n,
> > fmt_str, fmt_arg_0, ..., fmt_arg_n)
> > ```
> > where `test` is the `struct kunit` context argument, `expect_arg_{0, ..., 
> > n}`
> > are the arguments the expectations is being made about (so in the above 
> > example,
> > `of_property_match_string(...)` and `1`), and `fmt_*` is the optional format
> > string that comes at the end of some expectations.
> >
> > The pattern I had been trying to promote is the following:
> >
> > 1) If everything fits on 1 line, do that.
> > 2) If you must make a line split, prefer to keep `test` on its own line,
> > `expect_arg_{0, ..., n}` should be kept together, if possible, and the 
> > format
> > string should follow the conventions already most commonly used with format
> > strings.
> > 3) If you must split up `expect_arg_{0, ..., n}` each argument should get 
> > its
> > own line and should not share a line with either `test` or any `fmt_*`.
> >
> > The reason I care about this so much is because expectations should be
> > extremely easy to read; they are the most important part of a unit
> > test because they tell you what the test is verifying. I am not
> > married to the formatting I proposed above, but I want something that
> > will be extremely easy to identify the arguments that the expectation
> > is on. Maybe that means that I need to add some syntactic fluff to
> > make it clearer, I don't know, but this is definitely something we
> > need to get right, especially in the earliest examples.
>
> I will probably raise the ire of the kernel formatting rule makers by offering
> what I think is a _much_ more readable format __for this specific case__.
> In other words for drivers/of/unittest.c.
>
> If you can not make your mail window _very_ wide, or if this email has been
> line wrapped, this example will not be clear.
>
> Two possible formats:
>
>
> ### -  version 1, as created by the patch series
>
> static void of_unittest_property_string(struct kunit *test)
> {
> const char *strings[4];
> struct device_node *np;
> int rc;
>
> np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
> KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np);
>
> KUNIT_EXPECT_EQ(
> test,
> of_property_match_string(np, "phandle-list-names", "first"),
> 0);
> KUNIT_EXPECT_EQ(
> test,
> of_property_match_string(np, "phandle-list-names", "second"),
> 1);
> KUNIT_EXPECT_EQ(
>   

Re: [RFC v3 18/19] of: unittest: split out a couple of test cases from unittest

2019-02-27 Thread Brendan Higgins
On Wed, Feb 20, 2019 at 12:45 PM Frank Rowand  wrote:
>
> On 2/18/19 2:25 PM, Frank Rowand wrote:
> > On 2/15/19 2:56 AM, Brendan Higgins wrote:
> >> On Thu, Feb 14, 2019 at 6:05 PM Frank Rowand  
> >> wrote:
> >>>
> >>> On 2/14/19 4:56 PM, Brendan Higgins wrote:
> >>>> On Thu, Feb 14, 2019 at 3:57 PM Frank Rowand  
> >>>> wrote:
> >>>>>
> >>>>> On 12/5/18 3:54 PM, Brendan Higgins wrote:
> >>>>>> On Tue, Dec 4, 2018 at 2:58 AM Frank Rowand  
> >>>>>> wrote:
> >>>>>>>
>
> < snip >
>
> >
> > It makes it harder for me to read the source of the tests and
> > understand the order they will execute.  It also makes it harder
> > for me to read through the actual tests (in this example the
> > tests that are currently grouped in of_unittest_find_node_by_name())
> > because of all the extra function headers injected into the
> > existing single function to break it apart into many smaller
> > functions.
>
> < snip >
>
> >>>> This is not something I feel particularly strongly about, it is just
> >>>> pretty atypical from my experience to have so many unrelated test
> >>>> cases in a single file.
> >>>>
> >>>> Maybe you would prefer that I break up the test cases first, and then
> >>>> we split up the file as appropriate?
> >>>
> >>> I prefer that the test cases not be broken up arbitrarily.  There _may_
>
> I expect that I created confusion by putting this in a reply to patch 18/19.
> It is actually a comment about patch 19/19.  Sorry about that.
>

No worries.

>
> >>
> >> I wasn't trying to break them up arbitrarily. I thought I was doing it
> >> according to a pattern (breaking up the file, that is), but maybe I
> >> just hadn't looked at enough examples.
> >
> > This goes back to the kunit model of putting each test into a separate
> > function that can be a KUNIT_CASE().  That is a model that I do not agree
> > with for devicetree.
>
> So now that I am actually talking about patch 19/19, let me give a concrete
> example.  I will cut and paste (after my comments), the beginning portion
> of base-test.c, after applying patch 19/19 (the "base version".  Then I
> will cut and paste my alternative version which does not break the tests
> down into individual functions (the "frank version").

Awesome, thanks for putting the comparison together!

>
> I will also reply to this email with the base version and the frank version
> as attachments, which will make it easier to save as separate versions
> for easier viewing.  I'm not sure if an email with attachments will make
> it through the list servers, but I am cautiously optimistic.
>
> I am using v4 of the patch series because I never got v3 to cleanly apply
> and it is not a constructive use of my time to do so since I have v4 applied.
>
> One of the points I was trying to make is that readability suffers from the
> approach taken by patches 18/19 and 19/19.

I understood that point.

>
> The base version contains the extra text of a function header for each
> unit test.  This is visual noise and makes the file larger.  It is also
> one more possible location of an error (although not likely).

I don't see how it is much more visual noise than a comment.
Admittedly, a space versus an underscore might be nice, but I think it
is also more likely that a function name is more likely to be kept up
to date than a comment even if they are both informational. It also
forces the user to actually name all the tests. Even then, I am not
married to doing it this exact way. The thing I really care about is
isolating the code in each test case so that it can be executed
separately.

A side thought, when I was proofreading this, it occurred to me that
you might not like the function name over comment partly because you
think about them differently. You aren't used to seeing a function
used to frame things or communicate information in this way. Is this
true? Admittedly, I have gotten used to a lot of unit test frameworks
that break up test cases by function, so I wondering if part of the
difference in comfortability with this framing might come from the
fact that I am really used to seeing it this way and you are not? If
this is the case, maybe it would be better if we had something like:

KUNIT_DECLARE_CASE(case_id, "Test case description")
{
KUNIT_EXPECT_EQ(kunit, ...);
...
}

Just a thought.

>
> The frank version has converted each of the new function headers into
> a comment, using the f

Re: [RFC v4 00/17] kunit: introduce KUnit, the Linux kernel unit testing framework

2019-02-27 Thread Brendan Higgins
On Tue, Feb 19, 2019 at 10:46 PM Frank Rowand  wrote:
>
> On 2/19/19 10:34 PM, Brendan Higgins wrote:
> > On Mon, Feb 18, 2019 at 12:02 PM Frank Rowand  
> > wrote:
> > 
> >> I have not read through the patches in any detail.  I have read some of
> >> the code to try to understand the patches to the devicetree unit tests.
> >> So that may limit how valid my comments below are.
> >
> > No problem.
> >
> >>
> >> I found the code difficult to read in places where it should have been
> >> much simpler to read.  Structuring the code in a pseudo object oriented
> >> style meant that everywhere in a code path that I encountered a dynamic
> >> function call, I had to go find where that dynamic function call was
> >> initialized (and being the cautious person that I am, verify that
> >> no where else was the value of that dynamic function call).  With
> >> primitive vi and tags, that search would have instead just been a
> >> simple key press (or at worst a few keys) if hard coded function
> >> calls were done instead of dynamic function calls.  In the code paths
> >> that I looked at, I did not see any case of a dynamic function being
> >> anything other than the value it was originally initialized as.
> >> There may be such cases, I did not read the entire patch set.  There
> >> may also be cases envisioned in the architects mind of how this
> >> flexibility may be of future value.  Dunno.
> >
> > Yeah, a lot of it is intended to make architecture specific
> > implementations and some other future work easier. Some of it is also
> > for testing purposes. Admittedly some is for neither reason, but given
> > the heavy usage elsewhere, I figured there was no harm since it was
> > all private internal usage anyway.
> >
>
> Increasing the cost for me (and all the other potential code readers)
> to read the code is harm.

You are right. I like the object oriented C style; I didn't think it
hurt readability.

In any case, I will go through and replace instances where I am not
using it for one of the above reasons.


Re: [RFC v4 00/17] kunit: introduce KUnit, the Linux kernel unit testing framework

2019-02-27 Thread Brendan Higgins
On Fri, Feb 22, 2019 at 12:53 PM Thiago Jung Bauermann
 wrote:
>
>
> Frank Rowand  writes:
>
> > On 2/19/19 10:34 PM, Brendan Higgins wrote:
> >> On Mon, Feb 18, 2019 at 12:02 PM Frank Rowand  
> >> wrote:
> >> 
> >>> I have not read through the patches in any detail.  I have read some of
> >>> the code to try to understand the patches to the devicetree unit tests.
> >>> So that may limit how valid my comments below are.
> >>
> >> No problem.
> >>
> >>>
> >>> I found the code difficult to read in places where it should have been
> >>> much simpler to read.  Structuring the code in a pseudo object oriented
> >>> style meant that everywhere in a code path that I encountered a dynamic
> >>> function call, I had to go find where that dynamic function call was
> >>> initialized (and being the cautious person that I am, verify that
> >>> no where else was the value of that dynamic function call).  With
> >>> primitive vi and tags, that search would have instead just been a
> >>> simple key press (or at worst a few keys) if hard coded function
> >>> calls were done instead of dynamic function calls.  In the code paths
> >>> that I looked at, I did not see any case of a dynamic function being
> >>> anything other than the value it was originally initialized as.
> >>> There may be such cases, I did not read the entire patch set.  There
> >>> may also be cases envisioned in the architects mind of how this
> >>> flexibility may be of future value.  Dunno.
> >>
> >> Yeah, a lot of it is intended to make architecture specific
> >> implementations and some other future work easier. Some of it is also
> >> for testing purposes. Admittedly some is for neither reason, but given
> >> the heavy usage elsewhere, I figured there was no harm since it was
> >> all private internal usage anyway.
> >>
> >
> > Increasing the cost for me (and all the other potential code readers)
> > to read the code is harm.
>
> Dynamic function calls aren't necessary for arch-specific
> implementations either. See for example arch_kexec_image_load() in
> kernel/kexec_file.c, which uses a weak symbol that is overriden by
> arch-specific code. Not everybody likes weak symbols, so another
> alternative (which admitedly not everybody likes either) is to use a
> macro with the name of the arch-specific function, as used by
> arch_kexec_post_alloc_pages() in  for instance.

I personally have a strong preference for dynamic function calls over
weak symbols or macros, but I can change it if it really makes
anyone's eyes bleed.


Re: [RFC v4 08/17] kunit: test: add support for test abort

2019-02-27 Thread Brendan Higgins
On Tue, Feb 19, 2019 at 10:44 PM Frank Rowand  wrote:
>
> On 2/19/19 7:39 PM, Brendan Higgins wrote:
> > On Mon, Feb 18, 2019 at 11:52 AM Frank Rowand  
> > wrote:
> >>
> >> On 2/14/19 1:37 PM, Brendan Higgins wrote:
> >>> Add support for aborting/bailing out of test cases. Needed for
> >>> implementing assertions.
> >>>
> >>> Signed-off-by: Brendan Higgins 
> >>> ---
> >>> Changes Since Last Version
> >>>  - This patch is new introducing a new cross-architecture way to abort
> >>>out of a test case (needed for KUNIT_ASSERT_*, see next patch for
> >>>details).
> >>>  - On a side note, this is not a complete replacement for the UML abort
> >>>mechanism, but covers the majority of necessary functionality. UML
> >>>architecture specific featurs have been dropped from the initial
> >>>patchset.
> >>> ---
> >>>  include/kunit/test.h |  24 +
> >>>  kunit/Makefile   |   3 +-
> >>>  kunit/test-test.c| 127 ++
> >>>  kunit/test.c | 208 +--
> >>>  4 files changed, 353 insertions(+), 9 deletions(-)
> >>>  create mode 100644 kunit/test-test.c
> >>
> >> < snip >
> >>
> >>> diff --git a/kunit/test.c b/kunit/test.c
> >>> index d18c50d5ed671..6e5244642ab07 100644
> >>> --- a/kunit/test.c
> >>> +++ b/kunit/test.c
> >>> @@ -6,9 +6,9 @@
> >>>   * Author: Brendan Higgins 
> >>>   */
> >>>
> >>> -#include 
> >>>  #include 
> >>> -#include 
> >>> +#include 
> >>> +#include 
> >>>  #include 
> >>>
> >>>  static bool kunit_get_success(struct kunit *test)
> >>> @@ -32,6 +32,27 @@ static void kunit_set_success(struct kunit *test, bool 
> >>> success)
> >>>   spin_unlock_irqrestore(&test->lock, flags);
> >>>  }
> >>>
> >>> +static bool kunit_get_death_test(struct kunit *test)
> >>> +{
> >>> + unsigned long flags;
> >>> + bool death_test;
> >>> +
> >>> + spin_lock_irqsave(&test->lock, flags);
> >>> + death_test = test->death_test;
> >>> + spin_unlock_irqrestore(&test->lock, flags);
> >>> +
> >>> + return death_test;
> >>> +}
> >>> +
> >>> +static void kunit_set_death_test(struct kunit *test, bool death_test)
> >>> +{
> >>> + unsigned long flags;
> >>> +
> >>> + spin_lock_irqsave(&test->lock, flags);
> >>> + test->death_test = death_test;
> >>> + spin_unlock_irqrestore(&test->lock, flags);
> >>> +}
> >>> +
> >>>  static int kunit_vprintk_emit(const struct kunit *test,
> >>> int level,
> >>> const char *fmt,
> >>> @@ -70,13 +91,29 @@ static void kunit_fail(struct kunit *test, struct 
> >>> kunit_stream *stream)
> >>>   stream->commit(stream);
> >>>  }
> >>>
> >>> +static void __noreturn kunit_abort(struct kunit *test)
> >>> +{
> >>> + kunit_set_death_test(test, true);
> >>> +
> >>> + test->try_catch.throw(&test->try_catch);
> >>> +
> >>> + /*
> >>> +  * Throw could not abort from test.
> >>> +  */
> >>> + kunit_err(test, "Throw could not abort from test!");
> >>> + show_stack(NULL, NULL);
> >>> + BUG();
> >>
> >> kunit_abort() is what will be call as the result of an assert failure.
> >
> > Yep. Does that need clarified somewhere.
> >>
> >> BUG(), which is a panic, which is crashing the system is not acceptable
> >> in the Linux kernel.  You will just annoy Linus if you submit this.
> >
> > Sorry, I thought this was an acceptable use case since, a) this should
> > never be compiled in a production kernel, b) we are in a pretty bad,
> > unpredictable state if we get here and keep going. I think you might
> > have said elsewhere that you think "a" is not valid? In any case, I
> > can replace this with a WARN, would that be acceptable?
>
> A WARN may or may not make sense, depending on the conte

Re: [RFC v4 08/17] kunit: test: add support for test abort

2019-02-28 Thread Brendan Higgins
On Tue, Feb 26, 2019 at 12:35 PM Stephen Boyd  wrote:
>
> Quoting Brendan Higgins (2019-02-14 13:37:20)
> > Add support for aborting/bailing out of test cases. Needed for
> > implementing assertions.
>
> Can you add some more text here with the motivating reasons for
> implementing assertions and bailing out of test cases?

Sure. Yeah, this comes before the commit that adds assertions, so I
should probably put a better explanation here.
>
> For example, I wonder why unit tests can't just return with a failure

Well, you could. You can just do the check as you would without KUnit,
except call KUNIT_FAIL(...) before you return. For example, instead
of:

KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);

you could do:

if (IS_ERR_OR_NULL(ptr)) {
KUNIT_FAIL(test, "ptr is an errno or null: %ld", ptr);
return;
}

> when they need to abort and then the test runner would detect that error
> via the return value from the 'run test' function. That would be a more
> direct approach, but also more verbose than a single KUNIT_ASSERT()
> line. It would be more kernel idiomatic too because the control flow

Yeah, I was intentionally going against that idiom. I think that idiom
makes test logic more complicated than it needs to be, especially if
the assertion failure happens in a helper function; then you have to
pass that error all the way back up. It is important that test code
should be as simple as possible to the point of being immediately
obviously correct at first glance because there are no tests for
tests.

The idea with assertions is that you use them to state all the
preconditions for your test. Logically speaking, these are the
premises of the test case, so if a premise isn't true, there is no
point in continuing the test case because there are no conclusions
that can be drawn without the premises. Whereas, the expectation is
the thing you are trying to prove. It is not used universally in
x-unit style test frameworks, but I really like it as a convention.
You could still express the idea of a premise using the above idiom,
but I think KUNIT_ASSERT_* states the intended idea perfectly.

> isn't hidden inside a macro and it isn't intimately connected with
> kthreads and completions.

Yeah, I wasn't a fan of that myself, but it was broadly available. My
previous version (still the architecture specific version for UML, not
in this patchset though) relies on UML_LONGJMP, but is obviously only
works on UML. A number of people wanted support for other
architectures. Rob and Luis specifically wanted me to provide a
version of abort that would work on any architecture, even if it only
had reduced functionality; I thought this fit the bill okay.

>
> >
> > Signed-off-by: Brendan Higgins 
> [...]
> > diff --git a/kunit/test-test.c b/kunit/test-test.c
> > new file mode 100644
> > index 0..a936c041f1c8f
>
> Could this whole file be another patch? It seems to be a test for the
> try catch mechanism.

Sure.

>
> > diff --git a/kunit/test.c b/kunit/test.c
> > index d18c50d5ed671..6e5244642ab07 100644
> > --- a/kunit/test.c
> > +++ b/kunit/test.c
> [...]
> > +
> > +static void kunit_generic_throw(struct kunit_try_catch *try_catch)
> > +{
> > +   try_catch->context.try_result = -EFAULT;
> > +   complete_and_exit(try_catch->context.try_completion, -EFAULT);
> > +}
> > +
> > +static int kunit_generic_run_threadfn_adapter(void *data)
> > +{
> > +   struct kunit_try_catch *try_catch = data;
> >
> > +   try_catch->try(&try_catch->context);
> > +
> > +   complete_and_exit(try_catch->context.try_completion, 0);
>
> The exit code doesn't matter, right? If so, it might be clearer to just
> return 0 from this function because kthreads exit themselves as far as I
> recall.

You mean complete and then return?

>
> > +}
> > +
> > +static void kunit_generic_run_try_catch(struct kunit_try_catch *try_catch)
> > +{
> > +   struct task_struct *task_struct;
> > +   struct kunit *test = try_catch->context.test;
> > +   int exit_code, wake_result;
> > +   DECLARE_COMPLETION(test_case_completion);
>
> DECLARE_COMPLETION_ONSTACK()?

Whoops, yeah, that one.

>
> > +
> > +   try_catch->context.try_completion = &test_case_completion;
> > +   try_catch->context.try_result = 0;
> > +   task_struct = kthread_create(kunit_generic_run_threadfn_adapter,
> > +try_catch,
> > +"kunit_try_catch_thread");
> > +   if (IS_ERR_OR_NULL(task_struct)) {
>
> It looks like NULL is never returned fr

Re: Bad file pattern in MAINTAINERS section 'ARM/NUVOTON NPCM ARCHITECTURE'

2019-03-26 Thread Brendan Higgins
On Tue, Mar 26, 2019 at 5:11 AM Tomer Maimon  wrote:
>
> Hi Joe,
>
> Thanks for sending the notice.
>
> We will send a fix this week.
>
> Tomer
>
> On Mon, 25 Mar 2019 at 23:24, Joe Perches  wrote:
>>
>> A file pattern line in this section of the MAINTAINERS file in linux-next
>> does not have a match in the linux source files.

Hi Tomer,

Just thought I mentioned that I posted a fix here[1] sometime ago. The
patch should still apply cleanly.

On a side note, it would probably good to send a follow up patch that
removes me as a reviewer, and adds Benjamin Fair (CC'ed) as a
reviewer.

Cheers

[1] https://www.spinics.net/lists/kernel/msg2925741.html


Re: [PATCH v3 1/2] kunit: support failure from dynamic analysis tools

2021-02-11 Thread Brendan Higgins
On Thu, Feb 11, 2021 at 12:58 PM Daniel Latypov  wrote:
>
> On Thu, Feb 11, 2021 at 7:40 AM Alan Maguire  wrote:
> >
> > On Thu, 11 Feb 2021, David Gow wrote:
> >
> > > On Wed, Feb 10, 2021 at 6:14 AM Daniel Latypov  
> > > wrote:
> > > >
> > > > From: Uriel Guajardo 
> > > >
> > > > Add a kunit_fail_current_test() function to fail the currently running
> > > > test, if any, with an error message.
> > > >
> > > > This is largely intended for dynamic analysis tools like UBSAN and for
> > > > fakes.
> > > > E.g. say I had a fake ops struct for testing and I wanted my `free`
> > > > function to complain if it was called with an invalid argument, or
> > > > caught a double-free. Most return void and have no normal means of
> > > > signalling failure (e.g. super_operations, iommu_ops, etc.).
> > > >
> > > > Key points:
> > > > * Always update current->kunit_test so anyone can use it.
> > > >   * commit 83c4e7a0363b ("KUnit: KASAN Integration") only updated it for
> > > >   CONFIG_KASAN=y
> > > >
> > > > * Create a new header  so non-test code doesn't have
> > > > to include all of  (e.g. lib/ubsan.c)
> > > >
> > > > * Forward the file and line number to make it easier to track down
> > > > failures
> > > >
> > > > * Declare the helper function for nice __printf() warnings about 
> > > > mismatched
> > > > format strings even when KUnit is not enabled.
> > > >
> > > > Example output from kunit_fail_current_test("message"):
> > > > [15:19:34] [FAILED] example_simple_test
> > > > [15:19:34] # example_simple_test: initializing
> > > > [15:19:34] # example_simple_test: 
> > > > lib/kunit/kunit-example-test.c:24: message
> > > > [15:19:34] not ok 1 - example_simple_test
> > > >
> > > > Co-developed-by: Daniel Latypov 
> > > > Signed-off-by: Uriel Guajardo 
> > > > Signed-off-by: Daniel Latypov 
> > > > ---
> > > >  include/kunit/test-bug.h | 30 ++
> > > >  lib/kunit/test.c | 37 +
> > > >  2 files changed, 63 insertions(+), 4 deletions(-)
> > > >  create mode 100644 include/kunit/test-bug.h
> > > >
> > > > diff --git a/include/kunit/test-bug.h b/include/kunit/test-bug.h
> > > > new file mode 100644
> > > > index ..18b1034ec43a
> > > > --- /dev/null
> > > > +++ b/include/kunit/test-bug.h
> > > > @@ -0,0 +1,30 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > > +/*
> > > > + * KUnit API allowing dynamic analysis tools to interact with KUnit 
> > > > tests
> > > > + *
> > > > + * Copyright (C) 2020, Google LLC.
> > > > + * Author: Uriel Guajardo 
> > > > + */
> > > > +
> > > > +#ifndef _KUNIT_TEST_BUG_H
> > > > +#define _KUNIT_TEST_BUG_H
> > > > +
> > > > +#define kunit_fail_current_test(fmt, ...) \
> > > > +   __kunit_fail_current_test(__FILE__, __LINE__, fmt, 
> > > > ##__VA_ARGS__)
> > > > +
> > > > +#if IS_ENABLED(CONFIG_KUNIT)
> > >
> > > As the kernel test robot has pointed out on the second patch, this
> > > probably should be IS_BUILTIN(), otherwise this won't build if KUnit
> > > is a module, and the code calling it isn't.
> > >
> > > This does mean that things like UBSAN integration won't work if KUnit
> > > is a module, which is a shame.
> > >
> > > (It's worth noting that the KASAN integration worked around this by
> > > only calling inline functions, which would therefore be built-in even
> > > if the rest of KUnit was built as a module. I don't think it's quite
> > > as convenient to do that here, though.)
> > >
> >
> > Right, static inline'ing __kunit_fail_current_test() seems problematic
> > because it calls other exported functions; more below
> >
> > > > +
> > > > +extern __printf(3, 4) void __kunit_fail_current_test(const char *file, 
> > > > int line,
> > > > +   const char *fmt, 
> > > > ...);
> > > > +
> > > > +#else
> > > > +
> > > > +static __printf(3, 4) void __kunit_fail_current_test(const char *file, 
> > > > int line,
> > > > +   const char *fmt, 
> > > > ...)
> > > > +{
> > > > +}
> > > > +
> > > > +#endif
> > > > +
> > > > +
> > > > +#endif /* _KUNIT_TEST_BUG_H */
> > > > diff --git a/lib/kunit/test.c b/lib/kunit/test.c
> > > > index ec9494e914ef..5794059505cf 100644
> > > > --- a/lib/kunit/test.c
> > > > +++ b/lib/kunit/test.c
> > > > @@ -7,6 +7,7 @@
> > > >   */
> > > >
> > > >  #include 
> > > > +#include 
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > @@ -16,6 +17,38 @@
> > > >  #include "string-stream.h"
> > > >  #include "try-catch-impl.h"
> > > >
> > > > +/*
> > > > + * Fail the current test and print an error message to the log.
> > > > + */
> > > > +void __kunit_fail_current_test(const char *file, int line, const char 
> > > > *fmt, ...)
> > > > +{
> > > > +   va_list args;
> > > > +   int len;
> > > > +   char *buffer;
> > > > +
> > > > +   if (!current->kunit_test)
> > > > +   return;
> > > > +
> > > > +   kunit_set_failure(curr

Re: [PATCH] kunit: don't show `1 == 1` in failed assertion messages

2021-01-29 Thread Brendan Higgins
On Thu, Jan 28, 2021 at 6:26 PM Daniel Latypov  wrote:
>
> Currently, given something (fairly dystopian) like
> > KUNIT_EXPECT_EQ(test, 2 + 2, 5)
>
> KUnit will prints a failure message like this.
> >  Expected 2 + 2 == 5, but
> >  2 + 2 == 4
> >  5 == 5
>
> With this patch, the output just becomes
> >  Expected 2 + 2 == 5, but
> >  2 + 2 == 4
>
> This patch is slightly hacky, but it's quite common* to compare an
> expression to a literal integer value, so this can make KUnit less
> chatty in many cases. (This patch also fixes variants like
> KUNIT_EXPECT_GT, LE, et al.).
>
> It also allocates an additional string briefly, but given this only
> happens on test failures, it doesn't seem too bad a tradeoff.
> Also, in most cases it'll realize the lengths are unequal and bail out
> before the allocation.
>
> We could save the result of the formatted string to avoid wasting this
> extra work, but it felt cleaner to leave it as-is.
>
> Edge case: for something silly and unrealistic like
> > KUNIT_EXPECT_EQ(test, 4, 5);
>
> It'll generate this message with a trailing "but"
> >  Expected 2 + 2 == 5, but
> >  
>
> It didn't feel worth adding a check up-front to see if both sides are
> literals to handle this better.
>
> *A quick grep suggests 100+ comparisons to an integer literal as the
> right hand side.
>
> Signed-off-by: Daniel Latypov 

I don't feel very strongly about this either way. In any case:

Reviewed-by: Brendan Higgins 


  1   2   3   4   5   6   7   >