[PATCH v9 1/6] dt-bindings: clock: add dt binding header for mt7621 clocks

2021-02-17 Thread Sergio Paracuellos
Adds dt binding header for 'mediatek,mt7621-clk' clocks.

Acked-by: Rob Herring 
Signed-off-by: Sergio Paracuellos 
---
 include/dt-bindings/clock/mt7621-clk.h | 41 ++
 1 file changed, 41 insertions(+)
 create mode 100644 include/dt-bindings/clock/mt7621-clk.h

diff --git a/include/dt-bindings/clock/mt7621-clk.h 
b/include/dt-bindings/clock/mt7621-clk.h
new file mode 100644
index ..1422badcf9de
--- /dev/null
+++ b/include/dt-bindings/clock/mt7621-clk.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Author: Sergio Paracuellos 
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT7621_H
+#define _DT_BINDINGS_CLK_MT7621_H
+
+#define MT7621_CLK_XTAL0
+#define MT7621_CLK_CPU 1
+#define MT7621_CLK_BUS 2
+#define MT7621_CLK_50M 3
+#define MT7621_CLK_125M4
+#define MT7621_CLK_150M5
+#define MT7621_CLK_250M6
+#define MT7621_CLK_270M7
+
+#define MT7621_CLK_HSDMA   8
+#define MT7621_CLK_FE  9
+#define MT7621_CLK_SP_DIVTX10
+#define MT7621_CLK_TIMER   11
+#define MT7621_CLK_PCM 12
+#define MT7621_CLK_PIO 13
+#define MT7621_CLK_GDMA14
+#define MT7621_CLK_NAND15
+#define MT7621_CLK_I2C 16
+#define MT7621_CLK_I2S 17
+#define MT7621_CLK_SPI 18
+#define MT7621_CLK_UART1   19
+#define MT7621_CLK_UART2   20
+#define MT7621_CLK_UART3   21
+#define MT7621_CLK_ETH 22
+#define MT7621_CLK_PCIE0   23
+#define MT7621_CLK_PCIE1   24
+#define MT7621_CLK_PCIE2   25
+#define MT7621_CLK_CRYPTO  26
+#define MT7621_CLK_SHXC27
+
+#define MT7621_CLK_MAX 28
+
+#endif /* _DT_BINDINGS_CLK_MT7621_H */
-- 
2.25.1



[PATCH v9 4/6] staging: mt7621-dts: make use of new 'mt7621-clk'

2021-02-17 Thread Sergio Paracuellos
Clocks for SoC mt7621 have been properly integrated so there is
no need to declare fixed clocks at all in the device tree. Remove
all of them, add new device tree nodes for mt7621-clk and update
the rest of the nodes to use them.

Acked-by: Greg Kroah-Hartman 
Signed-off-by: Sergio Paracuellos 
---
 drivers/staging/mt7621-dts/gbpc1.dts   | 11 
 drivers/staging/mt7621-dts/mt7621.dtsi | 79 +-
 2 files changed, 38 insertions(+), 52 deletions(-)

diff --git a/drivers/staging/mt7621-dts/gbpc1.dts 
b/drivers/staging/mt7621-dts/gbpc1.dts
index a7c0d3115d72..7716d0efe524 100644
--- a/drivers/staging/mt7621-dts/gbpc1.dts
+++ b/drivers/staging/mt7621-dts/gbpc1.dts
@@ -100,17 +100,6 @@ partition@5 {
};
 };
 
- {
-   compatible = "fixed-clock";
-   /* This is normally 1/4 of cpuclock */
-   clock-frequency = <22500>;
-};
-
- {
-   compatible = "fixed-clock";
-   clock-frequency = <9>;
-};
-
  {
pinctrl-names = "default";
pinctrl-0 = <_pins>;
diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi 
b/drivers/staging/mt7621-dts/mt7621.dtsi
index 16fc94f65486..11d1670d4339 100644
--- a/drivers/staging/mt7621-dts/mt7621.dtsi
+++ b/drivers/staging/mt7621-dts/mt7621.dtsi
@@ -1,5 +1,6 @@
 #include 
 #include 
+#include 
 
 / {
#address-cells = <1>;
@@ -27,27 +28,6 @@ aliases {
serial0 = 
};
 
-   cpuclock: cpuclock@0 {
-   #clock-cells = <0>;
-   compatible = "fixed-clock";
-
-   /* FIXME: there should be way to detect this */
-   clock-frequency = <88000>;
-   };
-
-   sysclock: sysclock@0 {
-   #clock-cells = <0>;
-   compatible = "fixed-clock";
-
-   /* This is normally 1/4 of cpuclock */
-   clock-frequency = <22000>;
-   };
-
-   mmc_clock: mmc_clock@0 {
-   #clock-cells = <0>;
-   compatible = "fixed-clock";
-   clock-frequency = <4800>;
-   };
 
mmc_fixed_3v3: fixedregulator@0 {
compatible = "regulator-fixed";
@@ -76,10 +56,20 @@ palmbus: palmbus@1E00 {
#size-cells = <1>;
 
sysc: sysc@0 {
-   compatible = "mtk,mt7621-sysc";
+   compatible = "mtk,mt7621-sysc", "syscon";
reg = <0x0 0x100>;
};
 
+   pll: pll {
+   compatible = "mediatek,mt7621-clk";
+   #clock-cells = <1>;
+   ralink,sysctl = <>;
+   ralink,memctl = <>;
+   clock-output-names = "xtal", "cpu", "bus",
+"50m", "125m", "150m",
+"250m", "270m";
+   };
+
wdt: wdt@100 {
compatible = "mtk,mt7621-wdt";
reg = <0x100 0x100>;
@@ -101,8 +91,8 @@ i2c: i2c@900 {
compatible = "mediatek,mt7621-i2c";
reg = <0x900 0x100>;
 
-   clocks = <>;
-
+   clocks = < MT7621_CLK_I2C>;
+   clock-names = "i2c";
resets = < 16>;
reset-names = "i2c";
 
@@ -119,8 +109,8 @@ i2s: i2s@a00 {
compatible = "mediatek,mt7621-i2s";
reg = <0xa00 0x100>;
 
-   clocks = <>;
-
+   clocks = < MT7621_CLK_I2S>;
+   clock-names = "i2s";
resets = < 17>;
reset-names = "i2s";
 
@@ -138,7 +128,7 @@ i2s: i2s@a00 {
};
 
memc: memc@5000 {
-   compatible = "mtk,mt7621-memc";
+   compatible = "mtk,mt7621-memc", "syscon";
reg = <0x5000 0x1000>;
};
 
@@ -156,8 +146,8 @@ uartlite: uartlite@c00 {
compatible = "ns16550a";
reg = <0xc00 0x100>;
 
-   clocks = <>;
-   clock-frequency = <5000>;
+   clocks = < MT7621_CLK_UART1>;
+   clock-names = "uart1";
 
interrupt-parent = <>;
interrupts = ;
@@ -173,7 +163,8 @@ spi0: spi@b00 {
compatible = "ralink,mt7621-spi";
reg = <0xb00 0x100>;
 
-   clocks = <>;
+   clocks = < MT7621_CLK_SPI>;
+   clock-names = "spi";
 
resets = < 18>;
reset-names = "spi";
@@ -189,6 +180,8 @@ gdma: gdma@2800 {
compatible = "ralink,rt3883-gdma";
   

[PATCH v9 0/6] MIPS: ralink: add CPU clock detection and clock driver for MT7621

2021-02-17 Thread Sergio Paracuellos
This patchset ports CPU clock detection for MT7621 from OpenWrt
and adds a complete clock plan for the mt7621 SOC.

The documentation for this SOC only talks about two registers
regarding to the clocks:
* SYSC_REG_CPLL_CLKCFG0 - provides some information about boostrapped
refclock. PLL and dividers used for CPU and some sort of BUS (AHB?).
* SYSC_REG_CPLL_CLKCFG1 - a banch of gates to enable/disable clocks for
all or some ip cores.

Registers needed for this driver to work are in two already mapped areas
in its platform's device tree. These are 'sysc' and 'memc' nodes. Most
of other drivers just make use of platform operations defined in
'asm/mach-ralink/ralink_regs.h' but this can be avoided declaring this
two nodes to be accesible through syscon. Since these are the only two
needed control interfaces for this clock driver that seems to be the
correct thing to do.

No documentation about a probably existent set of dividers for each ip
core is included in the datasheets. So we cannot make anything better,
AFAICT.

Looking into driver code, and some openWRT patched there are
another frequences which are used in some drivers (uart, sd...).
According to all of this information the clock plan for this
SoC is set as follows:
 - Main top clock "xtal" from where all the rest of the world is
   derived.
 - CPU clock "cpu" derived from "xtal" frequencies and a bunch of
   register reads and predividers.
 - BUS clock "bus" derived from "cpu" and with (cpu / 4) MHz.
 - Fixed clocks from "xtal":
* "50m": 50 MHz.
* "125m": 125 MHz.
* "150m": 150 MHz.
* "250m": 250 MHz.
* "270m": 270 MHz.

We also have a buch of gate clocks with their parents:
 - "hsdma": "150m"
 - "fe": "250m"
 - "sp_divtx": "270m"
 - "timer": "50m"
 - "pcm": "270m"
 - "pio": "50m"
 - "gdma": "bus"
 - "nand": "125m"
 - "i2c": "50m"
 - "i2s": "270m"
 - "spi": "bus"
 - "uart1": "50m"
 - "uart2": "50m"
 - "uart3": "50m"
 - "eth": "50m"
 - "pcie0": "125m"
 - "pcie1": "125m"
 - "pcie2": "125m"
 - "crypto": "250m"
 - "shxc": "50m"

There was a previous attempt of doing this here[0] but the author
(Chuanhong Guo) did not wanted to make assumptions of a clock plan
for the platform that time. It seems that now he has a better idea of
how the clocks are dispossed for this SoC so he share code[1] where
some frequencies and clock parents for the gates are coded from a
real mediatek private clock plan.

I do really want this to be upstreamed so according to the comments
in previous attempt[0] from Oleksij Rempel and the frequencies in
code[1] I have tried to do this by myself.

All of this patches have been tested in a GNUBee PC1 resulting in a
working platform.

Changes in v9:
 - Set two missing ret values to its related PTR_ERR in function
   'mt7621_clk_probe' (also related with [3]).
 - Select MFC_SYSCON in Kconfig.

Changes in v8:
 - Fix kernel test robot complain about the use of 'ret' variable
   initialized: see [3]

Changes in v7:
 - Make use of CLK_OF_DECLARE_DRIVER instead of CLK_OF_DECLARE and
   register there only the top clocks that are needed in 'of_clk_init'.
   The rest of the clocks (fixed and gates) are now registered using
   a platform driver. Because we have avoid architecture dependent stuff
   now this has sense because we can enable this driver for COMPILE_TEST.
 - Convert fixed clocks and gates related function to receive a 'struct
   device' pointer instead of 'struct device_node' one.
 - Make use of dev_ APIS in stuff related with platform driver instead
   of use device_node related stuff. 
 - Add new static global 'mt7621_clk_early' to store pointers to clk_hw
   registered at 'of_clk_init' stage. Make use of this in platform device
   probe function to properly copy this into the new required 'clk_data'
   to provide a properly hierarchy clock structure.
 - Rename 'mt7621_register_top_clocks' function into a more accurate 
   name now which is 'mt7621_register_early_clocks'.
 - Enable driver for COMPILE_TEST.

Changes in v6:
 - Rewrite bindings to properly access the registers needed for the driver
   making use of syscon for two different areas: 'sysc' and 'memc'. With
   this changes architecture dependent include 'asm/mach-ralink/ralink_regs.h'
   is not needed anymore because we access this two syscons using a phandle
   through kernel's regmap APIs. Explanation of this two areas is in [2].
 - Add new 'mt7621_clk_priv' struct to store there pointers to regmap handlers
   to be able to use regmap operations from normal clock api functions. Add
   this pointer in 'mt7621_clk' and 'mt7621_clk_gate' before register its
   related clocks to make things work.
 - Add Greg's Acked-by in patches 4 and 5.
 - Rebase this series on the top of linux-next tag 'next-20210215'.

v5 RESEND notes:
 - I am resending this as I was told to do that.
 - Please, take into account Rob's comments to DT node patch and my
   reply with explanation about how are the current device tree 

Re: [PATCH v14 06/11] x86/elf: Move vmcore_elf_check_arch_cross to arch/x86/include/asm/elf.h

2021-02-17 Thread chenzhou



On 2021/2/18 14:31, Baoquan He wrote:
> On 01/30/21 at 03:10pm, Chen Zhou wrote:
>> Move macro vmcore_elf_check_arch_cross from arch/x86/include/asm/kexec.h
>> to arch/x86/include/asm/elf.h to fix the following compiling warning:
>>
>> make ARCH=i386
>> In file included from arch/x86/kernel/setup.c:39:0:
>> ./arch/x86/include/asm/kexec.h:77:0: warning: "vmcore_elf_check_arch_cross" 
>> redefined
>>  # define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
>>
>> In file included from arch/x86/kernel/setup.c:9:0:
>> ./include/linux/crash_dump.h:39:0: note: this is the location of the 
>> previous definition
>>  #define vmcore_elf_check_arch_cross(x) 0
>>
>> The root cause is that vmcore_elf_check_arch_cross under CONFIG_CRASH_CORE
>> depend on CONFIG_KEXEC_CORE. Commit 2db65f1db17d ("x86: kdump: move
>> reserve_crashkernel[_low]() into crash_core.c") triggered the issue.
>>
>> Suggested by Mike, simply move vmcore_elf_check_arch_cross from
>> arch/x86/include/asm/kexec.h to arch/x86/include/asm/elf.h to fix
>> the warning.
>>
>> Fixes: 2db65f1db17d ("x86: kdump: move reserve_crashkernel[_low]() into 
>> crash_core.c")
> Where does this commit id '2db65f1db17d' come from? Here you are fixing
> another pathc in the same patchset. Please merge this with patch 05/11.
Yeah, the commit id is invalid, i will merge this patch with patch 05/11.

Thanks,
Chen Zhou
>
>> Reported-by: kernel test robot 
>> Suggested-by: Mike Rapoport 
>> Signed-off-by: Chen Zhou 
>> ---
>>  arch/x86/include/asm/elf.h   | 3 +++
>>  arch/x86/include/asm/kexec.h | 3 ---
>>  2 files changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
>> index 66bdfe838d61..5333777cc758 100644
>> --- a/arch/x86/include/asm/elf.h
>> +++ b/arch/x86/include/asm/elf.h
>> @@ -94,6 +94,9 @@ extern unsigned int vdso32_enabled;
>>  
>>  #define elf_check_arch(x)   elf_check_arch_ia32(x)
>>  
>> +/* We can also handle crash dumps from 64 bit kernel. */
>> +# define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
>> +
>>  /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
>> contains a pointer to a function which might be registered using 
>> `atexit'.
>> This provides a mean for the dynamic linker to call DT_FINI functions for
>> diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
>> index 2b18f918203e..6fcae01a9cca 100644
>> --- a/arch/x86/include/asm/kexec.h
>> +++ b/arch/x86/include/asm/kexec.h
>> @@ -72,9 +72,6 @@ struct kimage;
>>  
>>  /* The native architecture */
>>  # define KEXEC_ARCH KEXEC_ARCH_386
>> -
>> -/* We can also handle crash dumps from 64 bit kernel. */
>> -# define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
>>  #else
>>  /* Maximum physical address we can use pages from */
>>  # define KEXEC_SOURCE_MEMORY_LIMIT  (MAXMEM-1)
>> -- 
>> 2.20.1
>>
> .
>



[PATCH V3 XRT Alveo 10/18] fpga: xrt: VSEC platform driver

2021-02-17 Thread Lizhi Hou
Add VSEC driver. VSEC is a hardware function discovered by walking
PCI Express configure space. A platform device node will be created
for it. VSEC provides board logic UUID and few offset of other hardware
functions.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/lib/xleaf/vsec.c | 359 ++
 1 file changed, 359 insertions(+)
 create mode 100644 drivers/fpga/xrt/lib/xleaf/vsec.c

diff --git a/drivers/fpga/xrt/lib/xleaf/vsec.c 
b/drivers/fpga/xrt/lib/xleaf/vsec.c
new file mode 100644
index ..8e5cb22522ec
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/vsec.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA VSEC Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ */
+
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+
+#define XRT_VSEC "xrt_vsec"
+
+#define VSEC_TYPE_UUID 0x50
+#define VSEC_TYPE_FLASH0x51
+#define VSEC_TYPE_PLATINFO 0x52
+#define VSEC_TYPE_MAILBOX  0x53
+#define VSEC_TYPE_END  0xff
+
+#define VSEC_UUID_LEN  16
+
+struct xrt_vsec_header {
+   u32 format;
+   u32 length;
+   u32 entry_sz;
+   u32 rsvd;
+} __packed;
+
+#define head_rd(g, r)  \
+   ioread32((void *)(g)->base + offsetof(struct xrt_vsec_header, r))
+
+#define GET_BAR(entry) (((entry)->bar_rev >> 4) & 0xf)
+#define GET_BAR_OFF(_entry)\
+   ({ typeof(_entry) entry = (_entry); \
+((entry)->off_lo | ((u64)(entry)->off_hi << 16)); })
+#define GET_REV(entry) ((entry)->bar_rev & 0xf)
+
+struct xrt_vsec_entry {
+   u8  type;
+   u8  bar_rev;
+   u16 off_lo;
+   u32 off_hi;
+   u8  ver_type;
+   u8  minor;
+   u8  major;
+   u8  rsvd0;
+   u32 rsvd1;
+} __packed;
+
+#define read_entry(g, i, e)\
+   do {\
+   u32 *p = (u32 *)((g)->base +\
+   sizeof(struct xrt_vsec_header) +\
+   (i) * sizeof(struct xrt_vsec_entry));   \
+   u32 off;\
+   for (off = 0;   \
+   off < sizeof(struct xrt_vsec_entry) / 4;\
+   off++)  \
+   *((u32 *)(e) + off) = ioread32(p + off);\
+   } while (0)
+
+struct vsec_device {
+   u8  type;
+   char*ep_name;
+   ulong   size;
+   char*regmap;
+};
+
+static struct vsec_device vsec_devs[] = {
+   {
+   .type = VSEC_TYPE_UUID,
+   .ep_name = XRT_MD_NODE_BLP_ROM,
+   .size = VSEC_UUID_LEN,
+   .regmap = "vsec-uuid",
+   },
+   {
+   .type = VSEC_TYPE_FLASH,
+   .ep_name = XRT_MD_NODE_FLASH_VSEC,
+   .size = 4096,
+   .regmap = "vsec-flash",
+   },
+   {
+   .type = VSEC_TYPE_PLATINFO,
+   .ep_name = XRT_MD_NODE_PLAT_INFO,
+   .size = 4,
+   .regmap = "vsec-platinfo",
+   },
+   {
+   .type = VSEC_TYPE_MAILBOX,
+   .ep_name = XRT_MD_NODE_MAILBOX_VSEC,
+   .size = 48,
+   .regmap = "vsec-mbx",
+   },
+};
+
+struct xrt_vsec {
+   struct platform_device  *pdev;
+   void*base;
+   ulong   length;
+
+   char*metadata;
+   charuuid[VSEC_UUID_LEN];
+};
+
+static char *type2epname(u32 type)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(vsec_devs); i++) {
+   if (vsec_devs[i].type == type)
+   return (vsec_devs[i].ep_name);
+   }
+
+   return NULL;
+}
+
+static ulong type2size(u32 type)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(vsec_devs); i++) {
+   if (vsec_devs[i].type == type)
+   return (vsec_devs[i].size);
+   }
+
+   return 0;
+}
+
+static char *type2regmap(u32 type)
+{
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(vsec_devs); i++) {
+   if (vsec_devs[i].type == type)
+   return (vsec_devs[i].regmap);
+   }
+
+   return NULL;
+}
+
+static int xrt_vsec_add_node(struct xrt_vsec *vsec,
+void *md_blob, struct xrt_vsec_entry *p_entry)
+{
+   struct xrt_md_endpoint ep;
+   char regmap_ver[64];
+   int ret;
+
+   if (!type2epname(p_entry->type))
+   return -EINVAL;
+
+   /*
+* VSEC may have more than 1 

Re: [PATCH V0 3/6] soc: qcom: dcc:Add driver support for Data Capture and Compare unit(DCC)

2021-02-17 Thread Vinod Koul
On 17-02-21, 12:18, Souradeep Chowdhury wrote:
> The DCC is a DMA Engine designed to capture and store data
> during system crash or software triggers.The DCC operates
^^^
Space after . (quite a few here, pls fix them)

> based on link list entries which provides it with data and
> addresses and the function it needs to perform.These functions
> are read,write and loop.Added the basic driver in this patch
> which contains a probe method which instantiates all the link
> list data specific to a SoC.Methods have also been added to
> handle all the functionalities specific to a linked list.Each
> DCC has it's own SRAM which needs to be instantiated at probe
> time as well.

So help me understand, in case of system crash how will this be used..?

> 
> Signed-off-by: Souradeep Chowdhury 
> ---
>  drivers/soc/qcom/Kconfig  |8 +
>  drivers/soc/qcom/Makefile |1 +
>  drivers/soc/qcom/dcc.c| 1055 
> +
>  3 files changed, 1064 insertions(+)
>  create mode 100644 drivers/soc/qcom/dcc.c
> 
> diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> index 79b568f..8819e0b 100644
> --- a/drivers/soc/qcom/Kconfig
> +++ b/drivers/soc/qcom/Kconfig
> @@ -69,6 +69,14 @@ config QCOM_LLCC
> SDM845. This provides interfaces to clients that use the LLCC.
> Say yes here to enable LLCC slice driver.
>  
> +config QCOM_DCC
> + tristate "Qualcomm Technologies, Inc. Data Capture and Compare engine 
> driver"
> + depends on ARCH_QCOM || COMPILE_TEST
> + help
> +   This option enables driver for Data Capture and Compare engine. DCC
> +   driver provides interface to configure DCC block and read back
> +   captured data from DCC's internal SRAM.
> +
>  config QCOM_KRYO_L2_ACCESSORS
>   bool
>   depends on ARCH_QCOM && ARM64 || COMPILE_TEST
> diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> index ad675a6..1b00870 100644
> --- a/drivers/soc/qcom/Makefile
> +++ b/drivers/soc/qcom/Makefile
> @@ -26,3 +26,4 @@ obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o
>  obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
>  obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
>  obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) +=  kryo-l2-accessors.o
> +obj-$(CONFIG_QCOM_DCC) += dcc.o
> diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
> new file mode 100644
> index 000..d67452b
> --- /dev/null
> +++ b/drivers/soc/qcom/dcc.c
> @@ -0,0 +1,1055 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define TIMEOUT_US   100
> +
> +#define BM(lsb, msb) ((BIT(msb) - BIT(lsb)) + BIT(msb))
> +#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
> +#define BVAL(val, n) ((val & BIT(n)) >> n)

Pls use macros available in bitfield.h rather than inventing your own..

> +
> +#define dcc_writel(drvdata, val, off)
> \
> + writel((val), drvdata->base + dcc_offset_conv(drvdata, off))
> +#define dcc_readl(drvdata, off)  
> \
> + readl(drvdata->base + dcc_offset_conv(drvdata, off))
> +
> +#define dcc_sram_readl(drvdata, off) \
> + readl(drvdata->ram_base + off)
> +
> +/* DCC registers */
> +#define DCC_HW_INFO  0x04
> +#define DCC_LL_NUM_INFO  0x10
> +#define DCC_STATUS   0x1C
> +#define DCC_LL_LOCK(m)   (0x34 + 0x80 * 
> m)
> +#define DCC_LL_CFG(m)(0x38 + 0x80 * 
> m)
> +#define DCC_LL_BASE(m)   (0x3c + 0x80 * 
> m)
> +#define DCC_FD_BASE(m)   (0x40 + 0x80 * 
> m)
> +#define DCC_LL_TIMEOUT(m)(0x44 + 0x80 * m)
> +#define DCC_LL_INT_ENABLE(m) (0x4C + 0x80 * m)
> +#define DCC_LL_INT_STATUS(m) (0x50 + 0x80 * m)
> +#define DCC_LL_SW_TRIGGER(m) (0x60 + 0x80 * m)
> +#define DCC_LL_BUS_ACCESS_STATUS(m)  (0x64 + 0x80 * m)
> +
> +#define DCC_MAP_LEVEL1   0x18
> +#define DCC_MAP_LEVEL2   0x34
> +#define DCC_MAP_LEVEL3   0x4C
> +
> +#define DCC_MAP_OFFSET1  0x10
> +#define DCC_MAP_OFFSET2  0x18
> +#define DCC_MAP_OFFSET3  0x1C
> +#define DCC_MAP_OFFSET4  0x8
> +
> +#define DCC_FIX_LOOP_OFFSET  16
> +#define DCC_VER_INFO_BIT 9
> +
> +#define DCC_READ0
> +#define DCC_WRITE   1
> +#define DCC_LOOP2
> +#define 

linux-next: build failure after merge of the gpio-brgl tree

2021-02-17 Thread Stephen Rothwell
Hi all,

After merging the gpio-brgl tree, today's linux-next build (arm
multi_v7_defconfig) failed like this:

drivers/gpio/gpio-pcf857x.c: In function 'pcf857x_probe':
drivers/gpio/gpio-pcf857x.c:335:41: error: expected ';' before 'if'
  335 |  gpio->status = gpio->read(gpio->client)
  | ^
  | ;
..
  338 |  if (client->irq) {
  |  ~~  

Caused by commit

  ab94f4c529bc ("gpio: pcf857x: Fix missing first interrupt")

I have used the gpio-brgl tree from next-20210217 for today.

-- 
Cheers,
Stephen Rothwell


pgptGG7rc1eFP.pgp
Description: OpenPGP digital signature


[PATCH V3 XRT Alveo 13/18] fpga: xrt: devctl platform driver

2021-02-17 Thread Lizhi Hou
Add devctl driver. devctl is a type of hardware function which only has
few registers to read or write. They are discovered by walking firmware
metadata. A platform device node will be created for them.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/devctl.h |  43 +
 drivers/fpga/xrt/lib/xleaf/devctl.c | 206 
 2 files changed, 249 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/devctl.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/devctl.c

diff --git a/drivers/fpga/xrt/include/xleaf/devctl.h 
b/drivers/fpga/xrt/include/xleaf/devctl.h
new file mode 100644
index ..96a40e066f83
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/devctl.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for XRT DEVCTL Leaf Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_DEVCTL_H_
+#define _XRT_DEVCTL_H_
+
+#include "xleaf.h"
+
+/*
+ * DEVCTL driver IOCTL calls.
+ */
+enum xrt_devctl_ioctl_cmd {
+   XRT_DEVCTL_READ = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+   XRT_DEVCTL_WRITE,
+};
+
+enum xrt_devctl_id {
+   XRT_DEVCTL_ROM_UUID,
+   XRT_DEVCTL_DDR_CALIB,
+   XRT_DEVCTL_GOLDEN_VER,
+   XRT_DEVCTL_MAX
+};
+
+struct xrt_devctl_ioctl_rw {
+   u32 xgir_id;
+   void*xgir_buf;
+   u32 xgir_len;
+   u32 xgir_offset;
+};
+
+struct xrt_devctl_ioctl_intf_uuid {
+   u32 xgir_uuid_num;
+   uuid_t  *xgir_uuids;
+};
+
+#endif /* _XRT_DEVCTL_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/devctl.c 
b/drivers/fpga/xrt/lib/xleaf/devctl.c
new file mode 100644
index ..caf8c6569f0f
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/devctl.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA devctl Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/devctl.h"
+
+#define XRT_DEVCTL "xrt_devctl"
+
+struct xrt_name_id {
+   char *ep_name;
+   int id;
+};
+
+static struct xrt_name_id name_id[XRT_DEVCTL_MAX] = {
+   { XRT_MD_NODE_BLP_ROM, XRT_DEVCTL_ROM_UUID },
+   { XRT_MD_NODE_GOLDEN_VER, XRT_DEVCTL_GOLDEN_VER },
+};
+
+struct xrt_devctl {
+   struct platform_device  *pdev;
+   void__iomem *base_addrs[XRT_DEVCTL_MAX];
+   ulong   sizes[XRT_DEVCTL_MAX];
+};
+
+static int xrt_devctl_name2id(struct xrt_devctl *devctl, const char *name)
+{
+   int i;
+
+   for (i = 0; i < XRT_DEVCTL_MAX && name_id[i].ep_name; i++) {
+   if (!strncmp(name_id[i].ep_name, name, 
strlen(name_id[i].ep_name) + 1))
+   return name_id[i].id;
+   }
+
+   return -EINVAL;
+}
+
+static int
+xrt_devctl_leaf_ioctl(struct platform_device *pdev, u32 cmd, void *arg)
+{
+   struct xrt_devctl   *devctl;
+   int ret = 0;
+
+   devctl = platform_get_drvdata(pdev);
+
+   switch (cmd) {
+   case XRT_XLEAF_EVENT:
+   /* Does not handle any event. */
+   break;
+   case XRT_DEVCTL_READ: {
+   struct xrt_devctl_ioctl_rw  *rw_arg = arg;
+   u32 *p_src, *p_dst, i;
+
+   if (rw_arg->xgir_len & 0x3) {
+   xrt_err(pdev, "invalid len %d", rw_arg->xgir_len);
+   return -EINVAL;
+   }
+
+   if (rw_arg->xgir_id >= XRT_DEVCTL_MAX) {
+   xrt_err(pdev, "invalid id %d", rw_arg->xgir_id);
+   return -EINVAL;
+   }
+
+   p_src = devctl->base_addrs[rw_arg->xgir_id];
+   if (!p_src) {
+   xrt_err(pdev, "io not found, id %d",
+   rw_arg->xgir_id);
+   return -EINVAL;
+   }
+   if (rw_arg->xgir_offset + rw_arg->xgir_len >
+   devctl->sizes[rw_arg->xgir_id]) {
+   xrt_err(pdev, "invalid argument, off %d, len %d",
+   rw_arg->xgir_offset, rw_arg->xgir_len);
+   return -EINVAL;
+   }
+   p_dst = rw_arg->xgir_buf;
+   for (i = 0; i < rw_arg->xgir_len / sizeof(u32); i++) {
+   u32 val = ioread32(p_src + rw_arg->xgir_offset + i);
+
+   memcpy(p_dst + i, , sizeof(u32));
+   }
+   break;
+   }
+   default:
+   xrt_err(pdev, "unsupported cmd %d", cmd);
+   return -EINVAL;
+   }
+
+   return ret;
+}
+
+static int xrt_devctl_remove(struct platform_device *pdev)
+{
+   struct xrt_devctl   *devctl;
+   int i;
+
+   

[PATCH V3 XRT Alveo 11/18] fpga: xrt: UCS platform driver

2021-02-17 Thread Lizhi Hou
Add UCS driver. UCS is a hardware function discovered by walking xclbin
metadata. A platform device node will be created for it.
UCS enables/disables the dynamic region clocks.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/ucs.h |  24 +++
 drivers/fpga/xrt/lib/xleaf/ucs.c | 235 +++
 2 files changed, 259 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/ucs.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/ucs.c

diff --git a/drivers/fpga/xrt/include/xleaf/ucs.h 
b/drivers/fpga/xrt/include/xleaf/ucs.h
new file mode 100644
index ..a5ef0e100e12
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/ucs.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for XRT UCS Leaf Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_UCS_H_
+#define _XRT_UCS_H_
+
+#include "xleaf.h"
+
+/*
+ * UCS driver IOCTL calls.
+ */
+enum xrt_ucs_ioctl_cmd {
+   XRT_UCS_CHECK = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+   XRT_UCS_ENABLE,
+};
+
+#endif /* _XRT_UCS_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/ucs.c b/drivers/fpga/xrt/lib/xleaf/ucs.c
new file mode 100644
index ..ae762c8fddbb
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/ucs.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA UCS Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/ucs.h"
+#include "xleaf/clock.h"
+
+#define UCS_ERR(ucs, fmt, arg...)   \
+   xrt_err((ucs)->pdev, fmt "\n", ##arg)
+#define UCS_WARN(ucs, fmt, arg...)  \
+   xrt_warn((ucs)->pdev, fmt "\n", ##arg)
+#define UCS_INFO(ucs, fmt, arg...)  \
+   xrt_info((ucs)->pdev, fmt "\n", ##arg)
+#define UCS_DBG(ucs, fmt, arg...)   \
+   xrt_dbg((ucs)->pdev, fmt "\n", ##arg)
+
+#define XRT_UCS"xrt_ucs"
+
+#define CHANNEL1_OFFSET0
+#define CHANNEL2_OFFSET8
+
+#define CLK_MAX_VALUE  6400
+
+struct ucs_control_status_ch1 {
+   unsigned int shutdown_clocks_latched:1;
+   unsigned int reserved1:15;
+   unsigned int clock_throttling_average:14;
+   unsigned int reserved2:2;
+};
+
+struct xrt_ucs {
+   struct platform_device  *pdev;
+   void __iomem*ucs_base;
+   struct mutexucs_lock; /* ucs dev lock */
+};
+
+static inline u32 reg_rd(struct xrt_ucs *ucs, u32 offset)
+{
+   return ioread32(ucs->ucs_base + offset);
+}
+
+static inline void reg_wr(struct xrt_ucs *ucs, u32 val, u32 offset)
+{
+   iowrite32(val, ucs->ucs_base + offset);
+}
+
+static void xrt_ucs_event_cb(struct platform_device *pdev, void *arg)
+{
+   struct platform_device  *leaf;
+   struct xrt_event *evt = (struct xrt_event *)arg;
+   enum xrt_events e = evt->xe_evt;
+   enum xrt_subdev_id id = evt->xe_subdev.xevt_subdev_id;
+   int instance = evt->xe_subdev.xevt_subdev_instance;
+
+   switch (e) {
+   case XRT_EVENT_POST_CREATION:
+   break;
+   default:
+   xrt_dbg(pdev, "ignored event %d", e);
+   return;
+   }
+
+   if (id != XRT_SUBDEV_CLOCK)
+   return;
+
+   leaf = xleaf_get_leaf_by_id(pdev, XRT_SUBDEV_CLOCK, instance);
+   if (!leaf) {
+   xrt_err(pdev, "does not get clock subdev");
+   return;
+   }
+
+   xleaf_ioctl(leaf, XRT_CLOCK_VERIFY, NULL);
+   xleaf_put_leaf(pdev, leaf);
+}
+
+static void ucs_check(struct xrt_ucs *ucs, bool *latched)
+{
+   struct ucs_control_status_ch1 *ucs_status_ch1;
+   u32 status;
+
+   mutex_lock(>ucs_lock);
+   status = reg_rd(ucs, CHANNEL1_OFFSET);
+   ucs_status_ch1 = (struct ucs_control_status_ch1 *)
+   if (ucs_status_ch1->shutdown_clocks_latched) {
+   UCS_ERR(ucs,
+   "Critical temperature or power event, kernel clocks 
have been stopped.");
+   UCS_ERR(ucs,
+   "run 'xbutil valiate -q' to continue. See AR 73398 for 
more details.");
+   /* explicitly indicate reset should be latched */
+   *latched = true;
+   } else if (ucs_status_ch1->clock_throttling_average >
+   CLK_MAX_VALUE) {
+   UCS_ERR(ucs, "kernel clocks %d exceeds expected maximum value 
%d.",
+   ucs_status_ch1->clock_throttling_average,
+   CLK_MAX_VALUE);
+   } else if (ucs_status_ch1->clock_throttling_average) {
+   UCS_ERR(ucs, "kernel clocks throttled at %d%%.",
+   (ucs_status_ch1->clock_throttling_average /
+(CLK_MAX_VALUE / 100)));
+   }
+   mutex_unlock(>ucs_lock);
+}
+
+static void 

[PATCH V3 XRT Alveo 16/18] fpga: xrt: DDR calibration platform driver

2021-02-17 Thread Lizhi Hou
Add DDR calibration driver. DDR calibration is a hardware function
discovered by walking firmware metadata. A platform device node will
be created for it. Hardware provides DDR calibration status through
this function.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/calib.h |  30 
 drivers/fpga/xrt/lib/xleaf/calib.c | 226 +
 2 files changed, 256 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/calib.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/calib.c

diff --git a/drivers/fpga/xrt/include/xleaf/calib.h 
b/drivers/fpga/xrt/include/xleaf/calib.h
new file mode 100644
index ..f8aba4594c58
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/calib.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for XRT DDR Calibration Leaf Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#ifndef _XRT_CALIB_H_
+#define _XRT_CALIB_H_
+
+#include "xleaf.h"
+#include 
+
+/*
+ * Memory calibration driver IOCTL calls.
+ */
+enum xrt_calib_results {
+   XRT_CALIB_UNKNOWN,
+   XRT_CALIB_SUCCEEDED,
+   XRT_CALIB_FAILED,
+};
+
+enum xrt_calib_ioctl_cmd {
+   XRT_CALIB_RESULT = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+};
+
+#endif /* _XRT_CALIB_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/calib.c 
b/drivers/fpga/xrt/lib/xleaf/calib.c
new file mode 100644
index ..fbb813636e76
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/calib.c
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA memory calibration driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * memory calibration
+ *
+ * Authors:
+ *  Lizhi Hou
+ */
+#include 
+#include "xclbin-helper.h"
+#include "metadata.h"
+#include "xleaf/calib.h"
+
+#define XRT_CALIB  "xrt_calib"
+
+struct calib_cache {
+   struct list_headlink;
+   const char  *ep_name;
+   char*data;
+   u32 data_size;
+};
+
+struct calib {
+   struct platform_device  *pdev;
+   void*calib_base;
+   struct mutexlock; /* calibration dev lock */
+   struct list_headcache_list;
+   u32 cache_num;
+   enum xrt_calib_results  result;
+};
+
+#define CALIB_DONE(calib)  \
+   (ioread32((calib)->calib_base) & BIT(0))
+
+static void calib_cache_clean_nolock(struct calib *calib)
+{
+   struct calib_cache *cache, *temp;
+
+   list_for_each_entry_safe(cache, temp, >cache_list, link) {
+   vfree(cache->data);
+   list_del(>link);
+   vfree(cache);
+   }
+   calib->cache_num = 0;
+}
+
+static void calib_cache_clean(struct calib *calib)
+{
+   mutex_lock(>lock);
+   calib_cache_clean_nolock(calib);
+   mutex_unlock(>lock);
+}
+
+static int calib_srsr(struct calib *calib, struct platform_device *srsr_leaf)
+{
+   return -EOPNOTSUPP;
+}
+
+static int calib_calibration(struct calib *calib)
+{
+   int i;
+
+   for (i = 0; i < 20; i++) {
+   if (CALIB_DONE(calib))
+   break;
+   msleep(500);
+   }
+
+   if (i == 20) {
+   xrt_err(calib->pdev,
+   "MIG calibration timeout after bitstream download");
+   return -ETIMEDOUT;
+   }
+
+   xrt_info(calib->pdev, "took %dms", i * 500);
+   return 0;
+}
+
+static void xrt_calib_event_cb(struct platform_device *pdev, void *arg)
+{
+   struct calib *calib = platform_get_drvdata(pdev);
+   struct xrt_event *evt = (struct xrt_event *)arg;
+   enum xrt_events e = evt->xe_evt;
+   enum xrt_subdev_id id = evt->xe_subdev.xevt_subdev_id;
+   int instance = evt->xe_subdev.xevt_subdev_instance;
+   struct platform_device *leaf;
+   int ret;
+
+   switch (e) {
+   case XRT_EVENT_POST_CREATION: {
+   if (id == XRT_SUBDEV_SRSR) {
+   leaf = xleaf_get_leaf_by_id(pdev,
+   XRT_SUBDEV_SRSR,
+   instance);
+   if (!leaf) {
+   xrt_err(pdev, "does not get SRSR subdev");
+   return;
+   }
+   ret = calib_srsr(calib, leaf);
+   xleaf_put_leaf(pdev, leaf);
+   calib->result =
+   ret ? XRT_CALIB_FAILED : XRT_CALIB_SUCCEEDED;
+   } else if (id == XRT_SUBDEV_UCS) {
+   ret = calib_calibration(calib);
+   calib->result =
+   ret ? XRT_CALIB_FAILED : XRT_CALIB_SUCCEEDED;
+   }
+   break;
+   }
+   default:
+

[PATCH V3 XRT Alveo 17/18] fpga: xrt: partition isolation platform driver

2021-02-17 Thread Lizhi Hou
Add partition isolation platform driver. partition isolation is
a hardware function discovered by walking firmware metadata.
A platform device node will be created for it. Partition isolation
function isolate the different fpga regions

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/axigate.h |  25 ++
 drivers/fpga/xrt/lib/xleaf/axigate.c | 298 +++
 2 files changed, 323 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/axigate.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/axigate.c

diff --git a/drivers/fpga/xrt/include/xleaf/axigate.h 
b/drivers/fpga/xrt/include/xleaf/axigate.h
new file mode 100644
index ..2cef71e13b30
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/axigate.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for XRT Axigate Leaf Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_AXIGATE_H_
+#define _XRT_AXIGATE_H_
+
+#include "xleaf.h"
+#include "metadata.h"
+
+/*
+ * AXIGATE driver IOCTL calls.
+ */
+enum xrt_axigate_ioctl_cmd {
+   XRT_AXIGATE_FREEZE = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h 
*/
+   XRT_AXIGATE_FREE,
+};
+
+#endif /* _XRT_AXIGATE_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/axigate.c 
b/drivers/fpga/xrt/lib/xleaf/axigate.c
new file mode 100644
index ..382969f9925f
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/axigate.c
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA AXI Gate Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/axigate.h"
+
+#define XRT_AXIGATE "xrt_axigate"
+
+struct axigate_regs {
+   u32 iag_wr;
+   u32 iag_rvsd;
+   u32 iag_rd;
+} __packed;
+
+struct xrt_axigate {
+   struct platform_device  *pdev;
+   void*base;
+   struct mutexgate_lock; /* gate dev lock */
+
+   void*evt_hdl;
+   const char  *ep_name;
+
+   boolgate_freezed;
+};
+
+/* the ep names are in the order of hardware layers */
+static const char * const xrt_axigate_epnames[] = {
+   XRT_MD_NODE_GATE_PLP,
+   XRT_MD_NODE_GATE_ULP,
+   NULL
+};
+
+#define reg_rd(g, r)   \
+   ioread32((void *)(g)->base + offsetof(struct axigate_regs, r))
+#define reg_wr(g, v, r)\
+   iowrite32(v, (void *)(g)->base + offsetof(struct axigate_regs, r))
+
+static inline void freeze_gate(struct xrt_axigate *gate)
+{
+   reg_wr(gate, 0, iag_wr);
+   ndelay(500);
+   reg_rd(gate, iag_rd);
+}
+
+static inline void free_gate(struct xrt_axigate *gate)
+{
+   reg_wr(gate, 0x2, iag_wr);
+   ndelay(500);
+   (void)reg_rd(gate, iag_rd);
+   reg_wr(gate, 0x3, iag_wr);
+   ndelay(500);
+   reg_rd(gate, iag_rd);
+}
+
+static int xrt_axigate_epname_idx(struct platform_device *pdev)
+{
+   int i;
+   int ret;
+   struct resource *res;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (!res) {
+   xrt_err(pdev, "Empty Resource!");
+   return -EINVAL;
+   }
+
+   for (i = 0; xrt_axigate_epnames[i]; i++) {
+   ret = strncmp(xrt_axigate_epnames[i], res->name,
+ strlen(xrt_axigate_epnames[i]) + 1);
+   if (!ret)
+   break;
+   }
+
+   ret = (xrt_axigate_epnames[i]) ? i : -EINVAL;
+   return ret;
+}
+
+static void xrt_axigate_freeze(struct platform_device *pdev)
+{
+   struct xrt_axigate  *gate;
+   u32 freeze = 0;
+
+   gate = platform_get_drvdata(pdev);
+
+   mutex_lock(>gate_lock);
+   freeze = reg_rd(gate, iag_rd);
+   if (freeze) {   /* gate is opened */
+   xleaf_broadcast_event(pdev, XRT_EVENT_PRE_GATE_CLOSE, false);
+   freeze_gate(gate);
+   }
+
+   gate->gate_freezed = true;
+   mutex_unlock(>gate_lock);
+
+   xrt_info(pdev, "freeze gate %s", gate->ep_name);
+}
+
+static void xrt_axigate_free(struct platform_device *pdev)
+{
+   struct xrt_axigate  *gate;
+   u32 freeze;
+
+   gate = platform_get_drvdata(pdev);
+
+   mutex_lock(>gate_lock);
+   freeze = reg_rd(gate, iag_rd);
+   if (!freeze) {  /* gate is closed */
+   free_gate(gate);
+   xleaf_broadcast_event(pdev, XRT_EVENT_POST_GATE_OPEN, true);
+   /* xrt_axigate_free() could be called in event cb, thus
+* we can not wait for the completes
+  

[PATCH V3 XRT Alveo 15/18] fpga: xrt: clock frequence counter platform driver

2021-02-17 Thread Lizhi Hou
Add clock frequence counter driver. Clock frequence counter is
a hardware function discovered by walking xclbin metadata. A platform
device node will be created for it. Other part of driver can read the
actual clock frequence through clock frequence counter driver.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/clkfreq.h |  23 +++
 drivers/fpga/xrt/lib/xleaf/clkfreq.c | 221 +++
 2 files changed, 244 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/clkfreq.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/clkfreq.c

diff --git a/drivers/fpga/xrt/include/xleaf/clkfreq.h 
b/drivers/fpga/xrt/include/xleaf/clkfreq.h
new file mode 100644
index ..29fc45e8a31b
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/clkfreq.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for XRT Clock Counter Leaf Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_CLKFREQ_H_
+#define _XRT_CLKFREQ_H_
+
+#include "xleaf.h"
+
+/*
+ * CLKFREQ driver IOCTL calls.
+ */
+enum xrt_clkfreq_ioctl_cmd {
+   XRT_CLKFREQ_READ = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+};
+
+#endif /* _XRT_CLKFREQ_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/clkfreq.c 
b/drivers/fpga/xrt/lib/xleaf/clkfreq.c
new file mode 100644
index ..2482dd2cff47
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/clkfreq.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA Clock Frequency Counter Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/clkfreq.h"
+
+#define CLKFREQ_ERR(clkfreq, fmt, arg...)   \
+   xrt_err((clkfreq)->pdev, fmt "\n", ##arg)
+#define CLKFREQ_WARN(clkfreq, fmt, arg...)  \
+   xrt_warn((clkfreq)->pdev, fmt "\n", ##arg)
+#define CLKFREQ_INFO(clkfreq, fmt, arg...)  \
+   xrt_info((clkfreq)->pdev, fmt "\n", ##arg)
+#define CLKFREQ_DBG(clkfreq, fmt, arg...)   \
+   xrt_dbg((clkfreq)->pdev, fmt "\n", ##arg)
+
+#define XRT_CLKFREQ"xrt_clkfreq"
+
+#define OCL_CLKWIZ_STATUS_MASK 0x
+
+#define OCL_CLKWIZ_STATUS_MEASURE_START0x1
+#define OCL_CLKWIZ_STATUS_MEASURE_DONE 0x2
+#define OCL_CLK_FREQ_COUNTER_OFFSET0x8
+#define OCL_CLK_FREQ_V5_COUNTER_OFFSET 0x10
+#define OCL_CLK_FREQ_V5_CLK0_ENABLED   0x1
+
+struct clkfreq {
+   struct platform_device  *pdev;
+   void __iomem*clkfreq_base;
+   const char  *clkfreq_ep_name;
+   struct mutexclkfreq_lock; /* clock counter dev lock */
+};
+
+static inline u32 reg_rd(struct clkfreq *clkfreq, u32 offset)
+{
+   return ioread32(clkfreq->clkfreq_base + offset);
+}
+
+static inline void reg_wr(struct clkfreq *clkfreq, u32 val, u32 offset)
+{
+   iowrite32(val, clkfreq->clkfreq_base + offset);
+}
+
+static u32 clkfreq_read(struct clkfreq *clkfreq)
+{
+   u32 freq = 0, status;
+   int times = 10;
+
+   mutex_lock(>clkfreq_lock);
+   reg_wr(clkfreq, OCL_CLKWIZ_STATUS_MEASURE_START, 0);
+   while (times != 0) {
+   status = reg_rd(clkfreq, 0);
+   if ((status & OCL_CLKWIZ_STATUS_MASK) ==
+   OCL_CLKWIZ_STATUS_MEASURE_DONE)
+   break;
+   mdelay(1);
+   times--;
+   };
+   if (times > 0) {
+   freq = (status & OCL_CLK_FREQ_V5_CLK0_ENABLED) ?
+   reg_rd(clkfreq, OCL_CLK_FREQ_V5_COUNTER_OFFSET) :
+   reg_rd(clkfreq, OCL_CLK_FREQ_COUNTER_OFFSET);
+   }
+   mutex_unlock(>clkfreq_lock);
+
+   return freq;
+}
+
+static ssize_t freq_show(struct device *dev, struct device_attribute *attr, 
char *buf)
+{
+   struct clkfreq *clkfreq = platform_get_drvdata(to_platform_device(dev));
+   u32 freq;
+   ssize_t count;
+
+   freq = clkfreq_read(clkfreq);
+   count = snprintf(buf, 64, "%d\n", freq);
+
+   return count;
+}
+static DEVICE_ATTR_RO(freq);
+
+static struct attribute *clkfreq_attrs[] = {
+   _attr_freq.attr,
+   NULL,
+};
+
+static struct attribute_group clkfreq_attr_group = {
+   .attrs = clkfreq_attrs,
+};
+
+static int
+xrt_clkfreq_leaf_ioctl(struct platform_device *pdev, u32 cmd, void *arg)
+{
+   struct clkfreq  *clkfreq;
+   int ret = 0;
+
+   clkfreq = platform_get_drvdata(pdev);
+
+   switch (cmd) {
+   case XRT_XLEAF_EVENT:
+   /* Does not handle any event. */
+   break;
+   case XRT_CLKFREQ_READ: {
+   *(u32 *)arg = clkfreq_read(clkfreq);
+   break;
+   }
+   default:
+   xrt_err(pdev, "unsupported cmd %d", cmd);
+   return -EINVAL;
+   }
+
+   return ret;

[PATCH V3 XRT Alveo 12/18] fpga: xrt: ICAP platform driver

2021-02-17 Thread Lizhi Hou
Add ICAP driver. ICAP is a hardware function discovered by walking
firmware metadata. A platform device node will be created for it.
FPGA bitstream is written to hardware through ICAP.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/icap.h |  29 +++
 drivers/fpga/xrt/lib/xleaf/icap.c | 317 ++
 2 files changed, 346 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/icap.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/icap.c

diff --git a/drivers/fpga/xrt/include/xleaf/icap.h 
b/drivers/fpga/xrt/include/xleaf/icap.h
new file mode 100644
index ..a14fc0ffa78f
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/icap.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for XRT ICAP Leaf Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_ICAP_H_
+#define _XRT_ICAP_H_
+
+#include "xleaf.h"
+
+/*
+ * ICAP driver IOCTL calls.
+ */
+enum xrt_icap_ioctl_cmd {
+   XRT_ICAP_WRITE = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+   XRT_ICAP_IDCODE,
+};
+
+struct xrt_icap_ioctl_wr {
+   void*xiiw_bit_data;
+   u32 xiiw_data_len;
+};
+
+#endif /* _XRT_ICAP_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/icap.c 
b/drivers/fpga/xrt/lib/xleaf/icap.c
new file mode 100644
index ..0500a97bdef9
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/icap.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA ICAP Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ *  Sonal Santan 
+ *  Max Zhen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/icap.h"
+#include "xclbin-helper.h"
+
+#define XRT_ICAP "xrt_icap"
+
+#define ICAP_ERR(icap, fmt, arg...)\
+   xrt_err((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_WARN(icap, fmt, arg...)   \
+   xrt_warn((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_INFO(icap, fmt, arg...)   \
+   xrt_info((icap)->pdev, fmt "\n", ##arg)
+#define ICAP_DBG(icap, fmt, arg...)\
+   xrt_dbg((icap)->pdev, fmt "\n", ##arg)
+
+/*
+ * AXI-HWICAP IP register layout
+ */
+struct icap_reg {
+   u32 ir_rsvd1[7];
+   u32 ir_gier;
+   u32 ir_isr;
+   u32 ir_rsvd2;
+   u32 ir_ier;
+   u32 ir_rsvd3[53];
+   u32 ir_wf;
+   u32 ir_rf;
+   u32 ir_sz;
+   u32 ir_cr;
+   u32 ir_sr;
+   u32 ir_wfv;
+   u32 ir_rfo;
+   u32 ir_asr;
+} __packed;
+
+struct icap {
+   struct platform_device  *pdev;
+   struct icap_reg *icap_regs;
+   struct mutexicap_lock; /* icap dev lock */
+
+   unsigned intidcode;
+};
+
+static inline u32 reg_rd(void __iomem *reg)
+{
+   if (!reg)
+   return -1;
+
+   return ioread32(reg);
+}
+
+static inline void reg_wr(void __iomem *reg, u32 val)
+{
+   if (!reg)
+   return;
+
+   iowrite32(val, reg);
+}
+
+static int wait_for_done(struct icap *icap)
+{
+   u32 w;
+   int i = 0;
+
+   WARN_ON(!mutex_is_locked(>icap_lock));
+   for (i = 0; i < 10; i++) {
+   udelay(5);
+   w = reg_rd(>icap_regs->ir_sr);
+   ICAP_INFO(icap, "XHWICAP_SR: %x", w);
+   if (w & 0x5)
+   return 0;
+   }
+
+   ICAP_ERR(icap, "bitstream download timeout");
+   return -ETIMEDOUT;
+}
+
+static int icap_write(struct icap *icap, const u32 *word_buf, int size)
+{
+   int i;
+   u32 value = 0;
+
+   for (i = 0; i < size; i++) {
+   value = be32_to_cpu(word_buf[i]);
+   reg_wr(>icap_regs->ir_wf, value);
+   }
+
+   reg_wr(>icap_regs->ir_cr, 0x1);
+
+   for (i = 0; i < 20; i++) {
+   value = reg_rd(>icap_regs->ir_cr);
+   if ((value & 0x1) == 0)
+   return 0;
+   ndelay(50);
+   }
+
+   ICAP_ERR(icap, "writing %d dwords timeout", size);
+   return -EIO;
+}
+
+static int bitstream_helper(struct icap *icap, const u32 *word_buffer,
+   u32 word_count)
+{
+   u32 remain_word;
+   u32 word_written = 0;
+   int wr_fifo_vacancy = 0;
+   int err = 0;
+
+   WARN_ON(!mutex_is_locked(>icap_lock));
+   for (remain_word = word_count; remain_word > 0;
+   remain_word -= word_written, word_buffer += word_written) {
+   wr_fifo_vacancy = reg_rd(>icap_regs->ir_wfv);
+   if (wr_fifo_vacancy <= 0) {
+   ICAP_ERR(icap, "no vacancy: %d", wr_fifo_vacancy);
+   err = -EIO;
+   break;
+   }
+   word_written = (wr_fifo_vacancy < remain_word) ?
+   wr_fifo_vacancy : 

Re: [PATCH v3] vfs: fix copy_file_range regression in cross-fs copies

2021-02-17 Thread Amir Goldstein
On Thu, Feb 18, 2021 at 7:33 AM Olga Kornievskaia  wrote:
>
> On Wed, Feb 17, 2021 at 3:30 PM Luis Henriques  wrote:
> >
> > A regression has been reported by Nicolas Boichat, found while using the
> > copy_file_range syscall to copy a tracefs file.  Before commit
> > 5dae222a5ff0 ("vfs: allow copy_file_range to copy across devices") the
> > kernel would return -EXDEV to userspace when trying to copy a file across
> > different filesystems.  After this commit, the syscall doesn't fail anymore
> > and instead returns zero (zero bytes copied), as this file's content is
> > generated on-the-fly and thus reports a size of zero.
> >
> > This patch restores some cross-filesystems copy restrictions that existed
> > prior to commit 5dae222a5ff0 ("vfs: allow copy_file_range to copy across
> > devices").  It also introduces a flag (COPY_FILE_SPLICE) that can be used
> > by filesystems calling directly into the vfs copy_file_range to override
> > these restrictions.  Right now, only NFS needs to set this flag.
> >
> > Fixes: 5dae222a5ff0 ("vfs: allow copy_file_range to copy across devices")
> > Link: 
> > https://lore.kernel.org/linux-fsdevel/20210212044405.4120619-1-drink...@chromium.org/
> > Link: 
> > https://lore.kernel.org/linux-fsdevel/CANMq1KDZuxir2LM5jOTm0xx+BnvW=zmpsg47cyhfjwnw7zs...@mail.gmail.com/
> > Link: 
> > https://lore.kernel.org/linux-fsdevel/20210126135012.1.If45b7cdc3ff707bc1efa17f5366057d60603c45f@changeid/
> > Reported-by: Nicolas Boichat 
> > Signed-off-by: Luis Henriques 
> > ---
> > Ok, I've tried to address all the issues and comments.  Hopefully this v3
> > is a bit closer to the final fix.
> >
> > Changes since v2
> > - do all the required checks earlier, in generic_copy_file_checks(),
> >   adding new checks for ->remap_file_range
> > - new COPY_FILE_SPLICE flag
> > - don't remove filesystem's fallback to generic_copy_file_range()
> > - updated commit changelog (and subject)
> > Changes since v1 (after Amir review)
> > - restored do_copy_file_range() helper
> > - return -EOPNOTSUPP if fs doesn't implement CFR
> > - updated commit description
>
> In my testing, this patch breaks NFS server-to-server copy file.

Hi Olga,

Can you please provide more details on the failed tests.

Does it fail on the client between two nfs mounts or does it fail
on the server? If the latter, between which two filesystems on the server?

Thanks,
Amir.


[PATCH V3 XRT Alveo 18/18] fpga: xrt: Kconfig and Makefile updates for XRT drivers

2021-02-17 Thread Lizhi Hou
Update fpga Kconfig/Makefile and add Kconfig/Makefile for new drivers.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 MAINTAINERS| 11 +++
 drivers/Makefile   |  1 +
 drivers/fpga/Kconfig   |  2 ++
 drivers/fpga/Makefile  |  4 
 drivers/fpga/xrt/Kconfig   |  8 
 drivers/fpga/xrt/lib/Kconfig   | 16 
 drivers/fpga/xrt/lib/Makefile  | 30 ++
 drivers/fpga/xrt/metadata/Kconfig  | 12 
 drivers/fpga/xrt/metadata/Makefile | 16 
 drivers/fpga/xrt/mgmt/Kconfig  | 15 +++
 drivers/fpga/xrt/mgmt/Makefile | 19 +++
 11 files changed, 134 insertions(+)
 create mode 100644 drivers/fpga/xrt/Kconfig
 create mode 100644 drivers/fpga/xrt/lib/Kconfig
 create mode 100644 drivers/fpga/xrt/lib/Makefile
 create mode 100644 drivers/fpga/xrt/metadata/Kconfig
 create mode 100644 drivers/fpga/xrt/metadata/Makefile
 create mode 100644 drivers/fpga/xrt/mgmt/Kconfig
 create mode 100644 drivers/fpga/xrt/mgmt/Makefile

diff --git a/MAINTAINERS b/MAINTAINERS
index d3e847f7f3dc..e6e147c2454c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6973,6 +6973,17 @@ F:   Documentation/fpga/
 F: drivers/fpga/
 F: include/linux/fpga/
 
+FPGA XRT DRIVERS
+M: Lizhi Hou 
+R: Max Zhen 
+R: Sonal Santan 
+L: linux-f...@vger.kernel.org
+S: Maintained
+W: https://github.com/Xilinx/XRT
+F: Documentation/fpga/xrt.rst
+F: drivers/fpga/xrt/
+F: include/uapi/linux/xrt/
+
 FPU EMULATOR
 M: Bill Metzenthen 
 S: Maintained
diff --git a/drivers/Makefile b/drivers/Makefile
index fd11b9ac4cc3..e03912af8e48 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -178,6 +178,7 @@ obj-$(CONFIG_STM)   += hwtracing/stm/
 obj-$(CONFIG_ANDROID)  += android/
 obj-$(CONFIG_NVMEM)+= nvmem/
 obj-$(CONFIG_FPGA) += fpga/
+obj-y  += fpga/xrt/metadata/
 obj-$(CONFIG_FSI)  += fsi/
 obj-$(CONFIG_TEE)  += tee/
 obj-$(CONFIG_MULTIPLEXER)  += mux/
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 5645226ca3ce..aeca635b1f25 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -216,4 +216,6 @@ config FPGA_MGR_ZYNQMP_FPGA
  to configure the programmable logic(PL) through PS
  on ZynqMP SoC.
 
+source "drivers/fpga/xrt/Kconfig"
+
 endif # FPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index d8e21dfc6778..2b4453ff7c52 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -46,3 +46,7 @@ dfl-afu-objs += dfl-afu-error.o
 
 # Drivers for FPGAs which implement DFL
 obj-$(CONFIG_FPGA_DFL_PCI) += dfl-pci.o
+
+# XRT drivers for Alveo
+obj-$(CONFIG_FPGA_XRT_LIB) += xrt/lib/
+obj-$(CONFIG_FPGA_XRT_XMGMT)   += xrt/mgmt/
diff --git a/drivers/fpga/xrt/Kconfig b/drivers/fpga/xrt/Kconfig
new file mode 100644
index ..0e2c59589ddd
--- /dev/null
+++ b/drivers/fpga/xrt/Kconfig
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Xilinx Alveo FPGA device configuration
+#
+
+source "drivers/fpga/xrt/metadata/Kconfig"
+source "drivers/fpga/xrt/lib/Kconfig"
+source "drivers/fpga/xrt/mgmt/Kconfig"
diff --git a/drivers/fpga/xrt/lib/Kconfig b/drivers/fpga/xrt/lib/Kconfig
new file mode 100644
index ..eed5cb73f5e2
--- /dev/null
+++ b/drivers/fpga/xrt/lib/Kconfig
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# XRT Alveo FPGA device configuration
+#
+
+config FPGA_XRT_LIB
+   tristate "XRT Alveo Driver Library"
+   depends on HWMON && PCI && HAS_IOMEM
+   select FPGA_XRT_METADATA
+   help
+ Select this option to enable Xilinx XRT Alveo driver library. This
+ library is core infrastructure of XRT Alveo FPGA drivers which
+ provides functions for working with device nodes, iteration and
+ lookup of platform devices, common interfaces for platform devices,
+ plumbing of function call and ioctls between platform devices and
+ parent partitions.
diff --git a/drivers/fpga/xrt/lib/Makefile b/drivers/fpga/xrt/lib/Makefile
new file mode 100644
index ..5641231b2a36
--- /dev/null
+++ b/drivers/fpga/xrt/lib/Makefile
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2020-2021 Xilinx, Inc. All rights reserved.
+#
+# Authors: sonal.san...@xilinx.com
+#
+
+FULL_XRT_PATH=$(srctree)/$(src)/..
+FULL_DTC_PATH=$(srctree)/scripts/dtc/libfdt
+
+obj-$(CONFIG_FPGA_XRT_LIB) += xrt-lib.o
+
+xrt-lib-objs :=\
+   main.o  \
+   xroot.o \
+   xclbin.o\
+   subdev.o\
+   cdev.o  \
+   group.o \
+   xleaf/vsec.o\
+   xleaf/axigate.o \
+   xleaf/devctl.o 

mm/hmm.c:333:15: sparse: sparse: cast to non-scalar

2021-02-17 Thread kernel test robot
tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 
master
head:   f40ddce88593482919761f74910f42f4b84c004b
commit: dee081bf8f824cabeb7c7495367d5dad0a444eb1 READ_ONCE: Drop pointer 
qualifiers when reading from scalar types
date:   10 months ago
config: alpha-randconfig-s032-20210218 (attached as .config)
compiler: alpha-linux-gcc (GCC) 9.3.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.3-215-g0fb77bb6-dirty
# 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=dee081bf8f824cabeb7c7495367d5dad0a444eb1
git remote add linus 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git fetch --no-tags linus master
git checkout dee081bf8f824cabeb7c7495367d5dad0a444eb1
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 
CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=alpha 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 


"sparse warnings: (new ones prefixed by >>)"
>> mm/hmm.c:333:15: sparse: sparse: cast to non-scalar
>> mm/hmm.c:333:15: sparse: sparse: cast from non-scalar

vim +333 mm/hmm.c

53f5c3f489ecdd Jérôme Glisse   2018-04-10  318  
53f5c3f489ecdd Jérôme Glisse   2018-04-10  319  static int 
hmm_vma_walk_pmd(pmd_t *pmdp,
53f5c3f489ecdd Jérôme Glisse   2018-04-10  320  
unsigned long start,
53f5c3f489ecdd Jérôme Glisse   2018-04-10  321  
unsigned long end,
53f5c3f489ecdd Jérôme Glisse   2018-04-10  322  
struct mm_walk *walk)
53f5c3f489ecdd Jérôme Glisse   2018-04-10  323  {
53f5c3f489ecdd Jérôme Glisse   2018-04-10  324  struct hmm_vma_walk 
*hmm_vma_walk = walk->private;
53f5c3f489ecdd Jérôme Glisse   2018-04-10  325  struct hmm_range *range 
= hmm_vma_walk->range;
2288a9a68175ce Jason Gunthorpe 2020-03-05  326  uint64_t *pfns = 
>pfns[(start - range->start) >> PAGE_SHIFT];
2288a9a68175ce Jason Gunthorpe 2020-03-05  327  unsigned long npages = 
(end - start) >> PAGE_SHIFT;
2288a9a68175ce Jason Gunthorpe 2020-03-05  328  unsigned long addr = 
start;
53f5c3f489ecdd Jérôme Glisse   2018-04-10  329  pte_t *ptep;
d08faca018c461 Jérôme Glisse   2018-10-30  330  pmd_t pmd;
53f5c3f489ecdd Jérôme Glisse   2018-04-10  331  
53f5c3f489ecdd Jérôme Glisse   2018-04-10  332  again:
d08faca018c461 Jérôme Glisse   2018-10-30 @333  pmd = READ_ONCE(*pmdp);
d08faca018c461 Jérôme Glisse   2018-10-30  334  if (pmd_none(pmd))
b7a16c7ad790d0 Steven Price2020-02-03  335  return 
hmm_vma_walk_hole(start, end, -1, walk);
53f5c3f489ecdd Jérôme Glisse   2018-04-10  336  
d08faca018c461 Jérôme Glisse   2018-10-30  337  if 
(thp_migration_supported() && is_pmd_migration_entry(pmd)) {
a3eb13c1579ba9 Jason Gunthorpe 2020-03-27  338  if 
(hmm_range_need_fault(hmm_vma_walk, pfns, npages, 0)) {
d08faca018c461 Jérôme Glisse   2018-10-30  339  
hmm_vma_walk->last = addr;
d2e8d551165ccb Ralph Campbell  2019-07-25  340  
pmd_migration_entry_wait(walk->mm, pmdp);
73231612dc7c90 Jérôme Glisse   2019-05-13  341  return 
-EBUSY;
d08faca018c461 Jérôme Glisse   2018-10-30  342  }
7d082987e5e562 Jason Gunthorpe 2020-03-04  343  return 
hmm_pfns_fill(start, end, range, HMM_PFN_NONE);
2288a9a68175ce Jason Gunthorpe 2020-03-05  344  }
2288a9a68175ce Jason Gunthorpe 2020-03-05  345  
2288a9a68175ce Jason Gunthorpe 2020-03-05  346  if (!pmd_present(pmd)) {
a3eb13c1579ba9 Jason Gunthorpe 2020-03-27  347  if 
(hmm_range_need_fault(hmm_vma_walk, pfns, npages, 0))
2288a9a68175ce Jason Gunthorpe 2020-03-05  348  return 
-EFAULT;
d28c2c9a487708 Ralph Campbell  2019-11-04  349  return 
hmm_pfns_fill(start, end, range, HMM_PFN_ERROR);
2288a9a68175ce Jason Gunthorpe 2020-03-05  350  }
d08faca018c461 Jérôme Glisse   2018-10-30  351  
d08faca018c461 Jérôme Glisse   2018-10-30  352  if (pmd_devmap(pmd) || 
pmd_trans_huge(pmd)) {
53f5c3f489ecdd Jérôme Glisse   2018-04-10  353  /*
d2e8d551165ccb Ralph Campbell  2019-07-25  354   * No need to 
take pmd_lock here, even if some other thread
53f5c3f489ecdd Jérôme Glisse   2018-04-10  355   * is splitting 
the huge pmd we will get that event through
53f5c3f489ecdd Jérôme Glisse   2018-04-10  356   * mmu_notifier 
callback.
53f5c3f489ecdd Jérôme Glisse   2018-04-10  357   *
d2e8d551165ccb Ralph Campbell  2019-07-25  358   * So just read 
pmd value and 

Re: [PATCH v2 3/3] vdpa/mlx5: defer clear_virtqueues to until DRIVER_OK

2021-02-17 Thread Jason Wang



On 2021/2/18 上午5:55, Si-Wei Liu wrote:



On 2/16/2021 7:21 AM, Eli Cohen wrote:

On Thu, Feb 11, 2021 at 09:33:14AM +0200, Eli Cohen wrote:

On Wed, Feb 10, 2021 at 01:48:00PM -0800, Si-Wei Liu wrote:

While virtq is stopped,  get_vq_state() is supposed to
be  called to  get  sync'ed  with  the latest internal
avail_index from device. The saved avail_index is used
to restate  the virtq  once device is started.  Commit
b35ccebe3ef7 introduced the clear_virtqueues() routine
to  reset  the saved  avail_index,  however, the index
gets cleared a bit earlier before get_vq_state() tries
to read it. This would cause consistency problems when
virtq is restarted, e.g. through a series of link down
and link up events. We  could  defer  the  clearing of
avail_index  to  until  the  device  is to be started,
i.e. until  VIRTIO_CONFIG_S_DRIVER_OK  is set again in
set_status().

Fixes: b35ccebe3ef7 ("vdpa/mlx5: Restore the hardware used index 
after change map")

Signed-off-by: Si-Wei Liu 
Acked-by: Jason Wang 

Acked-by: Eli Cohen 


I take it back. I think we don't need to clear the indexes at all. In
case we need to restore indexes we'll get the right values through
set_vq_state(). If we suspend the virtqueue due to VM being suspended,
qemu will query first and will provide the the queried value. In case of
VM reboot, it will provide 0 in set_vq_state().

I am sending a patch that addresses both reboot and suspend.
With set_vq_state() repurposed to restoring used_index I'm fine with 
this approach.


Do I have to repost a v3 of this series while dropping the 3rd patch?

-Siwei 



Yes, please.

Thanks




RE: [PATCH v10 10/16] KVM: x86: Introduce KVM_GET_SHARED_PAGES_LIST ioctl

2021-02-17 Thread Kalra, Ashish
[AMD Public Use]

-Original Message-
From: Sean Christopherson  
Sent: Wednesday, February 17, 2021 10:13 AM
To: Kalra, Ashish 
Cc: pbonz...@redhat.com; t...@linutronix.de; mi...@redhat.com; h...@zytor.com; 
rkrc...@redhat.com; j...@8bytes.org; b...@suse.de; Lendacky, Thomas 
; x...@kernel.org; k...@vger.kernel.org; 
linux-kernel@vger.kernel.org; srutherf...@google.com; 
venu.busire...@oracle.com; Singh, Brijesh 
Subject: Re: [PATCH v10 10/16] KVM: x86: Introduce KVM_GET_SHARED_PAGES_LIST 
ioctl

On Wed, Feb 17, 2021, Kalra, Ashish wrote:
>> From: Sean Christopherson  On Thu, Feb 04, 2021, 
>> Ashish Kalra wrote:
>> > From: Brijesh Singh 
>> > 
>> > The ioctl is used to retrieve a guest's shared pages list.
>> 
>> >What's the performance hit to boot time if KVM_HC_PAGE_ENC_STATUS is 
>> >passed through to userspace?  That way, userspace could manage the 
>> >set of pages >in whatever data structure they want, and these get/set 
>> >ioctls go away.
>> 
>> What is the advantage of passing KVM_HC_PAGE_ENC_STATUS through to 
>> user-space ?
>> 
>> As such it is just a simple interface to get the shared page list via 
>> the get/set ioctl's. simply an array is passed to these ioctl to 
>> get/set the shared pages list.

> It eliminates any probability of the kernel choosing the wrong data 
> structure, and it's two fewer ioctls to maintain and test.

The set shared pages list ioctl cannot be avoided as it needs to be issued to 
setup the shared pages list on the migrated
VM, it cannot be achieved by passing KVM_HC_PAGE_ENC_STATUS through to 
user-space.

So it makes sense to add both get/set shared pages list ioctl, passing through 
to user-space is just adding more complexity
without any significant gains.

> >Also, aren't there plans for an in-guest migration helper?  If so, do 
> >we have any idea what that interface will look like?  E.g. if we're 
> >going to end up with a full >fledged driver in the guest, why not 
> >bite the bullet now and bypass KVM entirely?
> 
> Even the in-guest migration helper will be using page encryption 
> status hypercalls, so some interface is surely required.

>If it's a driver with a more extensive interace, then the hypercalls can be 
>replaced by a driver operation.  That's obviously a big if, though.

> Also the in-guest migration will be mainly an OVMF component, won't  
> really be a full fledged kernel driver in the guest.

>Is there code and/or a description of what the proposed helper would look like?

Not right now, there are prototype(s) under development, I assume they will be 
posted upstream soon.

Thanks,
Ashish


Re: [PATCH v2 2/3] vdpa/mlx5: fix feature negotiation across device reset

2021-02-17 Thread Jason Wang



On 2021/2/11 上午5:47, Si-Wei Liu wrote:

The mlx_features denotes the capability for which
set of virtio features is supported by device. In
principle, this field needs not be cleared during
virtio device reset, as this capability is static
and does not change across reset.

In fact, the current code may have the assumption
that mlx_features can be reloaded from firmware
via the .get_features ops after device is reset
(via the .set_status ops), which is unfortunately
not true. The userspace VMM might save a copy
of backend capable features and won't call into
kernel again to get it on reset. This causes all
virtio features getting disabled on newly created
virtqs after device reset, while guest would hold
mismatched view of available features. For e.g.,
the guest may still assume tx checksum offload
is available after reset and feature negotiation,
causing frames with bogus (incomplete) checksum
transmitted on the wire.

Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for supported mlx5 devices")
Signed-off-by: Si-Wei Liu 



Acked-by: Jason Wang 



---
  drivers/vdpa/mlx5/net/mlx5_vnet.c | 25 +++--
  1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c 
b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index b8416c4..7c1f789 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -1486,16 +1486,8 @@ static u64 mlx_to_vritio_features(u16 dev_features)
  static u64 mlx5_vdpa_get_features(struct vdpa_device *vdev)
  {
struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
-   struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
-   u16 dev_features;
  
-	dev_features = MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, device_features_bits_mask);

-   ndev->mvdev.mlx_features = mlx_to_vritio_features(dev_features);
-   if (MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, virtio_version_1_0))
-   ndev->mvdev.mlx_features |= BIT_ULL(VIRTIO_F_VERSION_1);
-   ndev->mvdev.mlx_features |= BIT_ULL(VIRTIO_F_ACCESS_PLATFORM);
-   print_features(mvdev, ndev->mvdev.mlx_features, false);
-   return ndev->mvdev.mlx_features;
+   return mvdev->mlx_features;
  }
  
  static int verify_min_features(struct mlx5_vdpa_dev *mvdev, u64 features)

@@ -1788,7 +1780,6 @@ static void mlx5_vdpa_set_status(struct vdpa_device 
*vdev, u8 status)
clear_virtqueues(ndev);
mlx5_vdpa_destroy_mr(>mvdev);
ndev->mvdev.status = 0;
-   ndev->mvdev.mlx_features = 0;
++mvdev->generation;
return;
}
@@ -1907,6 +1898,19 @@ static int mlx5_get_vq_irq(struct vdpa_device *vdv, u16 
idx)
.free = mlx5_vdpa_free,
  };
  
+static void query_virtio_features(struct mlx5_vdpa_net *ndev)

+{
+   struct mlx5_vdpa_dev *mvdev = >mvdev;
+   u16 dev_features;
+
+   dev_features = MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, 
device_features_bits_mask);
+   mvdev->mlx_features = mlx_to_vritio_features(dev_features);
+   if (MLX5_CAP_DEV_VDPA_EMULATION(mvdev->mdev, virtio_version_1_0))
+   mvdev->mlx_features |= BIT_ULL(VIRTIO_F_VERSION_1);
+   mvdev->mlx_features |= BIT_ULL(VIRTIO_F_ACCESS_PLATFORM);
+   print_features(mvdev, mvdev->mlx_features, false);
+}
+
  static int query_mtu(struct mlx5_core_dev *mdev, u16 *mtu)
  {
u16 hw_mtu;
@@ -2005,6 +2009,7 @@ static int mlx5v_probe(struct auxiliary_device *adev,
init_mvqs(ndev);
mutex_init(>reslock);
config = >config;
+   query_virtio_features(ndev);
err = query_mtu(mdev, >mtu);
if (err)
goto err_mtu;




[PATCH V3 XRT Alveo 14/18] fpga: xrt: clock platform driver

2021-02-17 Thread Lizhi Hou
Add clock driver. Clock is a hardware function discovered by walking
xclbin metadata. A platform device node will be created for it. Other
part of driver configures clock through clock driver.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xleaf/clock.h |  31 ++
 drivers/fpga/xrt/lib/xleaf/clock.c | 648 +
 2 files changed, 679 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xleaf/clock.h
 create mode 100644 drivers/fpga/xrt/lib/xleaf/clock.c

diff --git a/drivers/fpga/xrt/include/xleaf/clock.h 
b/drivers/fpga/xrt/include/xleaf/clock.h
new file mode 100644
index ..a2da59b32551
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf/clock.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for XRT Clock Leaf Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ */
+
+#ifndef _XRT_CLOCK_H_
+#define _XRT_CLOCK_H_
+
+#include "xleaf.h"
+#include 
+
+/*
+ * CLOCK driver IOCTL calls.
+ */
+enum xrt_clock_ioctl_cmd {
+   XRT_CLOCK_SET = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h */
+   XRT_CLOCK_GET,
+   XRT_CLOCK_VERIFY,
+};
+
+struct xrt_clock_ioctl_get {
+   u16 freq;
+   u32 freq_cnter;
+};
+
+#endif /* _XRT_CLOCK_H_ */
diff --git a/drivers/fpga/xrt/lib/xleaf/clock.c 
b/drivers/fpga/xrt/lib/xleaf/clock.c
new file mode 100644
index ..a067b501a607
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xleaf/clock.c
@@ -0,0 +1,648 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA Clock Wizard Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou
+ *  Sonal Santan 
+ *  David Zhang 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/clock.h"
+#include "xleaf/clkfreq.h"
+
+/* CLOCK_MAX_NUM_CLOCKS should be a concept from XCLBIN_ in the future */
+#define CLOCK_MAX_NUM_CLOCKS   4
+#define OCL_CLKWIZ_STATUS_OFFSET   0x4
+#define OCL_CLKWIZ_STATUS_MASK 0x
+#define OCL_CLKWIZ_STATUS_MEASURE_START0x1
+#define OCL_CLKWIZ_STATUS_MEASURE_DONE 0x2
+#define OCL_CLKWIZ_CONFIG_OFFSET(n)(0x200 + 4 * (n))
+#define CLOCK_DEFAULT_EXPIRE_SECS  1
+
+#define CLOCK_ERR(clock, fmt, arg...)  \
+   xrt_err((clock)->pdev, fmt "\n", ##arg)
+#define CLOCK_WARN(clock, fmt, arg...) \
+   xrt_warn((clock)->pdev, fmt "\n", ##arg)
+#define CLOCK_INFO(clock, fmt, arg...) \
+   xrt_info((clock)->pdev, fmt "\n", ##arg)
+#define CLOCK_DBG(clock, fmt, arg...)  \
+   xrt_dbg((clock)->pdev, fmt "\n", ##arg)
+
+#define XRT_CLOCK  "xrt_clock"
+
+struct clock {
+   struct platform_device  *pdev;
+   void __iomem*clock_base;
+   struct mutexclock_lock; /* clock dev lock */
+
+   const char  *clock_ep_name;
+};
+
+/*
+ * Precomputed table with config0 and config2 register values together with
+ * target frequency. The steps are approximately 5 MHz apart. Table is
+ * generated by wiz.pl.
+ */
+static const struct xmgmt_ocl_clockwiz {
+   /* target frequency */
+   unsigned short ocl;
+   /* config0 register */
+   unsigned long config0;
+   /* config2 register */
+   unsigned int config2;
+} frequency_table[] = {
+   {/*1275.000*/   10.000, 0x02EE0C01, 0x0001F47F},
+   {/*1575.000*/   15.000, 0x02EE0F01, 0x0069},
+   {/*1600.000*/   20.000, 0x1001, 0x0050},
+   {/*1600.000*/   25.000, 0x1001, 0x0040},
+   {/*1575.000*/   30.000, 0x02EE0F01, 0x0001F434},
+   {/*1575.000*/   35.000, 0x02EE0F01, 0x002D},
+   {/*1600.000*/   40.000, 0x1001, 0x0028},
+   {/*1575.000*/   45.000, 0x02EE0F01, 0x0023},
+   {/*1600.000*/   50.000, 0x1001, 0x0020},
+   {/*1512.500*/   55.000, 0x007D0F01, 0x0001F41B},
+   {/*1575.000*/   60.000, 0x02EE0F01, 0xFA1A},
+   {/*1462.500*/   65.000, 0x02710E01, 0x0001F416},
+   {/*1575.000*/   70.000, 0x02EE0F01, 0x0001F416},
+   {/*1575.000*/   75.000, 0x02EE0F01, 0x0015},
+   {/*1600.000*/   80.000, 0x1001, 0x0014},
+   {/*1487.500*/   85.000, 0x036B0E01, 0x0001F411},
+   {/*1575.000*/   90.000, 0x02EE0F01, 0x0001F411},
+   {/*1425.000*/   95.000, 0x00FA0E01, 0x000F},
+   {/*1600.000*/   100.000,0x1001, 0x0010},
+   {/*1575.000*/   105.000,0x02EE0F01, 0x000F},
+   {/*1512.500*/   110.000,0x007D0F01, 0x0002EE0D},
+   {/*1437.500*/   115.000,0x01770E01, 0x0001F40C},
+   {/*1575.000*/   120.000,0x02EE0F01, 0x7D0D},
+   {/*1562.500*/   125.000,  

[PATCH V3 XRT Alveo 09/18] fpga: xrt: fpga-mgr and region implementation for xclbin download

2021-02-17 Thread Lizhi Hou
fpga-mgr and region implementation for xclbin download which will be
called from main platform driver

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/mgmt/fmgr-drv.c| 187 +++
 drivers/fpga/xrt/mgmt/fmgr.h|  28 ++
 drivers/fpga/xrt/mgmt/main-region.c | 471 
 3 files changed, 686 insertions(+)
 create mode 100644 drivers/fpga/xrt/mgmt/fmgr-drv.c
 create mode 100644 drivers/fpga/xrt/mgmt/fmgr.h
 create mode 100644 drivers/fpga/xrt/mgmt/main-region.c

diff --git a/drivers/fpga/xrt/mgmt/fmgr-drv.c b/drivers/fpga/xrt/mgmt/fmgr-drv.c
new file mode 100644
index ..a44d35ecdb60
--- /dev/null
+++ b/drivers/fpga/xrt/mgmt/fmgr-drv.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FPGA Manager Support for Xilinx Alveo Management Function Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors: sonal.san...@xilinx.com
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "xclbin-helper.h"
+#include "xleaf.h"
+#include "fmgr.h"
+#include "xleaf/axigate.h"
+#include "xleaf/icap.h"
+#include "main-impl.h"
+
+struct xfpga_class {
+   const struct platform_device *pdev;
+   char  name[64];
+};
+
+/*
+ * xclbin download plumbing -- find the download subsystem, ICAP and
+ * pass the xclbin for heavy lifting
+ */
+static int xmgmt_download_bitstream(struct platform_device *pdev,
+   const struct axlf *xclbin)
+
+{
+   struct hw_icap_bit_header bit_header = { 0 };
+   struct platform_device *icap_leaf = NULL;
+   struct xrt_icap_ioctl_wr arg;
+   char *bitstream = NULL;
+   u64 bit_len;
+   int ret;
+
+   ret = xrt_xclbin_get_section(xclbin, BITSTREAM, (void **), 
_len);
+   if (ret || !bitstream) {
+   xrt_err(pdev, "bitstream not found");
+   return -ENOENT;
+   }
+   ret = xrt_xclbin_parse_bitstream_header(bitstream,
+   DMA_HWICAP_BITFILE_BUFFER_SIZE,
+   _header);
+   if (ret) {
+   ret = -EINVAL;
+   xrt_err(pdev, "invalid bitstream header");
+   goto done;
+   }
+   if (bit_header.header_length + bit_header.bitstream_length > bit_len) {
+   ret = -EINVAL;
+   xrt_err(pdev, "invalid bitstream length. header %d, bitstream 
%d, section len %lld",
+   bit_header.header_length, bit_header.bitstream_length, 
bit_len);
+   goto done;
+   }
+
+   icap_leaf = xleaf_get_leaf_by_id(pdev, XRT_SUBDEV_ICAP, 
PLATFORM_DEVID_NONE);
+   if (!icap_leaf) {
+   ret = -ENODEV;
+   xrt_err(pdev, "icap does not exist");
+   xrt_xclbin_free_header(_header);
+   goto done;
+   }
+   arg.xiiw_bit_data = bitstream + bit_header.header_length;
+   arg.xiiw_data_len = bit_header.bitstream_length;
+   ret = xleaf_ioctl(icap_leaf, XRT_ICAP_WRITE, );
+   if (ret)
+   xrt_err(pdev, "write bitstream failed, ret = %d", ret);
+
+   xrt_xclbin_free_header(_header);
+done:
+   if (icap_leaf)
+   xleaf_put_leaf(pdev, icap_leaf);
+   vfree(bitstream);
+
+   return ret;
+}
+
+/*
+ * There is no HW prep work we do here since we need the full
+ * xclbin for its sanity check.
+ */
+static int xmgmt_pr_write_init(struct fpga_manager *mgr,
+  struct fpga_image_info *info,
+  const char *buf, size_t count)
+{
+   const struct axlf *bin = (const struct axlf *)buf;
+   struct xfpga_class *obj = mgr->priv;
+
+   if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+   xrt_info(obj->pdev, "%s only supports partial 
reconfiguration\n", obj->name);
+   return -EINVAL;
+   }
+
+   if (count < sizeof(struct axlf))
+   return -EINVAL;
+
+   if (count > bin->m_header.m_length)
+   return -EINVAL;
+
+   xrt_info(obj->pdev, "Prepare download of xclbin %pUb of length %lld B",
+>m_header.uuid, bin->m_header.m_length);
+
+   return 0;
+}
+
+/*
+ * The implementation requries full xclbin image before we can start
+ * programming the hardware via ICAP subsystem. Full image is required
+ * for checking the validity of xclbin and walking the sections to
+ * discover the bitstream.
+ */
+static int xmgmt_pr_write(struct fpga_manager *mgr,
+ const char *buf, size_t count)
+{
+   const struct axlf *bin = (const struct axlf *)buf;
+   struct xfpga_class *obj = mgr->priv;
+
+   if (bin->m_header.m_length != count)
+   return -EINVAL;
+
+   return xmgmt_download_bitstream((void *)obj->pdev, bin);
+}
+
+static int xmgmt_pr_write_complete(struct fpga_manager *mgr,
+ 

[PATCH V3 XRT Alveo 07/18] fpga: xrt: management physical function driver (root)

2021-02-17 Thread Lizhi Hou
The PCIE device driver which attaches to management function on Alveo
devices. It instantiates one or more partition drivers which in turn
instantiate platform drivers. The instantiation of partition and platform
drivers is completely data driven.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xroot.h | 114 +++
 drivers/fpga/xrt/mgmt/root.c | 342 +++
 2 files changed, 456 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xroot.h
 create mode 100644 drivers/fpga/xrt/mgmt/root.c

diff --git a/drivers/fpga/xrt/include/xroot.h b/drivers/fpga/xrt/include/xroot.h
new file mode 100644
index ..752e10daa85e
--- /dev/null
+++ b/drivers/fpga/xrt/include/xroot.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#ifndef _XRT_ROOT_H_
+#define _XRT_ROOT_H_
+
+#include 
+#include "subdev_id.h"
+#include "events.h"
+
+typedef bool (*xrt_subdev_match_t)(enum xrt_subdev_id,
+   struct platform_device *, void *);
+#define XRT_SUBDEV_MATCH_PREV  ((xrt_subdev_match_t)-1)
+#define XRT_SUBDEV_MATCH_NEXT  ((xrt_subdev_match_t)-2)
+
+/*
+ * Root IOCTL calls.
+ */
+enum xrt_root_ioctl_cmd {
+   /* Leaf actions. */
+   XRT_ROOT_GET_LEAF = 0,
+   XRT_ROOT_PUT_LEAF,
+   XRT_ROOT_GET_LEAF_HOLDERS,
+
+   /* Group actions. */
+   XRT_ROOT_CREATE_GROUP,
+   XRT_ROOT_REMOVE_GROUP,
+   XRT_ROOT_LOOKUP_GROUP,
+   XRT_ROOT_WAIT_GROUP_BRINGUP,
+
+   /* Event actions. */
+   XRT_ROOT_EVENT,
+   XRT_ROOT_EVENT_ASYNC,
+
+   /* Device info. */
+   XRT_ROOT_GET_RESOURCE,
+   XRT_ROOT_GET_ID,
+
+   /* Misc. */
+   XRT_ROOT_HOT_RESET,
+   XRT_ROOT_HWMON,
+};
+
+struct xrt_root_ioctl_get_leaf {
+   struct platform_device *xpigl_pdev; /* caller's pdev */
+   xrt_subdev_match_t xpigl_match_cb;
+   void *xpigl_match_arg;
+   struct platform_device *xpigl_leaf; /* target leaf pdev */
+};
+
+struct xrt_root_ioctl_put_leaf {
+   struct platform_device *xpipl_pdev; /* caller's pdev */
+   struct platform_device *xpipl_leaf; /* target's pdev */
+};
+
+struct xrt_root_ioctl_lookup_group {
+   struct platform_device *xpilp_pdev; /* caller's pdev */
+   xrt_subdev_match_t xpilp_match_cb;
+   void *xpilp_match_arg;
+   int xpilp_grp_inst;
+};
+
+struct xrt_root_ioctl_get_holders {
+   struct platform_device *xpigh_pdev; /* caller's pdev */
+   char *xpigh_holder_buf;
+   size_t xpigh_holder_buf_len;
+};
+
+struct xrt_root_ioctl_get_res {
+   struct resource *xpigr_res;
+};
+
+struct xrt_root_ioctl_get_id {
+   unsigned short  xpigi_vendor_id;
+   unsigned short  xpigi_device_id;
+   unsigned short  xpigi_sub_vendor_id;
+   unsigned short  xpigi_sub_device_id;
+};
+
+struct xrt_root_ioctl_hwmon {
+   bool xpih_register;
+   const char *xpih_name;
+   void *xpih_drvdata;
+   const struct attribute_group **xpih_groups;
+   struct device *xpih_hwmon_dev;
+};
+
+typedef int (*xrt_subdev_root_cb_t)(struct device *, void *, u32, void *);
+int xrt_subdev_root_request(struct platform_device *self, u32 cmd, void *arg);
+
+/*
+ * Defines physical function (MPF / UPF) specific operations
+ * needed in common root driver.
+ */
+struct xroot_pf_cb {
+   void (*xpc_hot_reset)(struct pci_dev *pdev);
+};
+
+int xroot_probe(struct pci_dev *pdev, struct xroot_pf_cb *cb, void **root);
+void xroot_remove(void *root);
+bool xroot_wait_for_bringup(void *root);
+int xroot_add_vsec_node(void *root, char *dtb);
+int xroot_create_group(void *xr, char *dtb);
+int xroot_add_simple_node(void *root, char *dtb, const char *endpoint);
+void xroot_broadcast(void *root, enum xrt_events evt);
+
+#endif /* _XRT_ROOT_H_ */
diff --git a/drivers/fpga/xrt/mgmt/root.c b/drivers/fpga/xrt/mgmt/root.c
new file mode 100644
index ..583a37c9d30c
--- /dev/null
+++ b/drivers/fpga/xrt/mgmt/root.c
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo Management Function Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "xroot.h"
+#include "main-impl.h"
+#include "metadata.h"
+
+#define XMGMT_MODULE_NAME  "xmgmt"
+#define XMGMT_DRIVER_VERSION   "4.0.0"
+
+#define XMGMT_PDEV(xm) ((xm)->pdev)
+#define XMGMT_DEV(xm)  (&(XMGMT_PDEV(xm)->dev))
+#define xmgmt_err(xm, fmt, args...)\
+   dev_err(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args)
+#define xmgmt_warn(xm, fmt, args...)   \
+   dev_warn(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args)
+#define xmgmt_info(xm, fmt, args...)   \
+   dev_info(XMGMT_DEV(xm), "%s: " fmt, __func__, ##args)
+#define xmgmt_dbg(xm, fmt, args...)\
+   

[PATCH V3 XRT Alveo 06/18] fpga: xrt: platform driver infrastructure

2021-02-17 Thread Lizhi Hou
infrastructure code providing APIs for managing leaf driver instance
groups, facilitating inter-leaf driver calls and root calls, managing leaf
driver device nodes.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/events.h|  48 ++
 drivers/fpga/xrt/include/subdev_id.h |  43 ++
 drivers/fpga/xrt/include/xleaf.h | 276 +
 drivers/fpga/xrt/lib/cdev.c  | 231 +++
 drivers/fpga/xrt/lib/subdev.c| 871 +++
 drivers/fpga/xrt/lib/subdev_pool.h   |  53 ++
 drivers/fpga/xrt/lib/xroot.c | 598 ++
 7 files changed, 2120 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/events.h
 create mode 100644 drivers/fpga/xrt/include/subdev_id.h
 create mode 100644 drivers/fpga/xrt/include/xleaf.h
 create mode 100644 drivers/fpga/xrt/lib/cdev.c
 create mode 100644 drivers/fpga/xrt/lib/subdev.c
 create mode 100644 drivers/fpga/xrt/lib/subdev_pool.h
 create mode 100644 drivers/fpga/xrt/lib/xroot.c

diff --git a/drivers/fpga/xrt/include/events.h 
b/drivers/fpga/xrt/include/events.h
new file mode 100644
index ..2a9aae8bceb4
--- /dev/null
+++ b/drivers/fpga/xrt/include/events.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#ifndef _XRT_EVENTS_H_
+#define _XRT_EVENTS_H_
+
+#include 
+#include "subdev_id.h"
+
+/*
+ * Event notification.
+ */
+enum xrt_events {
+   XRT_EVENT_TEST = 0, /* for testing */
+   /*
+* Events related to specific subdev
+* Callback arg: struct xrt_event_arg_subdev
+*/
+   XRT_EVENT_POST_CREATION,
+   XRT_EVENT_PRE_REMOVAL,
+   /*
+* Events related to change of the whole board
+* Callback arg: 
+*/
+   XRT_EVENT_PRE_HOT_RESET,
+   XRT_EVENT_POST_HOT_RESET,
+   XRT_EVENT_PRE_GATE_CLOSE,
+   XRT_EVENT_POST_GATE_OPEN,
+};
+
+struct xrt_event_arg_subdev {
+   enum xrt_subdev_id xevt_subdev_id;
+   int xevt_subdev_instance;
+};
+
+struct xrt_event {
+   enum xrt_events xe_evt;
+   struct xrt_event_arg_subdev xe_subdev;
+};
+
+#endif /* _XRT_EVENTS_H_ */
diff --git a/drivers/fpga/xrt/include/subdev_id.h 
b/drivers/fpga/xrt/include/subdev_id.h
new file mode 100644
index ..6205a9f26196
--- /dev/null
+++ b/drivers/fpga/xrt/include/subdev_id.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#ifndef _XRT_SUBDEV_ID_H_
+#define _XRT_SUBDEV_ID_H_
+
+/*
+ * Every subdev driver should have an ID for others to refer to it.
+ * There can be unlimited number of instances of a subdev driver. A
+ *  tuple should be a unique identification of
+ * a specific instance of a subdev driver.
+ * NOTE: PLEASE do not change the order of IDs. Sub devices in the same
+ * group are initialized by this order.
+ */
+enum xrt_subdev_id {
+   XRT_SUBDEV_GRP = 0,
+   XRT_SUBDEV_VSEC = 1,
+   XRT_SUBDEV_VSEC_GOLDEN = 2,
+   XRT_SUBDEV_DEVCTL = 3,
+   XRT_SUBDEV_AXIGATE = 4,
+   XRT_SUBDEV_ICAP = 5,
+   XRT_SUBDEV_TEST = 6,
+   XRT_SUBDEV_MGMT_MAIN = 7,
+   XRT_SUBDEV_QSPI = 8,
+   XRT_SUBDEV_MAILBOX = 9,
+   XRT_SUBDEV_CMC = 10,
+   XRT_SUBDEV_CALIB = 11,
+   XRT_SUBDEV_CLKFREQ = 12,
+   XRT_SUBDEV_CLOCK = 13,
+   XRT_SUBDEV_SRSR = 14,
+   XRT_SUBDEV_UCS = 15,
+   XRT_SUBDEV_NUM = 16, /* Total number of subdevs. */
+   XRT_ROOT = -1, /* Special ID for root driver. */
+};
+
+#endif /* _XRT_SUBDEV_ID_H_ */
diff --git a/drivers/fpga/xrt/include/xleaf.h b/drivers/fpga/xrt/include/xleaf.h
new file mode 100644
index ..10215a75d474
--- /dev/null
+++ b/drivers/fpga/xrt/include/xleaf.h
@@ -0,0 +1,276 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *Cheng Zhen 
+ *Sonal Santan 
+ */
+
+#ifndef _XRT_XLEAF_H_
+#define _XRT_XLEAF_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "libfdt.h"
+#include "subdev_id.h"
+#include "xroot.h"
+#include "events.h"
+
+/* All subdev drivers should use below common routines to print out msg. */
+#define DEV(pdev)  (&(pdev)->dev)
+#define DEV_PDATA(pdev)\
+   ((struct xrt_subdev_platdata *)dev_get_platdata(DEV(pdev)))
+#define DEV_DRVDATA(pdev)  \
+   ((struct xrt_subdev_drvdata *)  \
+   platform_get_device_id(pdev)->driver_data)
+#define FMT_PRT(prt_fn, pdev, fmt, args...)\
+   ({typeof(pdev) (_pdev) = (pdev);\
+   prt_fn(DEV(_pdev), "%s %s: " fmt,   \
+   

[PATCH V3 XRT Alveo 08/18] fpga: xrt: main platform driver for management function device

2021-02-17 Thread Lizhi Hou
platform driver that handles IOCTLs, such as hot reset and xclbin download.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xmgmt-main.h |  37 ++
 drivers/fpga/xrt/mgmt/main-impl.h |  37 ++
 drivers/fpga/xrt/mgmt/main.c  | 693 ++
 include/uapi/linux/xrt/xmgmt-ioctl.h  |  46 ++
 4 files changed, 813 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xmgmt-main.h
 create mode 100644 drivers/fpga/xrt/mgmt/main-impl.h
 create mode 100644 drivers/fpga/xrt/mgmt/main.c
 create mode 100644 include/uapi/linux/xrt/xmgmt-ioctl.h

diff --git a/drivers/fpga/xrt/include/xmgmt-main.h 
b/drivers/fpga/xrt/include/xmgmt-main.h
new file mode 100644
index ..1216d1881f8e
--- /dev/null
+++ b/drivers/fpga/xrt/include/xmgmt-main.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#ifndef _XMGMT_MAIN_H_
+#define _XMGMT_MAIN_H_
+
+#include 
+#include "xleaf.h"
+
+enum xrt_mgmt_main_ioctl_cmd {
+   /* section needs to be vfree'd by caller */
+   XRT_MGMT_MAIN_GET_AXLF_SECTION = XRT_XLEAF_CUSTOM_BASE, /* See comments 
in xleaf.h */
+   /* vbnv needs to be kfree'd by caller */
+   XRT_MGMT_MAIN_GET_VBNV,
+};
+
+enum provider_kind {
+   XMGMT_BLP,
+   XMGMT_PLP,
+   XMGMT_ULP,
+};
+
+struct xrt_mgmt_main_ioctl_get_axlf_section {
+   enum provider_kind xmmigas_axlf_kind;
+   enum axlf_section_kind xmmigas_section_kind;
+   void *xmmigas_section;
+   u64 xmmigas_section_size;
+};
+
+#endif /* _XMGMT_MAIN_H_ */
diff --git a/drivers/fpga/xrt/mgmt/main-impl.h 
b/drivers/fpga/xrt/mgmt/main-impl.h
new file mode 100644
index ..dd1b3e3773cc
--- /dev/null
+++ b/drivers/fpga/xrt/mgmt/main-impl.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Alveo Management Function Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou 
+ * Cheng Zhen 
+ */
+
+#ifndef _XMGMT_MAIN_IMPL_H_
+#define _XMGMT_MAIN_IMPL_H_
+
+#include 
+#include "xmgmt-main.h"
+
+struct fpga_manager;
+int xmgmt_process_xclbin(struct platform_device *pdev,
+struct fpga_manager *fmgr,
+const struct axlf *xclbin,
+enum provider_kind kind);
+void xmgmt_region_cleanup_all(struct platform_device *pdev);
+
+int bitstream_axlf_mailbox(struct platform_device *pdev, const void *xclbin);
+int xmgmt_hot_reset(struct platform_device *pdev);
+
+/* Getting dtb for specified group. Caller should vfree returned dtb .*/
+char *xmgmt_get_dtb(struct platform_device *pdev, enum provider_kind kind);
+char *xmgmt_get_vbnv(struct platform_device *pdev);
+int xmgmt_get_provider_uuid(struct platform_device *pdev,
+   enum provider_kind kind, uuid_t *uuid);
+
+int xmgmt_main_register_leaf(void);
+void xmgmt_main_unregister_leaf(void);
+
+#endif /* _XMGMT_MAIN_IMPL_H_ */
diff --git a/drivers/fpga/xrt/mgmt/main.c b/drivers/fpga/xrt/mgmt/main.c
new file mode 100644
index ..66ffb4e7029d
--- /dev/null
+++ b/drivers/fpga/xrt/mgmt/main.c
@@ -0,0 +1,693 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA MGMT PF entry point driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Sonal Santan 
+ */
+
+#include 
+#include 
+#include "xclbin-helper.h"
+#include "metadata.h"
+#include "xleaf.h"
+#include 
+#include "xleaf/devctl.h"
+#include "xmgmt-main.h"
+#include "fmgr.h"
+#include "xleaf/icap.h"
+#include "xleaf/axigate.h"
+#include "main-impl.h"
+
+#define XMGMT_MAIN "xmgmt_main"
+
+struct xmgmt_main {
+   struct platform_device *pdev;
+   struct axlf *firmware_blp;
+   struct axlf *firmware_plp;
+   struct axlf *firmware_ulp;
+   bool flash_ready;
+   bool devctl_ready;
+   struct fpga_manager *fmgr;
+   struct mutex busy_mutex; /* busy lock */
+
+   uuid_t *blp_intf_uuids;
+   u32 blp_intf_uuid_num;
+};
+
+/* Caller should be responsible for freeing the returned string. */
+char *xmgmt_get_vbnv(struct platform_device *pdev)
+{
+   struct xmgmt_main *xmm = platform_get_drvdata(pdev);
+   const char *vbnv;
+   char *ret;
+   int i;
+
+   if (xmm->firmware_plp)
+   vbnv = xmm->firmware_plp->m_header.m_platformVBNV;
+   else if (xmm->firmware_blp)
+   vbnv = xmm->firmware_blp->m_header.m_platformVBNV;
+   else
+   return NULL;
+
+   ret = kstrdup(vbnv, GFP_KERNEL);
+   if (!ret)
+   return NULL;
+
+   for (i = 0; i < strlen(ret); i++) {
+   if (ret[i] == ':' || ret[i] == '.')
+   ret[i] = '_';
+   }
+   return ret;
+}
+
+static int get_dev_uuid(struct platform_device *pdev, char *uuidstr, size_t 
len)
+{
+   char 

[PATCH V3 XRT Alveo 05/18] fpga: xrt: group platform driver

2021-02-17 Thread Lizhi Hou
group driver that manages life cycle of a bunch of leaf driver instances
and bridges them with root.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/group.h |  27 
 drivers/fpga/xrt/lib/group.c | 265 +++
 2 files changed, 292 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/group.h
 create mode 100644 drivers/fpga/xrt/lib/group.c

diff --git a/drivers/fpga/xrt/include/group.h b/drivers/fpga/xrt/include/group.h
new file mode 100644
index ..1874cdd5120d
--- /dev/null
+++ b/drivers/fpga/xrt/include/group.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#ifndef _XRT_GROUP_H_
+#define _XRT_GROUP_H_
+
+#include "xleaf.h"
+
+/*
+ * Group driver IOCTL calls.
+ */
+enum xrt_group_ioctl_cmd {
+   XRT_GROUP_GET_LEAF = XRT_XLEAF_CUSTOM_BASE, /* See comments in xleaf.h 
*/
+   XRT_GROUP_PUT_LEAF,
+   XRT_GROUP_INIT_CHILDREN,
+   XRT_GROUP_FINI_CHILDREN,
+   XRT_GROUP_TRIGGER_EVENT,
+};
+
+#endif /* _XRT_GROUP_H_ */
diff --git a/drivers/fpga/xrt/lib/group.c b/drivers/fpga/xrt/lib/group.c
new file mode 100644
index ..6ba56eea479b
--- /dev/null
+++ b/drivers/fpga/xrt/lib/group.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA Group Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#include 
+#include 
+#include "xleaf.h"
+#include "subdev_pool.h"
+#include "group.h"
+#include "metadata.h"
+#include "main.h"
+
+#define XRT_GRP "xrt_group"
+
+struct xrt_group {
+   struct platform_device *pdev;
+   struct xrt_subdev_pool leaves;
+   bool leaves_created;
+   struct mutex lock; /* lock for group */
+};
+
+static int xrt_grp_root_cb(struct device *dev, void *parg,
+  u32 cmd, void *arg)
+{
+   int rc;
+   struct platform_device *pdev =
+   container_of(dev, struct platform_device, dev);
+   struct xrt_group *xg = (struct xrt_group *)parg;
+
+   switch (cmd) {
+   case XRT_ROOT_GET_LEAF_HOLDERS: {
+   struct xrt_root_ioctl_get_holders *holders =
+   (struct xrt_root_ioctl_get_holders *)arg;
+   rc = xrt_subdev_pool_get_holders(>leaves,
+holders->xpigh_pdev,
+holders->xpigh_holder_buf,
+holders->xpigh_holder_buf_len);
+   break;
+   }
+   default:
+   /* Forward parent call to root. */
+   rc = xrt_subdev_root_request(pdev, cmd, arg);
+   break;
+   }
+
+   return rc;
+}
+
+static int xrt_grp_create_leaves(struct xrt_group *xg)
+{
+   struct xrt_subdev_platdata *pdata = DEV_PDATA(xg->pdev);
+   enum xrt_subdev_id did;
+   struct xrt_subdev_endpoints *eps = NULL;
+   int ep_count = 0, i, ret = 0, failed = 0;
+   unsigned long mlen;
+   char *dtb, *grp_dtb = NULL;
+   const char *ep_name;
+
+   mutex_lock(>lock);
+
+   if (xg->leaves_created) {
+   mutex_unlock(>lock);
+   return -EEXIST;
+   }
+
+   xrt_info(xg->pdev, "bringing up leaves...");
+
+   /* Create all leaves based on dtb. */
+   if (!pdata)
+   goto bail;
+
+   mlen = xrt_md_size(DEV(xg->pdev), pdata->xsp_dtb);
+   if (mlen == XRT_MD_INVALID_LENGTH) {
+   xrt_err(xg->pdev, "invalid dtb, len %ld", mlen);
+   goto bail;
+   }
+
+   grp_dtb = vmalloc(mlen);
+   if (!grp_dtb)
+   goto bail;
+
+   memcpy(grp_dtb, pdata->xsp_dtb, mlen);
+   for (did = 0; did < XRT_SUBDEV_NUM;) {
+   eps = eps ? eps + 1 : xrt_drv_get_endpoints(did);
+   if (!eps || !eps->xse_names) {
+   did++;
+   eps = NULL;
+   continue;
+   }
+   ret = xrt_md_create(DEV(xg->pdev), );
+   if (ret) {
+   xrt_err(xg->pdev, "create md failed, drv %s",
+   xrt_drv_name(did));
+   failed++;
+   continue;
+   }
+   for (i = 0; eps->xse_names[i].ep_name ||
+eps->xse_names[i].regmap_name; i++) {
+   ep_name = (char *)eps->xse_names[i].ep_name;
+   if (!ep_name) {
+   xrt_md_get_compatible_endpoint(DEV(xg->pdev),
+  grp_dtb,
+  
eps->xse_names[i].regmap_name,
+  _name);
+

[PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager

2021-02-17 Thread Lizhi Hou
xrt-lib kernel module infrastructure code to register and manage all
leaf driver modules.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/lib/main.c | 274 
 drivers/fpga/xrt/lib/main.h |  17 +++
 2 files changed, 291 insertions(+)
 create mode 100644 drivers/fpga/xrt/lib/main.c
 create mode 100644 drivers/fpga/xrt/lib/main.h

diff --git a/drivers/fpga/xrt/lib/main.c b/drivers/fpga/xrt/lib/main.c
new file mode 100644
index ..36fb62710843
--- /dev/null
+++ b/drivers/fpga/xrt/lib/main.c
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for Xilinx Alveo FPGA Support
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ * Cheng Zhen 
+ */
+
+#include 
+#include "xleaf.h"
+#include "xroot.h"
+#include "main.h"
+
+#define XRT_IPLIB_MODULE_NAME  "xrt-lib"
+#define XRT_IPLIB_MODULE_VERSION   "4.0.0"
+#define XRT_MAX_DEVICE_NODES   128
+#define XRT_DRVNAME(drv)   ((drv)->driver.name)
+
+/*
+ * Subdev driver is known by ID to others. We map the ID to it's
+ * struct platform_driver, which contains it's binding name and driver/file 
ops.
+ * We also map it to the endpoint name in DTB as well, if it's different
+ * than the driver's binding name.
+ */
+struct xrt_drv_map {
+   struct list_head list;
+   enum xrt_subdev_id id;
+   struct platform_driver *drv;
+   struct xrt_subdev_endpoints *eps;
+   struct ida ida; /* manage driver instance and char dev minor */
+};
+
+static DEFINE_MUTEX(xrt_lib_lock); /* global lock protecting xrt_drv_maps list 
*/
+static LIST_HEAD(xrt_drv_maps);
+struct class *xrt_class;
+
+static inline struct xrt_subdev_drvdata *
+xrt_drv_map2drvdata(struct xrt_drv_map *map)
+{
+   return (struct xrt_subdev_drvdata *)map->drv->id_table[0].driver_data;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id_nolock(enum xrt_subdev_id id)
+{
+   const struct list_head *ptr;
+
+   list_for_each(ptr, _drv_maps) {
+   struct xrt_drv_map *tmap = list_entry(ptr, struct xrt_drv_map, 
list);
+
+   if (tmap->id == id)
+   return tmap;
+   }
+   return NULL;
+}
+
+static struct xrt_drv_map *
+xrt_drv_find_map_by_id(enum xrt_subdev_id id)
+{
+   struct xrt_drv_map *map;
+
+   mutex_lock(_lib_lock);
+   map = xrt_drv_find_map_by_id_nolock(id);
+   mutex_unlock(_lib_lock);
+   /*
+* map should remain valid even after lock is dropped since a registered
+* driver should only be unregistered when driver module is being 
unloaded,
+* which means that the driver should not be used by then.
+*/
+   return map;
+}
+
+static int xrt_drv_register_driver(struct xrt_drv_map *map)
+{
+   struct xrt_subdev_drvdata *drvdata;
+   int rc = 0;
+   const char *drvname = XRT_DRVNAME(map->drv);
+
+   rc = platform_driver_register(map->drv);
+   if (rc) {
+   pr_err("register %s platform driver failed\n", drvname);
+   return rc;
+   }
+
+   drvdata = xrt_drv_map2drvdata(map);
+   if (drvdata) {
+   /* Initialize dev_t for char dev node. */
+   if (xleaf_devnode_enabled(drvdata)) {
+   rc = 
alloc_chrdev_region(>xsd_file_ops.xsf_dev_t, 0,
+XRT_MAX_DEVICE_NODES, drvname);
+   if (rc) {
+   platform_driver_unregister(map->drv);
+   pr_err("failed to alloc dev minor for %s: 
%d\n", drvname, rc);
+   return rc;
+   }
+   } else {
+   drvdata->xsd_file_ops.xsf_dev_t = (dev_t)-1;
+   }
+   }
+
+   ida_init(>ida);
+
+   pr_info("%s registered successfully\n", drvname);
+
+   return 0;
+}
+
+static void xrt_drv_unregister_driver(struct xrt_drv_map *map)
+{
+   const char *drvname = XRT_DRVNAME(map->drv);
+   struct xrt_subdev_drvdata *drvdata;
+
+   ida_destroy(>ida);
+
+   drvdata = xrt_drv_map2drvdata(map);
+   if (drvdata && drvdata->xsd_file_ops.xsf_dev_t != (dev_t)-1) {
+   unregister_chrdev_region(drvdata->xsd_file_ops.xsf_dev_t,
+XRT_MAX_DEVICE_NODES);
+   }
+
+   platform_driver_unregister(map->drv);
+
+   pr_info("%s unregistered successfully\n", drvname);
+}
+
+int xleaf_register_driver(enum xrt_subdev_id id,
+ struct platform_driver *drv,
+ struct xrt_subdev_endpoints *eps)
+{
+   struct xrt_drv_map *map;
+
+   mutex_lock(_lib_lock);
+
+   map = xrt_drv_find_map_by_id_nolock(id);
+   if (map) {
+   mutex_unlock(_lib_lock);
+   pr_err("Id %d already has a registered driver, 0x%p\n",
+  id, map->drv);
+ 

Re: [PATCH for 5.10] vdpa_sim: fix param validation in vdpasim_get_config()

2021-02-17 Thread Jason Wang



On 2021/2/12 上午12:25, Stefano Garzarella wrote:

Commit 65b709586e222fa6ffd4166ac7fdb5d5dad113ee upstream.

Before this patch, if 'offset + len' was equal to
sizeof(struct virtio_net_config), the entire buffer wasn't filled,
returning incorrect values to the caller.

Since 'vdpasim->config' type is 'struct virtio_net_config', we can
safely copy its content under this condition.

Commit 65b709586e22 ("vdpa_sim: add get_config callback in
vdpasim_dev_attr") unintentionally solved it upstream while
refactoring vdpa_sim.c to support multiple devices. But we don't want
to backport it to stable branches as it contains many changes.

Fixes: 2c53d0f64c06 ("vdpasim: vDPA device simulator")
Cc:  # 5.10.x
Signed-off-by: Stefano Garzarella 
---
  drivers/vdpa/vdpa_sim/vdpa_sim.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
index 6a90fdb9cbfc..8ca178d7b02f 100644
--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
+++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
@@ -572,7 +572,7 @@ static void vdpasim_get_config(struct vdpa_device *vdpa, 
unsigned int offset,
  {
struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
  
-	if (offset + len < sizeof(struct virtio_net_config))

+   if (offset + len <= sizeof(struct virtio_net_config))
memcpy(buf, (u8 *)>config + offset, len);
  }
  



Acked-by: Jason Wang 




[PATCH V3 XRT Alveo 03/18] fpga: xrt: xclbin file helper functions

2021-02-17 Thread Lizhi Hou
Alveo FPGA firmware and partial reconfigure file are in xclbin format. Add
code to enumerate and extract sections from xclbin files. xclbin.h is cross
platform and used across all platforms and OS

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/xclbin-helper.h |  52 +++
 drivers/fpga/xrt/lib/xclbin.c| 394 ++
 include/uapi/linux/xrt/xclbin.h  | 408 +++
 3 files changed, 854 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/xclbin-helper.h
 create mode 100644 drivers/fpga/xrt/lib/xclbin.c
 create mode 100644 include/uapi/linux/xrt/xclbin.h

diff --git a/drivers/fpga/xrt/include/xclbin-helper.h 
b/drivers/fpga/xrt/include/xclbin-helper.h
new file mode 100644
index ..68218efc9d0b
--- /dev/null
+++ b/drivers/fpga/xrt/include/xclbin-helper.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *David Zhang 
+ *Sonal Santan 
+ */
+
+#ifndef _XRT_XCLBIN_H
+#define _XRT_XCLBIN_H
+
+#include 
+#include 
+#include 
+
+#define ICAP_XCLBIN_V2 "xclbin2"
+#define DMA_HWICAP_BITFILE_BUFFER_SIZE 1024
+#define MAX_XCLBIN_SIZE (1024 * 1024 * 1024) /* Assuming xclbin <= 1G, always 
*/
+
+enum axlf_section_kind;
+struct axlf;
+
+/**
+ * Bitstream header information as defined by Xilinx tools.
+ * Please note that this struct definition is not owned by the driver.
+ */
+struct hw_icap_bit_header {
+   unsigned int header_length; /* Length of header in 32 bit words */
+   unsigned int bitstream_length;  /* Length of bitstream to read in 
bytes*/
+   unsigned char *design_name; /* Design name get from bitstream */
+   unsigned char *part_name;   /* Part name read from bitstream */
+   unsigned char *date;   /* Date read from bitstream header */
+   unsigned char *time;   /* Bitstream creation time */
+   unsigned int magic_length;  /* Length of the magic numbers */
+   unsigned char *version; /* Version string */
+};
+
+const char *xrt_xclbin_kind_to_string(enum axlf_section_kind kind);
+int xrt_xclbin_get_section(const struct axlf *xclbin,
+  enum axlf_section_kind kind, void **data,
+  uint64_t *len);
+int xrt_xclbin_get_metadata(struct device *dev, const struct axlf *xclbin, 
char **dtb);
+int xrt_xclbin_parse_bitstream_header(const unsigned char *data,
+ unsigned int size,
+ struct hw_icap_bit_header *header);
+void xrt_xclbin_free_header(struct hw_icap_bit_header *header);
+const char *xrt_clock_type2epname(enum CLOCK_TYPE type);
+
+#endif /* _XRT_XCLBIN_H */
diff --git a/drivers/fpga/xrt/lib/xclbin.c b/drivers/fpga/xrt/lib/xclbin.c
new file mode 100644
index ..47dc6ca25c1b
--- /dev/null
+++ b/drivers/fpga/xrt/lib/xclbin.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA Driver XCLBIN parser
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors: David Zhang 
+ */
+
+#include 
+#include 
+#include 
+#include "xclbin-helper.h"
+#include "metadata.h"
+
+/* Used for parsing bitstream header */
+#define XHI_EVEN_MAGIC_BYTE 0x0f
+#define XHI_ODD_MAGIC_BYTE  0xf0
+
+/* Extra mode for IDLE */
+#define XHI_OP_IDLE  -1
+#define XHI_BIT_HEADER_FAILURE -1
+
+/* The imaginary module length register */
+#define XHI_MLR  15
+
+static inline unsigned char xhi_data_and_inc(const unsigned char *d, int *i, 
int sz)
+{
+   unsigned char data;
+
+   if (*i >= sz)
+   return -1;
+
+   data = d[*i];
+   (*i)++;
+
+   return data;
+}
+
+static const struct axlf_section_header *
+xrt_xclbin_get_section_hdr(const struct axlf *xclbin,
+  enum axlf_section_kind kind)
+{
+   int i = 0;
+
+   for (i = 0; i < xclbin->m_header.m_numSections; i++) {
+   if (xclbin->m_sections[i].m_sectionKind == kind)
+   return >m_sections[i];
+   }
+
+   return NULL;
+}
+
+static int
+xrt_xclbin_check_section_hdr(const struct axlf_section_header *header,
+u64 xclbin_len)
+{
+   int ret;
+
+   ret = (header->m_sectionOffset + header->m_sectionSize) > xclbin_len ? 
-EINVAL : 0;
+
+   return ret;
+}
+
+static int xrt_xclbin_section_info(const struct axlf *xclbin,
+  enum axlf_section_kind kind,
+  u64 *offset, u64 *size)
+{
+   const struct axlf_section_header *mem_header = NULL;
+   u64 xclbin_len;
+   int err = 0;
+
+   mem_header = xrt_xclbin_get_section_hdr(xclbin, kind);
+   if (!mem_header)
+   return -EINVAL;
+
+   xclbin_len = xclbin->m_header.m_length;
+   if (xclbin_len > MAX_XCLBIN_SIZE)
+   

[PATCH V3 XRT Alveo 02/18] fpga: xrt: driver metadata helper functions

2021-02-17 Thread Lizhi Hou
XRT drivers use device tree as metadata format to discover HW subsystems
behind PCIe BAR. Thus libfdt functions are called for driver to parse
device tree blob.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 drivers/fpga/xrt/include/metadata.h  | 229 
 drivers/fpga/xrt/metadata/metadata.c | 524 +++
 2 files changed, 753 insertions(+)
 create mode 100644 drivers/fpga/xrt/include/metadata.h
 create mode 100644 drivers/fpga/xrt/metadata/metadata.c

diff --git a/drivers/fpga/xrt/include/metadata.h 
b/drivers/fpga/xrt/include/metadata.h
new file mode 100644
index ..b929bc469b73
--- /dev/null
+++ b/drivers/fpga/xrt/include/metadata.h
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Runtime (XRT) driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *  Lizhi Hou 
+ */
+
+#ifndef _XRT_METADATA_H
+#define _XRT_METADATA_H
+
+#include 
+#include 
+#include 
+
+#define XRT_MD_INVALID_LENGTH (~0UL)
+
+#define XRT_MD_PROP_COMPATIBLE "compatible"
+#define XRT_MD_PROP_PF_NUM "pcie_physical_function"
+#define XRT_MD_PROP_BAR_IDX "pcie_bar_mapping"
+#define XRT_MD_PROP_IO_OFFSET "reg"
+#define XRT_MD_PROP_INTERRUPTS "interrupts"
+#define XRT_MD_PROP_INTERFACE_UUID "interface_uuid"
+#define XRT_MD_PROP_LOGIC_UUID "logic_uuid"
+#define XRT_MD_PROP_VERSION_MAJOR "firmware_version_major"
+
+#define XRT_MD_PROP_HWICAP "axi_hwicap"
+#define XRT_MD_PROP_PDI_CONFIG "pdi_config_mem"
+
+#define XRT_MD_NODE_ENDPOINTS "addressable_endpoints"
+#define XRT_MD_INTERFACES_PATH "/interfaces"
+
+#define XRT_MD_NODE_FIRMWARE "firmware"
+#define XRT_MD_NODE_INTERFACES "interfaces"
+#define XRT_MD_NODE_PARTITION_INFO "partition_info"
+
+#define XRT_MD_NODE_FLASH "ep_card_flash_program_00"
+#define XRT_MD_NODE_XVC_PUB "ep_debug_bscan_user_00"
+#define XRT_MD_NODE_XVC_PRI "ep_debug_bscan_mgmt_00"
+#define XRT_MD_NODE_SYSMON "ep_cmp_sysmon_00"
+#define XRT_MD_NODE_AF_BLP_CTRL_MGMT "ep_firewall_blp_ctrl_mgmt_00"
+#define XRT_MD_NODE_AF_BLP_CTRL_USER "ep_firewall_blp_ctrl_user_00"
+#define XRT_MD_NODE_AF_CTRL_MGMT "ep_firewall_ctrl_mgmt_00"
+#define XRT_MD_NODE_AF_CTRL_USER "ep_firewall_ctrl_user_00"
+#define XRT_MD_NODE_AF_CTRL_DEBUG "ep_firewall_ctrl_debug_00"
+#define XRT_MD_NODE_AF_DATA_H2C "ep_firewall_data_h2c_00"
+#define XRT_MD_NODE_AF_DATA_C2H "ep_firewall_data_c2h_00"
+#define XRT_MD_NODE_AF_DATA_P2P "ep_firewall_data_p2p_00"
+#define XRT_MD_NODE_AF_DATA_M2M "ep_firewall_data_m2m_00"
+#define XRT_MD_NODE_CMC_REG "ep_cmc_regmap_00"
+#define XRT_MD_NODE_CMC_RESET "ep_cmc_reset_00"
+#define XRT_MD_NODE_CMC_MUTEX "ep_cmc_mutex_00"
+#define XRT_MD_NODE_CMC_FW_MEM "ep_cmc_firmware_mem_00"
+#define XRT_MD_NODE_ERT_FW_MEM "ep_ert_firmware_mem_00"
+#define XRT_MD_NODE_ERT_CQ_MGMT "ep_ert_command_queue_mgmt_00"
+#define XRT_MD_NODE_ERT_CQ_USER "ep_ert_command_queue_user_00"
+#define XRT_MD_NODE_MAILBOX_MGMT "ep_mailbox_mgmt_00"
+#define XRT_MD_NODE_MAILBOX_USER "ep_mailbox_user_00"
+#define XRT_MD_NODE_GATE_PLP "ep_pr_isolate_plp_00"
+#define XRT_MD_NODE_GATE_ULP "ep_pr_isolate_ulp_00"
+#define XRT_MD_NODE_PCIE_MON "ep_pcie_link_mon_00"
+#define XRT_MD_NODE_DDR_CALIB "ep_ddr_mem_calib_00"
+#define XRT_MD_NODE_CLK_KERNEL1 "ep_aclk_kernel_00"
+#define XRT_MD_NODE_CLK_KERNEL2 "ep_aclk_kernel_01"
+#define XRT_MD_NODE_CLK_KERNEL3 "ep_aclk_hbm_00"
+#define XRT_MD_NODE_KDMA_CTRL "ep_kdma_ctrl_00"
+#define XRT_MD_NODE_FPGA_CONFIG "ep_fpga_configuration_00"
+#define XRT_MD_NODE_ERT_SCHED "ep_ert_sched_00"
+#define XRT_MD_NODE_XDMA "ep_xdma_00"
+#define XRT_MD_NODE_MSIX "ep_msix_00"
+#define XRT_MD_NODE_QDMA "ep_qdma_00"
+#define XRT_MD_XRT_MD_NODE_QDMA4 "ep_qdma4_00"
+#define XRT_MD_NODE_STM "ep_stream_traffic_manager_00"
+#define XRT_MD_NODE_STM4 "ep_stream_traffic_manager4_00"
+#define XRT_MD_NODE_CLK_SHUTDOWN "ep_aclk_shutdown_00"
+#define XRT_MD_NODE_ERT_BASE "ep_ert_base_address_00"
+#define XRT_MD_NODE_ERT_RESET "ep_ert_reset_00"
+#define XRT_MD_NODE_CLKFREQ_K1 "ep_freq_cnt_aclk_kernel_00"
+#define XRT_MD_NODE_CLKFREQ_K2 "ep_freq_cnt_aclk_kernel_01"
+#define XRT_MD_NODE_CLKFREQ_HBM "ep_freq_cnt_aclk_hbm_00"
+#define XRT_MD_NODE_GAPPING "ep_gapping_demand_00"
+#define XRT_MD_NODE_UCS_CONTROL_STATUS "ep_ucs_control_status_00"
+#define XRT_MD_NODE_P2P "ep_p2p_00"
+#define XRT_MD_NODE_REMAP_P2P "ep_remap_p2p_00"
+#define XRT_MD_NODE_DDR4_RESET_GATE "ep_ddr_mem_srsr_gate_00"
+#define XRT_MD_NODE_ADDR_TRANSLATOR "ep_remap_data_c2h_00"
+#define XRT_MD_NODE_MAILBOX_XRT "ep_mailbox_user_to_ert_00"
+#define XRT_MD_NODE_PMC_INTR   "ep_pmc_intr_00"
+#define XRT_MD_NODE_PMC_MUX"ep_pmc_mux_00"
+
+/* driver defined endpoints */
+#define XRT_MD_NODE_VSEC "drv_ep_vsec_00"
+#define XRT_MD_NODE_VSEC_GOLDEN "drv_ep_vsec_golden_00"
+#define XRT_MD_NODE_BLP_ROM "drv_ep_blp_rom_00"
+#define XRT_MD_NODE_MAILBOX_VSEC "ep_mailbox_vsec_00"
+#define XRT_MD_NODE_PLAT_INFO "drv_ep_platform_info_mgmt_00"
+#define XRT_MD_NODE_TEST 

[PATCH V3 XRT Alveo 01/18] Documentation: fpga: Add a document describing XRT Alveo drivers

2021-02-17 Thread Lizhi Hou
Describe XRT driver architecture and provide basic overview of
Xilinx Alveo platform.

Signed-off-by: Sonal Santan 
Signed-off-by: Max Zhen 
Signed-off-by: Lizhi Hou 
---
 Documentation/fpga/index.rst |   1 +
 Documentation/fpga/xrt.rst   | 842 +++
 2 files changed, 843 insertions(+)
 create mode 100644 Documentation/fpga/xrt.rst

diff --git a/Documentation/fpga/index.rst b/Documentation/fpga/index.rst
index f80f95667ca2..30134357b70d 100644
--- a/Documentation/fpga/index.rst
+++ b/Documentation/fpga/index.rst
@@ -8,6 +8,7 @@ fpga
 :maxdepth: 1
 
 dfl
+xrt
 
 .. only::  subproject and html
 
diff --git a/Documentation/fpga/xrt.rst b/Documentation/fpga/xrt.rst
new file mode 100644
index ..9bc2d2785cb9
--- /dev/null
+++ b/Documentation/fpga/xrt.rst
@@ -0,0 +1,842 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==
+XRTV2 Linux Kernel Driver Overview
+==
+
+Authors:
+
+* Sonal Santan 
+* Max Zhen 
+* Lizhi Hou 
+
+XRTV2 drivers are second generation `XRT `_
+drivers which support `Alveo 
`_
+PCIe platforms from Xilinx.
+
+XRTV2 drivers support *subsystem* style data driven platforms where driver's
+configuration and behavior is determined by meta data provided by the platform
+(in *device tree* format). Primary management physical function (MPF) driver
+is called **xmgmt**. Primary user physical function (UPF) driver is called
+**xuser** and is under development. xrt driver framework and HW subsystem
+drivers are packaged into a library module called **xrt-lib**, which is
+shared by **xmgmt** and **xuser** (under development). The xrt driver framework
+implements a pseudo-bus which is used to discover HW subsystems and facilitate
+inter HW subsystem interaction.
+
+Driver Modules
+==
+
+xrt-lib.ko
+--
+
+Repository of all subsystem drivers and pure software modules that can 
potentially
+be shared between xmgmt and xuser. All these drivers are structured as Linux
+*platform driver* and are instantiated by xmgmt (or xuser under development) 
based
+on meta data associated with hardware. The metadata is in the form of device 
tree
+as mentioned before. Each platform driver statically defines a subsystem node
+array by using node name or a string in its ``compatible`` property. And this
+array is eventually translated to IOMEM resources of the platform device.
+
+The xrt-lib core infrastructure provides hooks to platform drivers for device 
node
+management, user file operations and ioctl callbacks. The core also provides 
pseudo-bus
+functionality for platform driver registration, discovery and inter platform 
driver
+ioctl calls.
+
+.. note::
+   See code in ``include/xleaf.h``
+
+
+xmgmt.ko
+
+
+The xmgmt driver is a PCIe device driver driving MPF found on Xilinx's Alveo
+PCIE device. It consists of one *root* driver, one or more *group* drivers
+and one or more *xleaf* drivers. The root and MPF specific xleaf drivers are
+in xmgmt.ko. The group driver and other xleaf drivers are in xrt-lib.ko.
+
+The instantiation of specific group driver or xleaf driver is completely data
+driven based on meta data (mostly in device tree format) found through VSEC
+capability and inside firmware files, such as platform xsabin or user xclbin 
file.
+The root driver manages life cycle of multiple group drivers, which, in turn,
+manages multiple xleaf drivers. This allows a single set of driver code to 
support
+all kinds of subsystems exposed by different shells. The difference among all
+these subsystems will be handled in xleaf drivers with root and group drivers
+being part of the infrastructure and provide common services for all leaves
+found on all platforms.
+
+The driver object model looks like the following::
+
++---+
+|   xroot   |
++-+-+
+  |
+  +---+---+
+  |   |
+  v   v
++---+  +---+
+|   group   |...   |   group   |
++-+-+  +--++
+  |   |
+  |   |
++-+++-++
+|  ||  |
+v  vv  v
++---+  +---++---+  +---+
+| xleaf |..| xleaf || xleaf |..| xleaf |
++---+  +---++---+  +---+
+
+As an example for Xilinx Alveo U50 before user xclbin download, the tree
+looks like the following::
+
++---+
+|   xmgmt   |
++-+-+
+  |
+

[PATCH V3 XRT Alveo 00/18] XRT Alveo driver overview

2021-02-17 Thread Lizhi Hou
Hello,

This is V3 of patch series which adds management physical function driver for 
Xilinx
Alveo PCIe accelerator cards, 
https://www.xilinx.com/products/boards-and-kits/alveo.html
This driver is part of Xilinx Runtime (XRT) open source stack.

XILINX ALVEO PLATFORM ARCHITECTURE

Alveo PCIe FPGA based platforms have a static *shell* partition and a partial
re-configurable *user* partition. The shell partition is automatically loaded 
from
flash when host is booted and PCIe is enumerated by BIOS. Shell cannot be 
changed
till the next cold reboot. The shell exposes two PCIe physical functions:

1. management physical function
2. user physical function

The patch series includes Documentation/xrt.rst which describes Alveo platform,
XRT driver architecture and deployment model in more detail.

Users compile their high level design in C/C++/OpenCL or RTL into FPGA image 
using
Vitis https://www.xilinx.com/products/design-tools/vitis/vitis-platform.html
tools. The compiled image is packaged as xclbin which contains partial bitstream
for the user partition and necessary metadata. Users can dynamically swap the 
image
running on the user partition in order to switch between different workloads by
loading different xclbins.

XRT DRIVERS FOR XILINX ALVEO

XRT Linux kernel driver *xmgmt* binds to management physical function of Alveo
platform. The modular driver framework is organized into several platform 
drivers
which primarily handle the following functionality:

1.  Loading firmware container also called xsabin at driver attach time
2.  Loading of user compiled xclbin with FPGA Manager integration
3.  Clock scaling of image running on user partition
4.  In-band sensors: temp, voltage, power, etc.
5.  Device reset and rescan

The platform drivers are packaged into *xrt-lib* helper module with well
defined interfaces. The module provides a pseudo-bus implementation for the
platform drivers. More details on the driver model can be found in
Documentation/xrt.rst.

User physical function driver is not included in this patch series.

LIBFDT REQUIREMENT

XRT driver infrastructure uses Device Tree as a metadata format to discover
HW subsystems in the Alveo PCIe device. The Device Tree schema used by XRT
is documented in Documentation/xrt.rst. Unlike previous V1 and V2 version
of patch series, V3 version does not require export of libfdt symbols.

TESTING AND VALIDATION

xmgmt driver can be tested with full XRT open source stack which includes user
space libraries, board utilities and (out of tree) first generation user 
physical
function driver xocl. XRT open source runtime stack is available at
https://github.com/Xilinx/XRT

Complete documentation for XRT open source stack including sections on Alveo/XRT
security and platform architecture can be found here:

https://xilinx.github.io/XRT/master/html/index.html
https://xilinx.github.io/XRT/master/html/security.html
https://xilinx.github.io/XRT/master/html/platforms_partitions.html

Changes since v2:
- Streamlined the driver framework into *xleaf*, *group* and *xroot*
- Updated documentation to show the driver model with examples
- Addressed kernel test robot errors
- Added a selftest for basic driver framework
- Documented device tree schema
- Removed need to export libfdt symbols

Changes since v1:
- Updated the driver to use fpga_region and fpga_bridge for FPGA
  programming
- Dropped platform drivers not related to PR programming to focus on XRT
  core framework
- Updated Documentation/fpga/xrt.rst with information on XRT core framework
- Addressed checkpatch issues
- Dropped xrt- prefix from some header files

For reference V1 version of patch series can be found here:

https://lore.kernel.org/lkml/20201217075046.28553-1-son...@xilinx.com/
https://lore.kernel.org/lkml/20201217075046.28553-2-son...@xilinx.com/
https://lore.kernel.org/lkml/20201217075046.28553-3-son...@xilinx.com/
https://lore.kernel.org/lkml/20201217075046.28553-4-son...@xilinx.com/
https://lore.kernel.org/lkml/20201217075046.28553-5-son...@xilinx.com/
https://lore.kernel.org/lkml/20201217075046.28553-6-son...@xilinx.com/
https://lore.kernel.org/lkml/20201217075046.28553-7-son...@xilinx.com/

Lizhi Hou (18):
  Documentation: fpga: Add a document describing XRT Alveo drivers
  fpga: xrt: driver metadata helper functions
  fpga: xrt: xclbin file helper functions
  fpga: xrt: xrt-lib platform driver manager
  fpga: xrt: group platform driver
  fpga: xrt: platform driver infrastructure
  fpga: xrt: management physical function driver (root)
  fpga: xrt: main platform driver for management function device
  fpga: xrt: fpga-mgr and region implementation for xclbin download
  fpga: xrt: VSEC platform driver
  fpga: xrt: UCS platform driver
  fpga: xrt: ICAP platform driver
  fpga: xrt: devctl platform driver
  fpga: xrt: clock platform driver
  fpga: xrt: clock frequence counter platform driver
  fpga: xrt: DDR calibration platform driver
  fpga: xrt: partition isolation platform driver
  fpga: xrt: 

RE: [PATCH] clk: imx8mp: Remove the none exist pcie clocks

2021-02-17 Thread Richard Zhu

> -Original Message-
> From: Jacky Bai 
> Sent: Thursday, February 18, 2021 2:11 PM
> To: Richard Zhu ; shawn...@kernel.org
> Cc: dl-linux-imx ; linux-arm-ker...@lists.infradead.org;
> linux-kernel@vger.kernel.org; Richard Zhu 
> Subject: RE: [PATCH] clk: imx8mp: Remove the none exist pcie clocks
> 
> > -Original Message-
> > From: Richard Zhu [mailto:hongxing@nxp.com]
> > Sent: Thursday, February 18, 2021 1:54 PM
> > To: shawn...@kernel.org; Jacky Bai 
> > Cc: dl-linux-imx ;
> > linux-arm-ker...@lists.infradead.org;
> > linux-kernel@vger.kernel.org; Richard Zhu 
> > Subject: [PATCH] clk: imx8mp: Remove the none exist pcie clocks
> >
> > In the i.MX8MP PCIe design, the PCIe PHY REF clock comes from external
> > OSC or internal system PLL. It is configured in the IOMUX_GPR14
> > register directly, and can't be contolled by CCM at all.
> > Remove the PCIE PHY clock from clock driver to clean up codes.
> > There is only one PCIe in i.MX8MP, remove the none exist second PCIe
> > related clocks.
> >
> 
> As Shawn suggested before, it is better to remove the corresponding clock ID
> in include/dt-bindings/clock/imx8mp-clock.h
> 
[Richard Zhu] Thanks for reminding.
Is it fine to leave the holes in the ID definitions in the header file if they 
are removed?

Best Regards
Richard Zhu
> BR
> Jacky Bai
> 
> > Signed-off-by: Richard Zhu 
> > Reviewed-by: Jason Liu 
> > ---
> >  drivers/clk/imx/clk-imx8mp.c | 15 ---
> >  1 file changed, 15 deletions(-)
> >
> > diff --git a/drivers/clk/imx/clk-imx8mp.c
> > b/drivers/clk/imx/clk-imx8mp.c index 2f4e1d674e1c..afbeb6bf1909 100644
> > --- a/drivers/clk/imx/clk-imx8mp.c
> > +++ b/drivers/clk/imx/clk-imx8mp.c
> > @@ -152,10 +152,6 @@ static const char * const imx8mp_can2_sels[] =
> > {"osc_24m", "sys_pll2_200m", "sys
> > "sys_pll1_160m", 
> > "sys_pll1_800m",
> "sys_pll3_out",
> > "sys_pll2_250m", 
> > "audio_pll2_out", };
> >
> > -static const char * const imx8mp_pcie_phy_sels[] = {"osc_24m",
> > "sys_pll2_100m", "sys_pll2_500m",
> > -   "clk_ext1", "clk_ext2", 
> > "clk_ext3",
> > -   "clk_ext4", 
> > "sys_pll1_400m", };
> > -
> >  static const char * const imx8mp_pcie_aux_sels[] = {"osc_24m",
> > "sys_pll2_200m", "sys_pll2_50m",
> > "sys_pll3_out", 
> > "sys_pll2_100m",
> "sys_pll1_80m",
> > "sys_pll1_160m", 
> > "sys_pll1_200m", }; @@
> > -380,14 +376,6 @@ static const char * const imx8mp_memrepair_sels[] =
> > {"osc_24m", "sys_pll2_100m",
> > "sys_pll1_800m", 
> > "sys_pll2_1000m",
> "sys_pll3_out",
> > "clk_ext3", 
> > "audio_pll2_out", };
> >
> > -static const char * const imx8mp_pcie2_ctrl_sels[] = {"osc_24m",
> > "sys_pll2_250m", "sys_pll2_200m",
> > - "sys_pll1_266m", 
> > "sys_pll1_800m",
> > "sys_pll2_500m",
> > - "sys_pll2_333m", 
> > "sys_pll3_out", };
> > -
> > -static const char * const imx8mp_pcie2_phy_sels[] = {"osc_24m",
> > "sys_pll2_100m", "sys_pll2_500m",
> > -"clk_ext1", "clk_ext2", 
> > "clk_ext3",
> > -"clk_ext4", 
> > "sys_pll1_400m", };
> > -
> >  static const char * const imx8mp_media_mipi_test_byte_sels[] =
> > {"osc_24m", "sys_pll2_200m", "sys_pll2_50m",
> > "sys_pll3_out", 
> > "sys_pll2_100m",
> > "sys_pll1_80m", 
> > "sys_pll1_160m", @@
> > -585,7 +573,6 @@ static int imx8mp_clocks_probe(struct platform_device
> > *pdev)
> > hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2",
> > imx8mp_vpu_g2_sels, ccm_base + 0xa180);
> > hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1",
> > imx8mp_can1_sels, ccm_base + 0xa200);
> > hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2",
> > imx8mp_can2_sels, ccm_base + 0xa280);
> > -   hws[IMX8MP_CLK_PCIE_PHY] = imx8m_clk_hw_composite("pcie_phy",
> > imx8mp_pcie_phy_sels, ccm_base + 0xa380);
> > hws[IMX8MP_CLK_PCIE_AUX] = imx8m_clk_hw_composite("pcie_aux",
> > imx8mp_pcie_aux_sels, ccm_base + 0xa400);
> > hws[IMX8MP_CLK_I2C5] = imx8m_clk_hw_composite("i2c5",
> > imx8mp_i2c5_sels, ccm_base + 0xa480);
> > hws[IMX8MP_CLK_I2C6] = imx8m_clk_hw_composite("i2c6",
> > imx8mp_i2c6_sels, ccm_base + 0xa500); @@ -643,8 +630,6 @@ static int
> > imx8mp_clocks_probe(struct platform_device *pdev)
> > hws[IMX8MP_CLK_MEDIA_CAM2_PIX] =
> > imx8m_clk_hw_composite("media_cam2_pix",
> > imx8mp_media_cam2_pix_sels, ccm_base + 0xbe80);
> > hws[IMX8MP_CLK_MEDIA_LDB] =
> > 

Re: [PATCH v14 06/11] x86/elf: Move vmcore_elf_check_arch_cross to arch/x86/include/asm/elf.h

2021-02-17 Thread Baoquan He
On 01/30/21 at 03:10pm, Chen Zhou wrote:
> Move macro vmcore_elf_check_arch_cross from arch/x86/include/asm/kexec.h
> to arch/x86/include/asm/elf.h to fix the following compiling warning:
> 
> make ARCH=i386
> In file included from arch/x86/kernel/setup.c:39:0:
> ./arch/x86/include/asm/kexec.h:77:0: warning: "vmcore_elf_check_arch_cross" 
> redefined
>  # define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
> 
> In file included from arch/x86/kernel/setup.c:9:0:
> ./include/linux/crash_dump.h:39:0: note: this is the location of the previous 
> definition
>  #define vmcore_elf_check_arch_cross(x) 0
> 
> The root cause is that vmcore_elf_check_arch_cross under CONFIG_CRASH_CORE
> depend on CONFIG_KEXEC_CORE. Commit 2db65f1db17d ("x86: kdump: move
> reserve_crashkernel[_low]() into crash_core.c") triggered the issue.
> 
> Suggested by Mike, simply move vmcore_elf_check_arch_cross from
> arch/x86/include/asm/kexec.h to arch/x86/include/asm/elf.h to fix
> the warning.
> 
> Fixes: 2db65f1db17d ("x86: kdump: move reserve_crashkernel[_low]() into 
> crash_core.c")

Where does this commit id '2db65f1db17d' come from? Here you are fixing
another pathc in the same patchset. Please merge this with patch 05/11.

> Reported-by: kernel test robot 
> Suggested-by: Mike Rapoport 
> Signed-off-by: Chen Zhou 
> ---
>  arch/x86/include/asm/elf.h   | 3 +++
>  arch/x86/include/asm/kexec.h | 3 ---
>  2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
> index 66bdfe838d61..5333777cc758 100644
> --- a/arch/x86/include/asm/elf.h
> +++ b/arch/x86/include/asm/elf.h
> @@ -94,6 +94,9 @@ extern unsigned int vdso32_enabled;
>  
>  #define elf_check_arch(x)elf_check_arch_ia32(x)
>  
> +/* We can also handle crash dumps from 64 bit kernel. */
> +# define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
> +
>  /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx
> contains a pointer to a function which might be registered using `atexit'.
> This provides a mean for the dynamic linker to call DT_FINI functions for
> diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h
> index 2b18f918203e..6fcae01a9cca 100644
> --- a/arch/x86/include/asm/kexec.h
> +++ b/arch/x86/include/asm/kexec.h
> @@ -72,9 +72,6 @@ struct kimage;
>  
>  /* The native architecture */
>  # define KEXEC_ARCH KEXEC_ARCH_386
> -
> -/* We can also handle crash dumps from 64 bit kernel. */
> -# define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
>  #else
>  /* Maximum physical address we can use pages from */
>  # define KEXEC_SOURCE_MEMORY_LIMIT  (MAXMEM-1)
> -- 
> 2.20.1
> 



[PATCH] staging: comedi: cast to (void __user *)

2021-02-17 Thread Atul Gopinathan
Resolve the following sparse warning:
drivers/staging//comedi/comedi_fops.c:2983:41: warning: incorrect type in 
argument 1 (different address spaces)
drivers/staging//comedi/comedi_fops.c:2983:41:expected void [noderef] 
 *uptr
drivers/staging//comedi/comedi_fops.c:2983:41:got unsigned int *chanlist

cmd->chanlist is of type (unsigned int *) as defined in
"struct comedi_cmd" in file drivers/staging/comedi/comedi.h

The function "ptr_to_compat()" expects argument of type
(void __user *) as defined in include/linux/compat.h

Signed-off-by: Atul Gopinathan 
---
 drivers/staging/comedi/comedi_fops.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/comedi/comedi_fops.c 
b/drivers/staging/comedi/comedi_fops.c
index e85a99b68f31..db483cc698fd 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2980,7 +2980,7 @@ static int put_compat_cmd(struct comedi32_cmd_struct 
__user *cmd32,
v32.stop_src = cmd->stop_src;
v32.stop_arg = cmd->stop_arg;
/* Assume chanlist pointer is unchanged. */
-   v32.chanlist = ptr_to_compat(cmd->chanlist);
+   v32.chanlist = ptr_to_compat((void __user *)cmd->chanlist);
v32.chanlist_len = cmd->chanlist_len;
v32.data = ptr_to_compat(cmd->data);
v32.data_len = cmd->data_len;
-- 
2.27.0



RE: [PATCH] clk: imx8mp: Remove the none exist pcie clocks

2021-02-17 Thread Jacky Bai
> -Original Message-
> From: Richard Zhu
> Sent: Thursday, February 18, 2021 2:19 PM
> To: Jacky Bai ; shawn...@kernel.org
> Cc: dl-linux-imx ; linux-arm-ker...@lists.infradead.org;
> linux-kernel@vger.kernel.org
> Subject: RE: [PATCH] clk: imx8mp: Remove the none exist pcie clocks
> 
> 
> > -Original Message-
> > From: Jacky Bai 
> > Sent: Thursday, February 18, 2021 2:11 PM
> > To: Richard Zhu ; shawn...@kernel.org
> > Cc: dl-linux-imx ;
> > linux-arm-ker...@lists.infradead.org;
> > linux-kernel@vger.kernel.org; Richard Zhu 
> > Subject: RE: [PATCH] clk: imx8mp: Remove the none exist pcie clocks
> >
> > > -Original Message-
> > > From: Richard Zhu [mailto:hongxing@nxp.com]
> > > Sent: Thursday, February 18, 2021 1:54 PM
> > > To: shawn...@kernel.org; Jacky Bai 
> > > Cc: dl-linux-imx ;
> > > linux-arm-ker...@lists.infradead.org;
> > > linux-kernel@vger.kernel.org; Richard Zhu 
> > > Subject: [PATCH] clk: imx8mp: Remove the none exist pcie clocks
> > >
> > > In the i.MX8MP PCIe design, the PCIe PHY REF clock comes from
> > > external OSC or internal system PLL. It is configured in the
> > > IOMUX_GPR14 register directly, and can't be contolled by CCM at all.
> > > Remove the PCIE PHY clock from clock driver to clean up codes.
> > > There is only one PCIe in i.MX8MP, remove the none exist second PCIe
> > > related clocks.
> > >
> >
> > As Shawn suggested before, it is better to remove the corresponding
> > clock ID in include/dt-bindings/clock/imx8mp-clock.h
> >
> [Richard Zhu] Thanks for reminding.
> Is it fine to leave the holes in the ID definitions in the header file if 
> they are
> removed?
> 

I think it is fine, need Shawn comments more.

> Best Regards
> Richard Zhu
> > BR
> > Jacky Bai
> >
> > > Signed-off-by: Richard Zhu 
> > > Reviewed-by: Jason Liu 
> > > ---
> > >  drivers/clk/imx/clk-imx8mp.c | 15 ---
> > >  1 file changed, 15 deletions(-)
> > >
> > > diff --git a/drivers/clk/imx/clk-imx8mp.c
> > > b/drivers/clk/imx/clk-imx8mp.c index 2f4e1d674e1c..afbeb6bf1909
> > > 100644
> > > --- a/drivers/clk/imx/clk-imx8mp.c
> > > +++ b/drivers/clk/imx/clk-imx8mp.c
> > > @@ -152,10 +152,6 @@ static const char * const imx8mp_can2_sels[] =
> > > {"osc_24m", "sys_pll2_200m", "sys
> > >   "sys_pll1_160m", 
> > > "sys_pll1_800m",
> > "sys_pll3_out",
> > >   "sys_pll2_250m", 
> > > "audio_pll2_out", };
> > >
> > > -static const char * const imx8mp_pcie_phy_sels[] = {"osc_24m",
> > > "sys_pll2_100m", "sys_pll2_500m",
> > > - "clk_ext1", "clk_ext2", 
> > > "clk_ext3",
> > > - "clk_ext4", 
> > > "sys_pll1_400m", };
> > > -
> > >  static const char * const imx8mp_pcie_aux_sels[] = {"osc_24m",
> > > "sys_pll2_200m", "sys_pll2_50m",
> > >   "sys_pll3_out", 
> > > "sys_pll2_100m",
> > "sys_pll1_80m",
> > >   "sys_pll1_160m", 
> > > "sys_pll1_200m", };
> @@
> > > -380,14 +376,6 @@ static const char * const imx8mp_memrepair_sels[]
> > > = {"osc_24m", "sys_pll2_100m",
> > >   "sys_pll1_800m", 
> > > "sys_pll2_1000m",
> > "sys_pll3_out",
> > >   "clk_ext3", 
> > > "audio_pll2_out", };
> > >
> > > -static const char * const imx8mp_pcie2_ctrl_sels[] = {"osc_24m",
> > > "sys_pll2_250m", "sys_pll2_200m",
> > > -   "sys_pll1_266m", 
> > > "sys_pll1_800m",
> > > "sys_pll2_500m",
> > > -   "sys_pll2_333m", 
> > > "sys_pll3_out", };
> > > -
> > > -static const char * const imx8mp_pcie2_phy_sels[] = {"osc_24m",
> > > "sys_pll2_100m", "sys_pll2_500m",
> > > -  "clk_ext1", "clk_ext2", 
> > > "clk_ext3",
> > > -  "clk_ext4", 
> > > "sys_pll1_400m", };
> > > -
> > >  static const char * const imx8mp_media_mipi_test_byte_sels[] =
> > > {"osc_24m", "sys_pll2_200m", "sys_pll2_50m",
> > >   "sys_pll3_out", 
> > > "sys_pll2_100m",
> > >   "sys_pll1_80m", 
> > > "sys_pll1_160m",
> @@
> > > -585,7 +573,6 @@ static int imx8mp_clocks_probe(struct
> > > platform_device
> > > *pdev)
> > >   hws[IMX8MP_CLK_VPU_G2] =
> imx8m_clk_hw_composite("vpu_g2",
> > > imx8mp_vpu_g2_sels, ccm_base + 0xa180);
> > >   hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1",
> > > imx8mp_can1_sels, ccm_base + 0xa200);
> > >   hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2",
> > > imx8mp_can2_sels, ccm_base + 0xa280);
> > > - hws[IMX8MP_CLK_PCIE_PHY] = imx8m_clk_hw_composite("pcie_phy",
> > > imx8mp_pcie_phy_sels, ccm_base + 0xa380);
> > >   hws[IMX8MP_CLK_PCIE_AUX] =
> 

Re: [PATCH 4/4] ASoC: fsl: drop unneeded snd_soc_dai_set_drvdata

2021-02-17 Thread Nicolin Chen
On Sat, Feb 13, 2021 at 11:19:07AM +0100, Julia Lawall wrote:
> snd_soc_dai_set_drvdata is not needed when the set data comes from
> snd_soc_dai_get_drvdata or dev_get_drvdata.  The problem was fixed
> usingthe following semantic patch: (http://coccinelle.lip6.fr/)
> 
> // 
> @@
> expression x,y,e;
> @@
>   x = dev_get_drvdata(y->dev)
>   ... when != x = e
> - snd_soc_dai_set_drvdata(y,x);
> 
> @@
> expression x,y,e;
> @@
>   x = snd_soc_dai_get_drvdata(y)
>   ... when != x = e
> - snd_soc_dai_set_drvdata(y,x);
> // 
> 
> Signed-off-by: Julia Lawall 

Acked-by: Nicolin Chen 


Re: [PATCH] Revert "ath9k: fix ath_tx_process_buffer() potential null ptr dereference"

2021-02-17 Thread Kalle Valo
Shuah Khan  wrote:

> This reverts commit a56c14bb21b296fb6d395164ab62ef2e419e5069.
> 
> ath_tx_process_buffer() doesn't dereference or check sta and passes it
> to ath_tx_complete_aggr() and ath_tx_complete_buf().
> 
> ath_tx_complete_aggr() checks the pointer before use. No problem here.
> 
> ath_tx_complete_buf() doesn't check or dereference sta and passes it on
> to ath_tx_complete(). ath_tx_complete() doesn't check or dereference sta,
> but assigns it to tx_info->status.status_driver_data[0]
> 
> ath_tx_complete_buf() is called from ath_tx_complete_aggr() passing
> null ieee80211_sta pointer.
> 
> There is a potential for dereference later on, if and when the
> tx_info->status.status_driver_data[0]is referenced. In addition, the
> rcu read lock might be released before referencing the contents.
> 
> ath_tx_complete_buf() should be fixed to check sta perhaps? Worth
> looking into.
> 
> Reverting this patch because it doesn't solve the problem and introduces
> memory leak by skipping buffer completion if the pointer (sta) is NULL.
> 
> Fixes: a56c14bb21b2 ("ath9k: fix ath_tx_process_buffer() potential null ptr 
> dereference")
> Signed-off-by: Shuah Khan 
> Signed-off-by: Kalle Valo 

Thanks. I added the commit id and Fixes tag to the commit log, see the new 
version above.

-- 
https://patchwork.kernel.org/project/linux-wireless/patch/20210217211801.22540-1-sk...@linuxfoundation.org/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches



Re: [RFC PATCH 5/7] dt-bindings: regulator: bd9576 add FET ON-resistance for OCW

2021-02-17 Thread Vaittinen, Matti
Morning Rob,

On Wed, 2021-02-17 at 15:34 -0600, Rob Herring wrote:
> On Thu, Feb 11, 2021 at 02:35:41PM +0200, Matti Vaittinen wrote:
> > BD9576MUF provides over-current protection and detection. Current
> > is
> > measured as voltage loss over external FET. Allow specifying FET's
> > on
> > resistance so current monitoring limits can be converted to
> > voltages.
> > 
> > Signed-off-by: Matti Vaittinen 
> > ---
> >  .../devicetree/bindings/regulator/rohm,bd9576-regulator.yaml | 5
> > +
> >  1 file changed, 5 insertions(+)
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/regulator/rohm,bd9576-
> > regulator.yaml
> > b/Documentation/devicetree/bindings/regulator/rohm,bd9576-
> > regulator.yaml
> > index b6515a0cee62..ad3f57e9cd9b 100644
> > --- a/Documentation/devicetree/bindings/regulator/rohm,bd9576-
> > regulator.yaml
> > +++ b/Documentation/devicetree/bindings/regulator/rohm,bd9576-
> > regulator.yaml
> > @@ -27,6 +27,11 @@ patternProperties:
> >Properties for single regulator.
> >  $ref: "regulator.yaml#"
> >  
> > +properties:
> > +  rohm,ocw-fet-ron-milliohms:
> 
> We have '-ohms' and '-micro-ohms' already. Neither range works for
> you?

Thanks for taking a look at this :)

I expect values to be magnitude of few hundred milliohms - which means
micro-ohms should be usable. I'll try to still check this as I am far
from being HW-expert. I probably can convert this to micro-ohms for v2.

Best Regards
Matti Vaittinen

--
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland
SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND

~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~

Simon says - in Latin please.
"non cogito me" dixit Rene Descarte, deinde evanescavit

(Thanks for the translation Simon)



Re: [PATCH] drm/dsi: Add _NO_ to MIPI_DSI_* flags disabling features

2021-02-17 Thread Xin Ji
Hi Nicolas,

On Thu, Feb 11, 2021 at 11:33:55AM +0800, Nicolas Boichat wrote:
> Many of the DSI flags have names opposite to their actual effects,
> e.g. MIPI_DSI_MODE_EOT_PACKET means that EoT packets will actually
> be disabled. Fix this by including _NO_ in the flag names, e.g.
> MIPI_DSI_MODE_NO_EOT_PACKET.

It is OK for anx7625.c part, Please add my r-b.

Reviewed-by: Xin Ji 

> 
> Signed-off-by: Nicolas Boichat 
> ---
> I considered adding _DISABLE_ instead, but that'd make the
> flag names a big too long.
> 
> Generated with:
> flag=MIPI_DSI_MODE_VIDEO_HFP; git grep $flag | cut -f1 -d':' | \
>   xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_VIDEO_NO_HFP/" {}
> flag=MIPI_DSI_MODE_VIDEO_HBP; git grep $flag | cut -f1 -d':' | \
>   xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_VIDEO_NO_HBP/" {}
> flag=MIPI_DSI_MODE_VIDEO_HSA; git grep $flag | cut -f1 -d':' | \
>   xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_VIDEO_NO_HSA/" {}
> flag=MIPI_DSI_MODE_EOT_PACKET; git grep $flag | cut -f1 -d':' | \
>   xargs -I{} sed -i -e "s/$flag/MIPI_DSI_MODE_NO_EOT_PACKET/" {}
> (then minor format changes)
> 
>  drivers/gpu/drm/bridge/adv7511/adv7533.c | 2 +-
>  drivers/gpu/drm/bridge/analogix/anx7625.c| 2 +-
>  drivers/gpu/drm/bridge/cdns-dsi.c| 4 ++--
>  drivers/gpu/drm/bridge/tc358768.c| 2 +-
>  drivers/gpu/drm/exynos/exynos_drm_dsi.c  | 8 
>  drivers/gpu/drm/mcde/mcde_dsi.c  | 2 +-
>  drivers/gpu/drm/mediatek/mtk_dsi.c   | 2 +-
>  drivers/gpu/drm/msm/dsi/dsi_host.c   | 8 
>  drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c | 2 +-
>  drivers/gpu/drm/panel/panel-dsi-cm.c | 2 +-
>  drivers/gpu/drm/panel/panel-elida-kd35t133.c | 2 +-
>  drivers/gpu/drm/panel/panel-khadas-ts050.c   | 2 +-
>  drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c   | 2 +-
>  drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c   | 2 +-
>  drivers/gpu/drm/panel/panel-novatek-nt35510.c| 2 +-
>  drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c   | 2 +-
>  drivers/gpu/drm/panel/panel-samsung-s6d16d0.c| 2 +-
>  drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c | 2 +-
>  drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c| 2 +-
>  drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c| 4 ++--
>  drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c  | 2 +-
>  drivers/gpu/drm/panel/panel-simple.c | 2 +-
>  drivers/gpu/drm/panel/panel-sony-acx424akp.c | 2 +-
>  drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c | 2 +-
>  include/drm/drm_mipi_dsi.h   | 8 
>  25 files changed, 36 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c 
> b/drivers/gpu/drm/bridge/adv7511/adv7533.c
> index aa19d5a40e31..59d718bde8c4 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
> @@ -165,7 +165,7 @@ int adv7533_attach_dsi(struct adv7511 *adv)
>   dsi->lanes = adv->num_dsi_lanes;
>   dsi->format = MIPI_DSI_FMT_RGB888;
>   dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
> -   MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
> +   MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
>  
>   ret = mipi_dsi_attach(dsi);
>   if (ret < 0) {
> diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> b/drivers/gpu/drm/bridge/analogix/anx7625.c
> index 65cc05982f82..beecfe6bf359 100644
> --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> @@ -1334,7 +1334,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
>   dsi->format = MIPI_DSI_FMT_RGB888;
>   dsi->mode_flags = MIPI_DSI_MODE_VIDEO   |
>   MIPI_DSI_MODE_VIDEO_SYNC_PULSE  |
> - MIPI_DSI_MODE_EOT_PACKET|
> + MIPI_DSI_MODE_NO_EOT_PACKET |
>   MIPI_DSI_MODE_VIDEO_HSE;
>  
>   if (mipi_dsi_attach(dsi) < 0) {
> diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c 
> b/drivers/gpu/drm/bridge/cdns-dsi.c
> index 76373e31df92..34aa24269a57 100644
> --- a/drivers/gpu/drm/bridge/cdns-dsi.c
> +++ b/drivers/gpu/drm/bridge/cdns-dsi.c
> @@ -829,7 +829,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
> *bridge)
>   tmp = DIV_ROUND_UP(dsi_cfg.htotal, nlanes) -
> DIV_ROUND_UP(dsi_cfg.hsa, nlanes);
>  
> - if (!(output->dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
> + if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
>   tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
>  
>   tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
> @@ -902,7 +902,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge 
> *bridge)
>   tmp = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
>   tmp &= ~(IF_VID_SELECT_MASK | HOST_EOT_GEN | IF_VID_MODE);
>  

Re: [PATCH] coccinelle: misc: add swap script

2021-02-17 Thread Denis Efremov



On 2/18/21 12:31 AM, Julia Lawall wrote:
>> +@depends on patch@
>> +identifier tmp;
>> +expression a, b;
>> +type T;
>> +@@
>> +
>> +(
>> +- T tmp;
>> +|
>> +- T tmp = 0;
>> +|
>> +- T *tmp = NULL;
>> +)
>> +... when != tmp
>> +- tmp = a;
>> +- a = b;
>> +- b = tmp;
>> ++ swap(a, b);
>> +... when != tmp
> 
> In this rule and the next one, if you remove the final ; from the b = tmp
> line and from the swap line, and put it into context code afterwards, them
> the generated code looks better on cases like fs/xfs/xfs_inode.c in the
> function xfs_lock_two_inodes where two successive swap calls are
> generated.
> 
> There are also some cases such as drivers/net/wireless/ath/ath5k/phy.c in
> the function ath5k_hw_get_median_noise_floor where the swap code makes up
> a whole if branch. 

> In this cases it would be good to remove the {}.

How this can be handled?

If I use this pattern:
@depends on patch@
identifier tmp;
expression a, b;
@@

(
  if (...)
- {
-   tmp = a;
-   a = b;
-   b = tmp
+   swap(a, b)
;
- }
|
-   tmp = a;
-   a = b;
-   b = tmp
+   swap(a, b)
;
)

The tool fails with error:

EXN: Failure("rule starting on line 58: already tagged token:\nC code 
context\nFile \"drivers/net/wireless/ath/ath5k/phy.c\", line 1574, column 4, 
charpos = 41650\n  around = 'sort',\n  whole content = \t\t\t\tsort[j - 1] = 
tmp;") in drivers/net/wireless/ath/ath5k/phy.c

Thanks,
Denis


RE: [PATCH] clk: imx8mp: Remove the none exist pcie clocks

2021-02-17 Thread Jacky Bai
> -Original Message-
> From: Richard Zhu [mailto:hongxing@nxp.com]
> Sent: Thursday, February 18, 2021 1:54 PM
> To: shawn...@kernel.org; Jacky Bai 
> Cc: dl-linux-imx ; linux-arm-ker...@lists.infradead.org;
> linux-kernel@vger.kernel.org; Richard Zhu 
> Subject: [PATCH] clk: imx8mp: Remove the none exist pcie clocks
> 
> In the i.MX8MP PCIe design, the PCIe PHY REF clock comes from external OSC
> or internal system PLL. It is configured in the IOMUX_GPR14 register directly,
> and can't be contolled by CCM at all.
> Remove the PCIE PHY clock from clock driver to clean up codes.
> There is only one PCIe in i.MX8MP, remove the none exist second PCIe related
> clocks.
> 

As Shawn suggested before, it is better to remove the corresponding clock ID in 
include/dt-bindings/clock/imx8mp-clock.h

BR
Jacky Bai

> Signed-off-by: Richard Zhu 
> Reviewed-by: Jason Liu 
> ---
>  drivers/clk/imx/clk-imx8mp.c | 15 ---
>  1 file changed, 15 deletions(-)
> 
> diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
> index 2f4e1d674e1c..afbeb6bf1909 100644
> --- a/drivers/clk/imx/clk-imx8mp.c
> +++ b/drivers/clk/imx/clk-imx8mp.c
> @@ -152,10 +152,6 @@ static const char * const imx8mp_can2_sels[] =
> {"osc_24m", "sys_pll2_200m", "sys
>   "sys_pll1_160m", 
> "sys_pll1_800m",
> "sys_pll3_out",
>   "sys_pll2_250m", 
> "audio_pll2_out", };
> 
> -static const char * const imx8mp_pcie_phy_sels[] = {"osc_24m",
> "sys_pll2_100m", "sys_pll2_500m",
> - "clk_ext1", "clk_ext2", 
> "clk_ext3",
> - "clk_ext4", 
> "sys_pll1_400m", };
> -
>  static const char * const imx8mp_pcie_aux_sels[] = {"osc_24m",
> "sys_pll2_200m", "sys_pll2_50m",
>   "sys_pll3_out", 
> "sys_pll2_100m",
> "sys_pll1_80m",
>   "sys_pll1_160m", 
> "sys_pll1_200m", }; @@
> -380,14 +376,6 @@ static const char * const imx8mp_memrepair_sels[] =
> {"osc_24m", "sys_pll2_100m",
>   "sys_pll1_800m", 
> "sys_pll2_1000m",
> "sys_pll3_out",
>   "clk_ext3", 
> "audio_pll2_out", };
> 
> -static const char * const imx8mp_pcie2_ctrl_sels[] = {"osc_24m",
> "sys_pll2_250m", "sys_pll2_200m",
> -   "sys_pll1_266m", 
> "sys_pll1_800m",
> "sys_pll2_500m",
> -   "sys_pll2_333m", 
> "sys_pll3_out", };
> -
> -static const char * const imx8mp_pcie2_phy_sels[] = {"osc_24m",
> "sys_pll2_100m", "sys_pll2_500m",
> -  "clk_ext1", "clk_ext2", 
> "clk_ext3",
> -  "clk_ext4", 
> "sys_pll1_400m", };
> -
>  static const char * const imx8mp_media_mipi_test_byte_sels[] =
> {"osc_24m", "sys_pll2_200m", "sys_pll2_50m",
>   "sys_pll3_out", 
> "sys_pll2_100m",
>   "sys_pll1_80m", 
> "sys_pll1_160m", @@
> -585,7 +573,6 @@ static int imx8mp_clocks_probe(struct platform_device
> *pdev)
>   hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2",
> imx8mp_vpu_g2_sels, ccm_base + 0xa180);
>   hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1",
> imx8mp_can1_sels, ccm_base + 0xa200);
>   hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2",
> imx8mp_can2_sels, ccm_base + 0xa280);
> - hws[IMX8MP_CLK_PCIE_PHY] = imx8m_clk_hw_composite("pcie_phy",
> imx8mp_pcie_phy_sels, ccm_base + 0xa380);
>   hws[IMX8MP_CLK_PCIE_AUX] = imx8m_clk_hw_composite("pcie_aux",
> imx8mp_pcie_aux_sels, ccm_base + 0xa400);
>   hws[IMX8MP_CLK_I2C5] = imx8m_clk_hw_composite("i2c5",
> imx8mp_i2c5_sels, ccm_base + 0xa480);
>   hws[IMX8MP_CLK_I2C6] = imx8m_clk_hw_composite("i2c6",
> imx8mp_i2c6_sels, ccm_base + 0xa500); @@ -643,8 +630,6 @@ static int
> imx8mp_clocks_probe(struct platform_device *pdev)
>   hws[IMX8MP_CLK_MEDIA_CAM2_PIX] =
> imx8m_clk_hw_composite("media_cam2_pix",
> imx8mp_media_cam2_pix_sels, ccm_base + 0xbe80);
>   hws[IMX8MP_CLK_MEDIA_LDB] =
> imx8m_clk_hw_composite("media_ldb", imx8mp_media_ldb_sels, ccm_base
> + 0xbf00);
>   hws[IMX8MP_CLK_MEMREPAIR] =
> imx8m_clk_hw_composite_critical("mem_repair", imx8mp_memrepair_sels,
> ccm_base + 0xbf80);
> - hws[IMX8MP_CLK_PCIE2_CTRL] =
> imx8m_clk_hw_composite("pcie2_ctrl", imx8mp_pcie2_ctrl_sels, ccm_base +
> 0xc000);
> - hws[IMX8MP_CLK_PCIE2_PHY] =
> imx8m_clk_hw_composite("pcie2_phy", imx8mp_pcie2_phy_sels, ccm_base
> + 0xc080);
>   hws[IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE] =
> imx8m_clk_hw_composite("media_mipi_test_byte",
> imx8mp_media_mipi_test_byte_sels, ccm_base + 0xc100);
>   hws[IMX8MP_CLK_ECSPI3] = 

RE: [PATCH v7 bpf-next 0/6] xsk: build skb by page (aka generic zerocopy xmit)

2021-02-17 Thread John Fastabend
Alexander Lobakin wrote:
> This series introduces XSK generic zerocopy xmit by adding XSK umem
> pages as skb frags instead of copying data to linear space.
> The only requirement for this for drivers is to be able to xmit skbs
> with skb_headlen(skb) == 0, i.e. all data including hard headers
> starts from frag 0.
> To indicate whether a particular driver supports this, a new netdev
> priv flag, IFF_TX_SKB_NO_LINEAR, is added (and declared in virtio_net
> as it's already capable of doing it). So consider implementing this
> in your drivers to greatly speed-up generic XSK xmit.

[...]
 
>  Performance Testing 
> 
> The test environment is Aliyun ECS server.
> Test cmd:
> ```
> xdpsock -i eth0 -t  -S -s 
> ```
> 
> Test result data:
> 
> size64  512 10241500
> copy1916747 1775988 1600203 1440054
> page1974058 1953655 1945463 1904478
> percent 3.0%10.0%   21.58%  32.3%
> 

For the series, but might be good to get Dave or Jakub to check
2/6 to be sure they agree.

Acked-by: John Fastabend 


[PATCH] clk: imx8mp: Remove the none exist pcie clocks

2021-02-17 Thread Richard Zhu
In the i.MX8MP PCIe design, the PCIe PHY REF clock comes from external
OSC or internal system PLL. It is configured in the IOMUX_GPR14 register
directly, and can't be contolled by CCM at all.
Remove the PCIE PHY clock from clock driver to clean up codes.
There is only one PCIe in i.MX8MP, remove the none exist second PCIe
related clocks.

Signed-off-by: Richard Zhu 
Reviewed-by: Jason Liu 
---
 drivers/clk/imx/clk-imx8mp.c | 15 ---
 1 file changed, 15 deletions(-)

diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index 2f4e1d674e1c..afbeb6bf1909 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -152,10 +152,6 @@ static const char * const imx8mp_can2_sels[] = {"osc_24m", 
"sys_pll2_200m", "sys
"sys_pll1_160m", 
"sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", 
"audio_pll2_out", };
 
-static const char * const imx8mp_pcie_phy_sels[] = {"osc_24m", 
"sys_pll2_100m", "sys_pll2_500m",
-   "clk_ext1", "clk_ext2", 
"clk_ext3",
-   "clk_ext4", 
"sys_pll1_400m", };
-
 static const char * const imx8mp_pcie_aux_sels[] = {"osc_24m", 
"sys_pll2_200m", "sys_pll2_50m",
"sys_pll3_out", 
"sys_pll2_100m", "sys_pll1_80m",
"sys_pll1_160m", 
"sys_pll1_200m", };
@@ -380,14 +376,6 @@ static const char * const imx8mp_memrepair_sels[] = 
{"osc_24m", "sys_pll2_100m",
"sys_pll1_800m", 
"sys_pll2_1000m", "sys_pll3_out",
"clk_ext3", 
"audio_pll2_out", };
 
-static const char * const imx8mp_pcie2_ctrl_sels[] = {"osc_24m", 
"sys_pll2_250m", "sys_pll2_200m",
- "sys_pll1_266m", 
"sys_pll1_800m", "sys_pll2_500m",
- "sys_pll2_333m", 
"sys_pll3_out", };
-
-static const char * const imx8mp_pcie2_phy_sels[] = {"osc_24m", 
"sys_pll2_100m", "sys_pll2_500m",
-"clk_ext1", "clk_ext2", 
"clk_ext3",
-"clk_ext4", 
"sys_pll1_400m", };
-
 static const char * const imx8mp_media_mipi_test_byte_sels[] = {"osc_24m", 
"sys_pll2_200m", "sys_pll2_50m",
"sys_pll3_out", 
"sys_pll2_100m",
"sys_pll1_80m", 
"sys_pll1_160m",
@@ -585,7 +573,6 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2", 
imx8mp_vpu_g2_sels, ccm_base + 0xa180);
hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1", imx8mp_can1_sels, 
ccm_base + 0xa200);
hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2", imx8mp_can2_sels, 
ccm_base + 0xa280);
-   hws[IMX8MP_CLK_PCIE_PHY] = imx8m_clk_hw_composite("pcie_phy", 
imx8mp_pcie_phy_sels, ccm_base + 0xa380);
hws[IMX8MP_CLK_PCIE_AUX] = imx8m_clk_hw_composite("pcie_aux", 
imx8mp_pcie_aux_sels, ccm_base + 0xa400);
hws[IMX8MP_CLK_I2C5] = imx8m_clk_hw_composite("i2c5", imx8mp_i2c5_sels, 
ccm_base + 0xa480);
hws[IMX8MP_CLK_I2C6] = imx8m_clk_hw_composite("i2c6", imx8mp_i2c6_sels, 
ccm_base + 0xa500);
@@ -643,8 +630,6 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_MEDIA_CAM2_PIX] = 
imx8m_clk_hw_composite("media_cam2_pix", imx8mp_media_cam2_pix_sels, ccm_base + 
0xbe80);
hws[IMX8MP_CLK_MEDIA_LDB] = imx8m_clk_hw_composite("media_ldb", 
imx8mp_media_ldb_sels, ccm_base + 0xbf00);
hws[IMX8MP_CLK_MEMREPAIR] = 
imx8m_clk_hw_composite_critical("mem_repair", imx8mp_memrepair_sels, ccm_base + 
0xbf80);
-   hws[IMX8MP_CLK_PCIE2_CTRL] = imx8m_clk_hw_composite("pcie2_ctrl", 
imx8mp_pcie2_ctrl_sels, ccm_base + 0xc000);
-   hws[IMX8MP_CLK_PCIE2_PHY] = imx8m_clk_hw_composite("pcie2_phy", 
imx8mp_pcie2_phy_sels, ccm_base + 0xc080);
hws[IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE] = 
imx8m_clk_hw_composite("media_mipi_test_byte", 
imx8mp_media_mipi_test_byte_sels, ccm_base + 0xc100);
hws[IMX8MP_CLK_ECSPI3] = imx8m_clk_hw_composite("ecspi3", 
imx8mp_ecspi3_sels, ccm_base + 0xc180);
hws[IMX8MP_CLK_PDM] = imx8m_clk_hw_composite("pdm", imx8mp_pdm_sels, 
ccm_base + 0xc200);
-- 
2.17.1



Re: [PATCH] arm64: defconfig: enable modern virtio pci device

2021-02-17 Thread Jason Wang



On 2021/2/11 下午7:52, Arnd Bergmann wrote:

On Wed, Feb 10, 2021 at 8:05 PM Anders Roxell  wrote:

Since patch ("virtio-pci: introduce modern device module") got added it
is not possible to boot a defconfig kernel in qemu with a virtio pci
device.  Add CONFIG_VIRTIO_PCI_MODERN=y fragment makes the kernel able
to boot.

Signed-off-by: Anders Roxell 
---
  arch/arm/configs/multi_v7_defconfig | 1 +
  arch/arm64/configs/defconfig| 1 +

Acked-by: Arnd Bergmann 

Michael, can you pick this up in the vhost tree that introduces the regression?

  Arnd



Hi:

Based on the discussion previously, the plan is to select 
VIRTIO_PCI_MODERN, and document the module that select it must depend on 
PCI.


I will post a patch soon.

Thanks



Re: [PATCH 2/2] mm: Make alloc_contig_range handle in-use hugetlb pages

2021-02-17 Thread Oscar Salvador
On Wed, Feb 17, 2021 at 04:33:18PM +0100, Michal Hocko wrote:
> OK, I have missed that. Maybe just extend the comment. 
> 
>   /*
>* Hugepage was succesfully isolated and on the tmigratepages
>* list 
>*/

Sure, I will improve it.

Thanks 

-- 
Oscar Salvador
SUSE L3


Re: [PATCH v2 3/3] mm: Fix missing mem cgroup soft limit tree updates

2021-02-17 Thread Johannes Weiner
On Wed, Feb 17, 2021 at 12:41:36PM -0800, Tim Chen wrote:
> On a per node basis, the mem cgroup soft limit tree on each node tracks
> how much a cgroup has exceeded its soft limit memory limit and sorts
> the cgroup by its excess usage.  On page release, the trees are not
> updated right away, until we have gathered a batch of pages belonging to
> the same cgroup. This reduces the frequency of updating the soft limit tree
> and locking of the tree and associated cgroup.
> 
> However, the batch of pages could contain pages from multiple nodes but
> only the soft limit tree from one node would get updated.  Change the
> logic so that we update the tree in batch of pages, with each batch of
> pages all in the same mem cgroup and memory node.  An update is issued for
> the batch of pages of a node collected till now whenever we encounter
> a page belonging to a different node.  Note that this batching for
> the same node logic is only relevant for v1 cgroup that has a memory
> soft limit.
> 
> Reviewed-by: Ying Huang 
> Signed-off-by: Tim Chen 
> ---
>  mm/memcontrol.c | 10 +-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index d72449eeb85a..8bddee75f5cb 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -6804,6 +6804,7 @@ struct uncharge_gather {
>   unsigned long pgpgout;
>   unsigned long nr_kmem;
>   struct page *dummy_page;
> + int nid;
>  };
>  
>  static inline void uncharge_gather_clear(struct uncharge_gather *ug)
> @@ -6849,7 +6850,13 @@ static void uncharge_page(struct page *page, struct 
> uncharge_gather *ug)
>* exclusive access to the page.
>*/
>  
> - if (ug->memcg != page_memcg(page)) {
> + if (ug->memcg != page_memcg(page) ||
> + /*
> +  * Update soft limit tree used in v1 cgroup in page batch for
> +  * the same node. Relevant only to v1 cgroup with a soft limit.
> +  */
> + (ug->dummy_page && ug->nid != page_to_nid(page) &&
> +  ug->memcg->soft_limit != PAGE_COUNTER_MAX)) {

Sorry, I used weird phrasing in my last email.

Can you please preface the checks you're adding with a
!cgroup_subsys_on_dfl(memory_cgrp_subsys) to static branch for
cgroup1? The uncharge path is pretty hot, and this would avoid the
runtime overhead on cgroup2 at least, which doesn't have the SL.

Also, do we need the ug->dummy_page check? It's only NULL on the first
loop - where ug->memcg is NULL as well and the branch is taken anyway.

The soft limit check is also slightly cheaper than the nid check, as
page_to_nid() might be out-of-line, so we should do it first. This?

/*
 * Batch-uncharge all pages of the same memcg.
 *
 * Unless we're looking at a cgroup1 with a softlimit
 * set: the soft limit trees are maintained per-node
 * and updated on uncharge (via dummy_page), so keep
 * batches confined to a single node as well.
 */
if (ug->memcg != page_memcg(page) ||
(!cgroup_subsys_on_dfl(memory_cgrp_subsys) &&
 ug->memcg->soft_limit != PAGE_COUNTER_MAX &&
 ug->nid != page_to_nid(page)))


Re: arch/arm/kernel/sys_oabi-compat.c:257:6: error: implicit declaration of function 'ep_op_has_event'

2021-02-17 Thread Randy Dunlap
On 2/17/21 9:26 PM, kernel test robot wrote:
> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 
> master
> head:   f40ddce88593482919761f74910f42f4b84c004b
> commit: c281634c865202e2776b0250678ff93c771947ff ARM: compat: remove 
> KERNEL_DS usage in sys_oabi_epoll_ctl()
> date:   10 months ago
> config: arm-randconfig-m031-20210218 (attached as .config)
> compiler: arm-linux-gnueabi-gcc (GCC) 9.3.0
> reproduce (this is a W=1 build):
> wget 
> https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
> ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c281634c865202e2776b0250678ff93c771947ff
> git remote add linus 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> git fetch --no-tags linus master
> git checkout c281634c865202e2776b0250678ff93c771947ff
> # save the attached .config to linux build tree
> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
> ARCH=arm 
> 
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot 
> 
> All errors (new ones prefixed by >>):
> 
>arch/arm/kernel/sys_oabi-compat.c:142:17: warning: no previous prototype 
> for 'sys_oabi_stat64' [-Wmissing-prototypes]
>  142 | asmlinkage long sys_oabi_stat64(const char __user * filename,
>  | ^~~
>arch/arm/kernel/sys_oabi-compat.c:152:17: warning: no previous prototype 
> for 'sys_oabi_lstat64' [-Wmissing-prototypes]
>  152 | asmlinkage long sys_oabi_lstat64(const char __user * filename,
>  | ^~~~
>arch/arm/kernel/sys_oabi-compat.c:162:17: warning: no previous prototype 
> for 'sys_oabi_fstat64' [-Wmissing-prototypes]
>  162 | asmlinkage long sys_oabi_fstat64(unsigned long fd,
>  | ^~~~
>arch/arm/kernel/sys_oabi-compat.c:172:17: warning: no previous prototype 
> for 'sys_oabi_fstatat64' [-Wmissing-prototypes]
>  172 | asmlinkage long sys_oabi_fstatat64(int dfd,
>  | ^~
>arch/arm/kernel/sys_oabi-compat.c:229:17: warning: no previous prototype 
> for 'sys_oabi_fcntl64' [-Wmissing-prototypes]
>  229 | asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
>  | ^~~~
>arch/arm/kernel/sys_oabi-compat.c:251:17: warning: no previous prototype 
> for 'sys_oabi_epoll_ctl' [-Wmissing-prototypes]
>  251 | asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd,
>  | ^~
>In file included from include/linux/kernel.h:11,
> from include/linux/list.h:9,
> from include/linux/wait.h:7,
> from include/linux/wait_bit.h:8,
> from include/linux/fs.h:6,
> from include/uapi/linux/aio_abi.h:31,
> from include/linux/syscalls.h:74,
> from arch/arm/kernel/sys_oabi-compat.c:73:
>arch/arm/kernel/sys_oabi-compat.c: In function 'sys_oabi_epoll_ctl':
>>> arch/arm/kernel/sys_oabi-compat.c:257:6: error: implicit declaration of 
>>> function 'ep_op_has_event' [-Werror=implicit-function-declaration]
>  257 |  if (ep_op_has_event(op) &&
>  |  ^~~
>include/linux/compiler.h:58:52: note: in definition of macro 
> '__trace_if_var'
>   58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) 
> : __trace_if_value(cond))
>  |^~~~
>arch/arm/kernel/sys_oabi-compat.c:257:2: note: in expansion of macro 'if'
>  257 |  if (ep_op_has_event(op) &&
>  |  ^~
>>> arch/arm/kernel/sys_oabi-compat.c:264:9: error: implicit declaration of 
>>> function 'do_epoll_ctl'; did you mean 'sys_epoll_ctl'? 
>>> [-Werror=implicit-function-declaration]
>  264 |  return do_epoll_ctl(epfd, op, fd, , false);
>  | ^~~~
>  | sys_epoll_ctl
>arch/arm/kernel/sys_oabi-compat.c: At top level:
>arch/arm/kernel/sys_oabi-compat.c:267:17: warning: no previous prototype 
> for 'sys_oabi_epoll_wait' [-Wmissing-prototypes]
>  267 | asmlinkage long sys_oabi_epoll_wait(int epfd,
>  | ^~~
>arch/arm/kernel/sys_oabi-compat.c:309:17: warning: no previous prototype 
> for 'sys_oabi_semtimedop' [-Wmissing-prototypes]
>  309 | asmlinkage long sys_oabi_semtimedop(int semid,
>  | ^~~
>arch/arm/kernel/sys_oabi-compat.c:352:17: warning: no previous prototype 
> for 'sys_oabi_semop' [-Wmissing-prototypes]
>  352 | asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf 
> __user *tsops,
>  | ^~
>

Re: RE: [PATCH v7 bpf-next 6/6] xsk: build skb by page (aka generic zerocopy xmit)

2021-02-17 Thread John Fastabend
Xuan Zhuo wrote:
> On Wed, 17 Feb 2021 16:46:04 -0800, John Fastabend  
> wrote:
> > Alexander Lobakin wrote:
> > > From: Xuan Zhuo 
> > >
> > > This patch is used to construct skb based on page to save memory copy
> > > overhead.
> > >
> > > This function is implemented based on IFF_TX_SKB_NO_LINEAR. Only the
> > > network card priv_flags supports IFF_TX_SKB_NO_LINEAR will use page to
> > > directly construct skb. If this feature is not supported, it is still
> > > necessary to copy data to construct skb.
> > >
> > >  Performance Testing 
> > >
> > > The test environment is Aliyun ECS server.
> > > Test cmd:
> > > ```
> > > xdpsock -i eth0 -t  -S -s 
> > > ```
> > >
> > > Test result data:
> > >
> > > size64  512 10241500
> > > copy1916747 1775988 1600203 1440054
> > > page1974058 1953655 1945463 1904478
> > > percent 3.0%10.0%   21.58%  32.3%
> > >
> > > Signed-off-by: Xuan Zhuo 
> > > Reviewed-by: Dust Li 
> > > [ alobakin:
> > >  - expand subject to make it clearer;
> > >  - improve skb->truesize calculation;
> > >  - reserve some headroom in skb for drivers;
> > >  - tailroom is not needed as skb is non-linear ]
> > > Signed-off-by: Alexander Lobakin 
> > > Acked-by: Magnus Karlsson 
> > > ---
> >
> > [...]
> >
> > > + buffer = xsk_buff_raw_get_data(pool, addr);
> > > + offset = offset_in_page(buffer);
> > > + addr = buffer - pool->addrs;
> > > +
> > > + for (copied = 0, i = 0; copied < len; i++) {
> > > + page = pool->umem->pgs[addr >> PAGE_SHIFT];
> >
> > Looks like we could walk off the end of pgs[] if len is larger than
> > the number of pgs? Do we need to guard against a misconfigured socket
> > causing a panic here? AFAIU len here is read from the user space
> > descriptor so is under user control. Or maybe I missed a check somewhere.
> >
> > Thanks,
> > John
> >
> 
> Don't worry about this, the legality of desc has been checked.
> 
> xskq_cons_peek_desc -> xskq_cons_read_desc ->
>xskq_cons_is_valid_desc -> xp_validate_desc

Ah OK I didn't dig past the cons_read_desc(). In that case LGTM.

Acked-by: John Fastabend 


Re: [PATCH V3 16/19] virtio-pci: introduce modern device module

2021-02-17 Thread Jason Wang



On 2021/2/10 下午8:35, Michael S. Tsirkin wrote:

On Wed, Feb 10, 2021 at 12:44:03PM +0800, Jason Wang wrote:

On 2021/2/9 下午10:20, Michael S. Tsirkin wrote:

On Mon, Jan 04, 2021 at 02:55:00PM +0800, Jason Wang wrote:

Signed-off-by: Jason Wang 
---
   drivers/virtio/Kconfig |  10 +-
   drivers/virtio/Makefile|   1 +
   drivers/virtio/virtio_pci_common.h |  27 +-
   drivers/virtio/virtio_pci_modern.c | 617 -
   drivers/virtio/virtio_pci_modern_dev.c | 599 
   include/linux/virtio_pci_modern.h  | 111 +
   6 files changed, 721 insertions(+), 644 deletions(-)
   create mode 100644 drivers/virtio/virtio_pci_modern_dev.c
   create mode 100644 include/linux/virtio_pci_modern.h

diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 7b41130d3f35..6b9b81f4b8c2 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -12,6 +12,14 @@ config ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS
  This option is selected if the architecture may need to enforce
  VIRTIO_F_ACCESS_PLATFORM
+config VIRTIO_PCI_MODERN
+   tristate "Modern Virtio PCI Device"
+   depends on PCI
+   help
+ Modern PCI device implementation. This module implements the
+ basic probe and control for devices which are based on modern
+ PCI device with possible vendor specific extensions.
+
   menuconfig VIRTIO_MENU
bool "Virtio drivers"
default y
@@ -20,7 +28,7 @@ if VIRTIO_MENU
   config VIRTIO_PCI
tristate "PCI driver for virtio devices"
-   depends on PCI
+   depends on VIRTIO_PCI_MODERN
select VIRTIO
help
  This driver provides support for virtio based paravirtual device

Looks like VIRTIO_PCI_MODERN is actually just a library that
virtio pci uses. Is that right?


Right.



In that case just select it
automatically, let's not make users enable it manually.


I've considered to do this but the problem is that the module depends on PCI
so it can't be selected I think.

Drop the dependency, document that whoever selects it must depend on PCI.



Fine with me. Will post a patch.

Thanks





Thanks






[RFC PATCH v5 15/19] virtio/vsock: setup SEQPACKET ops for transport

2021-02-17 Thread Arseny Krasnov
This adds SEQPACKET ops for virtio transport

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/virtio_transport.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
index 2700a63ab095..bd3a854bb366 100644
--- a/net/vmw_vsock/virtio_transport.c
+++ b/net/vmw_vsock/virtio_transport.c
@@ -469,6 +469,11 @@ static struct virtio_transport virtio_transport = {
.stream_is_active = virtio_transport_stream_is_active,
.stream_allow = virtio_transport_stream_allow,
 
+   .seqpacket_seq_send_len   = 
virtio_transport_seqpacket_seq_send_len,
+   .seqpacket_seq_send_eor   = 
virtio_transport_seqpacket_seq_send_eor,
+   .seqpacket_seq_get_len= 
virtio_transport_seqpacket_seq_get_len,
+   .seqpacket_dequeue= virtio_transport_seqpacket_dequeue,
+
.notify_poll_in   = virtio_transport_notify_poll_in,
.notify_poll_out  = virtio_transport_notify_poll_out,
.notify_recv_init = virtio_transport_notify_recv_init,
-- 
2.25.1



[RFC PATCH v5 16/19] vhost/vsock: setup SEQPACKET ops for transport

2021-02-17 Thread Arseny Krasnov
This also removes ignore of non-stream type of packets.

Signed-off-by: Arseny Krasnov 
---
 drivers/vhost/vsock.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 5e78fb719602..5c86d09e36d9 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -354,8 +354,7 @@ vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq,
return NULL;
}
 
-   if (le16_to_cpu(pkt->hdr.type) == VIRTIO_VSOCK_TYPE_STREAM)
-   pkt->len = le32_to_cpu(pkt->hdr.len);
+   pkt->len = le32_to_cpu(pkt->hdr.len);
 
/* No payload */
if (!pkt->len)
@@ -424,6 +423,11 @@ static struct virtio_transport vhost_transport = {
.stream_is_active = virtio_transport_stream_is_active,
.stream_allow = virtio_transport_stream_allow,
 
+   .seqpacket_seq_send_len   = 
virtio_transport_seqpacket_seq_send_len,
+   .seqpacket_seq_send_eor   = 
virtio_transport_seqpacket_seq_send_eor,
+   .seqpacket_seq_get_len= 
virtio_transport_seqpacket_seq_get_len,
+   .seqpacket_dequeue= virtio_transport_seqpacket_dequeue,
+
.notify_poll_in   = virtio_transport_notify_poll_in,
.notify_poll_out  = virtio_transport_notify_poll_out,
.notify_recv_init = virtio_transport_notify_recv_init,
-- 
2.25.1



drivers/atm/horizon.c:365:9: sparse: sparse: incorrect type in argument 1 (different base types)

2021-02-17 Thread kernel test robot
tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 
master
head:   f40ddce88593482919761f74910f42f4b84c004b
commit: c1d55d50139bea6bfe964458272a93dd899efb83 asm-generic/io.h: Fix sparse 
warnings on big-endian architectures
date:   7 months ago
config: microblaze-randconfig-s032-20210218 (attached as .config)
compiler: microblaze-linux-gcc (GCC) 9.3.0
reproduce:
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.3-215-g0fb77bb6-dirty
# 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c1d55d50139bea6bfe964458272a93dd899efb83
git remote add linus 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git fetch --no-tags linus master
git checkout c1d55d50139bea6bfe964458272a93dd899efb83
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 
CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=microblaze 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 


"sparse warnings: (new ones prefixed by >>)"
   drivers/atm/horizon.c:1135:22: sparse: sparse: incorrect type in assignment 
(different address spaces) @@ expected void *[usertype] tx_addr @@ got 
void [noderef] __user *iov_base @@
   drivers/atm/horizon.c:1135:22: sparse: expected void *[usertype] tx_addr
   drivers/atm/horizon.c:1135:22: sparse: got void [noderef] __user 
*iov_base
   drivers/atm/horizon.c:1173:49: sparse: sparse: incorrect type in argument 3 
(different base types) @@ expected unsigned int [usertype] data @@ got 
restricted __be32 [usertype] @@
   drivers/atm/horizon.c:1173:49: sparse: expected unsigned int [usertype] 
data
   drivers/atm/horizon.c:1173:49: sparse: got restricted __be32 [usertype]
   drivers/atm/horizon.c:1177:48: sparse: sparse: incorrect type in argument 3 
(different base types) @@ expected unsigned int [usertype] data @@ got 
restricted __be32 [usertype] @@
   drivers/atm/horizon.c:1177:48: sparse: expected unsigned int [usertype] 
data
   drivers/atm/horizon.c:1177:48: sparse: got restricted __be32 [usertype]
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:369:10: sparse: sparse: cast to restricted __le16
   drivers/atm/horizon.c:357:9: sparse: sparse: incorrect type in argument 1 
(different base types) @@ expected unsigned int [usertype] value @@ got 
restricted __le32 [usertype] @@
   drivers/atm/horizon.c:357:9: sparse: expected unsigned int [usertype] 
value
   drivers/atm/horizon.c:357:9: sparse: got restricted __le32 [usertype]
   drivers/atm/horizon.c:361:10: sparse: sparse: cast to restricted __le32
   drivers/atm/horizon.c:361:10: sparse: sparse: cast to restricted __le32
   drivers/atm/horizon.c:361:10: sparse: sparse: cast to restricted __le32
   drivers/atm/horizon.c:361:10: sparse: sparse: cast to restricted __le32
   drivers/atm/horizon.c:361:10: sparse: sparse: cast to restricted __le32
   drivers/atm/horizon.c:361:10: sparse: sparse: cast to restricted __le32
   drivers/atm/horizon.c:357:9: sparse: sparse: incorrect type in argument 1 
(different base types) @@ expected unsigned int [usertype] value @@ got 
restricted __le32 [usertype] @@
   drivers/atm/horizon.c:357:9: sparse: expected unsigned int [usertype] 
value
   drivers/atm/horizon.c:357:9: sparse: got restricted __le32 [usertype]
   drivers/atm/horizon.c:357:9: sparse: sparse: incorrect type in argument 1 
(different base types) @@ expected unsigned int [usertype] value @@ got 
restricted __le32 [usertype] @@
   drivers/atm/horizon.c:357:9: sparse: expected unsigned int [usertype] 
value
   drivers/atm/horizon.c:357:9: sparse: got restricted __le32 [usertype]
   drivers/atm/horizon.c:357:9: sparse: sparse: incorrect type in argument 1 
(different base types) @@ expected unsigned int [usertype] value @@ got 
restricted __le32 [usertype] @@
   drivers/atm/horizon.c:357:9: sparse: expected unsigned int [usertype] 
value
   drivers/atm/horizon.c:357:9: sparse: got restricted __le32 [usertype]
   drivers/atm/horizon.c:357:9: sparse: sparse: incorrect type in argument 1 
(different base types) @@ expected unsigned int [usertype] value @@ got 
restricted __le32 [usertype] 

[RFC PATCH v5 18/19] vsock_test: add SOCK_SEQPACKET tests

2021-02-17 Thread Arseny Krasnov
This adds two tests of SOCK_SEQPACKET socket: both transfer data and
then test MSG_EOR and MSG_TRUNC flags. Cases for connect(), bind(),
etc. are not tested, because it is same as for stream socket.

Signed-off-by: Arseny Krasnov 
---
 tools/testing/vsock/util.c   |  32 ++--
 tools/testing/vsock/util.h   |   3 +
 tools/testing/vsock/vsock_test.c | 126 +++
 3 files changed, 156 insertions(+), 5 deletions(-)

diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index 93cbd6f603f9..2acbb7703c6a 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -84,7 +84,7 @@ void vsock_wait_remote_close(int fd)
 }
 
 /* Connect to  and return the file descriptor. */
-int vsock_stream_connect(unsigned int cid, unsigned int port)
+static int vsock_connect(unsigned int cid, unsigned int port, int type)
 {
union {
struct sockaddr sa;
@@ -101,7 +101,7 @@ int vsock_stream_connect(unsigned int cid, unsigned int 
port)
 
control_expectln("LISTENING");
 
-   fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+   fd = socket(AF_VSOCK, type, 0);
 
timeout_begin(TIMEOUT);
do {
@@ -120,11 +120,21 @@ int vsock_stream_connect(unsigned int cid, unsigned int 
port)
return fd;
 }
 
+int vsock_stream_connect(unsigned int cid, unsigned int port)
+{
+   return vsock_connect(cid, port, SOCK_STREAM);
+}
+
+int vsock_seqpacket_connect(unsigned int cid, unsigned int port)
+{
+   return vsock_connect(cid, port, SOCK_SEQPACKET);
+}
+
 /* Listen on  and return the first incoming connection.  The remote
  * address is stored to clientaddrp.  clientaddrp may be NULL.
  */
-int vsock_stream_accept(unsigned int cid, unsigned int port,
-   struct sockaddr_vm *clientaddrp)
+static int vsock_accept(unsigned int cid, unsigned int port,
+   struct sockaddr_vm *clientaddrp, int type)
 {
union {
struct sockaddr sa;
@@ -145,7 +155,7 @@ int vsock_stream_accept(unsigned int cid, unsigned int port,
int client_fd;
int old_errno;
 
-   fd = socket(AF_VSOCK, SOCK_STREAM, 0);
+   fd = socket(AF_VSOCK, type, 0);
 
if (bind(fd, , sizeof(addr.svm)) < 0) {
perror("bind");
@@ -189,6 +199,18 @@ int vsock_stream_accept(unsigned int cid, unsigned int 
port,
return client_fd;
 }
 
+int vsock_stream_accept(unsigned int cid, unsigned int port,
+   struct sockaddr_vm *clientaddrp)
+{
+   return vsock_accept(cid, port, clientaddrp, SOCK_STREAM);
+}
+
+int vsock_seqpacket_accept(unsigned int cid, unsigned int port,
+  struct sockaddr_vm *clientaddrp)
+{
+   return vsock_accept(cid, port, clientaddrp, SOCK_SEQPACKET);
+}
+
 /* Transmit one byte and check the return value.
  *
  * expected_ret:
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index e53dd09d26d9..a3375ad2fb7f 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -36,8 +36,11 @@ struct test_case {
 void init_signals(void);
 unsigned int parse_cid(const char *str);
 int vsock_stream_connect(unsigned int cid, unsigned int port);
+int vsock_seqpacket_connect(unsigned int cid, unsigned int port);
 int vsock_stream_accept(unsigned int cid, unsigned int port,
struct sockaddr_vm *clientaddrp);
+int vsock_seqpacket_accept(unsigned int cid, unsigned int port,
+  struct sockaddr_vm *clientaddrp);
 void vsock_wait_remote_close(int fd);
 void send_byte(int fd, int expected_ret, int flags);
 void recv_byte(int fd, int expected_ret, int flags);
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index 5a4fb80fa832..5fca9be5b1dd 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -14,6 +14,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "timeout.h"
 #include "control.h"
@@ -279,6 +281,120 @@ static void test_stream_msg_peek_server(const struct 
test_opts *opts)
close(fd);
 }
 
+#define MESSAGES_CNT 7
+#define MESSAGE_EOR_IDX (MESSAGES_CNT / 2)
+static void test_seqpacket_msg_eor_client(const struct test_opts *opts)
+{
+   int fd;
+
+   fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
+   if (fd < 0) {
+   perror("connect");
+   exit(EXIT_FAILURE);
+   }
+
+   /* Send several messages, one with MSG_EOR flag */
+   for (int i = 0; i < MESSAGES_CNT; i++)
+   send_byte(fd, 1, (i != MESSAGE_EOR_IDX) ? 0 : MSG_EOR);
+
+   control_writeln("SENDDONE");
+   close(fd);
+}
+
+static void test_seqpacket_msg_eor_server(const struct test_opts *opts)
+{
+   int fd;
+   char buf[16];
+   struct msghdr msg = {0};
+   struct iovec iov = {0};
+
+   fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
+   if (fd < 0) {
+   perror("accept");
+   

[RFC PATCH v5 17/19] vsock/loopback: setup SEQPACKET ops for transport

2021-02-17 Thread Arseny Krasnov
This adds SEQPACKET ops for loopback transport

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/vsock_loopback.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/net/vmw_vsock/vsock_loopback.c b/net/vmw_vsock/vsock_loopback.c
index a45f7ffca8c5..c0da94119f74 100644
--- a/net/vmw_vsock/vsock_loopback.c
+++ b/net/vmw_vsock/vsock_loopback.c
@@ -89,6 +89,11 @@ static struct virtio_transport loopback_transport = {
.stream_is_active = virtio_transport_stream_is_active,
.stream_allow = virtio_transport_stream_allow,
 
+   .seqpacket_seq_send_len   = 
virtio_transport_seqpacket_seq_send_len,
+   .seqpacket_seq_send_eor   = 
virtio_transport_seqpacket_seq_send_eor,
+   .seqpacket_seq_get_len= 
virtio_transport_seqpacket_seq_get_len,
+   .seqpacket_dequeue= virtio_transport_seqpacket_dequeue,
+
.notify_poll_in   = virtio_transport_notify_poll_in,
.notify_poll_out  = virtio_transport_notify_poll_out,
.notify_recv_init = virtio_transport_notify_recv_init,
-- 
2.25.1



Re: [PATCH] vdpa/mlx5: fix param validation in mlx5_vdpa_get_config()

2021-02-17 Thread Jason Wang



On 2021/2/10 下午6:08, Stefano Garzarella wrote:

On Tue, Feb 09, 2021 at 04:31:23AM -0500, Michael S. Tsirkin wrote:

On Tue, Feb 09, 2021 at 11:24:03AM +0800, Jason Wang wrote:


On 2021/2/9 上午2:38, Michael S. Tsirkin wrote:
> On Mon, Feb 08, 2021 at 05:17:41PM +0100, Stefano Garzarella wrote:
> > It's legal to have 'offset + len' equal to
> > sizeof(struct virtio_net_config), since 'ndev->config' is a
> > 'struct virtio_net_config', so we can safely copy its content under
> > this condition.
> >
> > Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for supported 
mlx5 devices")

> > Cc: sta...@vger.kernel.org
> > Signed-off-by: Stefano Garzarella 
> > ---
> >   drivers/vdpa/mlx5/net/mlx5_vnet.c | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c 
b/drivers/vdpa/mlx5/net/mlx5_vnet.c

> > index dc88559a8d49..10e9b09932eb 100644
> > --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
> > +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
> > @@ -1820,7 +1820,7 @@ static void mlx5_vdpa_get_config(struct 
vdpa_device *vdev, unsigned int offset,

> >   struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
> >   struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
> > -    if (offset + len < sizeof(struct virtio_net_config))
> > +    if (offset + len <= sizeof(struct virtio_net_config))
> >   memcpy(buf, (u8 *)>config + offset, len);
> >   }
> Actually first I am not sure we need these checks at all.
> vhost_vdpa_config_validate already validates the values, right?


I think they're working at different levels. There's no guarantee that
vhost-vdpa is the driver for this vdpa device.


In fact, get_config returns void, so userspace can easily get
trash if it passes incorrect parameters by mistake, there is
no way for userspace to find out whether that is the case :(

Any objections to returning the # of bytes copied, or -1
on error?


Make sense for me, but are we sure we don't break userspace if we 
return the number of bytes instead of 0 on success?


I had a quick look at QEMU and it looks like we consider success if 
the return value is >= 0, but I need to check further.



So I think in the vdpa bus level, we can return #bytes and in vhost uAPI 
level, we can return error if the size is not expected otherwise zero?


Thanks








>
> Second, what will happen when we extend the struct and then
> run new userspace on an old kernel? Looks like it will just
> fail right? So what is the plan?


In this case, get_config() should match the spec behaviour. That is 
to say

the size of config space depends on the feature negotiated.

Thanks


Yes but spec says config space can be bigger than specified by features:

Drivers MUST NOT limit structure size and device configuration 
space size. Instead, drivers SHOULD only
check that device configuration space is large enough to contain 
the fields necessary for device operation.




So IIUC in the driver we should copy as much as we can.

If you agree, I can send an RFC series and we can continue the 
discussion on it, but I think we should queue this patch for stable 
branches.


Thanks,
Stefano





[RFC PATCH v5 19/19] virtio/vsock: update trace event for SEQPACKET

2021-02-17 Thread Arseny Krasnov
This updates current implementation for trace event of virtio vsock:
SEQPACKET socket's type, SEQPACKET specific ops and SEQPACKET 'msg_len'
and 'msg_cnt' fields are added.

Signed-off-by: Arseny Krasnov 
---
 .../events/vsock_virtio_transport_common.h| 48 +++
 net/vmw_vsock/virtio_transport_common.c   | 25 +-
 2 files changed, 61 insertions(+), 12 deletions(-)

diff --git a/include/trace/events/vsock_virtio_transport_common.h 
b/include/trace/events/vsock_virtio_transport_common.h
index 6782213778be..23bc0f39c450 100644
--- a/include/trace/events/vsock_virtio_transport_common.h
+++ b/include/trace/events/vsock_virtio_transport_common.h
@@ -9,9 +9,12 @@
 #include 
 
 TRACE_DEFINE_ENUM(VIRTIO_VSOCK_TYPE_STREAM);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_TYPE_SEQPACKET);
 
 #define show_type(val) \
-   __print_symbolic(val, { VIRTIO_VSOCK_TYPE_STREAM, "STREAM" })
+   __print_symbolic(val, \
+   { VIRTIO_VSOCK_TYPE_STREAM, "STREAM" }, \
+   { VIRTIO_VSOCK_TYPE_SEQPACKET, "SEQPACKET" })
 
 TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_INVALID);
 TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_REQUEST);
@@ -21,6 +24,8 @@ TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_SHUTDOWN);
 TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_RW);
 TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_CREDIT_UPDATE);
 TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_CREDIT_REQUEST);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_SEQ_BEGIN);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_SEQ_END);
 
 #define show_op(val) \
__print_symbolic(val, \
@@ -31,7 +36,9 @@ TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_CREDIT_REQUEST);
 { VIRTIO_VSOCK_OP_SHUTDOWN, "SHUTDOWN" }, \
 { VIRTIO_VSOCK_OP_RW, "RW" }, \
 { VIRTIO_VSOCK_OP_CREDIT_UPDATE, "CREDIT_UPDATE" }, \
-{ VIRTIO_VSOCK_OP_CREDIT_REQUEST, "CREDIT_REQUEST" })
+{ VIRTIO_VSOCK_OP_CREDIT_REQUEST, "CREDIT_REQUEST" }, \
+{ VIRTIO_VSOCK_OP_SEQ_BEGIN, "SEQ_BEGIN" }, \
+{ VIRTIO_VSOCK_OP_SEQ_END, "SEQ_END" })
 
 TRACE_EVENT(virtio_transport_alloc_pkt,
TP_PROTO(
@@ -40,7 +47,9 @@ TRACE_EVENT(virtio_transport_alloc_pkt,
 __u32 len,
 __u16 type,
 __u16 op,
-__u32 flags
+__u32 flags,
+__u32 msg_len,
+__u32 msg_cnt
),
TP_ARGS(
src_cid, src_port,
@@ -48,7 +57,9 @@ TRACE_EVENT(virtio_transport_alloc_pkt,
len,
type,
op,
-   flags
+   flags,
+   msg_len,
+   msg_cnt
),
TP_STRUCT__entry(
__field(__u32, src_cid)
@@ -59,6 +70,8 @@ TRACE_EVENT(virtio_transport_alloc_pkt,
__field(__u16, type)
__field(__u16, op)
__field(__u32, flags)
+   __field(__u32, msg_len)
+   __field(__u32, msg_cnt)
),
TP_fast_assign(
__entry->src_cid = src_cid;
@@ -69,14 +82,19 @@ TRACE_EVENT(virtio_transport_alloc_pkt,
__entry->type = type;
__entry->op = op;
__entry->flags = flags;
+   __entry->msg_len = msg_len;
+   __entry->msg_cnt = msg_cnt;
),
-   TP_printk("%u:%u -> %u:%u len=%u type=%s op=%s flags=%#x",
+   TP_printk("%u:%u -> %u:%u len=%u type=%s op=%s flags=%#x "
+ "msg_len=%u msg_cnt=%u",
  __entry->src_cid, __entry->src_port,
  __entry->dst_cid, __entry->dst_port,
  __entry->len,
  show_type(__entry->type),
  show_op(__entry->op),
- __entry->flags)
+ __entry->flags,
+ __entry->msg_len,
+ __entry->msg_cnt)
 );
 
 TRACE_EVENT(virtio_transport_recv_pkt,
@@ -88,7 +106,9 @@ TRACE_EVENT(virtio_transport_recv_pkt,
 __u16 op,
 __u32 flags,
 __u32 buf_alloc,
-__u32 fwd_cnt
+__u32 fwd_cnt,
+__u32 msg_len,
+__u32 msg_cnt
),
TP_ARGS(
src_cid, src_port,
@@ -98,7 +118,9 @@ TRACE_EVENT(virtio_transport_recv_pkt,
op,
flags,
buf_alloc,
-   fwd_cnt
+   fwd_cnt,
+   msg_len,
+   msg_cnt
),
TP_STRUCT__entry(
__field(__u32, src_cid)
@@ -111,6 +133,8 @@ TRACE_EVENT(virtio_transport_recv_pkt,
__field(__u32, flags)
__field(__u32, buf_alloc)
__field(__u32, fwd_cnt)
+   __field(__u32, msg_len)
+   __field(__u32, msg_cnt)
),
TP_fast_assign(
__entry->src_cid = src_cid;
@@ -123,9 +147,11 @@ 

[PATCH net 1/1] net: stmmac: fix CBS idleslope and sendslope calculation

2021-02-17 Thread Song Yoong Siang
From: "Song, Yoong Siang" 

When link speed is not 100 Mbps, port transmit rate and speed divider
are set to 8 and 100 respectively. These values are incorrect for
CBS idleslope and sendslope HW values calculation if the link speed is
not 1 Gbps.

This patch adds switch statement to set the values of port transmit rate
and speed divider for 10 Gbps, 5 Gbps, 2.5 Gbps, 1 Gbps, and 100 Mbps.
Note that CBS is not supported at 10 Mbps.

Fixes: bc41a6689b30 ("net: stmmac: tc: Remove the speed dependency")
Fixes: 1f705bc61aee ("net: stmmac: Add support for CBS QDISC")
Signed-off-by: Song, Yoong Siang 
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 30 +
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 5698554..44bb133 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -316,6 +316,32 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
if (!priv->dma_cap.av)
return -EOPNOTSUPP;
 
+   /* Port Transmit Rate and Speed Divider */
+   switch (priv->speed) {
+   case SPEED_1:
+   ptr = 32;
+   speed_div = 1000;
+   break;
+   case SPEED_5000:
+   ptr = 32;
+   speed_div = 500;
+   break;
+   case SPEED_2500:
+   ptr = 8;
+   speed_div = 250;
+   break;
+   case SPEED_1000:
+   ptr = 8;
+   speed_div = 100;
+   break;
+   case SPEED_100:
+   ptr = 4;
+   speed_div = 10;
+   break;
+   default:
+   return -EOPNOTSUPP;
+   }
+
mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
if (mode_to_use == MTL_QUEUE_DCB && qopt->enable) {
ret = stmmac_dma_qmode(priv, priv->ioaddr, queue, 
MTL_QUEUE_AVB);
@@ -332,10 +358,6 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
}
 
-   /* Port Transmit Rate and Speed Divider */
-   ptr = (priv->speed == SPEED_100) ? 4 : 8;
-   speed_div = (priv->speed == SPEED_100) ? 10 : 100;
-
/* Final adjustments for HW */
value = div_s64(qopt->idleslope * 1024ll * ptr, speed_div);
priv->plat->tx_queues_cfg[queue].idle_slope = value & GENMASK(31, 0);
-- 
2.7.4



Re: [PATCH v4 3/3] drm/bridge: anx7625: add MIPI DPI input feature support

2021-02-17 Thread Xin Ji
On Fri, Feb 05, 2021 at 01:33:46PM +0100, Robert Foss wrote:
> Hey Xin,
Hi Robert Foss, thanks for the comment, I'll split this patch at this seria.
Thanks,
Xin
> 
> On Thu, 28 Jan 2021 at 04:12, Xin Ji  wrote:
> >
> > Add MIPI rx DPI input support
> >
> > Reported-by: kernel test robot 
> > Signed-off-by: Xin Ji 
> > ---
> >  drivers/gpu/drm/bridge/analogix/anx7625.c | 326 
> > --
> >  drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +-
> >  2 files changed, 285 insertions(+), 61 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> > b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index 04536cc..628ae43 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > @@ -150,18 +150,18 @@ static int anx7625_write_and(struct anx7625_data *ctx,
> > return anx7625_reg_write(ctx, client, offset, (val & (mask)));
> >  }
> >
> > -static int anx7625_write_and_or(struct anx7625_data *ctx,
> > -   struct i2c_client *client,
> > -   u8 offset, u8 and_mask, u8 or_mask)
> > +static int anx7625_config_bit_matrix(struct anx7625_data *ctx)
> >  {
> > -   int val;
> > +   int i, ret;
> >
> > -   val = anx7625_reg_read(ctx, client, offset);
> > -   if (val < 0)
> > -   return val;
> > +   ret = anx7625_write_or(ctx, ctx->i2c.tx_p2_client,
> > +  AUDIO_CONTROL_REGISTER, 0x80);
> > +   for (i = 0; i < 13; i++)
> > +   ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > +VIDEO_BIT_MATRIX_12 + i,
> > +0x18 + i);
> >
> > -   return anx7625_reg_write(ctx, client,
> > -offset, (val & and_mask) | (or_mask));
> > +   return ret;
> >  }
> >
> >  static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
> > @@ -195,6 +195,60 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
> > return 0;
> >  }
> >
> > +static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
> > +u8 addrh, u8 addrm, u8 addrl,
> > +u8 len, u8 *buf)
> > +{
> > +   struct device *dev = >client->dev;
> > +   int ret;
> > +   u8 cmd;
> > +
> > +   if (len > MAX_DPCD_BUFFER_SIZE) {
> > +   DRM_DEV_ERROR(dev, "exceed aux buffer len.\n");
> > +   return -EINVAL;
> > +   }
> > +
> > +   cmd = ((len - 1) << 4) | 0x09;
> > +
> > +   /* Set command and length */
> > +   ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +   AP_AUX_COMMAND, cmd);
> > +
> > +   /* Set aux access address */
> > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +AP_AUX_ADDR_7_0, addrl);
> > +   ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
> > +AP_AUX_ADDR_15_8, addrm);
> > +   ret |= anx7625_write_and(ctx, ctx->i2c.rx_p0_client,
> > +AP_AUX_ADDR_19_16, addrh);
> > +
> > +   /* Enable aux access */
> > +   ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
> > +   AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
> > +
> > +   if (ret < 0) {
> > +   DRM_DEV_ERROR(dev, "cannot access aux related register.\n");
> > +   return -EIO;
> > +   }
> > +
> > +   usleep_range(2000, 2100);
> > +
> > +   ret = wait_aux_op_finish(ctx);
> > +   if (ret) {
> > +   DRM_DEV_ERROR(dev, "aux IO error: wait aux op finish.\n");
> > +   return ret;
> > +   }
> > +
> > +   ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
> > +AP_AUX_BUFF_START, len, buf);
> > +   if (ret < 0) {
> > +   DRM_DEV_ERROR(dev, "read dpcd register failed\n");
> > +   return -EIO;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> >  static int anx7625_video_mute_control(struct anx7625_data *ctx,
> >   u8 status)
> >  {
> > @@ -219,38 +273,6 @@ static int anx7625_video_mute_control(struct 
> > anx7625_data *ctx,
> > return ret;
> >  }
> >
> > -static int anx7625_config_audio_input(struct anx7625_data *ctx)
> > -{
> > -   struct device *dev = >client->dev;
> > -   int ret;
> > -
> > -   /* Channel num */
> > -   ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client,
> > -   AUDIO_CHANNEL_STATUS_6, I2S_CH_2 << 5);
> > -
> > -   /* FS */
> > -   ret |= anx7625_write_and_or(ctx, ctx->i2c.tx_p2_client,
> > -   AUDIO_CHANNEL_STATUS_4,
> > -   0xf0, AUDIO_FS_48K);
> > -   /* Word length */
> > -   ret |= anx7625_write_and_or(ctx, 

[RFC PATCH v5 13/19] virtio/vsock: add SEQPACKET receive logic

2021-02-17 Thread Arseny Krasnov
This modifies current receive logic for SEQPACKET support:
1) Inserts 'SEQ_BEGIN' packet to socket's rx queue.
2) Inserts 'RW' packet to socket's rx queue, but without merging with
   buffer of last packet in queue.
3) Performs check for packet and socket types on receive(if mismatch,
   then reset connection).

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/virtio_transport_common.c | 63 +
 1 file changed, 44 insertions(+), 19 deletions(-)

diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index e9a2de72ebbf..3ca0009c553e 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -165,6 +165,14 @@ void virtio_transport_deliver_tap_pkt(struct 
virtio_vsock_pkt *pkt)
 }
 EXPORT_SYMBOL_GPL(virtio_transport_deliver_tap_pkt);
 
+static u16 virtio_transport_get_type(struct sock *sk)
+{
+   if (sk->sk_type == SOCK_STREAM)
+   return VIRTIO_VSOCK_TYPE_STREAM;
+   else
+   return VIRTIO_VSOCK_TYPE_SEQPACKET;
+}
+
 /* This function can only be used on connecting/connected sockets,
  * since a socket assigned to a transport is required.
  *
@@ -1060,25 +1068,27 @@ virtio_transport_recv_enqueue(struct vsock_sock *vsk,
goto out;
}
 
-   /* Try to copy small packets into the buffer of last packet queued,
-* to avoid wasting memory queueing the entire buffer with a small
-* payload.
-*/
-   if (pkt->len <= GOOD_COPY_LEN && !list_empty(>rx_queue)) {
-   struct virtio_vsock_pkt *last_pkt;
+   if (le16_to_cpu(pkt->hdr.type) == VIRTIO_VSOCK_TYPE_STREAM) {
+   /* Try to copy small packets into the buffer of last packet 
queued,
+* to avoid wasting memory queueing the entire buffer with a 
small
+* payload.
+*/
+   if (pkt->len <= GOOD_COPY_LEN && !list_empty(>rx_queue)) {
+   struct virtio_vsock_pkt *last_pkt;
 
-   last_pkt = list_last_entry(>rx_queue,
-  struct virtio_vsock_pkt, list);
+   last_pkt = list_last_entry(>rx_queue,
+  struct virtio_vsock_pkt, 
list);
 
-   /* If there is space in the last packet queued, we copy the
-* new packet in its buffer.
-*/
-   if (pkt->len <= last_pkt->buf_len - last_pkt->len) {
-   memcpy(last_pkt->buf + last_pkt->len, pkt->buf,
-  pkt->len);
-   last_pkt->len += pkt->len;
-   free_pkt = true;
-   goto out;
+   /* If there is space in the last packet queued, we copy 
the
+* new packet in its buffer.
+*/
+   if (pkt->len <= last_pkt->buf_len - last_pkt->len) {
+   memcpy(last_pkt->buf + last_pkt->len, pkt->buf,
+  pkt->len);
+   last_pkt->len += pkt->len;
+   free_pkt = true;
+   goto out;
+   }
}
}
 
@@ -1098,9 +1108,13 @@ virtio_transport_recv_connected(struct sock *sk,
int err = 0;
 
switch (le16_to_cpu(pkt->hdr.op)) {
+   case VIRTIO_VSOCK_OP_SEQ_BEGIN:
+   case VIRTIO_VSOCK_OP_SEQ_END:
case VIRTIO_VSOCK_OP_RW:
virtio_transport_recv_enqueue(vsk, pkt);
-   sk->sk_data_ready(sk);
+
+   if (le16_to_cpu(pkt->hdr.op) != VIRTIO_VSOCK_OP_SEQ_BEGIN)
+   sk->sk_data_ready(sk);
return err;
case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
sk->sk_write_space(sk);
@@ -1243,6 +1257,12 @@ virtio_transport_recv_listen(struct sock *sk, struct 
virtio_vsock_pkt *pkt,
return 0;
 }
 
+static bool virtio_transport_valid_type(u16 type)
+{
+   return (type == VIRTIO_VSOCK_TYPE_STREAM) ||
+  (type == VIRTIO_VSOCK_TYPE_SEQPACKET);
+}
+
 /* We are under the virtio-vsock's vsock->rx_lock or vhost-vsock's vq->mutex
  * lock.
  */
@@ -1268,7 +1288,7 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
le32_to_cpu(pkt->hdr.buf_alloc),
le32_to_cpu(pkt->hdr.fwd_cnt));
 
-   if (le16_to_cpu(pkt->hdr.type) != VIRTIO_VSOCK_TYPE_STREAM) {
+   if (!virtio_transport_valid_type(le16_to_cpu(pkt->hdr.type))) {
(void)virtio_transport_reset_no_sock(t, pkt);
goto free_pkt;
}
@@ -1285,6 +1305,11 @@ void virtio_transport_recv_pkt(struct virtio_transport 
*t,
}
}
 
+   if (virtio_transport_get_type(sk) != le16_to_cpu(pkt->hdr.type)) {
+   

[RFC PATCH v5 12/19] virtio/vsock: fetch length for SEQPACKET record

2021-02-17 Thread Arseny Krasnov
This adds transport callback which tries to fetch record begin marker
from socket's rx queue. It is called from af_vsock.c before reading data
packets of record.

Signed-off-by: Arseny Krasnov 
---
 include/linux/virtio_vsock.h|  1 +
 net/vmw_vsock/virtio_transport_common.c | 53 +
 2 files changed, 54 insertions(+)

diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
index 003d06ae4a85..022667d57884 100644
--- a/include/linux/virtio_vsock.h
+++ b/include/linux/virtio_vsock.h
@@ -85,6 +85,7 @@ virtio_transport_dgram_dequeue(struct vsock_sock *vsk,
   struct msghdr *msg,
   size_t len, int flags);
 
+size_t virtio_transport_seqpacket_seq_get_len(struct vsock_sock *vsk);
 int
 virtio_transport_seqpacket_dequeue(struct vsock_sock *vsk,
   struct msghdr *msg,
diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index d8ec2dfa2315..e9a2de72ebbf 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -399,6 +399,59 @@ static inline void virtio_transport_remove_pkt(struct 
virtio_vsock_pkt *pkt)
virtio_transport_free_pkt(pkt);
 }
 
+static size_t virtio_transport_drop_until_seq_begin(struct virtio_vsock_sock 
*vvs)
+{
+   struct virtio_vsock_pkt *pkt, *n;
+   size_t bytes_dropped = 0;
+
+   list_for_each_entry_safe(pkt, n, >rx_queue, list) {
+   if (le16_to_cpu(pkt->hdr.op) == VIRTIO_VSOCK_OP_SEQ_BEGIN)
+   break;
+
+   bytes_dropped += le32_to_cpu(pkt->hdr.len);
+   virtio_transport_dec_rx_pkt(vvs, pkt);
+   virtio_transport_remove_pkt(pkt);
+   }
+
+   return bytes_dropped;
+}
+
+size_t virtio_transport_seqpacket_seq_get_len(struct vsock_sock *vsk)
+{
+   struct virtio_vsock_seq_hdr *seq_hdr;
+   struct virtio_vsock_sock *vvs;
+   struct virtio_vsock_pkt *pkt;
+   size_t bytes_dropped;
+
+   vvs = vsk->trans;
+
+   spin_lock_bh(>rx_lock);
+
+   /* Fetch all orphaned 'RW' packets and send credit update. */
+   bytes_dropped = virtio_transport_drop_until_seq_begin(vvs);
+
+   if (list_empty(>rx_queue))
+   goto out;
+
+   pkt = list_first_entry(>rx_queue, struct virtio_vsock_pkt, list);
+
+   vvs->user_read_copied = 0;
+
+   seq_hdr = (struct virtio_vsock_seq_hdr *)pkt->buf;
+   vvs->user_read_seq_len = le32_to_cpu(seq_hdr->msg_len);
+   vvs->curr_rx_msg_cnt = le32_to_cpu(seq_hdr->msg_cnt);
+   virtio_transport_dec_rx_pkt(vvs, pkt);
+   virtio_transport_remove_pkt(pkt);
+out:
+   spin_unlock_bh(>rx_lock);
+
+   if (bytes_dropped)
+   virtio_transport_send_credit_update(vsk);
+
+   return vvs->user_read_seq_len;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_seqpacket_seq_get_len);
+
 static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
 struct msghdr *msg,
 bool *msg_ready)
-- 
2.25.1



[RFC PATCH v5 14/19] virtio/vsock: rest of SOCK_SEQPACKET support

2021-02-17 Thread Arseny Krasnov
This adds rest of logic for SEQPACKET:
1) SEQPACKET specific functions which send SEQ_BEGIN/SEQ_END.
   Note that both functions may sleep to wait enough space for
   SEQPACKET header.
2) SEQ_BEGIN/SEQ_END in TAP packet capture.
3) Send SHUTDOWN on socket close for SEQPACKET type.
4) Set SEQPACKET packet type during send.
5) Set MSG_EOR in flags for SEQPACKET during send.

Signed-off-by: Arseny Krasnov 
---
 include/linux/virtio_vsock.h|  3 ++
 net/vmw_vsock/virtio_transport_common.c | 67 -
 2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
index 022667d57884..bf09d9aafa20 100644
--- a/include/linux/virtio_vsock.h
+++ b/include/linux/virtio_vsock.h
@@ -41,6 +41,7 @@ struct virtio_vsock_sock {
u32 user_read_seq_len;
u32 user_read_copied;
u32 curr_rx_msg_cnt;
+   u32 next_tx_msg_cnt;
 };
 
 struct virtio_vsock_pkt {
@@ -85,6 +86,8 @@ virtio_transport_dgram_dequeue(struct vsock_sock *vsk,
   struct msghdr *msg,
   size_t len, int flags);
 
+int virtio_transport_seqpacket_seq_send_len(struct vsock_sock *vsk, size_t 
len, int flags);
+int virtio_transport_seqpacket_seq_send_eor(struct vsock_sock *vsk, int flags);
 size_t virtio_transport_seqpacket_seq_get_len(struct vsock_sock *vsk);
 int
 virtio_transport_seqpacket_dequeue(struct vsock_sock *vsk,
diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index 3ca0009c553e..8431d0a891ed 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -139,6 +139,8 @@ static struct sk_buff *virtio_transport_build_skb(void 
*opaque)
break;
case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
case VIRTIO_VSOCK_OP_CREDIT_REQUEST:
+   case VIRTIO_VSOCK_OP_SEQ_BEGIN:
+   case VIRTIO_VSOCK_OP_SEQ_END:
hdr->op = cpu_to_le16(AF_VSOCK_OP_CONTROL);
break;
default:
@@ -187,7 +189,12 @@ static int virtio_transport_send_pkt_info(struct 
vsock_sock *vsk,
struct virtio_vsock_pkt *pkt;
u32 pkt_len = info->pkt_len;
 
-   info->type = VIRTIO_VSOCK_TYPE_STREAM;
+   info->type = virtio_transport_get_type(sk_vsock(vsk));
+
+   if (info->type == VIRTIO_VSOCK_TYPE_SEQPACKET &&
+   info->msg &&
+   info->msg->msg_flags & MSG_EOR)
+   info->flags |= VIRTIO_VSOCK_RW_EOR;
 
t_ops = virtio_transport_get_ops(vsk);
if (unlikely(!t_ops))
@@ -401,6 +408,62 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
return err;
 }
 
+static int virtio_transport_seqpacket_send_ctrl(struct vsock_sock *vsk,
+   int type,
+   size_t len,
+   int flags)
+{
+   struct virtio_vsock_sock *vvs = vsk->trans;
+   struct virtio_vsock_pkt_info info = {
+   .op = type,
+   .vsk = vsk,
+   .pkt_len = sizeof(struct virtio_vsock_seq_hdr)
+   };
+
+   struct virtio_vsock_seq_hdr seq_hdr = {
+   .msg_cnt = cpu_to_le32(vvs->next_tx_msg_cnt),
+   .msg_len = cpu_to_le32(len)
+   };
+
+   struct kvec seq_hdr_kiov = {
+   .iov_base = (void *)_hdr,
+   .iov_len = sizeof(struct virtio_vsock_seq_hdr)
+   };
+
+   struct msghdr msg = {0};
+
+   //XXX: do we need 'vsock_transport_send_notify_data' pointer?
+   if (vsock_wait_space(sk_vsock(vsk),
+sizeof(struct virtio_vsock_seq_hdr),
+flags, NULL))
+   return -1;
+
+   iov_iter_kvec(_iter, WRITE, _hdr_kiov, 1, sizeof(seq_hdr));
+
+   info.msg = 
+   vvs->next_tx_msg_cnt++;
+
+   return virtio_transport_send_pkt_info(vsk, );
+}
+
+int virtio_transport_seqpacket_seq_send_len(struct vsock_sock *vsk, size_t 
len, int flags)
+{
+   return virtio_transport_seqpacket_send_ctrl(vsk,
+   VIRTIO_VSOCK_OP_SEQ_BEGIN,
+   len,
+   flags);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_seqpacket_seq_send_len);
+
+int virtio_transport_seqpacket_seq_send_eor(struct vsock_sock *vsk, int flags)
+{
+   return virtio_transport_seqpacket_send_ctrl(vsk,
+   VIRTIO_VSOCK_OP_SEQ_END,
+   0,
+   flags);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_seqpacket_seq_send_eor);
+
 static inline void virtio_transport_remove_pkt(struct virtio_vsock_pkt *pkt)
 {
list_del(>list);
@@ -999,7 +1062,7 @@ void virtio_transport_release(struct vsock_sock *vsk)
struct sock *sk = >sk;

[RFC PATCH v5 11/19] virtio/vsock: dequeue callback for SOCK_SEQPACKET

2021-02-17 Thread Arseny Krasnov
This adds transport callback and it's logic for SEQPACKET dequeue.
Callback fetches RW packets from rx queue of socket until whole record
is copied(if user's buffer is full, user is not woken up). This is done
to not stall sender, because if we wake up user and it leaves syscall,
nobody will send credit update for rest of record, and sender will wait
for next enter of read syscall at receiver's side. So if user buffer is
full, we just send credit update and drop data. If during copy SEQ_BEGIN
was found(and not all data was copied), copying is restarted by reset
user's iov iterator(previous unfinished data is dropped).

Signed-off-by: Arseny Krasnov 
---
 include/linux/virtio_vsock.h|  10 +++
 include/uapi/linux/virtio_vsock.h   |  16 
 net/vmw_vsock/virtio_transport_common.c | 114 
 3 files changed, 140 insertions(+)

diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
index dc636b727179..003d06ae4a85 100644
--- a/include/linux/virtio_vsock.h
+++ b/include/linux/virtio_vsock.h
@@ -36,6 +36,11 @@ struct virtio_vsock_sock {
u32 rx_bytes;
u32 buf_alloc;
struct list_head rx_queue;
+
+   /* For SOCK_SEQPACKET */
+   u32 user_read_seq_len;
+   u32 user_read_copied;
+   u32 curr_rx_msg_cnt;
 };
 
 struct virtio_vsock_pkt {
@@ -80,6 +85,11 @@ virtio_transport_dgram_dequeue(struct vsock_sock *vsk,
   struct msghdr *msg,
   size_t len, int flags);
 
+int
+virtio_transport_seqpacket_dequeue(struct vsock_sock *vsk,
+  struct msghdr *msg,
+  int flags,
+  bool *msg_ready);
 s64 virtio_transport_stream_has_data(struct vsock_sock *vsk);
 s64 virtio_transport_stream_has_space(struct vsock_sock *vsk);
 
diff --git a/include/uapi/linux/virtio_vsock.h 
b/include/uapi/linux/virtio_vsock.h
index 1d57ed3d84d2..cf9c165e5cca 100644
--- a/include/uapi/linux/virtio_vsock.h
+++ b/include/uapi/linux/virtio_vsock.h
@@ -63,8 +63,14 @@ struct virtio_vsock_hdr {
__le32  fwd_cnt;
 } __attribute__((packed));
 
+struct virtio_vsock_seq_hdr {
+   __le32  msg_cnt;
+   __le32  msg_len;
+} __attribute__((packed));
+
 enum virtio_vsock_type {
VIRTIO_VSOCK_TYPE_STREAM = 1,
+   VIRTIO_VSOCK_TYPE_SEQPACKET = 2,
 };
 
 enum virtio_vsock_op {
@@ -83,6 +89,11 @@ enum virtio_vsock_op {
VIRTIO_VSOCK_OP_CREDIT_UPDATE = 6,
/* Request the peer to send the credit info to us */
VIRTIO_VSOCK_OP_CREDIT_REQUEST = 7,
+
+   /* Record begin for SOCK_SEQPACKET */
+   VIRTIO_VSOCK_OP_SEQ_BEGIN = 8,
+   /* Record end for SOCK_SEQPACKET */
+   VIRTIO_VSOCK_OP_SEQ_END = 9,
 };
 
 /* VIRTIO_VSOCK_OP_SHUTDOWN flags values */
@@ -91,4 +102,9 @@ enum virtio_vsock_shutdown {
VIRTIO_VSOCK_SHUTDOWN_SEND = 2,
 };
 
+/* VIRTIO_VSOCK_OP_RW flags values */
+enum virtio_vsock_rw {
+   VIRTIO_VSOCK_RW_EOR = 1,
+};
+
 #endif /* _UAPI_LINUX_VIRTIO_VSOCK_H */
diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index 833104b71a1c..d8ec2dfa2315 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -393,6 +393,108 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
return err;
 }
 
+static inline void virtio_transport_remove_pkt(struct virtio_vsock_pkt *pkt)
+{
+   list_del(>list);
+   virtio_transport_free_pkt(pkt);
+}
+
+static int virtio_transport_seqpacket_do_dequeue(struct vsock_sock *vsk,
+struct msghdr *msg,
+bool *msg_ready)
+{
+   struct virtio_vsock_sock *vvs = vsk->trans;
+   struct virtio_vsock_pkt *pkt;
+   int err = 0;
+   size_t user_buf_len = msg->msg_iter.count;
+
+   *msg_ready = false;
+   spin_lock_bh(>rx_lock);
+
+   while (!*msg_ready && !list_empty(>rx_queue) && !err) {
+   pkt = list_first_entry(>rx_queue, struct virtio_vsock_pkt, 
list);
+
+   switch (le16_to_cpu(pkt->hdr.op)) {
+   case VIRTIO_VSOCK_OP_SEQ_BEGIN: {
+   /* Unexpected 'SEQ_BEGIN' during record copy:
+* Leave receive loop, 'EAGAIN' will restart it from
+* outer receive loop, packet is still in queue and
+* counters are cleared. So in next loop enter,
+* 'SEQ_BEGIN' will be dequeued first. User's iov
+* iterator will be reset in outer loop. Also
+* send credit update, because some bytes could be
+* copied. User will never see unfinished record.
+*/
+   err = -EAGAIN;
+   break;
+   }
+   case VIRTIO_VSOCK_OP_SEQ_END: {
+ 

[RFC PATCH v5 09/19] virtio/vsock: set packet's type in send

2021-02-17 Thread Arseny Krasnov
This moves passing type of packet from 'info' srtucture to send
function. There is no sense to set type of packet which differs
from type of socket, and since at current time only stream type
is supported, so force to use this type.

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/virtio_transport_common.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index e4370b1b7494..1c9d71ca5e8e 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -179,6 +179,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock 
*vsk,
struct virtio_vsock_pkt *pkt;
u32 pkt_len = info->pkt_len;
 
+   info->type = VIRTIO_VSOCK_TYPE_STREAM;
+
t_ops = virtio_transport_get_ops(vsk);
if (unlikely(!t_ops))
return -EFAULT;
@@ -624,7 +626,6 @@ int virtio_transport_connect(struct vsock_sock *vsk)
 {
struct virtio_vsock_pkt_info info = {
.op = VIRTIO_VSOCK_OP_REQUEST,
-   .type = VIRTIO_VSOCK_TYPE_STREAM,
.vsk = vsk,
};
 
@@ -636,7 +637,6 @@ int virtio_transport_shutdown(struct vsock_sock *vsk, int 
mode)
 {
struct virtio_vsock_pkt_info info = {
.op = VIRTIO_VSOCK_OP_SHUTDOWN,
-   .type = VIRTIO_VSOCK_TYPE_STREAM,
.flags = (mode & RCV_SHUTDOWN ?
  VIRTIO_VSOCK_SHUTDOWN_RCV : 0) |
 (mode & SEND_SHUTDOWN ?
@@ -665,7 +665,6 @@ virtio_transport_stream_enqueue(struct vsock_sock *vsk,
 {
struct virtio_vsock_pkt_info info = {
.op = VIRTIO_VSOCK_OP_RW,
-   .type = VIRTIO_VSOCK_TYPE_STREAM,
.msg = msg,
.pkt_len = len,
.vsk = vsk,
@@ -688,7 +687,6 @@ static int virtio_transport_reset(struct vsock_sock *vsk,
 {
struct virtio_vsock_pkt_info info = {
.op = VIRTIO_VSOCK_OP_RST,
-   .type = VIRTIO_VSOCK_TYPE_STREAM,
.reply = !!pkt,
.vsk = vsk,
};
@@ -990,7 +988,6 @@ virtio_transport_send_response(struct vsock_sock *vsk,
 {
struct virtio_vsock_pkt_info info = {
.op = VIRTIO_VSOCK_OP_RESPONSE,
-   .type = VIRTIO_VSOCK_TYPE_STREAM,
.remote_cid = le64_to_cpu(pkt->hdr.src_cid),
.remote_port = le32_to_cpu(pkt->hdr.src_port),
.reply = true,
-- 
2.25.1



[RFC PATCH v5 10/19] virtio/vsock: simplify credit update function API

2021-02-17 Thread Arseny Krasnov
'virtio_transport_send_credit_update()' has some extra args:
1) 'type' may be set in 'virtio_transport_send_pkt_info()' using type
   of socket.
2) This function is static and 'hdr' arg was always NULL.

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/virtio_transport_common.c | 15 ---
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/net/vmw_vsock/virtio_transport_common.c 
b/net/vmw_vsock/virtio_transport_common.c
index 1c9d71ca5e8e..833104b71a1c 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -271,13 +271,10 @@ void virtio_transport_put_credit(struct virtio_vsock_sock 
*vvs, u32 credit)
 }
 EXPORT_SYMBOL_GPL(virtio_transport_put_credit);
 
-static int virtio_transport_send_credit_update(struct vsock_sock *vsk,
-  int type,
-  struct virtio_vsock_hdr *hdr)
+static int virtio_transport_send_credit_update(struct vsock_sock *vsk)
 {
struct virtio_vsock_pkt_info info = {
.op = VIRTIO_VSOCK_OP_CREDIT_UPDATE,
-   .type = type,
.vsk = vsk,
};
 
@@ -385,11 +382,8 @@ virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
 * messages, we set the limit to a high value. TODO: experiment
 * with different values.
 */
-   if (free_space < VIRTIO_VSOCK_MAX_PKT_BUF_SIZE) {
-   virtio_transport_send_credit_update(vsk,
-   VIRTIO_VSOCK_TYPE_STREAM,
-   NULL);
-   }
+   if (free_space < VIRTIO_VSOCK_MAX_PKT_BUF_SIZE)
+   virtio_transport_send_credit_update(vsk);
 
return total;
 
@@ -498,8 +492,7 @@ void virtio_transport_notify_buffer_size(struct vsock_sock 
*vsk, u64 *val)
 
vvs->buf_alloc = *val;
 
-   virtio_transport_send_credit_update(vsk, VIRTIO_VSOCK_TYPE_STREAM,
-   NULL);
+   virtio_transport_send_credit_update(vsk);
 }
 EXPORT_SYMBOL_GPL(virtio_transport_notify_buffer_size);
 
-- 
2.25.1



[RFC PATCH v5 08/19] af_vsock: update comments for stream sockets

2021-02-17 Thread Arseny Krasnov
This replaces 'stream' to 'connect oriented' in comments as SEQPACKET is
also connect oriented.

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/af_vsock.c | 31 +--
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index f4b02c6d35d1..f1bf6a5ad15e 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -415,8 +415,8 @@ static void vsock_deassign_transport(struct vsock_sock *vsk)
 
 /* Assign a transport to a socket and call the .init transport callback.
  *
- * Note: for stream socket this must be called when vsk->remote_addr is set
- * (e.g. during the connect() or when a connection request on a listener
+ * Note: for connection oriented socket this must be called when 
vsk->remote_addr
+ * is set (e.g. during the connect() or when a connection request on a listener
  * socket is received).
  * The vsk->remote_addr is used to decide which transport to use:
  *  - remote CID == VMADDR_CID_LOCAL or g2h->local_cid or VMADDR_CID_HOST if
@@ -470,10 +470,10 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct 
vsock_sock *psk)
return 0;
 
/* transport->release() must be called with sock lock acquired.
-* This path can only be taken during vsock_stream_connect(),
-* where we have already held the sock lock.
-* In the other cases, this function is called on a new socket
-* which is not assigned to any transport.
+* This path can only be taken during vsock_connect(), where we
+* have already held the sock lock. In the other cases, this
+* function is called on a new socket which is not assigned to
+* any transport.
 */
vsk->transport->release(vsk);
vsock_deassign_transport(vsk);
@@ -658,9 +658,10 @@ static int __vsock_bind_connectible(struct vsock_sock *vsk,
 
vsock_addr_init(>local_addr, new_addr.svm_cid, new_addr.svm_port);
 
-   /* Remove stream sockets from the unbound list and add them to the hash
-* table for easy lookup by its address.  The unbound list is simply an
-* extra entry at the end of the hash table, a trick used by AF_UNIX.
+   /* Remove connection oriented sockets from the unbound list and add them
+* to the hash table for easy lookup by its address.  The unbound list
+* is simply an extra entry at the end of the hash table, a trick used
+* by AF_UNIX.
 */
__vsock_remove_bound(vsk);
__vsock_insert_bound(vsock_bound_sockets(>local_addr), vsk);
@@ -951,10 +952,10 @@ static int vsock_shutdown(struct socket *sock, int mode)
if ((mode & ~SHUTDOWN_MASK) || !mode)
return -EINVAL;
 
-   /* If this is a STREAM socket and it is not connected then bail out
-* immediately.  If it is a DGRAM socket then we must first kick the
-* socket so that it wakes up from any sleeping calls, for example
-* recv(), and then afterwards return the error.
+   /* If this is a connection oriented socket and it is not connected then
+* bail out immediately.  If it is a DGRAM socket then we must first
+* kick the socket so that it wakes up from any sleeping calls, for
+* example recv(), and then afterwards return the error.
 */
 
sk = sock->sk;
@@ -1783,7 +1784,9 @@ static int vsock_connectible_sendmsg(struct socket *sock, 
struct msghdr *msg,
 
transport = vsk->transport;
 
-   /* Callers should not provide a destination with stream sockets. */
+   /* Callers should not provide a destination with connection oriented
+* sockets.
+*/
if (msg->msg_namelen) {
err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
goto out;
-- 
2.25.1



[RFC PATCH v5 06/19] af_vsock: implement send logic for SEQPACKET

2021-02-17 Thread Arseny Krasnov
This adds some logic to current stream enqueue function for SEQPACKET
support:
1) Send record's begin/end marker.
2) Return value from enqueue function is whole record length or error
   for SOCK_SEQPACKET.

Signed-off-by: Arseny Krasnov 
---
 include/net/af_vsock.h   |  2 ++
 net/vmw_vsock/af_vsock.c | 22 --
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 6fbe88306403..0d4dd9386fb1 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -136,6 +136,8 @@ struct vsock_transport {
bool (*stream_allow)(u32 cid, u32 port);
 
/* SEQ_PACKET. */
+   int (*seqpacket_seq_send_len)(struct vsock_sock *vsk, size_t len, int 
flags);
+   int (*seqpacket_seq_send_eor)(struct vsock_sock *vsk, int flags);
size_t (*seqpacket_seq_get_len)(struct vsock_sock *vsk);
int (*seqpacket_dequeue)(struct vsock_sock *vsk, struct msghdr *msg,
 int flags, bool *msg_ready);
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 09b377422b1e..f352cd9d91ce 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1801,6 +1801,12 @@ static int vsock_connectible_sendmsg(struct socket 
*sock, struct msghdr *msg,
if (err < 0)
goto out;
 
+   if (sk->sk_type == SOCK_SEQPACKET) {
+   err = transport->seqpacket_seq_send_len(vsk, len, 
msg->msg_flags);
+   if (err < 0)
+   goto out;
+   }
+
while (total_written < len) {
ssize_t written;
 
@@ -1847,9 +1853,21 @@ static int vsock_connectible_sendmsg(struct socket 
*sock, struct msghdr *msg,
 
}
 
+   if (sk->sk_type == SOCK_SEQPACKET) {
+   err = transport->seqpacket_seq_send_eor(vsk, msg->msg_flags);
+   if (err < 0)
+   goto out;
+   }
+
 out_err:
-   if (total_written > 0)
-   err = total_written;
+   if (total_written > 0) {
+   /* Return number of written bytes only if:
+* 1) SOCK_STREAM socket.
+* 2) SOCK_SEQPACKET socket when whole buffer is sent.
+*/
+   if (sk->sk_type == SOCK_STREAM || total_written == len)
+   err = total_written;
+   }
 out:
release_sock(sk);
return err;
-- 
2.25.1



[RFC PATCH v5 07/19] af_vsock: rest of SEQPACKET support

2021-02-17 Thread Arseny Krasnov
This does rest of SOCK_SEQPACKET support:
1) Adds socket ops for SEQPACKET type.
2) Allows to create socket with SEQPACKET type.

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/af_vsock.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index f352cd9d91ce..f4b02c6d35d1 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -452,6 +452,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct 
vsock_sock *psk)
new_transport = transport_dgram;
break;
case SOCK_STREAM:
+   case SOCK_SEQPACKET:
if (vsock_use_local_transport(remote_cid))
new_transport = transport_local;
else if (remote_cid <= VMADDR_CID_HOST || !transport_h2g ||
@@ -484,6 +485,14 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct 
vsock_sock *psk)
if (!new_transport || !try_module_get(new_transport->module))
return -ENODEV;
 
+   if (sk->sk_type == SOCK_SEQPACKET) {
+   if (!new_transport->seqpacket_seq_send_len ||
+   !new_transport->seqpacket_seq_send_eor ||
+   !new_transport->seqpacket_seq_get_len ||
+   !new_transport->seqpacket_dequeue)
+   return -ESOCKTNOSUPPORT;
+   }
+
ret = new_transport->init(vsk, psk);
if (ret) {
module_put(new_transport->module);
@@ -684,6 +693,7 @@ static int __vsock_bind(struct sock *sk, struct sockaddr_vm 
*addr)
 
switch (sk->sk_socket->type) {
case SOCK_STREAM:
+   case SOCK_SEQPACKET:
spin_lock_bh(_table_lock);
retval = __vsock_bind_connectible(vsk, addr);
spin_unlock_bh(_table_lock);
@@ -769,7 +779,7 @@ static struct sock *__vsock_create(struct net *net,
 
 static bool sock_type_connectible(u16 type)
 {
-   return type == SOCK_STREAM;
+   return (type == SOCK_STREAM) || (type == SOCK_SEQPACKET);
 }
 
 static void __vsock_release(struct sock *sk, int level)
@@ -2191,6 +2201,27 @@ static const struct proto_ops vsock_stream_ops = {
.sendpage = sock_no_sendpage,
 };
 
+static const struct proto_ops vsock_seqpacket_ops = {
+   .family = PF_VSOCK,
+   .owner = THIS_MODULE,
+   .release = vsock_release,
+   .bind = vsock_bind,
+   .connect = vsock_connect,
+   .socketpair = sock_no_socketpair,
+   .accept = vsock_accept,
+   .getname = vsock_getname,
+   .poll = vsock_poll,
+   .ioctl = sock_no_ioctl,
+   .listen = vsock_listen,
+   .shutdown = vsock_shutdown,
+   .setsockopt = vsock_connectible_setsockopt,
+   .getsockopt = vsock_connectible_getsockopt,
+   .sendmsg = vsock_connectible_sendmsg,
+   .recvmsg = vsock_connectible_recvmsg,
+   .mmap = sock_no_mmap,
+   .sendpage = sock_no_sendpage,
+};
+
 static int vsock_create(struct net *net, struct socket *sock,
int protocol, int kern)
 {
@@ -2211,6 +2242,9 @@ static int vsock_create(struct net *net, struct socket 
*sock,
case SOCK_STREAM:
sock->ops = _stream_ops;
break;
+   case SOCK_SEQPACKET:
+   sock->ops = _seqpacket_ops;
+   break;
default:
return -ESOCKTNOSUPPORT;
}
-- 
2.25.1



[RFC PATCH v5 04/19] af_vsock: implement SEQPACKET receive loop

2021-02-17 Thread Arseny Krasnov
This adds receive loop for SEQPACKET. It looks like receive loop for
STREAM, but there is a little bit difference:
1) It doesn't call notify callbacks.
2) It doesn't care about 'SO_SNDLOWAT' and 'SO_RCVLOWAT' values, because
   there is no sense for these values in SEQPACKET case.
3) It waits until whole record is received or error is found during
   receiving.
4) It processes and sets 'MSG_TRUNC' flag.

So to avoid extra conditions for two types of socket inside one loop, two
independent functions were created.

Signed-off-by: Arseny Krasnov 
---
 include/net/af_vsock.h   |  5 +++
 net/vmw_vsock/af_vsock.c | 97 +++-
 2 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index b1c717286993..01563338cc03 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -135,6 +135,11 @@ struct vsock_transport {
bool (*stream_is_active)(struct vsock_sock *);
bool (*stream_allow)(u32 cid, u32 port);
 
+   /* SEQ_PACKET. */
+   size_t (*seqpacket_seq_get_len)(struct vsock_sock *vsk);
+   int (*seqpacket_dequeue)(struct vsock_sock *vsk, struct msghdr *msg,
+int flags, bool *msg_ready);
+
/* Notification. */
int (*notify_poll_in)(struct vsock_sock *, size_t, bool *);
int (*notify_poll_out)(struct vsock_sock *, size_t, bool *);
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index d277dc1cdbdf..b754927a556a 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1972,6 +1972,98 @@ static int __vsock_stream_recvmsg(struct sock *sk, 
struct msghdr *msg,
return err;
 }
 
+static int __vsock_seqpacket_recvmsg(struct sock *sk, struct msghdr *msg,
+size_t len, int flags)
+{
+   const struct vsock_transport *transport;
+   const struct iovec *orig_iov;
+   unsigned long orig_nr_segs;
+   bool msg_ready;
+   struct vsock_sock *vsk;
+   size_t record_len;
+   long timeout;
+   int err = 0;
+   DEFINE_WAIT(wait);
+
+   vsk = vsock_sk(sk);
+   transport = vsk->transport;
+
+   timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+   orig_nr_segs = msg->msg_iter.nr_segs;
+   orig_iov = msg->msg_iter.iov;
+   msg_ready = false;
+   record_len = 0;
+
+   while (1) {
+   err = vsock_wait_data(sk, , timeout, NULL, 0);
+
+   if (err <= 0) {
+   /* In case of any loop break(timeout, signal
+* interrupt or shutdown), we report user that
+* nothing was copied.
+*/
+   err = 0;
+   break;
+   }
+
+   if (record_len == 0) {
+   record_len =
+   transport->seqpacket_seq_get_len(vsk);
+
+   if (record_len == 0)
+   continue;
+   }
+
+   err = transport->seqpacket_dequeue(vsk, msg,
+   flags, _ready);
+
+   if (err < 0) {
+   if (err == -EAGAIN) {
+   iov_iter_init(>msg_iter, READ,
+ orig_iov, orig_nr_segs,
+ len);
+   /* Clear 'MSG_EOR' here, because dequeue
+* callback above set it again if it was
+* set by sender. This 'MSG_EOR' is from
+* dropped record.
+*/
+   msg->msg_flags &= ~MSG_EOR;
+   record_len = 0;
+   continue;
+   }
+
+   err = -ENOMEM;
+   break;
+   }
+
+   if (msg_ready)
+   break;
+   }
+
+   if (sk->sk_err)
+   err = -sk->sk_err;
+   else if (sk->sk_shutdown & RCV_SHUTDOWN)
+   err = 0;
+
+   if (msg_ready) {
+   /* User sets MSG_TRUNC, so return real length of
+* packet.
+*/
+   if (flags & MSG_TRUNC)
+   err = record_len;
+   else
+   err = len - msg->msg_iter.count;
+
+   /* Always set MSG_TRUNC if real length of packet is
+* bigger than user's buffer.
+*/
+   if (record_len > len)
+   msg->msg_flags |= MSG_TRUNC;
+   }
+
+   return err;
+}
+
 static int
 vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
  int flags)
@@ -2027,7 +2119,10 @@ vsock_connectible_recvmsg(struct socket *sock, struct 

[RFC PATCH v5 05/19] af_vsock: separate wait space loop

2021-02-17 Thread Arseny Krasnov
This moves loop that waits for space on send to separate function,
because it will be used for SEQ_BEGIN/SEQ_END sending before and
after data transmission. Waiting for SEQ_BEGIN/SEQ_END is needed
because such packets carries SEQPACKET header that couldn't be
fragmented by credit mechanism, so to avoid it, sender waits until
enough space will be ready.

Signed-off-by: Arseny Krasnov 
---
 include/net/af_vsock.h   |  2 +
 net/vmw_vsock/af_vsock.c | 99 +---
 2 files changed, 63 insertions(+), 38 deletions(-)

diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index 01563338cc03..6fbe88306403 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -205,6 +205,8 @@ void vsock_remove_sock(struct vsock_sock *vsk);
 void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
 int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk);
 bool vsock_find_cid(unsigned int cid);
+int vsock_wait_space(struct sock *sk, size_t space, int flags,
+struct vsock_transport_send_notify_data *send_data);
 
 / TAP /
 
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index b754927a556a..09b377422b1e 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1692,6 +1692,65 @@ static int vsock_connectible_getsockopt(struct socket 
*sock,
return 0;
 }
 
+int vsock_wait_space(struct sock *sk, size_t space, int flags,
+struct vsock_transport_send_notify_data *send_data)
+{
+   const struct vsock_transport *transport;
+   struct vsock_sock *vsk;
+   long timeout;
+   int err;
+
+   DEFINE_WAIT_FUNC(wait, woken_wake_function);
+
+   vsk = vsock_sk(sk);
+   transport = vsk->transport;
+   timeout = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
+   err = 0;
+
+   add_wait_queue(sk_sleep(sk), );
+
+   while (vsock_stream_has_space(vsk) < space &&
+  sk->sk_err == 0 &&
+  !(sk->sk_shutdown & SEND_SHUTDOWN) &&
+  !(vsk->peer_shutdown & RCV_SHUTDOWN)) {
+
+   /* Don't wait for non-blocking sockets. */
+   if (timeout == 0) {
+   err = -EAGAIN;
+   goto out_err;
+   }
+
+   if (send_data) {
+   err = transport->notify_send_pre_block(vsk, send_data);
+   if (err < 0)
+   goto out_err;
+   }
+
+   release_sock(sk);
+   timeout = wait_woken(, TASK_INTERRUPTIBLE, timeout);
+   lock_sock(sk);
+   if (signal_pending(current)) {
+   err = sock_intr_errno(timeout);
+   goto out_err;
+   } else if (timeout == 0) {
+   err = -EAGAIN;
+   goto out_err;
+   }
+   }
+
+   if (sk->sk_err) {
+   err = -sk->sk_err;
+   } else if ((sk->sk_shutdown & SEND_SHUTDOWN) ||
+  (vsk->peer_shutdown & RCV_SHUTDOWN)) {
+   err = -EPIPE;
+   }
+
+out_err:
+   remove_wait_queue(sk_sleep(sk), );
+   return err;
+}
+EXPORT_SYMBOL_GPL(vsock_wait_space);
+
 static int vsock_connectible_sendmsg(struct socket *sock, struct msghdr *msg,
 size_t len)
 {
@@ -1699,10 +1758,8 @@ static int vsock_connectible_sendmsg(struct socket 
*sock, struct msghdr *msg,
struct vsock_sock *vsk;
const struct vsock_transport *transport;
ssize_t total_written;
-   long timeout;
int err;
struct vsock_transport_send_notify_data send_data;
-   DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
sk = sock->sk;
vsk = vsock_sk(sk);
@@ -1740,9 +1797,6 @@ static int vsock_connectible_sendmsg(struct socket *sock, 
struct msghdr *msg,
goto out;
}
 
-   /* Wait for room in the produce queue to enqueue our user's data. */
-   timeout = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
-
err = transport->notify_send_init(vsk, _data);
if (err < 0)
goto out;
@@ -1750,39 +1804,8 @@ static int vsock_connectible_sendmsg(struct socket 
*sock, struct msghdr *msg,
while (total_written < len) {
ssize_t written;
 
-   add_wait_queue(sk_sleep(sk), );
-   while (vsock_stream_has_space(vsk) == 0 &&
-  sk->sk_err == 0 &&
-  !(sk->sk_shutdown & SEND_SHUTDOWN) &&
-  !(vsk->peer_shutdown & RCV_SHUTDOWN)) {
-
-   /* Don't wait for non-blocking sockets. */
-   if (timeout == 0) {
-   err = -EAGAIN;
-   remove_wait_queue(sk_sleep(sk), );
-   goto out_err;
-   }
-
-   err = 

[RFC PATCH v5 03/19] af_vsock: separate receive data loop

2021-02-17 Thread Arseny Krasnov
This moves STREAM specific data receive logic to dedicated function:
'__vsock_stream_recvmsg()', while checks that will be same for both
types of socket are in shared function: 'vsock_connectible_recvmsg()'.

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/af_vsock.c | 116 ++-
 1 file changed, 67 insertions(+), 49 deletions(-)

diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 6cf7bb977aa1..d277dc1cdbdf 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1894,65 +1894,22 @@ static int vsock_wait_data(struct sock *sk, struct 
wait_queue_entry *wait,
return data;
 }
 
-static int
-vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
- int flags)
+static int __vsock_stream_recvmsg(struct sock *sk, struct msghdr *msg,
+ size_t len, int flags)
 {
-   struct sock *sk;
-   struct vsock_sock *vsk;
+   struct vsock_transport_recv_notify_data recv_data;
const struct vsock_transport *transport;
-   int err;
-   size_t target;
+   struct vsock_sock *vsk;
ssize_t copied;
+   size_t target;
long timeout;
-   struct vsock_transport_recv_notify_data recv_data;
+   int err;
 
DEFINE_WAIT(wait);
 
-   sk = sock->sk;
vsk = vsock_sk(sk);
-   err = 0;
-
-   lock_sock(sk);
-
transport = vsk->transport;
 
-   if (!transport || sk->sk_state != TCP_ESTABLISHED) {
-   /* Recvmsg is supposed to return 0 if a peer performs an
-* orderly shutdown. Differentiate between that case and when a
-* peer has not connected or a local shutdown occured with the
-* SOCK_DONE flag.
-*/
-   if (sock_flag(sk, SOCK_DONE))
-   err = 0;
-   else
-   err = -ENOTCONN;
-
-   goto out;
-   }
-
-   if (flags & MSG_OOB) {
-   err = -EOPNOTSUPP;
-   goto out;
-   }
-
-   /* We don't check peer_shutdown flag here since peer may actually shut
-* down, but there can be data in the queue that a local socket can
-* receive.
-*/
-   if (sk->sk_shutdown & RCV_SHUTDOWN) {
-   err = 0;
-   goto out;
-   }
-
-   /* It is valid on Linux to pass in a zero-length receive buffer.  This
-* is not an error.  We may as well bail out now.
-*/
-   if (!len) {
-   err = 0;
-   goto out;
-   }
-
/* We must not copy less than target bytes into the user's buffer
 * before returning successfully, so we wait for the consume queue to
 * have that much data to consume before dequeueing.  Note that this
@@ -2011,6 +1968,67 @@ vsock_connectible_recvmsg(struct socket *sock, struct 
msghdr *msg, size_t len,
if (copied > 0)
err = copied;
 
+out:
+   return err;
+}
+
+static int
+vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ int flags)
+{
+   struct sock *sk;
+   struct vsock_sock *vsk;
+   const struct vsock_transport *transport;
+   int err;
+
+   DEFINE_WAIT(wait);
+
+   sk = sock->sk;
+   vsk = vsock_sk(sk);
+   err = 0;
+
+   lock_sock(sk);
+
+   transport = vsk->transport;
+
+   if (!transport || sk->sk_state != TCP_ESTABLISHED) {
+   /* Recvmsg is supposed to return 0 if a peer performs an
+* orderly shutdown. Differentiate between that case and when a
+* peer has not connected or a local shutdown occurred with the
+* SOCK_DONE flag.
+*/
+   if (sock_flag(sk, SOCK_DONE))
+   err = 0;
+   else
+   err = -ENOTCONN;
+
+   goto out;
+   }
+
+   if (flags & MSG_OOB) {
+   err = -EOPNOTSUPP;
+   goto out;
+   }
+
+   /* We don't check peer_shutdown flag here since peer may actually shut
+* down, but there can be data in the queue that a local socket can
+* receive.
+*/
+   if (sk->sk_shutdown & RCV_SHUTDOWN) {
+   err = 0;
+   goto out;
+   }
+
+   /* It is valid on Linux to pass in a zero-length receive buffer.  This
+* is not an error.  We may as well bail out now.
+*/
+   if (!len) {
+   err = 0;
+   goto out;
+   }
+
+   err = __vsock_stream_recvmsg(sk, msg, len, flags);
+
 out:
release_sock(sk);
return err;
-- 
2.25.1



[RFC PATCH v5 01/19] af_vsock: update functions for connectible socket

2021-02-17 Thread Arseny Krasnov
This prepares af_vsock.c for SEQPACKET support: some functions such
as setsockopt(), getsockopt(), connect(), recvmsg(), sendmsg() are
shared between both types of sockets, so rename them in general
manner.

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/af_vsock.c | 64 +---
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 5546710d8ac1..656370e11707 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -604,8 +604,8 @@ static void vsock_pending_work(struct work_struct *work)
 
 / SOCKET OPERATIONS /
 
-static int __vsock_bind_stream(struct vsock_sock *vsk,
-  struct sockaddr_vm *addr)
+static int __vsock_bind_connectible(struct vsock_sock *vsk,
+   struct sockaddr_vm *addr)
 {
static u32 port;
struct sockaddr_vm new_addr;
@@ -685,7 +685,7 @@ static int __vsock_bind(struct sock *sk, struct sockaddr_vm 
*addr)
switch (sk->sk_socket->type) {
case SOCK_STREAM:
spin_lock_bh(_table_lock);
-   retval = __vsock_bind_stream(vsk, addr);
+   retval = __vsock_bind_connectible(vsk, addr);
spin_unlock_bh(_table_lock);
break;
 
@@ -767,6 +767,11 @@ static struct sock *__vsock_create(struct net *net,
return sk;
 }
 
+static bool sock_type_connectible(u16 type)
+{
+   return type == SOCK_STREAM;
+}
+
 static void __vsock_release(struct sock *sk, int level)
 {
if (sk) {
@@ -785,7 +790,7 @@ static void __vsock_release(struct sock *sk, int level)
 
if (vsk->transport)
vsk->transport->release(vsk);
-   else if (sk->sk_type == SOCK_STREAM)
+   else if (sock_type_connectible(sk->sk_type))
vsock_remove_sock(vsk);
 
sock_orphan(sk);
@@ -947,7 +952,7 @@ static int vsock_shutdown(struct socket *sock, int mode)
lock_sock(sk);
if (sock->state == SS_UNCONNECTED) {
err = -ENOTCONN;
-   if (sk->sk_type == SOCK_STREAM)
+   if (sock_type_connectible(sk->sk_type))
goto out;
} else {
sock->state = SS_DISCONNECTING;
@@ -960,7 +965,7 @@ static int vsock_shutdown(struct socket *sock, int mode)
sk->sk_shutdown |= mode;
sk->sk_state_change(sk);
 
-   if (sk->sk_type == SOCK_STREAM) {
+   if (sock_type_connectible(sk->sk_type)) {
sock_reset_flag(sk, SOCK_DONE);
vsock_send_shutdown(sk, mode);
}
@@ -1015,7 +1020,7 @@ static __poll_t vsock_poll(struct file *file, struct 
socket *sock,
if (!(sk->sk_shutdown & SEND_SHUTDOWN))
mask |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND;
 
-   } else if (sock->type == SOCK_STREAM) {
+   } else if (sock_type_connectible(sk->sk_type)) {
const struct vsock_transport *transport;
 
lock_sock(sk);
@@ -1262,8 +1267,8 @@ static void vsock_connect_timeout(struct work_struct 
*work)
sock_put(sk);
 }
 
-static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,
-   int addr_len, int flags)
+static int vsock_connect(struct socket *sock, struct sockaddr *addr,
+int addr_len, int flags)
 {
int err;
struct sock *sk;
@@ -1413,7 +1418,7 @@ static int vsock_accept(struct socket *sock, struct 
socket *newsock, int flags,
 
lock_sock(listener);
 
-   if (sock->type != SOCK_STREAM) {
+   if (!sock_type_connectible(sock->type)) {
err = -EOPNOTSUPP;
goto out;
}
@@ -1490,7 +1495,7 @@ static int vsock_listen(struct socket *sock, int backlog)
 
lock_sock(sk);
 
-   if (sock->type != SOCK_STREAM) {
+   if (!sock_type_connectible(sk->sk_type)) {
err = -EOPNOTSUPP;
goto out;
}
@@ -1534,11 +1539,11 @@ static void vsock_update_buffer_size(struct vsock_sock 
*vsk,
vsk->buffer_size = val;
 }
 
-static int vsock_stream_setsockopt(struct socket *sock,
-  int level,
-  int optname,
-  sockptr_t optval,
-  unsigned int optlen)
+static int vsock_connectible_setsockopt(struct socket *sock,
+   int level,
+   int optname,
+   sockptr_t optval,
+   unsigned int optlen)
 {
int err;
struct sock *sk;
@@ -1616,10 +1621,10 @@ static int vsock_stream_setsockopt(struct socket *sock,
return err;
 }
 
-static int vsock_stream_getsockopt(struct socket 

[RFC PATCH v5 02/19] af_vsock: separate wait data loop

2021-02-17 Thread Arseny Krasnov
This moves wait loop for data to dedicated function, because later
it will be used by SEQPACKET data receive loop.

Signed-off-by: Arseny Krasnov 
---
 net/vmw_vsock/af_vsock.c | 155 +--
 1 file changed, 83 insertions(+), 72 deletions(-)

diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 656370e11707..6cf7bb977aa1 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1832,6 +1832,68 @@ static int vsock_connectible_sendmsg(struct socket 
*sock, struct msghdr *msg,
return err;
 }
 
+static int vsock_wait_data(struct sock *sk, struct wait_queue_entry *wait,
+  long timeout,
+  struct vsock_transport_recv_notify_data *recv_data,
+  size_t target)
+{
+   const struct vsock_transport *transport;
+   struct vsock_sock *vsk;
+   s64 data;
+   int err;
+
+   vsk = vsock_sk(sk);
+   err = 0;
+   transport = vsk->transport;
+   prepare_to_wait(sk_sleep(sk), wait, TASK_INTERRUPTIBLE);
+
+   while ((data = vsock_stream_has_data(vsk)) == 0) {
+   if (sk->sk_err != 0 ||
+   (sk->sk_shutdown & RCV_SHUTDOWN) ||
+   (vsk->peer_shutdown & SEND_SHUTDOWN)) {
+   break;
+   }
+
+   /* Don't wait for non-blocking sockets. */
+   if (timeout == 0) {
+   err = -EAGAIN;
+   break;
+   }
+
+   if (recv_data) {
+   err = transport->notify_recv_pre_block(vsk, target, 
recv_data);
+   if (err < 0)
+   break;
+   }
+
+   release_sock(sk);
+   timeout = schedule_timeout(timeout);
+   lock_sock(sk);
+
+   if (signal_pending(current)) {
+   err = sock_intr_errno(timeout);
+   break;
+   } else if (timeout == 0) {
+   err = -EAGAIN;
+   break;
+   }
+   }
+
+   finish_wait(sk_sleep(sk), wait);
+
+   if (err)
+   return err;
+
+   /* Internal transport error when checking for available
+* data. XXX This should be changed to a connection
+* reset in a later change.
+*/
+   if (data < 0)
+   return -ENOMEM;
+
+   return data;
+}
+
 static int
 vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
  int flags)
@@ -1911,85 +1973,34 @@ vsock_connectible_recvmsg(struct socket *sock, struct 
msghdr *msg, size_t len,
 
 
while (1) {
-   s64 ready;
-
-   prepare_to_wait(sk_sleep(sk), , TASK_INTERRUPTIBLE);
-   ready = vsock_stream_has_data(vsk);
-
-   if (ready == 0) {
-   if (sk->sk_err != 0 ||
-   (sk->sk_shutdown & RCV_SHUTDOWN) ||
-   (vsk->peer_shutdown & SEND_SHUTDOWN)) {
-   finish_wait(sk_sleep(sk), );
-   break;
-   }
-   /* Don't wait for non-blocking sockets. */
-   if (timeout == 0) {
-   err = -EAGAIN;
-   finish_wait(sk_sleep(sk), );
-   break;
-   }
+   ssize_t read;
 
-   err = transport->notify_recv_pre_block(
-   vsk, target, _data);
-   if (err < 0) {
-   finish_wait(sk_sleep(sk), );
-   break;
-   }
-   release_sock(sk);
-   timeout = schedule_timeout(timeout);
-   lock_sock(sk);
+   err = vsock_wait_data(sk, , timeout, _data, target);
+   if (err <= 0)
+   break;
 
-   if (signal_pending(current)) {
-   err = sock_intr_errno(timeout);
-   finish_wait(sk_sleep(sk), );
-   break;
-   } else if (timeout == 0) {
-   err = -EAGAIN;
-   finish_wait(sk_sleep(sk), );
-   break;
-   }
-   } else {
-   ssize_t read;
-
-   finish_wait(sk_sleep(sk), );
-
-   if (ready < 0) {
-   /* Invalid queue pair content. XXX This should
-   * be changed to a connection reset in a later
-   * change.
-   */
-
-   err = 

[RFC PATCH v5 00/19] virtio/vsock: introduce SOCK_SEQPACKET support

2021-02-17 Thread Arseny Krasnov
This patchset impelements support of SOCK_SEQPACKET for virtio
transport.
As SOCK_SEQPACKET guarantees to save record boundaries, so to
do it, two new packet operations were added: first for start of record
 and second to mark end of record(SEQ_BEGIN and SEQ_END later). Also,
both operations carries metadata - to maintain boundaries and payload
integrity. Metadata is introduced by adding special header with two
fields - message count and message length:

struct virtio_vsock_seq_hdr {
__le32  msg_cnt;
__le32  msg_len;
} __attribute__((packed));

This header is transmitted as payload of SEQ_BEGIN and SEQ_END
packets(buffer of second virtio descriptor in chain) in the same way as
data transmitted in RW packets. Payload was chosen as buffer for this
header to avoid touching first virtio buffer which carries header of
packet, because someone could check that size of this buffer is equal
to size of packet header. To send record, packet with start marker is
sent first(it's header contains length of record and counter), then
counter is incremented and all data is sent as usual 'RW' packets and
finally SEQ_END is sent(it also carries counter of message, which is
counter of SEQ_BEGIN + 1), also after sedning SEQ_END counter is
incremented again. On receiver's side, length of record is known from
packet with start record marker. To check that no packets were dropped
by transport, counters of two sequential SEQ_BEGIN and SEQ_END are
checked(counter of SEQ_END must be bigger that counter of SEQ_BEGIN by
1) and length of data between two markers is compared to length in
SEQ_BEGIN header.
Now as  packets of one socket are not reordered neither on
vsock nor on vhost transport layers, such markers allows to restore
original record on receiver's side. If user's buffer is smaller that
record length, when all out of size data is dropped.
Maximum length of datagram is not limited as in stream socket,
because same credit logic is used. Difference with stream socket is
that user is not woken up until whole record is received or error
occurred. Implementation also supports 'MSG_EOR' and 'MSG_TRUNC' flags.
Tests also implemented.

 Arseny Krasnov (19):
  af_vsock: update functions for connectible socket
  af_vsock: separate wait data loop
  af_vsock: separate receive data loop
  af_vsock: implement SEQPACKET receive loop
  af_vsock: separate wait space loop
  af_vsock: implement send logic for SEQPACKET
  af_vsock: rest of SEQPACKET support
  af_vsock: update comments for stream sockets
  virtio/vsock: set packet's type in send
  virtio/vsock: simplify credit update function API
  virtio/vsock: dequeue callback for SOCK_SEQPACKET
  virtio/vsock: fetch length for SEQPACKET record
  virtio/vsock: add SEQPACKET receive logic
  virtio/vsock: rest of SOCK_SEQPACKET support
  virtio/vsock: setup SEQPACKET ops for transport
  vhost/vsock: setup SEQPACKET ops for transport
  vsock/loopback: setup SEQPACKET ops for transport
  vsock_test: add SOCK_SEQPACKET tests
  virtio/vsock: update trace event for SEQPACKET

 drivers/vhost/vsock.c|   8 +-
 include/linux/virtio_vsock.h |  14 +
 include/net/af_vsock.h   |   9 +
 .../events/vsock_virtio_transport_common.h   |  48 +-
 include/uapi/linux/virtio_vsock.h|  16 +
 net/vmw_vsock/af_vsock.c | 590 +++--
 net/vmw_vsock/virtio_transport.c |   5 +
 net/vmw_vsock/virtio_transport_common.c  | 342 --
 net/vmw_vsock/vsock_loopback.c   |   5 +
 tools/testing/vsock/util.c   |  32 +-
 tools/testing/vsock/util.h   |   3 +
 tools/testing/vsock/vsock_test.c | 126 
 12 files changed, 951 insertions(+), 247 deletions(-)

 v4 -> v5:
 - patches reorganized:
   1) Setting of packet's type in 'virtio_transport_send_pkt_info()'
  is moved to separate patch.
   2) Simplifying of 'virtio_transport_send_credit_update()' is
  moved to separate patch and before main virtio/vsock patches.
 - style problem fixed
 - in 'af_vsock: separate receive data loop' extra 'release_sock()'
   removed
 - added trace event fields for SEQPACKET
 - in 'af_vsock: separate wait data loop':
   1) 'vsock_wait_data()' removed 'goto out;'
   2) Comment for invalid data amount is changed.
 - in 'af_vsock: rest of SEQPACKET support', 'new_transport' pointer
   check is moved after 'try_module_get()'
 - in 'af_vsock: update comments for stream sockets', 'connect-oriented'
   replaced with 'connection-oriented'
 - in 'loopback/vsock: setup SEQPACKET ops for transport',
   'loopback/vsock' replaced with 'vsock/loopback'

 v3 -> v4:
 - SEQPACKET specific metadata moved from packet header to payload
   and called 'virtio_vsock_seq_hdr'
 - record integrity check:
   1) SEQ_END operation was added, which marks end of record.
   2) Both SEQ_BEGIN and SEQ_END carries 

Re: [PATCH v3] vfs: fix copy_file_range regression in cross-fs copies

2021-02-17 Thread Olga Kornievskaia
On Wed, Feb 17, 2021 at 3:30 PM Luis Henriques  wrote:
>
> A regression has been reported by Nicolas Boichat, found while using the
> copy_file_range syscall to copy a tracefs file.  Before commit
> 5dae222a5ff0 ("vfs: allow copy_file_range to copy across devices") the
> kernel would return -EXDEV to userspace when trying to copy a file across
> different filesystems.  After this commit, the syscall doesn't fail anymore
> and instead returns zero (zero bytes copied), as this file's content is
> generated on-the-fly and thus reports a size of zero.
>
> This patch restores some cross-filesystems copy restrictions that existed
> prior to commit 5dae222a5ff0 ("vfs: allow copy_file_range to copy across
> devices").  It also introduces a flag (COPY_FILE_SPLICE) that can be used
> by filesystems calling directly into the vfs copy_file_range to override
> these restrictions.  Right now, only NFS needs to set this flag.
>
> Fixes: 5dae222a5ff0 ("vfs: allow copy_file_range to copy across devices")
> Link: 
> https://lore.kernel.org/linux-fsdevel/20210212044405.4120619-1-drink...@chromium.org/
> Link: 
> https://lore.kernel.org/linux-fsdevel/CANMq1KDZuxir2LM5jOTm0xx+BnvW=zmpsg47cyhfjwnw7zs...@mail.gmail.com/
> Link: 
> https://lore.kernel.org/linux-fsdevel/20210126135012.1.If45b7cdc3ff707bc1efa17f5366057d60603c45f@changeid/
> Reported-by: Nicolas Boichat 
> Signed-off-by: Luis Henriques 
> ---
> Ok, I've tried to address all the issues and comments.  Hopefully this v3
> is a bit closer to the final fix.
>
> Changes since v2
> - do all the required checks earlier, in generic_copy_file_checks(),
>   adding new checks for ->remap_file_range
> - new COPY_FILE_SPLICE flag
> - don't remove filesystem's fallback to generic_copy_file_range()
> - updated commit changelog (and subject)
> Changes since v1 (after Amir review)
> - restored do_copy_file_range() helper
> - return -EOPNOTSUPP if fs doesn't implement CFR
> - updated commit description

In my testing, this patch breaks NFS server-to-server copy file.

>
>  fs/nfsd/vfs.c  |  3 ++-
>  fs/read_write.c| 44 +---
>  include/linux/fs.h |  7 +++
>  3 files changed, 50 insertions(+), 4 deletions(-)
>
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 04937e51de56..14e55822c223 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -578,7 +578,8 @@ ssize_t nfsd_copy_file_range(struct file *src, u64 
> src_pos, struct file *dst,
>  * limit like this and pipeline multiple COPY requests.
>  */
> count = min_t(u64, count, 1 << 22);
> -   return vfs_copy_file_range(src, src_pos, dst, dst_pos, count, 0);
> +   return vfs_copy_file_range(src, src_pos, dst, dst_pos, count,
> +  COPY_FILE_SPLICE);
>  }
>
>  __be32 nfsd4_vfs_fallocate(struct svc_rqst *rqstp, struct svc_fh *fhp,
> diff --git a/fs/read_write.c b/fs/read_write.c
> index 75f764b43418..40a16003fb05 100644
> --- a/fs/read_write.c
> +++ b/fs/read_write.c
> @@ -1410,6 +1410,33 @@ static ssize_t do_copy_file_range(struct file 
> *file_in, loff_t pos_in,
>flags);
>  }
>
> +/*
> + * This helper function checks whether copy_file_range can actually be used,
> + * depending on the source and destination filesystems being the same.
> + *
> + * In-kernel callers may set COPY_FILE_SPLICE to override these checks.
> + */
> +static int fops_copy_file_checks(struct file *file_in, struct file *file_out,
> +unsigned int flags)
> +{
> +   if (WARN_ON_ONCE(flags & ~COPY_FILE_SPLICE))
> +   return -EINVAL;
> +
> +   if (flags & COPY_FILE_SPLICE)
> +   return 0;
> +   /*
> +* We got here from userspace, so forbid copies if copy_file_range 
> isn't
> +* implemented or if we're doing a cross-fs copy.
> +*/
> +   if (!file_out->f_op->copy_file_range)
> +   return -EOPNOTSUPP;
> +   else if (file_out->f_op->copy_file_range !=
> +file_in->f_op->copy_file_range)
> +   return -EXDEV;
> +
> +   return 0;
> +}
> +
>  /*
>   * Performs necessary checks before doing a file copy
>   *
> @@ -1427,6 +1454,14 @@ static int generic_copy_file_checks(struct file 
> *file_in, loff_t pos_in,
> loff_t size_in;
> int ret;
>
> +   /* Only check f_ops if we're not trying to clone */
> +   if (!file_in->f_op->remap_file_range ||
> +   (file_inode(file_in)->i_sb == file_inode(file_out)->i_sb)) {
> +   ret = fops_copy_file_checks(file_in, file_out, flags);
> +   if (ret)
> +   return ret;
> +   }
> +
> ret = generic_file_rw_checks(file_in, file_out);
> if (ret)
> return ret;
> @@ -1474,9 +1509,6 @@ ssize_t vfs_copy_file_range(struct file *file_in, 
> loff_t pos_in,
>  {
> ssize_t ret;
>
> -   if (flags != 0)
> -   return -EINVAL;
> -
>   

[net-next PATCH v6 15/15] net: dpaa2-mac: Add ACPI support for DPAA2 MAC driver

2021-02-17 Thread Calvin Johnson
Modify dpaa2_mac_get_node() to get the dpmac fwnode from either
DT or ACPI.

Modify dpaa2_mac_get_if_mode() to get interface mode from dpmac_node
which is a fwnode.

Modify dpaa2_pcs_create() to create pcs from dpmac_node fwnode.

Modify dpaa2_mac_connect() to support ACPI along with DT.

Signed-off-by: Calvin Johnson 
---

Changes in v6:
- use dev_fwnode()
- remove useless else
- replace of_device_is_available() to fwnode_device_is_available()

Changes in v5:
- replace fwnode_get_id() with OF and ACPI function calls

Changes in v4: None
Changes in v3: None
Changes in v2:
- Refactor OF functions to use fwnode functions

 .../net/ethernet/freescale/dpaa2/dpaa2-mac.c  | 91 +++
 1 file changed, 55 insertions(+), 36 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index ccaf7e35abeb..3e39a15b001f 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /* Copyright 2019 NXP */
 
+#include 
+#include 
+
 #include "dpaa2-eth.h"
 #include "dpaa2-mac.h"
 
@@ -34,39 +37,53 @@ static int phy_mode(enum dpmac_eth_if eth_if, 
phy_interface_t *if_mode)
return 0;
 }
 
-/* Caller must call of_node_put on the returned value */
-static struct device_node *dpaa2_mac_get_node(u16 dpmac_id)
+static struct fwnode_handle *dpaa2_mac_get_node(struct device *dev,
+   u16 dpmac_id)
 {
-   struct device_node *dpmacs, *dpmac = NULL;
-   u32 id;
+   struct fwnode_handle *fwnode, *parent, *child  = NULL;
+   struct device_node *dpmacs = NULL;
int err;
+   u32 id;
 
-   dpmacs = of_find_node_by_name(NULL, "dpmacs");
-   if (!dpmacs)
-   return NULL;
+   fwnode = dev_fwnode(dev->parent);
+   if (is_of_node(fwnode)) {
+   dpmacs = of_find_node_by_name(NULL, "dpmacs");
+   if (!dpmacs)
+   return NULL;
+   parent = of_fwnode_handle(dpmacs);
+   } else if (is_acpi_node(fwnode)) {
+   parent = fwnode;
+   }
 
-   while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) {
-   err = of_property_read_u32(dpmac, "reg", );
+   fwnode_for_each_child_node(parent, child) {
+   err = -EINVAL;
+   if (is_acpi_device_node(child))
+   err = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), 
);
+   else if (is_of_node(child))
+   err = of_property_read_u32(to_of_node(child), "reg", 
);
if (err)
continue;
-   if (id == dpmac_id)
-   break;
-   }
 
-   of_node_put(dpmacs);
-
-   return dpmac;
+   if (id == dpmac_id) {
+   if (is_of_node(fwnode))
+   of_node_put(dpmacs);
+   return child;
+   }
+   }
+   if (is_of_node(fwnode))
+   of_node_put(dpmacs);
+   return NULL;
 }
 
-static int dpaa2_mac_get_if_mode(struct device_node *node,
+static int dpaa2_mac_get_if_mode(struct fwnode_handle *dpmac_node,
 struct dpmac_attr attr)
 {
phy_interface_t if_mode;
int err;
 
-   err = of_get_phy_mode(node, _mode);
-   if (!err)
-   return if_mode;
+   err = fwnode_get_phy_mode(dpmac_node);
+   if (err > 0)
+   return err;
 
err = phy_mode(attr.eth_if, _mode);
if (!err)
@@ -235,26 +252,27 @@ static const struct phylink_mac_ops dpaa2_mac_phylink_ops 
= {
 };
 
 static int dpaa2_pcs_create(struct dpaa2_mac *mac,
-   struct device_node *dpmac_node, int id)
+   struct fwnode_handle *dpmac_node,
+   int id)
 {
struct mdio_device *mdiodev;
-   struct device_node *node;
+   struct fwnode_handle *node;
 
-   node = of_parse_phandle(dpmac_node, "pcs-handle", 0);
-   if (!node) {
+   node = fwnode_find_reference(dpmac_node, "pcs-handle", 0);
+   if (IS_ERR(node)) {
/* do not error out on old DTS files */
netdev_warn(mac->net_dev, "pcs-handle node not found\n");
return 0;
}
 
-   if (!of_device_is_available(node)) {
+   if (!fwnode_device_is_available(node)) {
netdev_err(mac->net_dev, "pcs-handle node not available\n");
-   of_node_put(node);
+   fwnode_handle_put(node);
return -ENODEV;
}
 
-   mdiodev = of_mdio_find_device(node);
-   of_node_put(node);
+   mdiodev = fwnode_mdio_find_device(node);
+   fwnode_handle_put(node);
if (!mdiodev)
return -EPROBE_DEFER;
 
@@ -283,13 +301,12 @@ static void 

[net-next PATCH v6 14/15] net: phylink: Refactor phylink_of_phy_connect()

2021-02-17 Thread Calvin Johnson
Refactor phylink_of_phy_connect() to use phylink_fwnode_phy_connect().

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/phy/phylink.c | 39 +--
 1 file changed, 1 insertion(+), 38 deletions(-)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 23753f92e0a6..ce7e918430c8 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1084,44 +1084,7 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy);
 int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
   u32 flags)
 {
-   struct device_node *phy_node;
-   struct phy_device *phy_dev;
-   int ret;
-
-   /* Fixed links and 802.3z are handled without needing a PHY */
-   if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
-   (pl->cfg_link_an_mode == MLO_AN_INBAND &&
-phy_interface_mode_is_8023z(pl->link_interface)))
-   return 0;
-
-   phy_node = of_parse_phandle(dn, "phy-handle", 0);
-   if (!phy_node)
-   phy_node = of_parse_phandle(dn, "phy", 0);
-   if (!phy_node)
-   phy_node = of_parse_phandle(dn, "phy-device", 0);
-
-   if (!phy_node) {
-   if (pl->cfg_link_an_mode == MLO_AN_PHY)
-   return -ENODEV;
-   return 0;
-   }
-
-   phy_dev = of_phy_find_device(phy_node);
-   /* We're done with the phy_node handle */
-   of_node_put(phy_node);
-   if (!phy_dev)
-   return -ENODEV;
-
-   ret = phy_attach_direct(pl->netdev, phy_dev, flags,
-   pl->link_interface);
-   if (ret)
-   return ret;
-
-   ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
-   if (ret)
-   phy_detach(phy_dev);
-
-   return ret;
+   return phylink_fwnode_phy_connect(pl, of_fwnode_handle(dn), flags);
 }
 EXPORT_SYMBOL_GPL(phylink_of_phy_connect);
 
-- 
2.17.1



[net-next PATCH v6 13/15] net: phylink: introduce phylink_fwnode_phy_connect()

2021-02-17 Thread Calvin Johnson
Define phylink_fwnode_phy_connect() to connect phy specified by
a fwnode to a phylink instance.

Signed-off-by: Calvin Johnson 
---

Changes in v6:
- remove OF check for fixed-link

Changes in v5: None
Changes in v4:
- call phy_device_free() before returning

Changes in v3: None
Changes in v2: None

 drivers/net/phy/phylink.c | 54 +++
 include/linux/phylink.h   |  3 +++
 2 files changed, 57 insertions(+)

diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 053c92e02cd8..23753f92e0a6 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2015 Russell King
  */
+#include 
 #include 
 #include 
 #include 
@@ -1124,6 +1125,59 @@ int phylink_of_phy_connect(struct phylink *pl, struct 
device_node *dn,
 }
 EXPORT_SYMBOL_GPL(phylink_of_phy_connect);
 
+/**
+ * phylink_fwnode_phy_connect() - connect the PHY specified in the fwnode.
+ * @pl: a pointer to a  phylink returned from phylink_create()
+ * @fwnode: a pointer to a  fwnode_handle.
+ * @flags: PHY-specific flags to communicate to the PHY device driver
+ *
+ * Connect the phy specified @fwnode to the phylink instance specified
+ * by @pl.
+ *
+ * Returns 0 on success or a negative errno.
+ */
+int phylink_fwnode_phy_connect(struct phylink *pl,
+  struct fwnode_handle *fwnode,
+  u32 flags)
+{
+   struct fwnode_handle *phy_fwnode;
+   struct phy_device *phy_dev;
+   int ret;
+
+   /* Fixed links and 802.3z are handled without needing a PHY */
+   if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
+   (pl->cfg_link_an_mode == MLO_AN_INBAND &&
+phy_interface_mode_is_8023z(pl->link_interface)))
+   return 0;
+
+   phy_fwnode = fwnode_get_phy_node(fwnode);
+   if (IS_ERR(phy_fwnode)) {
+   if (pl->cfg_link_an_mode == MLO_AN_PHY)
+   return -ENODEV;
+   return 0;
+   }
+
+   phy_dev = fwnode_phy_find_device(phy_fwnode);
+   /* We're done with the phy_node handle */
+   fwnode_handle_put(phy_fwnode);
+   if (!phy_dev)
+   return -ENODEV;
+
+   ret = phy_attach_direct(pl->netdev, phy_dev, flags,
+   pl->link_interface);
+   if (ret) {
+   phy_device_free(phy_dev);
+   return ret;
+   }
+
+   ret = phylink_bringup_phy(pl, phy_dev, pl->link_config.interface);
+   if (ret)
+   phy_detach(phy_dev);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(phylink_fwnode_phy_connect);
+
 /**
  * phylink_disconnect_phy() - disconnect any PHY attached to the phylink
  *   instance.
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index d81a714cfbbd..75d4f99090fd 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -439,6 +439,9 @@ void phylink_destroy(struct phylink *);
 
 int phylink_connect_phy(struct phylink *, struct phy_device *);
 int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
+int phylink_fwnode_phy_connect(struct phylink *pl,
+  struct fwnode_handle *fwnode,
+  u32 flags);
 void phylink_disconnect_phy(struct phylink *);
 
 void phylink_mac_change(struct phylink *, bool up);
-- 
2.17.1



RE: [RFC] IRQ handlers run with some high-priority interrupts(not NMI) enabled on some platform

2021-02-17 Thread Finn Thain
On Wed, 17 Feb 2021, Song Bao Hua (Barry Song) wrote:

> > On Sat, 13 Feb 2021, Song Bao Hua (Barry Song) wrote:
> > 
> > >
> > > So what is really confusing and a pain to me is that: For years 
> > > people like me have been writing device drivers with the idea that 
> > > irq handlers run with interrupts disabled after those commits in 
> > > genirq. So I don't need to care about if some other IRQs on the same 
> > > cpu will jump out to access the data the current IRQ handler is 
> > > accessing.
> > >
> > > but it turns out the assumption is not true on some platform. So 
> > > should I start to program devices driver with the new idea 
> > > interrupts can actually come while irqhandler is running?
> > >
> > > That's the question which really bothers me.
> > >
> > 
> > That scenario seems a little contrived to me (drivers for two or more 
> > devices sharing state through their interrupt handlers). Is it real? I 
> > suppose every platform has its quirks. The irq lock in 
> > sonic_interrupt() is only there because of a platform quirk (the same 
> > device can trigger either of two IRQs). Anyway, no-one expects all 
> > drivers to work on all platforms; I don't know why it bothers you so 
> > much when platforms differ.
> 
> Basically, we wrote drivers with the assumption that this driver will be 
> cross-platform. (Of course there are some drivers which can only work on 
> one platform, for example, if the IP of the device is only used in one 
> platform as an internal component of a specific SoC.)
> 
> So once a device has two or more interrupts, we need to consider one 
> interrupt might preempt another one on m68k on the same cpu if we also 
> want to support this driver on m68k. this usually doesn't matter on 
> other platforms.
> 

When users show up who desire to run your drivers on their platform, you 
can expect them to bring patches and a MAINTAINERS file entry. AFAIK, 
Linux development has always worked that way.

Besides, not all m68k platforms implement priority masking. So there's no 
problem with portability to m68k per se.

> on the other hand, there are more than 400 irqs_disabled() in kernel, I 
> am really not sure if they are running with the knowledge that the true 
> irqs_disabled() actually means some interrupts are off and some others 
> are still open on m68k.

Firstly, use of irqs_disabled() is considered an antipattern by some 
developers. Please see, 
https://lore.kernel.org/linux-scsi/X8pfD5XtLoOygdez@lx-t490/
and
commit e6b6be53ec91 ("Merge branch 'net-in_interrupt-cleanup-and-fixes'")

This means that the differences in semantics between the irqs_disabled() 
implementations on various architectures are moot.

Secondly, the existence of irqs_disabled() call sites does not imply a 
flaw in your drivers nor in the m68k interrupt scheme. The actual semantic 
differences are immaterial at many (all?) of these call sites.

> Or they are running with the assumption that the true irqs_disabled() 
> means IRQ is totally quiet? If the latter is true, those drivers might 
> fail to work on m68k as well.
> 

Yes it's possible, and that was my fear too back in 2017 when I raised the 
same question with the m68k maintainer. But I never found any code making 
that assumption. If you know of such a bug, do tell. So far, your fears 
remain unfounded.

> Thanks
> Barry
> 


[net-next PATCH v6 12/15] net/fsl: Use fwnode_mdiobus_register()

2021-02-17 Thread Calvin Johnson
fwnode_mdiobus_register() internally takes care of both DT
and ACPI cases to register mdiobus. Replace existing
of_mdiobus_register() with fwnode_mdiobus_register().

Note: For both ACPI and DT cases, endianness of MDIO controller
need to be specified using "little-endian" property.

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4:
- Cleanup xgmac_mdio_probe()

Changes in v3:
- Avoid unnecessary line removal
- Remove unused inclusion of acpi.h

Changes in v2: None

 drivers/net/ethernet/freescale/xgmac_mdio.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c 
b/drivers/net/ethernet/freescale/xgmac_mdio.c
index bfa2826c5545..dca5305e7185 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -2,6 +2,7 @@
  * QorIQ 10G MDIO Controller
  *
  * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2021 NXP
  *
  * Authors: Andy Fleming 
  *  Timur Tabi 
@@ -243,10 +244,9 @@ static int xgmac_mdio_read(struct mii_bus *bus, int 
phy_id, int regnum)
 
 static int xgmac_mdio_probe(struct platform_device *pdev)
 {
-   struct device_node *np = pdev->dev.of_node;
-   struct mii_bus *bus;
-   struct resource *res;
struct mdio_fsl_priv *priv;
+   struct resource *res;
+   struct mii_bus *bus;
int ret;
 
/* In DPAA-1, MDIO is one of the many FMan sub-devices. The FMan
@@ -279,13 +279,16 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
goto err_ioremap;
}
 
+   /* For both ACPI and DT cases, endianness of MDIO controller
+* needs to be specified using "little-endian" property.
+*/
priv->is_little_endian = device_property_read_bool(>dev,
   "little-endian");
 
priv->has_a011043 = device_property_read_bool(>dev,
  "fsl,erratum-a011043");
 
-   ret = of_mdiobus_register(bus, np);
+   ret = fwnode_mdiobus_register(bus, pdev->dev.fwnode);
if (ret) {
dev_err(>dev, "cannot register MDIO bus\n");
goto err_registration;
-- 
2.17.1



[net-next PATCH v6 09/15] ACPI: utils: Introduce acpi_get_local_address()

2021-02-17 Thread Calvin Johnson
Introduce a wrapper around the _ADR evaluation.

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5:
- Replace fwnode_get_id() with acpi_get_local_address()

Changes in v4:
- Improve code structure to handle all cases

Changes in v3:
- Modified to retrieve reg property value for ACPI as well
- Resolved compilation issue with CONFIG_ACPI = n
- Added more info into documentation

Changes in v2: None

 drivers/acpi/utils.c | 14 ++
 include/linux/acpi.h |  7 +++
 2 files changed, 21 insertions(+)

diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index d5411a166685..0d3a2b111c0f 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -296,6 +296,20 @@ acpi_evaluate_integer(acpi_handle handle,
 
 EXPORT_SYMBOL(acpi_evaluate_integer);
 
+int acpi_get_local_address(acpi_handle handle, u32 *addr)
+{
+   unsigned long long adr;
+   acpi_status status;
+
+   status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, );
+   if (ACPI_FAILURE(status))
+   return -ENODATA;
+
+   *addr = (u32)adr;
+   return 0;
+}
+EXPORT_SYMBOL(acpi_get_local_address);
+
 acpi_status
 acpi_evaluate_reference(acpi_handle handle,
acpi_string pathname,
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 053bf05fb1f7..4e5ce2b4a69d 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -699,6 +699,8 @@ static inline u64 acpi_arch_get_root_pointer(void)
 }
 #endif
 
+int acpi_get_local_address(acpi_handle handle, u32 *addr);
+
 #else  /* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -946,6 +948,11 @@ static inline struct acpi_device 
*acpi_resource_consumer(struct resource *res)
return NULL;
 }
 
+static inline int acpi_get_local_address(acpi_handle handle, u32 *addr)
+{
+   return -ENODEV;
+}
+
 #endif /* !CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
-- 
2.17.1



[net-next PATCH v6 11/15] net: mdiobus: Introduce fwnode_mdiobus_register()

2021-02-17 Thread Calvin Johnson
Introduce fwnode_mdiobus_register() to register PHYs on the  mdiobus.
If the fwnode is DT node, then call of_mdiobus_register().
If it is an ACPI node, then call acpi_mdiobus_register().

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4:
- Remove redundant else from fwnode_mdiobus_register()

Changes in v3:
- Use acpi_mdiobus_register()

Changes in v2: None

 drivers/net/phy/mdio_bus.c | 21 +
 include/linux/phy.h|  1 +
 2 files changed, 22 insertions(+)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 6158ea6e350b..4264053fdd14 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -9,6 +9,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -566,6 +567,26 @@ static int mdiobus_create_device(struct mii_bus *bus,
return ret;
 }
 
+/**
+ * fwnode_mdiobus_register - Register mii_bus and create PHYs from fwnode
+ * @mdio: pointer to mii_bus structure
+ * @fwnode: pointer to fwnode of MDIO bus.
+ *
+ * This function returns of_mdiobus_register() for DT and
+ * acpi_mdiobus_register() for ACPI.
+ */
+int fwnode_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
+{
+   if (is_of_node(fwnode))
+   return of_mdiobus_register(mdio, to_of_node(fwnode));
+
+   if (is_acpi_node(fwnode))
+   return acpi_mdiobus_register(mdio, fwnode);
+
+   return -EINVAL;
+}
+EXPORT_SYMBOL(fwnode_mdiobus_register);
+
 /**
  * __mdiobus_register - bring up all the PHYs on a given bus and attach them 
to bus
  * @bus: target mii_bus
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 4b004a65762e..85a09703f251 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -391,6 +391,7 @@ static inline struct mii_bus *mdiobus_alloc(void)
return mdiobus_alloc_size(0);
 }
 
+int fwnode_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle 
*fwnode);
 int __mdiobus_register(struct mii_bus *bus, struct module *owner);
 int __devm_mdiobus_register(struct device *dev, struct mii_bus *bus,
struct module *owner);
-- 
2.17.1



[net-next PATCH v6 10/15] net: mdio: Add ACPI support code for mdio

2021-02-17 Thread Calvin Johnson
Define acpi_mdiobus_register() to Register mii_bus and create PHYs for
each ACPI child node.

Signed-off-by: Calvin Johnson 
---

Changes in v6:
- use GENMASK() and ACPI_COMPANION_SET()
- some cleanup
- remove unwanted header inclusion

Changes in v5:
- add missing MODULE_LICENSE()
- replace fwnode_get_id() with OF and ACPI function calls

Changes in v4: None
Changes in v3: None
Changes in v2: None

 MAINTAINERS  |  1 +
 drivers/net/mdio/Kconfig |  7 +
 drivers/net/mdio/Makefile|  1 +
 drivers/net/mdio/acpi_mdio.c | 51 
 include/linux/acpi_mdio.h| 25 ++
 5 files changed, 85 insertions(+)
 create mode 100644 drivers/net/mdio/acpi_mdio.c
 create mode 100644 include/linux/acpi_mdio.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1a219335efe0..41d16d77b6cf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6680,6 +6680,7 @@ F:Documentation/devicetree/bindings/net/mdio*
 F: Documentation/devicetree/bindings/net/qca,ar803x.yaml
 F: Documentation/networking/phy.rst
 F: drivers/net/mdio/
+F: drivers/net/mdio/acpi_mdio.c
 F: drivers/net/mdio/of_mdio.c
 F: drivers/net/pcs/
 F: drivers/net/phy/
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index a10cc460d7cf..df6bb7837d6a 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -27,6 +27,13 @@ config OF_MDIO
help
  OpenFirmware MDIO bus (Ethernet PHY) accessors
 
+config ACPI_MDIO
+   def_tristate PHYLIB
+   depends on ACPI
+   depends on PHYLIB
+   help
+ ACPI MDIO bus (Ethernet PHY) accessors
+
 if MDIO_BUS
 
 config MDIO_DEVRES
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index 5c498dde463f..2373ade8af13 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -2,6 +2,7 @@
 # Makefile for Linux MDIO bus drivers
 
 obj-$(CONFIG_OF_MDIO)  += of_mdio.o
+obj-$(CONFIG_ACPI_MDIO)+= acpi_mdio.o
 
 obj-$(CONFIG_MDIO_ASPEED)  += mdio-aspeed.o
 obj-$(CONFIG_MDIO_BCM_IPROC)   += mdio-bcm-iproc.o
diff --git a/drivers/net/mdio/acpi_mdio.c b/drivers/net/mdio/acpi_mdio.c
new file mode 100644
index ..091c8272e596
--- /dev/null
+++ b/drivers/net/mdio/acpi_mdio.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ACPI helpers for the MDIO (Ethernet PHY) API
+ *
+ * This file provides helper functions for extracting PHY device information
+ * out of the ACPI ASL and using it to populate an mii_bus.
+ */
+
+#include 
+#include 
+
+MODULE_AUTHOR("Calvin Johnson ");
+MODULE_LICENSE("GPL");
+
+/**
+ * acpi_mdiobus_register - Register mii_bus and create PHYs from the ACPI ASL.
+ * @mdio: pointer to mii_bus structure
+ * @fwnode: pointer to fwnode of MDIO bus.
+ *
+ * This function registers the mii_bus structure and registers a phy_device
+ * for each child node of @fwnode.
+ */
+int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode)
+{
+   struct fwnode_handle *child;
+   u32 addr;
+   int ret;
+
+   /* Mask out all PHYs from auto probing. */
+   mdio->phy_mask = GENMASK(31, 0);
+   ret = mdiobus_register(mdio);
+   if (ret)
+   return ret;
+
+   ACPI_COMPANION_SET(>dev, to_acpi_device_node(fwnode));
+
+   /* Loop over the child nodes and register a phy_device for each PHY */
+   fwnode_for_each_child_node(fwnode, child) {
+   ret = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), );
+   if (ret || addr >= PHY_MAX_ADDR)
+   continue;
+
+   ret = fwnode_mdiobus_register_phy(mdio, child, addr);
+   if (ret == -ENODEV)
+   dev_err(>dev,
+   "MDIO device at address %d is missing.\n",
+   addr);
+   }
+   return 0;
+}
+EXPORT_SYMBOL(acpi_mdiobus_register);
diff --git a/include/linux/acpi_mdio.h b/include/linux/acpi_mdio.h
new file mode 100644
index ..748d261fe2f9
--- /dev/null
+++ b/include/linux/acpi_mdio.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * ACPI helper for the MDIO (Ethernet PHY) API
+ */
+
+#ifndef __LINUX_ACPI_MDIO_H
+#define __LINUX_ACPI_MDIO_H
+
+#include 
+
+#if IS_ENABLED(CONFIG_ACPI_MDIO)
+int acpi_mdiobus_register(struct mii_bus *mdio, struct fwnode_handle *fwnode);
+#else /* CONFIG_ACPI_MDIO */
+static inline int acpi_mdiobus_register(struct mii_bus *mdio, struct 
fwnode_handle *fwnode)
+{
+   /*
+* Fall back to mdiobus_register() function to register a bus.
+* This way, we don't have to keep compat bits around in drivers.
+*/
+
+   return mdiobus_register(mdio);
+}
+#endif
+
+#endif /* __LINUX_ACPI_MDIO_H */
-- 
2.17.1



[net-next PATCH v6 07/15] net: mdiobus: Introduce fwnode_mdiobus_register_phy()

2021-02-17 Thread Calvin Johnson
Introduce fwnode_mdiobus_register_phy() to register PHYs on the
mdiobus. From the compatible string, identify whether the PHY is
c45 and based on this create a PHY device instance which is
registered on the mdiobus.

uninitialized symbol 'mii_ts'
Reported-by: kernel test robot 
Reported-by: Dan Carpenter 

Signed-off-by: Calvin Johnson 
---

Changes in v6:
- Initialize mii_ts to NULL

Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/mdio/of_mdio.c |  3 +-
 drivers/net/phy/mdio_bus.c | 65 ++
 include/linux/mdio.h   |  2 ++
 include/linux/of_mdio.h|  6 +++-
 4 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index 612a37970f14..d3f7f104f1ed 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -32,7 +32,7 @@ static int of_get_phy_id(struct device_node *device, u32 
*phy_id)
return fwnode_get_phy_id(of_fwnode_handle(device), phy_id);
 }
 
-static struct mii_timestamper *of_find_mii_timestamper(struct device_node 
*node)
+struct mii_timestamper *of_find_mii_timestamper(struct device_node *node)
 {
struct of_phandle_args arg;
int err;
@@ -49,6 +49,7 @@ static struct mii_timestamper *of_find_mii_timestamper(struct 
device_node *node)
 
return register_mii_timestamper(arg.np, arg.args[0]);
 }
+EXPORT_SYMBOL(of_find_mii_timestamper);
 
 int of_mdiobus_phy_device_register(struct mii_bus *mdio, struct phy_device 
*phy,
  struct device_node *child, u32 addr)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 823518554079..6158ea6e350b 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -8,6 +8,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -106,6 +107,70 @@ int mdiobus_unregister_device(struct mdio_device *mdiodev)
 }
 EXPORT_SYMBOL(mdiobus_unregister_device);
 
+int fwnode_mdiobus_register_phy(struct mii_bus *bus,
+   struct fwnode_handle *child, u32 addr)
+{
+   struct mii_timestamper *mii_ts = NULL;
+   struct phy_device *phy;
+   bool is_c45 = false;
+   u32 phy_id;
+   int rc;
+
+   if (is_of_node(child)) {
+   mii_ts = of_find_mii_timestamper(to_of_node(child));
+   if (IS_ERR(mii_ts))
+   return PTR_ERR(mii_ts);
+   }
+
+   rc = fwnode_property_match_string(child, "compatible", 
"ethernet-phy-ieee802.3-c45");
+   if (rc >= 0)
+   is_c45 = true;
+
+   if (is_c45 || fwnode_get_phy_id(child, _id))
+   phy = get_phy_device(bus, addr, is_c45);
+   else
+   phy = phy_device_create(bus, addr, phy_id, 0, NULL);
+   if (IS_ERR(phy)) {
+   if (mii_ts)
+   unregister_mii_timestamper(mii_ts);
+   return PTR_ERR(phy);
+   }
+
+   if (is_acpi_node(child)) {
+   phy->irq = bus->irq[addr];
+
+   /* Associate the fwnode with the device structure so it
+* can be looked up later.
+*/
+   phy->mdio.dev.fwnode = child;
+
+   /* All data is now stored in the phy struct, so register it */
+   rc = phy_device_register(phy);
+   if (rc) {
+   phy_device_free(phy);
+   fwnode_handle_put(phy->mdio.dev.fwnode);
+   return rc;
+   }
+   } else if (is_of_node(child)) {
+   rc = of_mdiobus_phy_device_register(bus, phy, 
to_of_node(child), addr);
+   if (rc) {
+   if (mii_ts)
+   unregister_mii_timestamper(mii_ts);
+   phy_device_free(phy);
+   return rc;
+   }
+   }
+
+   /* phy->mii_ts may already be defined by the PHY driver. A
+* mii_timestamper probed via the device tree will still have
+* precedence.
+*/
+   if (mii_ts)
+   phy->mii_ts = mii_ts;
+   return 0;
+}
+EXPORT_SYMBOL(fwnode_mdiobus_register_phy);
+
 struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
 {
struct mdio_device *mdiodev = bus->mdio_map[addr];
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index ffb787d5ebde..7f4215c069fe 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -381,6 +381,8 @@ int mdiobus_register_device(struct mdio_device *mdiodev);
 int mdiobus_unregister_device(struct mdio_device *mdiodev);
 bool mdiobus_is_registered_device(struct mii_bus *bus, int addr);
 struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr);
+int fwnode_mdiobus_register_phy(struct mii_bus *bus,
+ struct fwnode_handle *child, u32 addr);
 
 /**
  * mdio_module_driver() - Helper macro for registering 

[net-next PATCH v6 05/15] net: phy: Introduce fwnode_get_phy_id()

2021-02-17 Thread Calvin Johnson
Extract phy_id from compatible string. This will be used by
fwnode_mdiobus_register_phy() to create phy device using the
phy_id.

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- Use traditional comparison pattern
- Use GENMASK

Changes in v2: None

 drivers/net/phy/phy_device.c | 21 +
 include/linux/phy.h  |  5 +
 2 files changed, 26 insertions(+)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 537a25b9ee94..5703d4229821 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -819,6 +819,27 @@ static int get_phy_c22_id(struct mii_bus *bus, int addr, 
u32 *phy_id)
return 0;
 }
 
+/* Extract the phy ID from the compatible string of the form
+ * ethernet-phy-id..
+ */
+int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id)
+{
+   unsigned int upper, lower;
+   const char *cp;
+   int ret;
+
+   ret = fwnode_property_read_string(fwnode, "compatible", );
+   if (ret)
+   return ret;
+
+   if (sscanf(cp, "ethernet-phy-id%4x.%4x", , ) != 2)
+   return -EINVAL;
+
+   *phy_id = ((upper & GENMASK(15, 0)) << 16) | (lower & GENMASK(15, 0));
+   return 0;
+}
+EXPORT_SYMBOL(fwnode_get_phy_id);
+
 /**
  * get_phy_device - reads the specified PHY device and returns its @phy_device
  * struct
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 720a2a8cf355..4b004a65762e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1366,6 +1366,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, 
int addr, u32 phy_id,
 bool is_c45,
 struct phy_c45_device_ids *c45_ids);
 #if IS_ENABLED(CONFIG_PHYLIB)
+int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id);
 struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
 struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
 struct phy_device *device_phy_find_device(struct device *dev);
@@ -1374,6 +1375,10 @@ struct phy_device *get_phy_device(struct mii_bus *bus, 
int addr, bool is_c45);
 int phy_device_register(struct phy_device *phy);
 void phy_device_free(struct phy_device *phydev);
 #else
+static inline int fwnode_get_phy_id(struct fwnode_handle *fwnode, u32 *phy_id)
+{
+   return 0;
+}
 static inline
 struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
 {
-- 
2.17.1



[net-next PATCH v6 04/15] of: mdio: Refactor of_phy_find_device()

2021-02-17 Thread Calvin Johnson
Refactor of_phy_find_device() to use fwnode_phy_find_device().

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/mdio/of_mdio.c | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index d5e0970b2561..b5e0b5b22f1a 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -360,18 +360,7 @@ EXPORT_SYMBOL(of_mdio_find_device);
  */
 struct phy_device *of_phy_find_device(struct device_node *phy_np)
 {
-   struct mdio_device *mdiodev;
-
-   mdiodev = of_mdio_find_device(phy_np);
-   if (!mdiodev)
-   return NULL;
-
-   if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
-   return to_phy_device(>dev);
-
-   put_device(>dev);
-
-   return NULL;
+   return fwnode_phy_find_device(of_fwnode_handle(phy_np));
 }
 EXPORT_SYMBOL(of_phy_find_device);
 
-- 
2.17.1



[net-next PATCH v6 08/15] of: mdio: Refactor of_mdiobus_register_phy()

2021-02-17 Thread Calvin Johnson
Refactor of_mdiobus_register_phy() to use fwnode_mdiobus_register_phy().

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/mdio/of_mdio.c | 40 +-
 1 file changed, 1 insertion(+), 39 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index d3f7f104f1ed..a0d804cfc1f0 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -98,45 +98,7 @@ EXPORT_SYMBOL(of_mdiobus_phy_device_register);
 static int of_mdiobus_register_phy(struct mii_bus *mdio,
struct device_node *child, u32 addr)
 {
-   struct mii_timestamper *mii_ts;
-   struct phy_device *phy;
-   bool is_c45;
-   int rc;
-   u32 phy_id;
-
-   mii_ts = of_find_mii_timestamper(child);
-   if (IS_ERR(mii_ts))
-   return PTR_ERR(mii_ts);
-
-   is_c45 = of_device_is_compatible(child,
-"ethernet-phy-ieee802.3-c45");
-
-   if (!is_c45 && !of_get_phy_id(child, _id))
-   phy = phy_device_create(mdio, addr, phy_id, 0, NULL);
-   else
-   phy = get_phy_device(mdio, addr, is_c45);
-   if (IS_ERR(phy)) {
-   if (mii_ts)
-   unregister_mii_timestamper(mii_ts);
-   return PTR_ERR(phy);
-   }
-
-   rc = of_mdiobus_phy_device_register(mdio, phy, child, addr);
-   if (rc) {
-   if (mii_ts)
-   unregister_mii_timestamper(mii_ts);
-   phy_device_free(phy);
-   return rc;
-   }
-
-   /* phy->mii_ts may already be defined by the PHY driver. A
-* mii_timestamper probed via the device tree will still have
-* precedence.
-*/
-   if (mii_ts)
-   phy->mii_ts = mii_ts;
-
-   return 0;
+   return fwnode_mdiobus_register_phy(mdio, of_fwnode_handle(child), addr);
 }
 
 static int of_mdiobus_register_device(struct mii_bus *mdio,
-- 
2.17.1



[net-next PATCH v6 03/15] net: phy: Introduce phy related fwnode functions

2021-02-17 Thread Calvin Johnson
Define fwnode_phy_find_device() to iterate an mdiobus and find the
phy device of the provided phy fwnode. Additionally define
device_phy_find_device() to find phy device of provided device.

Define fwnode_get_phy_node() to get phy_node using named reference.

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3:
- Add more info on legacy DT properties "phy" and "phy-device"
- Redefine fwnode_phy_find_device() to follow of_phy_find_device()

Changes in v2:
- use reverse christmas tree ordering for local variables

 drivers/net/phy/phy_device.c | 62 
 include/linux/phy.h  | 20 
 2 files changed, 82 insertions(+)

diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index e673912e8938..537a25b9ee94 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -2844,6 +2845,67 @@ struct mdio_device *fwnode_mdio_find_device(struct 
fwnode_handle *fwnode)
 }
 EXPORT_SYMBOL(fwnode_mdio_find_device);
 
+/**
+ * fwnode_phy_find_device - For provided phy_fwnode, find phy_device.
+ *
+ * @phy_fwnode: Pointer to the phy's fwnode.
+ *
+ * If successful, returns a pointer to the phy_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
+ */
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
+{
+   struct mdio_device *mdiodev;
+
+   mdiodev = fwnode_mdio_find_device(phy_fwnode);
+   if (!mdiodev)
+   return NULL;
+
+   if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
+   return to_phy_device(>dev);
+
+   put_device(>dev);
+
+   return NULL;
+}
+EXPORT_SYMBOL(fwnode_phy_find_device);
+
+/**
+ * device_phy_find_device - For the given device, get the phy_device
+ * @dev: Pointer to the given device
+ *
+ * Refer return conditions of fwnode_phy_find_device().
+ */
+struct phy_device *device_phy_find_device(struct device *dev)
+{
+   return fwnode_phy_find_device(dev_fwnode(dev));
+}
+EXPORT_SYMBOL_GPL(device_phy_find_device);
+
+/**
+ * fwnode_get_phy_node - Get the phy_node using the named reference.
+ * @fwnode: Pointer to fwnode from which phy_node has to be obtained.
+ *
+ * Refer return conditions of fwnode_find_reference().
+ * For ACPI, only "phy-handle" is supported. Legacy DT properties "phy"
+ * and "phy-device" are not supported in ACPI. DT supports all the three
+ * named references to the phy node.
+ */
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
+{
+   struct fwnode_handle *phy_node;
+
+   /* Only phy-handle is used for ACPI */
+   phy_node = fwnode_find_reference(fwnode, "phy-handle", 0);
+   if (is_acpi_node(fwnode) || !IS_ERR(phy_node))
+   return phy_node;
+   phy_node = fwnode_find_reference(fwnode, "phy", 0);
+   if (IS_ERR(phy_node))
+   phy_node = fwnode_find_reference(fwnode, "phy-device", 0);
+   return phy_node;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_phy_node);
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
diff --git a/include/linux/phy.h b/include/linux/phy.h
index f5eb1e3981a1..720a2a8cf355 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1367,6 +1367,9 @@ struct phy_device *phy_device_create(struct mii_bus *bus, 
int addr, u32 phy_id,
 struct phy_c45_device_ids *c45_ids);
 #if IS_ENABLED(CONFIG_PHYLIB)
 struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode);
+struct phy_device *device_phy_find_device(struct device *dev);
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode);
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
 int phy_device_register(struct phy_device *phy);
 void phy_device_free(struct phy_device *phydev);
@@ -1376,6 +1379,23 @@ struct mdio_device *fwnode_mdio_find_device(struct 
fwnode_handle *fwnode)
 {
return 0;
 }
+static inline
+struct phy_device *fwnode_phy_find_device(struct fwnode_handle *phy_fwnode)
+{
+   return NULL;
+}
+
+static inline struct phy_device *device_phy_find_device(struct device *dev)
+{
+   return NULL;
+}
+
+static inline
+struct fwnode_handle *fwnode_get_phy_node(struct fwnode_handle *fwnode)
+{
+   return NULL;
+}
+
 static inline
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
 {
-- 
2.17.1



Re: [PATCH net] net: ag71xx: remove unnecessary MTU reservation

2021-02-17 Thread Oleksij Rempel
On Thu, Feb 18, 2021 at 11:45:14AM +0800, DENG Qingfang wrote:
> 2 bytes of the MTU are reserved for Atheros DSA tag, but DSA core
> has already handled that since commit dc0fe7d47f9f.
> Remove the unnecessary reservation.
> 
> Fixes: d51b6ce441d3 ("net: ethernet: add ag71xx driver")
> Signed-off-by: DENG Qingfang 

Reviewed-by: Oleksij Rempel 

Thank you!

> ---
>  drivers/net/ethernet/atheros/ag71xx.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/atheros/ag71xx.c 
> b/drivers/net/ethernet/atheros/ag71xx.c
> index dd5c8a9038bb..a60ce9030581 100644
> --- a/drivers/net/ethernet/atheros/ag71xx.c
> +++ b/drivers/net/ethernet/atheros/ag71xx.c
> @@ -223,8 +223,6 @@
>  #define AG71XX_REG_RX_SM 0x01b0
>  #define AG71XX_REG_TX_SM 0x01b4
>  
> -#define ETH_SWITCH_HEADER_LEN2
> -
>  #define AG71XX_DEFAULT_MSG_ENABLE\
>   (NETIF_MSG_DRV  \
>   | NETIF_MSG_PROBE   \
> @@ -933,7 +931,7 @@ static void ag71xx_hw_setup(struct ag71xx *ag)
>  
>  static unsigned int ag71xx_max_frame_len(unsigned int mtu)
>  {
> - return ETH_SWITCH_HEADER_LEN + ETH_HLEN + VLAN_HLEN + mtu + ETH_FCS_LEN;
> + return ETH_HLEN + VLAN_HLEN + mtu + ETH_FCS_LEN;
>  }
>  
>  static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac)
> -- 
> 2.25.1
> 
> 

-- 
Pengutronix e.K.   | |
Steuerwalder Str. 21   | http://www.pengutronix.de/  |
31137 Hildesheim, Germany  | Phone: +49-5121-206917-0|
Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |


[net-next PATCH v6 06/15] of: mdio: Refactor of_get_phy_id()

2021-02-17 Thread Calvin Johnson
With the introduction of fwnode_get_phy_id(), refactor of_get_phy_id()
to use fwnode equivalent.

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/mdio/of_mdio.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index b5e0b5b22f1a..612a37970f14 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -29,17 +29,7 @@ MODULE_LICENSE("GPL");
  * ethernet-phy-id. */
 static int of_get_phy_id(struct device_node *device, u32 *phy_id)
 {
-   struct property *prop;
-   const char *cp;
-   unsigned int upper, lower;
-
-   of_property_for_each_string(device, "compatible", prop, cp) {
-   if (sscanf(cp, "ethernet-phy-id%4x.%4x", , ) == 2) {
-   *phy_id = ((upper & 0x) << 16) | (lower & 0x);
-   return 0;
-   }
-   }
-   return -EINVAL;
+   return fwnode_get_phy_id(of_fwnode_handle(device), phy_id);
 }
 
 static struct mii_timestamper *of_find_mii_timestamper(struct device_node 
*node)
-- 
2.17.1



[net-next PATCH v6 01/15] Documentation: ACPI: DSD: Document MDIO PHY

2021-02-17 Thread Calvin Johnson
Introduce ACPI mechanism to get PHYs registered on a MDIO bus and
provide them to be connected to MAC.

Describe properties "phy-handle" and "phy-mode".

Signed-off-by: Calvin Johnson 
---

Changes in v6:
- Minor cleanup

Changes in v5:
- More cleanup

Changes in v4:
- More cleanup

Changes in v3: None
Changes in v2:
- Updated with more description in document

 Documentation/firmware-guide/acpi/dsd/phy.rst | 133 ++
 1 file changed, 133 insertions(+)
 create mode 100644 Documentation/firmware-guide/acpi/dsd/phy.rst

diff --git a/Documentation/firmware-guide/acpi/dsd/phy.rst 
b/Documentation/firmware-guide/acpi/dsd/phy.rst
new file mode 100644
index ..7d01ae8b3cc6
--- /dev/null
+++ b/Documentation/firmware-guide/acpi/dsd/phy.rst
@@ -0,0 +1,133 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=
+MDIO bus and PHYs in ACPI
+=
+
+The PHYs on an MDIO bus [1] are probed and registered using
+fwnode_mdiobus_register_phy().
+
+Later, for connecting these PHYs to their respective MACs, the PHYs registered
+on the MDIO bus have to be referenced.
+
+This document introduces two _DSD properties that are to be used
+for connecting PHYs on the MDIO bus [3] to the MAC layer.
+
+These properties are defined in accordance with the "Device
+Properties UUID For _DSD" [2] document and the
+daffd814-6eba-4d8c-8a91-bc9bbf4aa301 UUID must be used in the Device
+Data Descriptors containing them.
+
+phy-handle
+--
+For each MAC node, a device property "phy-handle" is used to reference
+the PHY that is registered on an MDIO bus. This is mandatory for
+network interfaces that have PHYs connected to MAC via MDIO bus.
+
+During the MDIO bus driver initialization, PHYs on this bus are probed
+using the _ADR object as shown below and are registered on the MDIO bus.
+
+::
+  Scope(\_SB.MDI0)
+  {
+Device(PHY1) {
+  Name (_ADR, 0x1)
+} // end of PHY1
+
+Device(PHY2) {
+  Name (_ADR, 0x2)
+} // end of PHY2
+  }
+
+Later, during the MAC driver initialization, the registered PHY devices
+have to be retrieved from the MDIO bus. For this, the MAC driver needs
+references to the previously registered PHYs which are provided
+as device object references (e.g. \_SB.MDI0.PHY1).
+
+phy-mode
+
+The "phy-mode" _DSD property is used to describe the connection to
+the PHY. The valid values for "phy-mode" are defined in [4].
+
+The following ASL example illustrates the usage of these properties.
+
+DSDT entry for MDIO node
+
+
+The MDIO bus has an SoC component (MDIO controller) and a platform
+component (PHYs on the MDIO bus).
+
+a) Silicon Component
+This node describes the MDIO controller, MDI0
+-
+::
+   Scope(_SB)
+   {
+ Device(MDI0) {
+   Name(_HID, "NXP0006")
+   Name(_CCA, 1)
+   Name(_UID, 0)
+   Name(_CRS, ResourceTemplate() {
+ Memory32Fixed(ReadWrite, MDI0_BASE, MDI_LEN)
+ Interrupt(ResourceConsumer, Level, ActiveHigh, Shared)
+  {
+MDI0_IT
+  }
+   }) // end of _CRS for MDI0
+ } // end of MDI0
+   }
+
+b) Platform Component
+The PHY1 and PHY2 nodes represent the PHYs connected to MDIO bus MDI0
+-
+::
+   Scope(\_SB.MDI0)
+   {
+ Device(PHY1) {
+   Name (_ADR, 0x1)
+ } // end of PHY1
+
+ Device(PHY2) {
+   Name (_ADR, 0x2)
+ } // end of PHY2
+   }
+
+DSDT entries representing MAC nodes
+---
+
+Below are the MAC nodes where PHY nodes are referenced.
+phy-mode and phy-handle are used as explained earlier.
+--
+::
+   Scope(\_SB.MCE0.PR17)
+   {
+ Name (_DSD, Package () {
+ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+Package () {
+Package (2) {"phy-mode", "rgmii-id"},
+Package (2) {"phy-handle", \_SB.MDI0.PHY1}
+ }
+  })
+   }
+
+   Scope(\_SB.MCE0.PR18)
+   {
+ Name (_DSD, Package () {
+   ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+   Package () {
+   Package (2) {"phy-mode", "rgmii-id"},
+   Package (2) {"phy-handle", \_SB.MDI0.PHY2}}
+   }
+ })
+   }
+
+References
+==
+
+[1] Documentation/networking/phy.rst
+
+[2] 
https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
+
+[3] Documentation/firmware-guide/acpi/DSD-properties-rules.rst
+
+[4] Documentation/devicetree/bindings/net/ethernet-controller.yaml
-- 
2.17.1



[net-next PATCH v6 02/15] net: phy: Introduce fwnode_mdio_find_device()

2021-02-17 Thread Calvin Johnson
Define fwnode_mdio_find_device() to get a pointer to the
mdio_device from fwnode passed to the function.

Refactor of_mdio_find_device() to use fwnode_mdio_find_device().

Signed-off-by: Calvin Johnson 
---

Changes in v6: None
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/net/mdio/of_mdio.c   | 11 +--
 drivers/net/phy/phy_device.c | 23 +++
 include/linux/phy.h  |  6 ++
 3 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/net/mdio/of_mdio.c b/drivers/net/mdio/of_mdio.c
index ea9d5855fb52..d5e0970b2561 100644
--- a/drivers/net/mdio/of_mdio.c
+++ b/drivers/net/mdio/of_mdio.c
@@ -347,16 +347,7 @@ EXPORT_SYMBOL(of_mdiobus_register);
  */
 struct mdio_device *of_mdio_find_device(struct device_node *np)
 {
-   struct device *d;
-
-   if (!np)
-   return NULL;
-
-   d = bus_find_device_by_of_node(_bus_type, np);
-   if (!d)
-   return NULL;
-
-   return to_mdio_device(d);
+   return fwnode_mdio_find_device(of_fwnode_handle(np));
 }
 EXPORT_SYMBOL(of_mdio_find_device);
 
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index ce495473cd5d..e673912e8938 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2821,6 +2821,29 @@ static bool phy_drv_supports_irq(struct phy_driver 
*phydrv)
return phydrv->config_intr && phydrv->handle_interrupt;
 }
 
+/**
+ * fwnode_mdio_find_device - Given a fwnode, find the mdio_device
+ * @np: pointer to the mdio_device's fwnode
+ *
+ * If successful, returns a pointer to the mdio_device with the embedded
+ * struct device refcount incremented by one, or NULL on failure.
+ * The caller should call put_device() on the mdio_device after its use
+ */
+struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
+{
+   struct device *d;
+
+   if (!fwnode)
+   return NULL;
+
+   d = bus_find_device_by_fwnode(_bus_type, fwnode);
+   if (!d)
+   return NULL;
+
+   return to_mdio_device(d);
+}
+EXPORT_SYMBOL(fwnode_mdio_find_device);
+
 /**
  * phy_probe - probe and init a PHY device
  * @dev: device to probe and init
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 1a12e4436b5b..f5eb1e3981a1 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1366,11 +1366,17 @@ struct phy_device *phy_device_create(struct mii_bus 
*bus, int addr, u32 phy_id,
 bool is_c45,
 struct phy_c45_device_ids *c45_ids);
 #if IS_ENABLED(CONFIG_PHYLIB)
+struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode);
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
 int phy_device_register(struct phy_device *phy);
 void phy_device_free(struct phy_device *phydev);
 #else
 static inline
+struct mdio_device *fwnode_mdio_find_device(struct fwnode_handle *fwnode)
+{
+   return 0;
+}
+static inline
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
 {
return NULL;
-- 
2.17.1



[net-next PATCH v6 00/15] ACPI support for dpaa2 driver

2021-02-17 Thread Calvin Johnson


This patch set provides ACPI support to DPAA2 network drivers.

It also introduces new fwnode based APIs to support phylink and phy
layers
Following functions are defined:
  phylink_fwnode_phy_connect()
  fwnode_mdiobus_register_phy()
  fwnode_mdiobus_register()
  fwnode_get_phy_id()
  fwnode_phy_find_device()
  device_phy_find_device()
  fwnode_get_phy_node()
  fwnode_mdio_find_device()
  acpi_get_local_address()

First one helps in connecting phy to phylink instance.
Next three helps in getting phy_id and registering phy to mdiobus
Next two help in finding a phy on a mdiobus.
Next one helps in getting phy_node from a fwnode.
Last one is used to get local address from _ADR object.

Corresponding OF functions are refactored.

Tested-on: T2080RDB, LS1046ARDB, LS2088ARDB and LX2160ARDB


Changes in v6:
- Minor cleanup
- Initialize mii_ts to NULL
- use GENMASK() and ACPI_COMPANION_SET()
- some cleanup
- remove unwanted header inclusion
- remove OF check for fixed-link
- use dev_fwnode()
- remove useless else
- replace of_device_is_available() to fwnode_device_is_available()

Changes in v5:
- More cleanup
- Replace fwnode_get_id() with acpi_get_local_address()
- add missing MODULE_LICENSE()
- replace fwnode_get_id() with OF and ACPI function calls
- replace fwnode_get_id() with OF and ACPI function calls

Changes in v4:
- More cleanup
- Improve code structure to handle all cases
- Remove redundant else from fwnode_mdiobus_register()
- Cleanup xgmac_mdio_probe()
- call phy_device_free() before returning

Changes in v3:
- Add more info on legacy DT properties "phy" and "phy-device"
- Redefine fwnode_phy_find_device() to follow of_phy_find_device()
- Use traditional comparison pattern
- Use GENMASK
- Modified to retrieve reg property value for ACPI as well
- Resolved compilation issue with CONFIG_ACPI = n
- Added more info into documentation
- Use acpi_mdiobus_register()
- Avoid unnecessary line removal
- Remove unused inclusion of acpi.h

Changes in v2:
- Updated with more description in document
- use reverse christmas tree ordering for local variables
- Refactor OF functions to use fwnode functions

Calvin Johnson (15):
  Documentation: ACPI: DSD: Document MDIO PHY
  net: phy: Introduce fwnode_mdio_find_device()
  net: phy: Introduce phy related fwnode functions
  of: mdio: Refactor of_phy_find_device()
  net: phy: Introduce fwnode_get_phy_id()
  of: mdio: Refactor of_get_phy_id()
  net: mdiobus: Introduce fwnode_mdiobus_register_phy()
  of: mdio: Refactor of_mdiobus_register_phy()
  ACPI: utils: Introduce acpi_get_local_address()
  net: mdio: Add ACPI support code for mdio
  net: mdiobus: Introduce fwnode_mdiobus_register()
  net/fsl: Use fwnode_mdiobus_register()
  net: phylink: introduce phylink_fwnode_phy_connect()
  net: phylink: Refactor phylink_of_phy_connect()
  net: dpaa2-mac: Add ACPI support for DPAA2 MAC driver

 Documentation/firmware-guide/acpi/dsd/phy.rst | 133 ++
 MAINTAINERS   |   1 +
 drivers/acpi/utils.c  |  14 ++
 .../net/ethernet/freescale/dpaa2/dpaa2-mac.c  |  91 +++-
 drivers/net/ethernet/freescale/xgmac_mdio.c   |  11 +-
 drivers/net/mdio/Kconfig  |   7 +
 drivers/net/mdio/Makefile |   1 +
 drivers/net/mdio/acpi_mdio.c  |  51 +++
 drivers/net/mdio/of_mdio.c|  79 +--
 drivers/net/phy/mdio_bus.c|  86 +++
 drivers/net/phy/phy_device.c  | 106 ++
 drivers/net/phy/phylink.c |  41 --
 include/linux/acpi.h  |   7 +
 include/linux/acpi_mdio.h |  25 
 include/linux/mdio.h  |   2 +
 include/linux/of_mdio.h   |   6 +-
 include/linux/phy.h   |  32 +
 include/linux/phylink.h   |   3 +
 18 files changed, 570 insertions(+), 126 deletions(-)
 create mode 100644 Documentation/firmware-guide/acpi/dsd/phy.rst
 create mode 100644 drivers/net/mdio/acpi_mdio.c
 create mode 100644 include/linux/acpi_mdio.h

-- 
2.17.1



arch/arm/kernel/sys_oabi-compat.c:257:6: error: implicit declaration of function 'ep_op_has_event'

2021-02-17 Thread kernel test robot
tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 
master
head:   f40ddce88593482919761f74910f42f4b84c004b
commit: c281634c865202e2776b0250678ff93c771947ff ARM: compat: remove KERNEL_DS 
usage in sys_oabi_epoll_ctl()
date:   10 months ago
config: arm-randconfig-m031-20210218 (attached as .config)
compiler: arm-linux-gnueabi-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c281634c865202e2776b0250678ff93c771947ff
git remote add linus 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git fetch --no-tags linus master
git checkout c281634c865202e2776b0250678ff93c771947ff
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

   arch/arm/kernel/sys_oabi-compat.c:142:17: warning: no previous prototype for 
'sys_oabi_stat64' [-Wmissing-prototypes]
 142 | asmlinkage long sys_oabi_stat64(const char __user * filename,
 | ^~~
   arch/arm/kernel/sys_oabi-compat.c:152:17: warning: no previous prototype for 
'sys_oabi_lstat64' [-Wmissing-prototypes]
 152 | asmlinkage long sys_oabi_lstat64(const char __user * filename,
 | ^~~~
   arch/arm/kernel/sys_oabi-compat.c:162:17: warning: no previous prototype for 
'sys_oabi_fstat64' [-Wmissing-prototypes]
 162 | asmlinkage long sys_oabi_fstat64(unsigned long fd,
 | ^~~~
   arch/arm/kernel/sys_oabi-compat.c:172:17: warning: no previous prototype for 
'sys_oabi_fstatat64' [-Wmissing-prototypes]
 172 | asmlinkage long sys_oabi_fstatat64(int dfd,
 | ^~
   arch/arm/kernel/sys_oabi-compat.c:229:17: warning: no previous prototype for 
'sys_oabi_fcntl64' [-Wmissing-prototypes]
 229 | asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
 | ^~~~
   arch/arm/kernel/sys_oabi-compat.c:251:17: warning: no previous prototype for 
'sys_oabi_epoll_ctl' [-Wmissing-prototypes]
 251 | asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd,
 | ^~
   In file included from include/linux/kernel.h:11,
from include/linux/list.h:9,
from include/linux/wait.h:7,
from include/linux/wait_bit.h:8,
from include/linux/fs.h:6,
from include/uapi/linux/aio_abi.h:31,
from include/linux/syscalls.h:74,
from arch/arm/kernel/sys_oabi-compat.c:73:
   arch/arm/kernel/sys_oabi-compat.c: In function 'sys_oabi_epoll_ctl':
>> arch/arm/kernel/sys_oabi-compat.c:257:6: error: implicit declaration of 
>> function 'ep_op_has_event' [-Werror=implicit-function-declaration]
 257 |  if (ep_op_has_event(op) &&
 |  ^~~
   include/linux/compiler.h:58:52: note: in definition of macro '__trace_if_var'
  58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : 
__trace_if_value(cond))
 |^~~~
   arch/arm/kernel/sys_oabi-compat.c:257:2: note: in expansion of macro 'if'
 257 |  if (ep_op_has_event(op) &&
 |  ^~
>> arch/arm/kernel/sys_oabi-compat.c:264:9: error: implicit declaration of 
>> function 'do_epoll_ctl'; did you mean 'sys_epoll_ctl'? 
>> [-Werror=implicit-function-declaration]
 264 |  return do_epoll_ctl(epfd, op, fd, , false);
 | ^~~~
 | sys_epoll_ctl
   arch/arm/kernel/sys_oabi-compat.c: At top level:
   arch/arm/kernel/sys_oabi-compat.c:267:17: warning: no previous prototype for 
'sys_oabi_epoll_wait' [-Wmissing-prototypes]
 267 | asmlinkage long sys_oabi_epoll_wait(int epfd,
 | ^~~
   arch/arm/kernel/sys_oabi-compat.c:309:17: warning: no previous prototype for 
'sys_oabi_semtimedop' [-Wmissing-prototypes]
 309 | asmlinkage long sys_oabi_semtimedop(int semid,
 | ^~~
   arch/arm/kernel/sys_oabi-compat.c:352:17: warning: no previous prototype for 
'sys_oabi_semop' [-Wmissing-prototypes]
 352 | asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user 
*tsops,
 | ^~
   arch/arm/kernel/sys_oabi-compat.c:358:16: warning: no previous prototype for 
'sys_oabi_ipc' [-Wmissing-prototypes]
 358 | asmlinkage int sys_oabi_ipc(uint call, int first, int second, int 
third,
 |^~~~
   

RE: [PATCH v3] scsi: storvsc: Parameterize number hardware queues

2021-02-17 Thread Michael Kelley
From: Melanie Plageman  Sent: Wednesday, February 
17, 2021 4:05 PM
> 
> On Fri, Feb 12, 2021 at 04:35:16PM +, Michael Kelley wrote:
> > From: Melanie Plageman  Sent: Thursday, February 
> > 11,
> 2021 3:18 PM
> > >
> > > Add ability to set the number of hardware queues with new module 
> > > parameter,
> > > storvsc_max_hw_queues. The default value remains the number of CPUs.  This
> > > functionality is useful in some environments (e.g. Microsoft Azure) where
> > > decreasing the number of hardware queues has been shown to improve
> > > performance.
> > >
> > > Signed-off-by: Melanie Plageman (Microsoft) 
> > > ---
> > >  drivers/scsi/storvsc_drv.c | 28 ++--
> > >  1 file changed, 26 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
> > > index 2e4fa77445fd..a64e6664c915 100644
> > > --- a/drivers/scsi/storvsc_drv.c
> > > +++ b/drivers/scsi/storvsc_drv.c
> > > @@ -378,10 +378,14 @@ static u32 max_outstanding_req_per_channel;
> > >  static int storvsc_change_queue_depth(struct scsi_device *sdev, int 
> > > queue_depth);
> > >
> > >  static int storvsc_vcpus_per_sub_channel = 4;
> > > +static int storvsc_max_hw_queues = -1;
> > >
> > >  module_param(storvsc_ringbuffer_size, int, S_IRUGO);
> > >  MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
> > >
> > > +module_param(storvsc_max_hw_queues, int, S_IRUGO|S_IWUSR);
> > > +MODULE_PARM_DESC(storvsc_max_hw_queues, "Maximum number of hardware
> > > queues");
> > > +
> >
> > There's been an effort underway to not use the symbolic permissions in
> > module_param(), but to just use the octal digits (like 0600 for root only
> > access).   But I couldn't immediately find documentation on why this
> > change is being made.  And clearly it hasn't been applied to the
> > existing module_param() uses here in storvsc_drv.c.  But with this being
> > a new parameter, let's use the recommended octal digit format.
> 
> Thanks. I will update this in v4.
> 
> >
> > >  module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
> > >  MODULE_PARM_DESC(storvsc_vcpus_per_sub_channel, "Ratio of VCPUs to
> > > subchannels");
> > >
> > > @@ -1897,6 +1901,7 @@ static int storvsc_probe(struct hv_device *device,
> > >  {
> > >   int ret;
> > >   int num_cpus = num_online_cpus();
> > > + int num_present_cpus = num_present_cpus();
> > >   struct Scsi_Host *host;
> > >   struct hv_host_device *host_dev;
> > >   bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
> > > @@ -2004,8 +2009,19 @@ static int storvsc_probe(struct hv_device *device,
> > >* For non-IDE disks, the host supports multiple channels.
> > >* Set the number of HW queues we are supporting.
> > >*/
> > > - if (!dev_is_ide)
> > > - host->nr_hw_queues = num_present_cpus();
> > > + if (!dev_is_ide) {
> > > + if (storvsc_max_hw_queues == -1)
> > > + host->nr_hw_queues = num_present_cpus;
> > > + else if (storvsc_max_hw_queues > num_present_cpus ||
> > > +  storvsc_max_hw_queues == 0 ||
> > > + storvsc_max_hw_queues < -1) {
> > > + storvsc_log(device, STORVSC_LOGGING_WARN,
> > > + "Resetting invalid storvsc_max_hw_queues value 
> > > to default.\n");
> > > + host->nr_hw_queues = num_present_cpus;
> > > + storvsc_max_hw_queues = -1;
> > > + } else
> > > + host->nr_hw_queues = storvsc_max_hw_queues;
> > > + }
> >
> > I have a couple of thoughts about the above logic.  As the code is written,
> > valid values are integers from 1 to the number of CPUs, and -1.  The logic
> > would be simpler if the module parameter was an unsigned int instead of
> > a signed int, and zero was the marker for "use number of CPUs".  Then
> > you wouldn't have to check for negative values or have special handling
> > for -1.
> 
> I used -1 because the linter ./scripts/checkpatch.pl throws an ERROR "do
> not initialise statics to 0"

OK, right.  The intent of that warning is not that using zero as a value
is bad.  The intent that to indicate that statics are by default initialized
to zero, so explicitly adding the "= 0" is unnecessary.  So feel free to
use "0" as the marker for "use numbers of CPUs".  Just don't
add the "= 0" in the variable declaration. :-)

> 
> >
> > Second, I think you can avoid intertwining the logic for checking for an
> > invalid value, and actually setting host->nr_hw_queues.  Check for an
> > invalid value first, then do the setting of host->hr_hw_queues.
> >
> > Putting both thoughts together, you could get code like this:
> >
> > if (!dev_is ide) {
> > if (storvsc_max_hw_queues > num_present_cpus) {
> > storvsc_max_hw_queues = 0;
> > storvsc_log(device, STORVSC_LOGGING_WARN,
> > "Resetting invalid storvsc_max_hw_queues value 
> > to 

[PATCH] PCI: imx6: Limit DBI register length for imx6qp pcie

2021-02-17 Thread Richard Zhu
Refer to commit 075af61c19cd ("PCI: imx6: Limit DBI register length"),
i.MX6QP PCIe has the similar issue.
Define the length of the DBI registers and limit config space to its
length for i.MX6QP PCIe too.

Signed-off-by: Richard Zhu 
---
 drivers/pci/controller/dwc/pci-imx6.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/pci/controller/dwc/pci-imx6.c 
b/drivers/pci/controller/dwc/pci-imx6.c
index 0cf1333c0440..853ea8e82952 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -1175,6 +1175,7 @@ static const struct imx6_pcie_drvdata drvdata[] = {
.variant = IMX6QP,
.flags = IMX6_PCIE_FLAG_IMX6_PHY |
 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
+   .dbi_length = 0x200,
},
[IMX7D] = {
.variant = IMX7D,
-- 
2.17.1



Re: [PATCH 2/2] rcu-tasks: add RCU-tasks self tests

2021-02-17 Thread Masami Hiramatsu
On Wed, 17 Feb 2021 10:17:38 -0800
"Paul E. McKenney"  wrote:

> > > 1.Spawn ksoftirqd earlier.
> > > 
> > > 2.Suppress attempts to awaken ksoftirqd before it exists,
> > >   forcing all ksoftirq execution on the back of interrupts.
> > > 
> > > Uladzislau and I each produced patches for #1, and I produced a patch
> > > for #2.
> > > 
> > > The only other option I know of is to push the call to init_kprobes()
> > > later in the boot sequence, perhaps to its original subsys_initcall(),
> > > or maybe only as late as core_initcall().  I added Masami and Steve on
> > > CC for their thoughts on this.
> > > 
> > > Is there some other proper fix that I am missing?
> > 
> > Oh, I missed that the synchronize_rcu_tasks() will be involved the kprobes
> > in early stage. Does the problem only exist in the synchronize_rcu_tasks()
> > instead of synchronize_rcu()? If so I can just stop optimizer in early stage
> > because I just want to enable kprobes in early stage, but not optprobes.
> > 
> > Does the following patch help?
> 
> It does look to me like it would!  I clearly should have asked you about
> this a couple of months ago.  ;-)
> 
> The proof of the pudding would be whether the powerpc guys can apply
> this to v5.10-rc7 and have their kernel come up without hanging at boot.

Who could I ask for testing this patch, Uladzislau?
I think the test machine which enough slow or the kernel has much initcall
to run optimization thread while booting.
In my environment, I could not reproduce that issue because the optimizer
was sheduled after some tick passed. At that point, ksoftirqd has already
been initialized.

Thank you,


-- 
Masami Hiramatsu 


Re: linux-next: manual merge of the irqchip tree with the sunxi tree

2021-02-17 Thread Stephen Rothwell
Hi all,

On Mon, 15 Feb 2021 09:11:24 +1100 Stephen Rothwell  
wrote:
>
> On Mon, 1 Feb 2021 14:42:59 +1100 Stephen Rothwell  
> wrote:
> >
> > Today's linux-next merge of the irqchip tree got a conflict in:
> > 
> >   
> > Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
> > 
> > between commit:
> > 
> >   752b0aac99c7 ("dt-bindings: irq: sun7i-nmi: Add binding documentation for 
> > the V3s NMI")
> > 
> > from the sunxi tree and commit:
> > 
> >   ad6b47cdef76 ("dt-bindings: irq: sun6i-r: Split the binding from 
> > sun7i-nmi")
> > 
> > from the irqchip tree.
> > 
> > I fixed it up (I think - see below) and can carry the fix as
> > necessary. This is now fixed as far as linux-next is concerned, but any
> > non trivial conflicts should be mentioned to your upstream maintainer
> > when your tree is submitted for merging.  You may also want to consider
> > cooperating with the maintainer of the conflicting tree to minimise any
> > particularly complex conflicts.
> > 
> > diff --cc 
> > Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
> > index 4fd1e2780026,f34ecc8c7093..
> > --- 
> > a/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
> > +++ 
> > b/Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
> > @@@ -25,17 -25,7 +25,10 @@@ properties
> > - const: allwinner,sun6i-a31-sc-nmi
> >   deprecated: true
> > - const: allwinner,sun7i-a20-sc-nmi
> > -   - items:
> > -   - const: allwinner,sun8i-a83t-r-intc
> > -   - const: allwinner,sun6i-a31-r-intc
> >  +  - items:
> >  +  - const: allwinner,sun8i-v3s-nmi
> >  +  - const: allwinner,sun9i-a80-nmi
> > - const: allwinner,sun9i-a80-nmi
> > -   - items:
> > -   - const: allwinner,sun50i-a64-r-intc
> > -   - const: allwinner,sun6i-a31-r-intc
> > - items:
> > - const: allwinner,sun50i-a100-nmi
> > - const: allwinner,sun9i-a80-nmi  
> 
> With the merge window about to open, this is a reminder that this
> conflict still exists.  It is now between the arm-soc tree and the
> irqchip tree.

This is now a conflict between the arm-soc tree and the tip tree.

-- 
Cheers,
Stephen Rothwell


pgpCHSSr1yVF7.pgp
Description: OpenPGP digital signature


Re: [PATCH v1] vdpa/mlx5: Restore the hardware used index after change map

2021-02-17 Thread Jason Wang



On 2021/2/10 下午4:59, Si-Wei Liu wrote:



On 2/9/2021 7:53 PM, Jason Wang wrote:


On 2021/2/10 上午10:30, Si-Wei Liu wrote:



On 2/8/2021 10:37 PM, Jason Wang wrote:


On 2021/2/9 下午2:12, Eli Cohen wrote:

On Tue, Feb 09, 2021 at 11:20:14AM +0800, Jason Wang wrote:

On 2021/2/8 下午6:04, Eli Cohen wrote:

On Mon, Feb 08, 2021 at 05:04:27PM +0800, Jason Wang wrote:

On 2021/2/8 下午2:37, Eli Cohen wrote:

On Mon, Feb 08, 2021 at 12:27:18PM +0800, Jason Wang wrote:

On 2021/2/6 上午7:07, Si-Wei Liu wrote:

On 2/3/2021 11:36 PM, Eli Cohen wrote:
When a change of memory map occurs, the hardware resources 
are destroyed
and then re-created again with the new memory map. In such 
case, we need
to restore the hardware available and used indices. The 
driver failed to

restore the used index which is added here.

Also, since the driver also fails to reset the available 
and used
indices upon device reset, fix this here to avoid 
regression caused by

the fact that used index may not be zero upon device reset.

Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for 
supported mlx5

devices")
Signed-off-by: Eli Cohen
---
v0 -> v1:
Clear indices upon device reset

     drivers/vdpa/mlx5/net/mlx5_vnet.c | 18 ++
     1 file changed, 18 insertions(+)

diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c
b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index 88dde3455bfd..b5fe6d2ad22f 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -87,6 +87,7 @@ struct mlx5_vq_restore_info {
     u64 device_addr;
     u64 driver_addr;
     u16 avail_index;
+    u16 used_index;
     bool ready;
     struct vdpa_callback cb;
     bool restore;
@@ -121,6 +122,7 @@ struct mlx5_vdpa_virtqueue {
     u32 virtq_id;
     struct mlx5_vdpa_net *ndev;
     u16 avail_idx;
+    u16 used_idx;
     int fw_state;
       /* keep last in the struct */
@@ -804,6 +806,7 @@ static int create_virtqueue(struct 
mlx5_vdpa_net

*ndev, struct mlx5_vdpa_virtque
       obj_context = 
MLX5_ADDR_OF(create_virtio_net_q_in, in,

obj_context);
     MLX5_SET(virtio_net_q_object, obj_context, 
hw_available_index,

mvq->avail_idx);
+    MLX5_SET(virtio_net_q_object, obj_context, hw_used_index,
mvq->used_idx);
     MLX5_SET(virtio_net_q_object, obj_context,
queue_feature_bit_mask_12_3,
get_features_12_3(ndev->mvdev.actual_features));
     vq_ctx = MLX5_ADDR_OF(virtio_net_q_object, 
obj_context,

virtio_q_context);
@@ -1022,6 +1025,7 @@ static int connect_qps(struct 
mlx5_vdpa_net

*ndev, struct mlx5_vdpa_virtqueue *m
     struct mlx5_virtq_attr {
     u8 state;
     u16 available_index;
+    u16 used_index;
     };
       static int query_virtqueue(struct mlx5_vdpa_net 
*ndev, struct

mlx5_vdpa_virtqueue *mvq,
@@ -1052,6 +1056,7 @@ static int query_virtqueue(struct
mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueu
     memset(attr, 0, sizeof(*attr));
     attr->state = MLX5_GET(virtio_net_q_object, 
obj_context, state);

     attr->available_index = MLX5_GET(virtio_net_q_object,
obj_context, hw_available_index);
+    attr->used_index = MLX5_GET(virtio_net_q_object, 
obj_context,

hw_used_index);
     kfree(out);
     return 0;
     @@ -1535,6 +1540,16 @@ static void 
teardown_virtqueues(struct

mlx5_vdpa_net *ndev)
     }
     }
     +static void clear_virtqueues(struct mlx5_vdpa_net *ndev)
+{
+    int i;
+
+    for (i = ndev->mvdev.max_vqs - 1; i >= 0; i--) {
+    ndev->vqs[i].avail_idx = 0;
+    ndev->vqs[i].used_idx = 0;
+    }
+}
+
     /* TODO: cross-endian support */
     static inline bool mlx5_vdpa_is_little_endian(struct 
mlx5_vdpa_dev

*mvdev)
     {
@@ -1610,6 +1625,7 @@ static int save_channel_info(struct
mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqu
     return err;
       ri->avail_index = attr.available_index;
+    ri->used_index = attr.used_index;
     ri->ready = mvq->ready;
     ri->num_ent = mvq->num_ent;
     ri->desc_addr = mvq->desc_addr;
@@ -1654,6 +1670,7 @@ static void restore_channels_info(struct
mlx5_vdpa_net *ndev)
     continue;
       mvq->avail_idx = ri->avail_index;
+    mvq->used_idx = ri->used_index;
     mvq->ready = ri->ready;
     mvq->num_ent = ri->num_ent;
     mvq->desc_addr = ri->desc_addr;
@@ -1768,6 +1785,7 @@ static void mlx5_vdpa_set_status(struct
vdpa_device *vdev, u8 status)
     if (!status) {
     mlx5_vdpa_info(mvdev, "performing device 
reset\n");

     teardown_driver(ndev);
+    clear_virtqueues(ndev);
The clearing looks fine at the first glance, as it aligns 
with the other
state cleanups floating around at the same place. However, 
the thing is
get_vq_state() is supposed to be called right after to get 
sync'ed with
the latest internal avail_index from device while vq is 
stopped. The
index was saved in the driver software at vq suspension, but 
before the
virtq object is destroyed. We shouldn't 

Re: [PATCH 3/3] Input: applespi: Add trace_event module param for early tracing.

2021-02-17 Thread kernel test robot
Hi "Ronald,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on input/next]
[also build test ERROR on v5.11 next-20210217]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Ronald-Tschal-r/Input-applespi-Don-t-wait-for-responses-to-commands-indefinitely/20210218-032205
base:   https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
config: ia64-allyesconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://github.com/0day-ci/linux/commit/838cd23e96675132bdd30878d1b24a59b8a534e1
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Ronald-Tschal-r/Input-applespi-Don-t-wait-for-responses-to-commands-indefinitely/20210218-032205
git checkout 838cd23e96675132bdd30878d1b24a59b8a534e1
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
ARCH=ia64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

   ia64-linux-ld: drivers/input/keyboard/applespi.o: in function 
`applespi_probe':
>> applespi.c:(.text+0xf22): undefined reference to `trace_set_clr_event'

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for FRAME_POINTER
   Depends on DEBUG_KERNEL && (M68K || UML || SUPERH) || 
ARCH_WANT_FRAME_POINTERS
   Selected by
   - FAULT_INJECTION_STACKTRACE_FILTER && FAULT_INJECTION_DEBUG_FS && 
STACKTRACE_SUPPORT && !X86_64 && !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM 
&& !ARC && !X86

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org


.config.gz
Description: application/gzip


RE: [PATCH v4] drm/i915/gen9bc: Handle TGP PCH during suspend/resume

2021-02-17 Thread Surendrakumar Upadhyay, TejaskumarX


> -Original Message-
> From: Lyude Paul 
> Sent: 18 February 2021 02:49
> To: Deak, Imre 
> Cc: intel-...@lists.freedesktop.org; Surendrakumar Upadhyay, TejaskumarX
> ; Roper, Matthew D
> ; Jani Nikula ;
> Joonas Lahtinen ; Vivi, Rodrigo
> ; David Airlie ; Daniel Vetter
> ; open list:DRM DRIVERS  de...@lists.freedesktop.org>; open list 
> Subject: Re: [PATCH v4] drm/i915/gen9bc: Handle TGP PCH during
> suspend/resume
> 
> On Wed, 2021-02-17 at 23:18 +0200, Imre Deak wrote:
> > On Wed, Feb 17, 2021 at 01:00:16PM -0500, Lyude Paul wrote:
> > > From: Tejas Upadhyay
> 
> > >
> > > For Legacy S3 suspend/resume GEN9 BC needs to enable and setup TGP
> > > PCH.
> > >
> > > v2:
> > > * Move Wa_14010685332 into it's own function - vsyrjala
> > > * Add TODO comment about figuring out if we can move this workaround
> > > - imre
> > > v3:
> > > * Rename cnp_irq_post_reset() to cnp_display_clock_wa()
> > > * Add TODO item mentioning we need to clarify which platforms this
> > >   workaround applies to
> > > * Just use ibx_irq_reset() in gen8_irq_reset(). This code should be
> > >   functionally equivalent on gen9 bc to the code v2 added
> > > * Drop icp_hpd_irq_setup() call in spt_hpd_irq_setup(), this looks
> > > to be
> > >   more or less identical to spt_hpd_irq_setup() minus additionally
> > > enabling
> > >   one port. Will update i915 to use icp_hpd_irq_setup() for ICP in a
> > >   separate patch.
> > > v4:
> > > * Revert Wa_14010685332 system list in comments to how it was before
> > > * Add back HAS_PCH_SPLIT() check before calling ibx_irq_reset()
> > >
> > > Cc: Matt Roper 
> > > Signed-off-by: Tejas Upadhyay
> > > 
> > > Signed-off-by: Lyude Paul 
> >
> > Thanks, looks ok to me:
> > Reviewed-by: Imre Deak 
> >
> > nit: cnp_display_clock_gating_wa() would be an even better name, could
> > be renamed while applying.
> 
> Sure thing. JFYI - I'm going to hold off on pushing this patch until I've got
> confirmation from the OEMs this is for that these patches still fix their 
> issues
> (since I unfortunately don't have any access to this hardware).

I can follow up with OEM to test or I can get it tested in my LAB, as I have 
RKL RVP (CML CPU) + TGP PCH with me.

> 
> >
> > > ---
> > >  drivers/gpu/drm/i915/i915_irq.c | 49
> > > +
> > >  1 file changed, 32 insertions(+), 17 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/i915_irq.c
> > > b/drivers/gpu/drm/i915/i915_irq.c index 98145a7f28a4..9b56a8f81e1a
> > > 100644
> > > --- a/drivers/gpu/drm/i915/i915_irq.c
> > > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > > @@ -3040,6 +3040,24 @@ static void valleyview_irq_reset(struct
> > > drm_i915_private *dev_priv)
> > > spin_unlock_irq(_priv->irq_lock);
> > >  }
> > >
> > > +static void cnp_display_clock_wa(struct drm_i915_private *dev_priv)
> > > +{
> > > +   struct intel_uncore *uncore = _priv->uncore;
> > > +
> > > +   /*
> > > +    * Wa_14010685332:cnp/cmp,tgp,adp
> > > +    * TODO: Clarify which platforms this applies to
> > > +    * TODO: Figure out if this workaround can be applied in the
> > > +s0ix
> > > suspend/resume handlers as
> > > +    * on earlier platforms and whether the workaround is also
> > > +needed
> > > for runtime suspend/resume
> > > +    */
> > > +   if (INTEL_PCH_TYPE(dev_priv) == PCH_CNP ||
> > > +   (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP &&
> > > +INTEL_PCH_TYPE(dev_priv)
> > > < PCH_DG1)) {
> > > +   intel_uncore_rmw(uncore, SOUTH_CHICKEN1,
> > > SBCLK_RUN_REFCLK_DIS,
> > > +    SBCLK_RUN_REFCLK_DIS);
> > > +   intel_uncore_rmw(uncore, SOUTH_CHICKEN1,
> > > SBCLK_RUN_REFCLK_DIS, 0);
> > > +   }
> > > +}
> > > +
> > >  static void gen8_irq_reset(struct drm_i915_private *dev_priv)
> > >  {
> > > struct intel_uncore *uncore = _priv->uncore; @@ -3063,6
> > > +3081,8 @@ static void gen8_irq_reset(struct drm_i915_private
> > > *dev_priv)
> > >
> > > if (HAS_PCH_SPLIT(dev_priv))
> > > ibx_irq_reset(dev_priv);
> > > +
> > > +   cnp_display_clock_wa(dev_priv);
> > >  }
> > >
> > >  static void gen11_display_irq_reset(struct drm_i915_private
> > > *dev_priv) @@ -3104,15 +3124,7 @@ static void
> > > gen11_display_irq_reset(struct drm_i915_private *dev_priv)
> > > if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
> > > GEN3_IRQ_RESET(uncore, SDE);
> > >
> > > -   /* Wa_14010685332:cnp/cmp,tgp,adp */
> > > -   if (INTEL_PCH_TYPE(dev_priv) == PCH_CNP ||
> > > -   (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP &&
> > > -    INTEL_PCH_TYPE(dev_priv) < PCH_DG1)) {
> > > -   intel_uncore_rmw(uncore, SOUTH_CHICKEN1,
> > > -    SBCLK_RUN_REFCLK_DIS,
> > > SBCLK_RUN_REFCLK_DIS);
> > > -   intel_uncore_rmw(uncore, SOUTH_CHICKEN1,
> > > -    SBCLK_RUN_REFCLK_DIS, 0);
> > > -   }
> > > +   

  1   2   3   4   5   6   7   8   9   10   >