From s.hauer at pengutronix.de  Thu Sep  1 01:44:27 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 1 Sep 2022 10:44:27 +0200
Subject: [PATCH] fixup-next: linux/nvmem-consumer.h: fix warning
In-Reply-To: <20220831092614.68259-1-antonynpavlov@gmail.com>
References: <20220831092614.68259-1-antonynpavlov@gmail.com>
Message-ID: <20220901084427.GR24324@pengutronix.de>

On Wed, Aug 31, 2022 at 12:26:14PM +0300, Antony Pavlov wrote:
> This fixes the commit 06825a0ec35343a1
> ("nvmem: import Linux nvmem_cell_read_variable_le_u32")
> from the next branch.
> 
> The warning is:
> 
> include/linux/nvmem-consumer.h:84:9: warning: returning 'void *' from a
> function with return type 'int' makes integer from pointer without a
> cast [-Wint-conversion]
>    84 |  return ERR_PTR(-EOPNOTSUPP);
>       |         ^~~~~~~~~~~~~~~~~~~~
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  include/linux/nvmem-consumer.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> index b461f840957..1fce7e1ae09 100644
> --- a/include/linux/nvmem-consumer.h
> +++ b/include/linux/nvmem-consumer.h
> @@ -81,7 +81,7 @@ static inline int nvmem_cell_read_variable_le_u32(struct device_d *dev,
>  						  const char *cell_id,
>  						  u32 *val)
>  {
> -	return ERR_PTR(-EOPNOTSUPP);
> +	return -EOPNOTSUPP;
>  }
>  
>  static inline int nvmem_cell_write(struct nvmem_cell *cell,
> -- 
> 2.37.2
> 
> 

-- 
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-5555 |


From s.hauer at pengutronix.de  Thu Sep  1 01:44:55 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 1 Sep 2022 10:44:55 +0200
Subject: [PATCH] Documentation/gen_commands.py: use python3
In-Reply-To: <20220831085001.66538-1-antonynpavlov@gmail.com>
References: <20220831085001.66538-1-antonynpavlov@gmail.com>
Message-ID: <20220901084455.GS24324@pengutronix.de>

On Wed, Aug 31, 2022 at 11:50:01AM +0300, Antony Pavlov wrote:
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  Documentation/gen_commands.py | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/Documentation/gen_commands.py b/Documentation/gen_commands.py
> index a55b1acd82f..7c62a030dce 100755
> --- a/Documentation/gen_commands.py
> +++ b/Documentation/gen_commands.py
> @@ -1,6 +1,4 @@
> -#!/usr/bin/env python
> -
> -from __future__ import print_function
> +#!/usr/bin/env python3
>  
>  import errno
>  import os
> -- 
> 2.37.2
> 
> 

-- 
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-5555 |


From a.fatoum at pengutronix.de  Thu Sep  1 03:41:36 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu,  1 Sep 2022 12:41:36 +0200
Subject: [PATCH master] ARM: sync_caches_for_execution: don't flush disabled data cache
Message-ID: <20220901104136.171051-1-a.fatoum@pengutronix.de>

We unconditionally clean and then invalidate D-cache entries in
sync_caches_for_execution by calling arm_early_mmu_cache_flush().

The function afterwards takes care to invalidate the I-cache.

This misbehaves though when the D-Cache contains stale dirty
entries for currently executing code. Most boards avoid this
pitfall, because barebox_arm_entry calls
arm_early_mmu_cache_invalidate() and sync_caches_for_execution()
is only called afterwards. But for some boards,
relocate_to_current_adr() is called before barebox_arm_entry and
various board code works around this by calling
arm_early_mmu_cache_invalidate() first.

Make this unnecessary by not flushing the data cache when it's disabled
and instead only invalidate the I-Cache.

This fixes a hang observed on a serial-booted i.MX6Q rev 1.5
executing relocate_to_current_adr() -> sync_caches_for_execution()
from On-Chip SRAM.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/cpu/common.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/cpu/common.c b/arch/arm/cpu/common.c
index 8cfcc8f6ce7a..5ccacf204751 100644
--- a/arch/arm/cpu/common.c
+++ b/arch/arm/cpu/common.c
@@ -23,6 +23,12 @@
  */
 void sync_caches_for_execution(void)
 {
+	/* if caches are disabled, don't do data cache maintenance */
+	if (!(get_cr() & CR_C)) {
+		icache_invalidate();
+		return;
+	}
+
 	/*
 	 * Despite the name arm_early_mmu_cache_flush not only flushes the
 	 * data cache, but also invalidates the instruction cache.
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Sep  1 03:41:53 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu,  1 Sep 2022 12:41:53 +0200
Subject: [PATCH] usb: gadget: fsl_udc: add imx6_barebox_(load/start)_usb
Message-ID: <20220901104153.171235-1-a.fatoum@pengutronix.de>

These can be called from barebox PBL when booted from USB to continue
USB boot. This isn't necessary in the general case when RAM setup is
done via DCD, but for cases where setup is done in PBL, these helpers
come in handy. Tested on i.MX6Q.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/usb/gadget/fsl_udc_pbl.c | 11 +++++++++++
 include/soc/fsl/fsl_udc.h        |  3 +++
 2 files changed, 14 insertions(+)

diff --git a/drivers/usb/gadget/fsl_udc_pbl.c b/drivers/usb/gadget/fsl_udc_pbl.c
index 0fbe941b1222..8b714d4c8b02 100644
--- a/drivers/usb/gadget/fsl_udc_pbl.c
+++ b/drivers/usb/gadget/fsl_udc_pbl.c
@@ -4,6 +4,7 @@
 #include <usb/ch9.h>
 #include <soc/fsl/fsl_udc.h>
 #include <mach/imx8mm-regs.h>
+#include <mach/imx6-regs.h>
 
 static void fsl_queue_td(struct usb_dr_device *dr, struct ep_td_struct *dtd,
 			 int ep_is_in)
@@ -199,6 +200,16 @@ int imx_barebox_start_usb(void __iomem *dr, void *dest)
 	bb();
 }
 
+int imx6_barebox_load_usb(void *dest)
+{
+	return imx_barebox_load_usb(IOMEM(MX6_OTG_BASE_ADDR), dest);
+}
+
+int imx6_barebox_start_usb(void *dest)
+{
+	return imx_barebox_start_usb(IOMEM(MX6_OTG_BASE_ADDR), dest);
+}
+
 int imx8mm_barebox_load_usb(void *dest)
 {
 	return imx_barebox_load_usb(IOMEM(MX8MM_USB1_BASE_ADDR), dest);
diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
index 9fb6da58a146..aa1db2fb3816 100644
--- a/include/soc/fsl/fsl_udc.h
+++ b/include/soc/fsl/fsl_udc.h
@@ -382,6 +382,9 @@ struct ep_td_struct {
 int imx_barebox_load_usb(void __iomem *dr, void *dest);
 int imx_barebox_start_usb(void __iomem *dr, void *dest);
 
+int imx6_barebox_load_usb(void *dest);
+int imx6_barebox_start_usb(void *dest);
+
 int imx8mm_barebox_load_usb(void *dest);
 int imx8mm_barebox_start_usb(void *dest);
 
-- 
2.30.2



From sha at pengutronix.de  Thu Sep  1 04:48:24 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 1 Sep 2022 13:48:24 +0200
Subject: [PATCH] usb: gadget: fsl_udc: add imx6_barebox_(load/start)_usb
In-Reply-To: <20220901104153.171235-1-a.fatoum@pengutronix.de>
References: <20220901104153.171235-1-a.fatoum@pengutronix.de>
Message-ID: <20220901114824.GT24324@pengutronix.de>

On Thu, Sep 01, 2022 at 12:41:53PM +0200, Ahmad Fatoum wrote:
> These can be called from barebox PBL when booted from USB to continue
> USB boot. This isn't necessary in the general case when RAM setup is
> done via DCD, but for cases where setup is done in PBL, these helpers
> come in handy. Tested on i.MX6Q.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/usb/gadget/fsl_udc_pbl.c | 11 +++++++++++
>  include/soc/fsl/fsl_udc.h        |  3 +++
>  2 files changed, 14 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/usb/gadget/fsl_udc_pbl.c b/drivers/usb/gadget/fsl_udc_pbl.c
> index 0fbe941b1222..8b714d4c8b02 100644
> --- a/drivers/usb/gadget/fsl_udc_pbl.c
> +++ b/drivers/usb/gadget/fsl_udc_pbl.c
> @@ -4,6 +4,7 @@
>  #include <usb/ch9.h>
>  #include <soc/fsl/fsl_udc.h>
>  #include <mach/imx8mm-regs.h>
> +#include <mach/imx6-regs.h>
>  
>  static void fsl_queue_td(struct usb_dr_device *dr, struct ep_td_struct *dtd,
>  			 int ep_is_in)
> @@ -199,6 +200,16 @@ int imx_barebox_start_usb(void __iomem *dr, void *dest)
>  	bb();
>  }
>  
> +int imx6_barebox_load_usb(void *dest)
> +{
> +	return imx_barebox_load_usb(IOMEM(MX6_OTG_BASE_ADDR), dest);
> +}
> +
> +int imx6_barebox_start_usb(void *dest)
> +{
> +	return imx_barebox_start_usb(IOMEM(MX6_OTG_BASE_ADDR), dest);
> +}
> +
>  int imx8mm_barebox_load_usb(void *dest)
>  {
>  	return imx_barebox_load_usb(IOMEM(MX8MM_USB1_BASE_ADDR), dest);
> diff --git a/include/soc/fsl/fsl_udc.h b/include/soc/fsl/fsl_udc.h
> index 9fb6da58a146..aa1db2fb3816 100644
> --- a/include/soc/fsl/fsl_udc.h
> +++ b/include/soc/fsl/fsl_udc.h
> @@ -382,6 +382,9 @@ struct ep_td_struct {
>  int imx_barebox_load_usb(void __iomem *dr, void *dest);
>  int imx_barebox_start_usb(void __iomem *dr, void *dest);
>  
> +int imx6_barebox_load_usb(void *dest);
> +int imx6_barebox_start_usb(void *dest);
> +
>  int imx8mm_barebox_load_usb(void *dest);
>  int imx8mm_barebox_start_usb(void *dest);
>  
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From a.fatoum at pengutronix.de  Thu Sep  1 05:21:56 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 1 Sep 2022 14:21:56 +0200
Subject: [PATCH 2/3] ARM: socfpga: add support for Enclustra AA1
In-Reply-To: <25fec987-ca1b-05bb-1dad-7bc8fb57bb18@pengutronix.de>
References: <20220707104127.3330997-1-s.trumtrar@pengutronix.de>
 <20220707104127.3330997-2-s.trumtrar@pengutronix.de>
 <25fec987-ca1b-05bb-1dad-7bc8fb57bb18@pengutronix.de>
Message-ID: <d630c102-b92a-16d7-409d-e494d4d46d03@pengutronix.de>

Hi,

On 07.07.22 12:57, Ahmad Fatoum wrote:
> On 07.07.22 12:41, Steffen Trumtrar wrote:
>> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>

[snip]

>> +static noinline void aa1_start(void)
>> +{
>> +	int pbl_index = 0;
>> +	int barebox = 0;
>> +	int bitstream = 0;
>> +
>> +	arm_early_mmu_cache_invalidate();
> 
> Is this really required? If MMU is enabled by the time you
> enter here, you risk executing garbage before hitting
> this line anyway and if it's disabled, caches will be invalidated
> just before MMU is enabled already.
> 
>> +
>> +	relocate_to_current_adr();

I see now that I was mistaken here, because relocate_to_current_adr()
called directly after will call sync_for_execution(), which will clean
D$ and invalidate I$. If we happen to have stale dirty D$ entries,
these will be flushed and corrupt memory, which
arm_early_mmu_cache_invalidate() avoided. I still think we shouldn't
expect board code to call arm_early_mmu_cache_invalidate(), rather
sync_caches_for_execution() should take care to only invalidate I$,
when caches are disabled.

My "ARM: sync_caches_for_execution: don't flush disabled data cache"
patch from earlier today should resolve this. You'll probably want
to cherry pick it..

Cheers,
Ahmad


-- 
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-5555 |


From s.hauer at pengutronix.de  Thu Sep  1 07:35:34 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu,  1 Sep 2022 16:35:34 +0200
Subject: [PATCH] ARM: i.MX8MM: add Innocom WB15 support
Message-ID: <20220901143534.2219624-1-s.hauer@pengutronix.de>

From: Ahmad Fatoum <a.fatoum at pengutronix.de>

The Innocom WB15-EVK is a Rpi form factor board built around the
i.MX8MML-based WB15 SoM. Add basic board support.

The dts files are split up into three files:
- imx8mm-innocom-wb15.dtsi: This is the SoM dtsi file
- imx8mm-innocom-wb15-evk-upstream.dts: base board dts file, generic
  part
- imx8mm-innocom-wb15-evk.dts: base board dts file, barebox specific
  part

The former two are currently under upstream review and can be replaced
by the upstream version once merged.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boards/Makefile                      |    1 +
 arch/arm/boards/innocom-imx8mm-wb15/Makefile  |    4 +
 arch/arm/boards/innocom-imx8mm-wb15/board.c   |   40 +
 .../flash-header-imx8mm-wb15.imxcfg           |    7 +
 .../arm/boards/innocom-imx8mm-wb15/lowlevel.c |   91 +
 .../arm/boards/innocom-imx8mm-wb15/lowlevel.h |    9 +
 .../innocom-imx8mm-wb15/lpddr4-timing.c       | 1856 +++++++++++++++++
 arch/arm/configs/imx_v8_defconfig             |    1 +
 arch/arm/dts/Makefile                         |    1 +
 .../dts/imx8mm-innocom-wb15-evk-upstream.dts  |  147 ++
 arch/arm/dts/imx8mm-innocom-wb15-evk.dts      |   60 +
 arch/arm/dts/imx8mm-innocom-wb15.dtsi         |  481 +++++
 arch/arm/mach-imx/Kconfig                     |   11 +
 images/Makefile.imx                           |    5 +
 14 files changed, 2714 insertions(+)
 create mode 100644 arch/arm/boards/innocom-imx8mm-wb15/Makefile
 create mode 100644 arch/arm/boards/innocom-imx8mm-wb15/board.c
 create mode 100644 arch/arm/boards/innocom-imx8mm-wb15/flash-header-imx8mm-wb15.imxcfg
 create mode 100644 arch/arm/boards/innocom-imx8mm-wb15/lowlevel.c
 create mode 100644 arch/arm/boards/innocom-imx8mm-wb15/lowlevel.h
 create mode 100644 arch/arm/boards/innocom-imx8mm-wb15/lpddr4-timing.c
 create mode 100644 arch/arm/dts/imx8mm-innocom-wb15-evk-upstream.dts
 create mode 100644 arch/arm/dts/imx8mm-innocom-wb15-evk.dts
 create mode 100644 arch/arm/dts/imx8mm-innocom-wb15.dtsi

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 5a11c52831..16a9044352 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_MACH_HABA_KNX_LITE)		+= haba-knx/
 obj-$(CONFIG_MACH_IMX21ADS)			+= freescale-mx21-ads/
 obj-$(CONFIG_MACH_IMX233_OLINUXINO)		+= imx233-olinuxino/
 obj-$(CONFIG_MACH_IMX27ADS)			+= freescale-mx27-ads/
+obj-$(CONFIG_MACH_INNOCOM_WB15)			+= innocom-imx8mm-wb15/
 obj-$(CONFIG_MACH_KAMSTRUP_MX7_CONCENTRATOR)	+= kamstrup-mx7-concentrator/
 obj-$(CONFIG_MACH_KINDLE3)			+= kindle3/
 obj-$(CONFIG_MACH_KONTRON_SAMX6I)		+= kontron-samx6i/
diff --git a/arch/arm/boards/innocom-imx8mm-wb15/Makefile b/arch/arm/boards/innocom-imx8mm-wb15/Makefile
new file mode 100644
index 0000000000..10abebc539
--- /dev/null
+++ b/arch/arm/boards/innocom-imx8mm-wb15/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+lwl-y += lowlevel.o lpddr4-timing.o
+obj-y += board.o
diff --git a/arch/arm/boards/innocom-imx8mm-wb15/board.c b/arch/arm/boards/innocom-imx8mm-wb15/board.c
new file mode 100644
index 0000000000..902a691ddb
--- /dev/null
+++ b/arch/arm/boards/innocom-imx8mm-wb15/board.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: 2022 Ahmad Fatoum, Pengutronix
+
+#include <bootsource.h>
+#include <common.h>
+#include <deep-probe.h>
+#include <init.h>
+#include <mach/bbu.h>
+
+static int innocom_wb15_evk_probe(struct device_d *dev)
+{
+	int emmc_bbu_flag = 0;
+	int sd_bbu_flag = 0;
+
+	if (bootsource_get() == BOOTSOURCE_MMC && bootsource_get_instance() == 1) {
+		of_device_enable_path("/chosen/environment-sd");
+		sd_bbu_flag = BBU_HANDLER_FLAG_DEFAULT;
+	} else {
+		of_device_enable_path("/chosen/environment-emmc");
+		emmc_bbu_flag = BBU_HANDLER_FLAG_DEFAULT;
+	}
+
+	imx8m_bbu_internal_mmcboot_register_handler("eMMC", "/dev/mmc0", emmc_bbu_flag);
+	imx8m_bbu_internal_mmc_register_handler("SD", "/dev/mmc1.barebox", sd_bbu_flag);
+
+	return 0;
+}
+
+static const struct of_device_id innocom_wb15_evk_of_match[] = {
+	{ .compatible = "innocom,wb15-evk" },
+	{ /* sentinel */ },
+};
+BAREBOX_DEEP_PROBE_ENABLE(innocom_wb15_evk_of_match);
+
+static struct driver_d innocom_wb15_evkboard_driver = {
+	.name = "board-innocom-wb15-evk",
+	.probe = innocom_wb15_evk_probe,
+	.of_compatible = DRV_OF_COMPAT(innocom_wb15_evk_of_match),
+};
+coredevice_platform_driver(innocom_wb15_evkboard_driver);
diff --git a/arch/arm/boards/innocom-imx8mm-wb15/flash-header-imx8mm-wb15.imxcfg b/arch/arm/boards/innocom-imx8mm-wb15/flash-header-imx8mm-wb15.imxcfg
new file mode 100644
index 0000000000..10606ce29c
--- /dev/null
+++ b/arch/arm/boards/innocom-imx8mm-wb15/flash-header-imx8mm-wb15.imxcfg
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+soc imx8mm
+
+loadaddr 0x007e1000
+max_load_size 0x3f000
+ivtofs 0x400
diff --git a/arch/arm/boards/innocom-imx8mm-wb15/lowlevel.c b/arch/arm/boards/innocom-imx8mm-wb15/lowlevel.c
new file mode 100644
index 0000000000..2c1e4497bf
--- /dev/null
+++ b/arch/arm/boards/innocom-imx8mm-wb15/lowlevel.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <common.h>
+#include <debug_ll.h>
+#include <asm/barebox-arm.h>
+#include <pbl/i2c.h>
+#include <pbl/pmic.h>
+#include <mach/esdctl.h>
+#include <mach/atf.h>
+#include <mach/generic.h>
+#include <mach/iomux-mx8mm.h>
+#include <mach/imx8m-ccm-regs.h>
+#include <mfd/bd71837.h>
+#include <mach/xload.h>
+#include <soc/imx8m/ddr.h>
+#include <image-metadata.h>
+
+#include "lowlevel.h"
+
+extern char __dtb_z_imx8mm_innocom_wb15_evk_start[];
+
+#define UART_PAD_CTRL	MUX_PAD_CTRL(PAD_CTL_DSE_3P3V_45_OHM)
+
+static void setup_uart(void)
+{
+	void __iomem *uart = IOMEM(MX8M_UART2_BASE_ADDR);
+
+	imx8m_early_setup_uart_clock();
+
+	imx8mm_setup_pad(IMX8MM_PAD_UART2_TXD_UART2_TX | UART_PAD_CTRL);
+	imx8m_uart_setup(uart);
+
+	pbl_set_putc(imx_uart_putc, uart);
+	putc_ll('>');
+}
+
+static struct pmic_config bd71837_cfg[] = {
+	/* decrease RESET key long push time from the default 10s to 10ms */
+	{ BD718XX_PWRONCONFIG1, 0x0 },
+	/* unlock the PMIC regs */
+	{ BD718XX_REGLOCK, 0x1 },
+	/* Set VDD_SOC/VDD_DRAM to typical value 0.85v for nominal mode */
+	{ BD718XX_BUCK1_VOLT_RUN, 0xf },
+	/* increase VDD_DRAM to 0.975v for 3Ghz DDR */
+	{ BD718XX_1ST_NODVS_BUCK_VOLT, 0x83 },
+	/* lock the PMIC regs */
+	{ BD718XX_REGLOCK, 0x11 },
+};
+
+void innocom_wb15_power_init_board(void)
+{
+	struct pbl_i2c *i2c;
+
+	imx8mm_setup_pad(IMX8MM_PAD_I2C1_SCL_I2C1_SCL);
+	imx8mm_setup_pad(IMX8MM_PAD_I2C1_SDA_I2C1_SDA);
+
+	imx8mm_early_clock_init();
+	imx8m_ccgr_clock_enable(IMX8M_CCM_CCGR_I2C1);
+
+	i2c = imx8m_i2c_early_init(IOMEM(MX8MQ_I2C1_BASE_ADDR));
+
+	pmic_configure(i2c, 0x4b, bd71837_cfg, ARRAY_SIZE(bd71837_cfg));
+}
+
+ENTRY_FUNCTION(start_innocom_wb15_evk, r0, r1, r2)
+{
+	IMD_USED_OF(imx8mm_innocom_wb15_evk);
+
+	imx8mm_cpu_lowlevel_init();
+
+	relocate_to_current_adr();
+	setup_c();
+
+	setup_uart();
+
+	/*
+	 * If we are in EL3 we are running for the first time out of OCRAM,
+	 * we'll need to initialize the DRAM and run TF-A (BL31). The TF-A
+	 * will then jump to DRAM in EL2
+	 */
+	if (current_el() == 3) {
+		innocom_wb15_power_init_board();
+
+		imx8mm_ddr_init(&innocom_wb15_dram_timing, DRAM_TYPE_LPDDR4);
+
+		imx8mm_load_and_start_image_via_tfa();
+	}
+
+	/* Standard entry we hit once we initialized both DDR and ATF */
+	imx8mm_barebox_entry(__dtb_z_imx8mm_innocom_wb15_evk_start);
+}
diff --git a/arch/arm/boards/innocom-imx8mm-wb15/lowlevel.h b/arch/arm/boards/innocom-imx8mm-wb15/lowlevel.h
new file mode 100644
index 0000000000..904affd087
--- /dev/null
+++ b/arch/arm/boards/innocom-imx8mm-wb15/lowlevel.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef INNOCOM_WB15_LOWLEVEL_H_
+#define INNOCOM_WB15_LOWLEVEL_H_
+
+void innocom_wb15_power_init_board(void);
+extern struct dram_timing_info innocom_wb15_dram_timing;
+
+#endif
diff --git a/arch/arm/boards/innocom-imx8mm-wb15/lpddr4-timing.c b/arch/arm/boards/innocom-imx8mm-wb15/lpddr4-timing.c
new file mode 100644
index 0000000000..0318e7fdc3
--- /dev/null
+++ b/arch/arm/boards/innocom-imx8mm-wb15/lpddr4-timing.c
@@ -0,0 +1,1856 @@
+/*
+ * Copyright 2018 InnoComm Mobile Technology Corp.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Generated code from MX8M_DDR_tool
+ * Align with uboot-imx_v2018.03_4.14.78_1.0.0_ga
+ */
+
+#include <common.h>
+#include <soc/imx8m/ddr.h>
+
+#define DDR_ONE_RANK
+#include <soc/imx8m/lpddr4_define.h>
+
+#include "lowlevel.h"
+
+static struct dram_cfg_param ddr_ddrc_cfg_1g_2ch1cs15r10cx32[] = {
+	/** Initialize DDRC registers **/
+	{0x3d400304,0x1},
+	{0x3d400030,0x1},
+	{0x3d400000,0xa1080020},
+	{0x3d400020,0x223},
+	{0x3d400024,0x2ee00},
+	{0x3d400064,0x49006c},
+	{0x3d4000d0,0xc0030495},
+	{0x3d4000d4,0x770000},
+	{0x3d4000dc,0xc40024},
+	{0x3d4000e0,0x310000},
+	{0x3d4000e8,0x66004d},
+	{0x3d4000ec,0x16004d},
+	{0x3d400100,0x1618141a},
+	{0x3d400104,0x504a6},
+	{0x3d40010c,0x909000},
+	{0x3d400110,0xb04060b},
+	{0x3d400114,0x2030909},
+	{0x3d400118,0x1010006},
+	{0x3d40011c,0x301},
+	{0x3d400130,0x20500},
+	{0x3d400134,0xb100002},
+	{0x3d400138,0x71},
+	{0x3d400144,0x78003c},
+	{0x3d400180,0x2580012},
+	{0x3d400184,0x1e0493e},
+	{0x3d400188,0x0},
+	{0x3d400190,0x4938208},
+	{0x3d400194,0x80303},
+	{0x3d4001b4,0x1308},
+	{0x3d4001a0,0xe0400018},
+	{0x3d4001a4,0xdf00e4},
+	{0x3d4001a8,0x80000000},
+	{0x3d4001b0,0x11},
+	{0x3d4001c0,0x1},
+	{0x3d4001c4,0x1},
+	{0x3d4000f4,0xc99},
+	{0x3d400108,0x60c1514},
+	{0x3d400200,0x1f},
+	{0x3d40020c,0x0},
+	{0x3d400210,0x1f1f},
+	{0x3d400204,0x80808},
+	{0x3d400214,0x7070707},
+	{0x3d400218,0xf070707},
+	{0x3d40021c,0xf0f},
+	{0x3d400250,0x29001701},
+	{0x3d400254,0x2c},
+	{0x3d40025c,0x4000030},
+	{0x3d400264,0x900093e7},
+	{0x3d40026c,0x2005574},
+	{0x3d400400,0x111},
+	{0x3d400408,0x72ff},
+	{0x3d400494,0x2100e07},
+	{0x3d400498,0x620096},
+	{0x3d40049c,0x1100e07},
+	{0x3d4004a0,0xc8012c},
+	{0x3d402020,0x21},
+	{0x3d402024,0x7d00},
+	{0x3d402050,0x20d040},
+	{0x3d402064,0xc0012},
+	{0x3d4020dc,0x840000},
+	{0x3d4020e0,0x310000},
+	{0x3d4020e8,0x66004d},
+	{0x3d4020ec,0x16004d},
+	{0x3d402100,0xa040305},
+	{0x3d402104,0x30407},
+	{0x3d402108,0x203060b},
+	{0x3d40210c,0x505000},
+	{0x3d402110,0x2040202},
+	{0x3d402114,0x2030202},
+	{0x3d402118,0x1010004},
+	{0x3d40211c,0x301},
+	{0x3d402130,0x20300},
+	{0x3d402134,0xa100002},
+	{0x3d402138,0x13},
+	{0x3d402144,0x14000a},
+	{0x3d402180,0x640004},
+	{0x3d402190,0x3818200},
+	{0x3d402194,0x80303},
+	{0x3d4021b4,0x100},
+	{0x3d4020f4,0xc99},
+	{0x3d403020,0x21},
+	{0x3d403024,0x1f40},
+	{0x3d403050,0x20d040},
+	{0x3d403064,0x30005},
+	{0x3d4030dc,0x840000},
+	{0x3d4030e0,0x310000},
+	{0x3d4030e8,0x66004d},
+	{0x3d4030ec,0x16004d},
+	{0x3d403100,0xa010102},
+	{0x3d403104,0x30404},
+	{0x3d403108,0x203060b},
+	{0x3d40310c,0x505000},
+	{0x3d403110,0x2040202},
+	{0x3d403114,0x2030202},
+	{0x3d403118,0x1010004},
+	{0x3d40311c,0x301},
+	{0x3d403130,0x20300},
+	{0x3d403134,0xa100002},
+	{0x3d403138,0x5},
+	{0x3d403144,0x50003},
+	{0x3d403180,0x190004},
+	{0x3d403190,0x3818200},
+	{0x3d403194,0x80303},
+	{0x3d4031b4,0x100},
+	{0x3d4030f4,0xc99},
+	{0x3d400028,0x0},
+};
+
+/* PHY Initialize Configuration */
+static struct dram_cfg_param ddr_ddrphy_cfg[] = {
+	{0x100a0,0x0},
+	{0x100a1,0x1},
+	{0x100a2,0x2},
+	{0x100a3,0x3},
+	{0x100a4,0x4},
+	{0x100a5,0x5},
+	{0x100a6,0x6},
+	{0x100a7,0x7},
+	{0x110a0,0x0},
+	{0x110a1,0x1},
+	{0x110a2,0x3},
+	{0x110a3,0x4},
+	{0x110a4,0x5},
+	{0x110a5,0x2},
+	{0x110a6,0x7},
+	{0x110a7,0x6},
+	{0x120a0,0x0},
+	{0x120a1,0x1},
+	{0x120a2,0x3},
+	{0x120a3,0x2},
+	{0x120a4,0x5},
+	{0x120a5,0x4},
+	{0x120a6,0x7},
+	{0x120a7,0x6},
+	{0x130a0,0x0},
+	{0x130a1,0x1},
+	{0x130a2,0x2},
+	{0x130a3,0x3},
+	{0x130a4,0x4},
+	{0x130a5,0x5},
+	{0x130a6,0x6},
+	{0x130a7,0x7},
+	{0x1005f,0x1ff},
+	{0x1015f,0x1ff},
+	{0x1105f,0x1ff},
+	{0x1115f,0x1ff},
+	{0x1205f,0x1ff},
+	{0x1215f,0x1ff},
+	{0x1305f,0x1ff},
+	{0x1315f,0x1ff},
+	{0x11005f,0x1ff},
+	{0x11015f,0x1ff},
+	{0x11105f,0x1ff},
+	{0x11115f,0x1ff},
+	{0x11205f,0x1ff},
+	{0x11215f,0x1ff},
+	{0x11305f,0x1ff},
+	{0x11315f,0x1ff},
+	{0x21005f,0x1ff},
+	{0x21015f,0x1ff},
+	{0x21105f,0x1ff},
+	{0x21115f,0x1ff},
+	{0x21205f,0x1ff},
+	{0x21215f,0x1ff},
+	{0x21305f,0x1ff},
+	{0x21315f,0x1ff},
+	{0x55,0x1ff},
+	{0x1055,0x1ff},
+	{0x2055,0x1ff},
+	{0x3055,0x1ff},
+	{0x4055,0x1ff},
+	{0x5055,0x1ff},
+	{0x6055,0x1ff},
+	{0x7055,0x1ff},
+	{0x8055,0x1ff},
+	{0x9055,0x1ff},
+	{0x200c5,0xa},
+	{0x1200c5,0x7},
+	{0x2200c5,0x7},
+	{0x2002e,0x2},
+	{0x12002e,0x2},
+	{0x22002e,0x2},
+	{0x90204,0x0},
+	{0x190204,0x0},
+	{0x290204,0x0},
+	{0x20024,0x1ab},
+	{0x2003a,0x0},
+	{0x120024,0x1ab},
+	{0x2003a,0x0},
+	{0x220024,0x1ab},
+	{0x2003a,0x0},
+	{0x20056,0x2},
+	{0x120056,0xa},
+	{0x220056,0xa},
+	{0x1004d,0xe00},
+	{0x1014d,0xe00},
+	{0x1104d,0xe00},
+	{0x1114d,0xe00},
+	{0x1204d,0xe00},
+	{0x1214d,0xe00},
+	{0x1304d,0xe00},
+	{0x1314d,0xe00},
+	{0x11004d,0xe00},
+	{0x11014d,0xe00},
+	{0x11104d,0xe00},
+	{0x11114d,0xe00},
+	{0x11204d,0xe00},
+	{0x11214d,0xe00},
+	{0x11304d,0xe00},
+	{0x11314d,0xe00},
+	{0x21004d,0xe00},
+	{0x21014d,0xe00},
+	{0x21104d,0xe00},
+	{0x21114d,0xe00},
+	{0x21204d,0xe00},
+	{0x21214d,0xe00},
+	{0x21304d,0xe00},
+	{0x21314d,0xe00},
+	{0x10049,0xeba},
+	{0x10149,0xeba},
+	{0x11049,0xeba},
+	{0x11149,0xeba},
+	{0x12049,0xeba},
+	{0x12149,0xeba},
+	{0x13049,0xeba},
+	{0x13149,0xeba},
+	{0x110049,0xeba},
+	{0x110149,0xeba},
+	{0x111049,0xeba},
+	{0x111149,0xeba},
+	{0x112049,0xeba},
+	{0x112149,0xeba},
+	{0x113049,0xeba},
+	{0x113149,0xeba},
+	{0x210049,0xeba},
+	{0x210149,0xeba},
+	{0x211049,0xeba},
+	{0x211149,0xeba},
+	{0x212049,0xeba},
+	{0x212149,0xeba},
+	{0x213049,0xeba},
+	{0x213149,0xeba},
+	{0x43,0x63},
+	{0x1043,0x63},
+	{0x2043,0x63},
+	{0x3043,0x63},
+	{0x4043,0x63},
+	{0x5043,0x63},
+	{0x6043,0x63},
+	{0x7043,0x63},
+	{0x8043,0x63},
+	{0x9043,0x63},
+	{0x20018,0x3},
+	{0x20075,0x4},
+	{0x20050,0x0},
+	{0x20008,0x258},
+	{0x120008,0x64},
+	{0x220008,0x19},
+	{0x20088,0x9},
+	{0x200b2,0xdc},
+	{0x10043,0x5a1},
+	{0x10143,0x5a1},
+	{0x11043,0x5a1},
+	{0x11143,0x5a1},
+	{0x12043,0x5a1},
+	{0x12143,0x5a1},
+	{0x13043,0x5a1},
+	{0x13143,0x5a1},
+	{0x1200b2,0xdc},
+	{0x110043,0x5a1},
+	{0x110143,0x5a1},
+	{0x111043,0x5a1},
+	{0x111143,0x5a1},
+	{0x112043,0x5a1},
+	{0x112143,0x5a1},
+	{0x113043,0x5a1},
+	{0x113143,0x5a1},
+	{0x2200b2,0xdc},
+	{0x210043,0x5a1},
+	{0x210143,0x5a1},
+	{0x211043,0x5a1},
+	{0x211143,0x5a1},
+	{0x212043,0x5a1},
+	{0x212143,0x5a1},
+	{0x213043,0x5a1},
+	{0x213143,0x5a1},
+	{0x200fa,0x1},
+	{0x1200fa,0x1},
+	{0x2200fa,0x1},
+	{0x20019,0x1},
+	{0x120019,0x1},
+	{0x220019,0x1},
+	{0x200f0,0x660},
+	{0x200f1,0x0},
+	{0x200f2,0x4444},
+	{0x200f3,0x8888},
+	{0x200f4,0x5665},
+	{0x200f5,0x0},
+	{0x200f6,0x0},
+	{0x200f7,0xf000},
+	{0x20025,0x0},
+	{0x2002d,0x0},
+	{0x12002d,0x0},
+	{0x22002d,0x0},
+	{0x200c7,0x21},
+	{0x1200c7,0x21},
+	{0x2200c7,0x21},
+	{0x200ca,0x24},
+	{0x1200ca,0x24},
+	{0x2200ca,0x24},
+};
+
+/* ddr phy trained csr */
+static struct dram_cfg_param ddr_ddrphy_trained_csr[] = {
+	{ 0x200b2, 0x0 },
+	{ 0x1200b2, 0x0 },
+	{ 0x2200b2, 0x0 },
+	{ 0x200cb, 0x0 },
+	{ 0x10043, 0x0 },
+	{ 0x110043, 0x0 },
+	{ 0x210043, 0x0 },
+	{ 0x10143, 0x0 },
+	{ 0x110143, 0x0 },
+	{ 0x210143, 0x0 },
+	{ 0x11043, 0x0 },
+	{ 0x111043, 0x0 },
+	{ 0x211043, 0x0 },
+	{ 0x11143, 0x0 },
+	{ 0x111143, 0x0 },
+	{ 0x211143, 0x0 },
+	{ 0x12043, 0x0 },
+	{ 0x112043, 0x0 },
+	{ 0x212043, 0x0 },
+	{ 0x12143, 0x0 },
+	{ 0x112143, 0x0 },
+	{ 0x212143, 0x0 },
+	{ 0x13043, 0x0 },
+	{ 0x113043, 0x0 },
+	{ 0x213043, 0x0 },
+	{ 0x13143, 0x0 },
+	{ 0x113143, 0x0 },
+	{ 0x213143, 0x0 },
+	{ 0x80, 0x0 },
+	{ 0x100080, 0x0 },
+	{ 0x200080, 0x0 },
+	{ 0x1080, 0x0 },
+	{ 0x101080, 0x0 },
+	{ 0x201080, 0x0 },
+	{ 0x2080, 0x0 },
+	{ 0x102080, 0x0 },
+	{ 0x202080, 0x0 },
+	{ 0x3080, 0x0 },
+	{ 0x103080, 0x0 },
+	{ 0x203080, 0x0 },
+	{ 0x4080, 0x0 },
+	{ 0x104080, 0x0 },
+	{ 0x204080, 0x0 },
+	{ 0x5080, 0x0 },
+	{ 0x105080, 0x0 },
+	{ 0x205080, 0x0 },
+	{ 0x6080, 0x0 },
+	{ 0x106080, 0x0 },
+	{ 0x206080, 0x0 },
+	{ 0x7080, 0x0 },
+	{ 0x107080, 0x0 },
+	{ 0x207080, 0x0 },
+	{ 0x8080, 0x0 },
+	{ 0x108080, 0x0 },
+	{ 0x208080, 0x0 },
+	{ 0x9080, 0x0 },
+	{ 0x109080, 0x0 },
+	{ 0x209080, 0x0 },
+	{ 0x10080, 0x0 },
+	{ 0x110080, 0x0 },
+	{ 0x210080, 0x0 },
+	{ 0x10180, 0x0 },
+	{ 0x110180, 0x0 },
+	{ 0x210180, 0x0 },
+	{ 0x11080, 0x0 },
+	{ 0x111080, 0x0 },
+	{ 0x211080, 0x0 },
+	{ 0x11180, 0x0 },
+	{ 0x111180, 0x0 },
+	{ 0x211180, 0x0 },
+	{ 0x12080, 0x0 },
+	{ 0x112080, 0x0 },
+	{ 0x212080, 0x0 },
+	{ 0x12180, 0x0 },
+	{ 0x112180, 0x0 },
+	{ 0x212180, 0x0 },
+	{ 0x13080, 0x0 },
+	{ 0x113080, 0x0 },
+	{ 0x213080, 0x0 },
+	{ 0x13180, 0x0 },
+	{ 0x113180, 0x0 },
+	{ 0x213180, 0x0 },
+	{ 0x10081, 0x0 },
+	{ 0x110081, 0x0 },
+	{ 0x210081, 0x0 },
+	{ 0x10181, 0x0 },
+	{ 0x110181, 0x0 },
+	{ 0x210181, 0x0 },
+	{ 0x11081, 0x0 },
+	{ 0x111081, 0x0 },
+	{ 0x211081, 0x0 },
+	{ 0x11181, 0x0 },
+	{ 0x111181, 0x0 },
+	{ 0x211181, 0x0 },
+	{ 0x12081, 0x0 },
+	{ 0x112081, 0x0 },
+	{ 0x212081, 0x0 },
+	{ 0x12181, 0x0 },
+	{ 0x112181, 0x0 },
+	{ 0x212181, 0x0 },
+	{ 0x13081, 0x0 },
+	{ 0x113081, 0x0 },
+	{ 0x213081, 0x0 },
+	{ 0x13181, 0x0 },
+	{ 0x113181, 0x0 },
+	{ 0x213181, 0x0 },
+	{ 0x100d0, 0x0 },
+	{ 0x1100d0, 0x0 },
+	{ 0x2100d0, 0x0 },
+	{ 0x101d0, 0x0 },
+	{ 0x1101d0, 0x0 },
+	{ 0x2101d0, 0x0 },
+	{ 0x110d0, 0x0 },
+	{ 0x1110d0, 0x0 },
+	{ 0x2110d0, 0x0 },
+	{ 0x111d0, 0x0 },
+	{ 0x1111d0, 0x0 },
+	{ 0x2111d0, 0x0 },
+	{ 0x120d0, 0x0 },
+	{ 0x1120d0, 0x0 },
+	{ 0x2120d0, 0x0 },
+	{ 0x121d0, 0x0 },
+	{ 0x1121d0, 0x0 },
+	{ 0x2121d0, 0x0 },
+	{ 0x130d0, 0x0 },
+	{ 0x1130d0, 0x0 },
+	{ 0x2130d0, 0x0 },
+	{ 0x131d0, 0x0 },
+	{ 0x1131d0, 0x0 },
+	{ 0x2131d0, 0x0 },
+	{ 0x100d1, 0x0 },
+	{ 0x1100d1, 0x0 },
+	{ 0x2100d1, 0x0 },
+	{ 0x101d1, 0x0 },
+	{ 0x1101d1, 0x0 },
+	{ 0x2101d1, 0x0 },
+	{ 0x110d1, 0x0 },
+	{ 0x1110d1, 0x0 },
+	{ 0x2110d1, 0x0 },
+	{ 0x111d1, 0x0 },
+	{ 0x1111d1, 0x0 },
+	{ 0x2111d1, 0x0 },
+	{ 0x120d1, 0x0 },
+	{ 0x1120d1, 0x0 },
+	{ 0x2120d1, 0x0 },
+	{ 0x121d1, 0x0 },
+	{ 0x1121d1, 0x0 },
+	{ 0x2121d1, 0x0 },
+	{ 0x130d1, 0x0 },
+	{ 0x1130d1, 0x0 },
+	{ 0x2130d1, 0x0 },
+	{ 0x131d1, 0x0 },
+	{ 0x1131d1, 0x0 },
+	{ 0x2131d1, 0x0 },
+	{ 0x10068, 0x0 },
+	{ 0x10168, 0x0 },
+	{ 0x10268, 0x0 },
+	{ 0x10368, 0x0 },
+	{ 0x10468, 0x0 },
+	{ 0x10568, 0x0 },
+	{ 0x10668, 0x0 },
+	{ 0x10768, 0x0 },
+	{ 0x10868, 0x0 },
+	{ 0x11068, 0x0 },
+	{ 0x11168, 0x0 },
+	{ 0x11268, 0x0 },
+	{ 0x11368, 0x0 },
+	{ 0x11468, 0x0 },
+	{ 0x11568, 0x0 },
+	{ 0x11668, 0x0 },
+	{ 0x11768, 0x0 },
+	{ 0x11868, 0x0 },
+	{ 0x12068, 0x0 },
+	{ 0x12168, 0x0 },
+	{ 0x12268, 0x0 },
+	{ 0x12368, 0x0 },
+	{ 0x12468, 0x0 },
+	{ 0x12568, 0x0 },
+	{ 0x12668, 0x0 },
+	{ 0x12768, 0x0 },
+	{ 0x12868, 0x0 },
+	{ 0x13068, 0x0 },
+	{ 0x13168, 0x0 },
+	{ 0x13268, 0x0 },
+	{ 0x13368, 0x0 },
+	{ 0x13468, 0x0 },
+	{ 0x13568, 0x0 },
+	{ 0x13668, 0x0 },
+	{ 0x13768, 0x0 },
+	{ 0x13868, 0x0 },
+	{ 0x10069, 0x0 },
+	{ 0x10169, 0x0 },
+	{ 0x10269, 0x0 },
+	{ 0x10369, 0x0 },
+	{ 0x10469, 0x0 },
+	{ 0x10569, 0x0 },
+	{ 0x10669, 0x0 },
+	{ 0x10769, 0x0 },
+	{ 0x10869, 0x0 },
+	{ 0x11069, 0x0 },
+	{ 0x11169, 0x0 },
+	{ 0x11269, 0x0 },
+	{ 0x11369, 0x0 },
+	{ 0x11469, 0x0 },
+	{ 0x11569, 0x0 },
+	{ 0x11669, 0x0 },
+	{ 0x11769, 0x0 },
+	{ 0x11869, 0x0 },
+	{ 0x12069, 0x0 },
+	{ 0x12169, 0x0 },
+	{ 0x12269, 0x0 },
+	{ 0x12369, 0x0 },
+	{ 0x12469, 0x0 },
+	{ 0x12569, 0x0 },
+	{ 0x12669, 0x0 },
+	{ 0x12769, 0x0 },
+	{ 0x12869, 0x0 },
+	{ 0x13069, 0x0 },
+	{ 0x13169, 0x0 },
+	{ 0x13269, 0x0 },
+	{ 0x13369, 0x0 },
+	{ 0x13469, 0x0 },
+	{ 0x13569, 0x0 },
+	{ 0x13669, 0x0 },
+	{ 0x13769, 0x0 },
+	{ 0x13869, 0x0 },
+	{ 0x1008c, 0x0 },
+	{ 0x11008c, 0x0 },
+	{ 0x21008c, 0x0 },
+	{ 0x1018c, 0x0 },
+	{ 0x11018c, 0x0 },
+	{ 0x21018c, 0x0 },
+	{ 0x1108c, 0x0 },
+	{ 0x11108c, 0x0 },
+	{ 0x21108c, 0x0 },
+	{ 0x1118c, 0x0 },
+	{ 0x11118c, 0x0 },
+	{ 0x21118c, 0x0 },
+	{ 0x1208c, 0x0 },
+	{ 0x11208c, 0x0 },
+	{ 0x21208c, 0x0 },
+	{ 0x1218c, 0x0 },
+	{ 0x11218c, 0x0 },
+	{ 0x21218c, 0x0 },
+	{ 0x1308c, 0x0 },
+	{ 0x11308c, 0x0 },
+	{ 0x21308c, 0x0 },
+	{ 0x1318c, 0x0 },
+	{ 0x11318c, 0x0 },
+	{ 0x21318c, 0x0 },
+	{ 0x1008d, 0x0 },
+	{ 0x11008d, 0x0 },
+	{ 0x21008d, 0x0 },
+	{ 0x1018d, 0x0 },
+	{ 0x11018d, 0x0 },
+	{ 0x21018d, 0x0 },
+	{ 0x1108d, 0x0 },
+	{ 0x11108d, 0x0 },
+	{ 0x21108d, 0x0 },
+	{ 0x1118d, 0x0 },
+	{ 0x11118d, 0x0 },
+	{ 0x21118d, 0x0 },
+	{ 0x1208d, 0x0 },
+	{ 0x11208d, 0x0 },
+	{ 0x21208d, 0x0 },
+	{ 0x1218d, 0x0 },
+	{ 0x11218d, 0x0 },
+	{ 0x21218d, 0x0 },
+	{ 0x1308d, 0x0 },
+	{ 0x11308d, 0x0 },
+	{ 0x21308d, 0x0 },
+	{ 0x1318d, 0x0 },
+	{ 0x11318d, 0x0 },
+	{ 0x21318d, 0x0 },
+	{ 0x100c0, 0x0 },
+	{ 0x1100c0, 0x0 },
+	{ 0x2100c0, 0x0 },
+	{ 0x101c0, 0x0 },
+	{ 0x1101c0, 0x0 },
+	{ 0x2101c0, 0x0 },
+	{ 0x102c0, 0x0 },
+	{ 0x1102c0, 0x0 },
+	{ 0x2102c0, 0x0 },
+	{ 0x103c0, 0x0 },
+	{ 0x1103c0, 0x0 },
+	{ 0x2103c0, 0x0 },
+	{ 0x104c0, 0x0 },
+	{ 0x1104c0, 0x0 },
+	{ 0x2104c0, 0x0 },
+	{ 0x105c0, 0x0 },
+	{ 0x1105c0, 0x0 },
+	{ 0x2105c0, 0x0 },
+	{ 0x106c0, 0x0 },
+	{ 0x1106c0, 0x0 },
+	{ 0x2106c0, 0x0 },
+	{ 0x107c0, 0x0 },
+	{ 0x1107c0, 0x0 },
+	{ 0x2107c0, 0x0 },
+	{ 0x108c0, 0x0 },
+	{ 0x1108c0, 0x0 },
+	{ 0x2108c0, 0x0 },
+	{ 0x110c0, 0x0 },
+	{ 0x1110c0, 0x0 },
+	{ 0x2110c0, 0x0 },
+	{ 0x111c0, 0x0 },
+	{ 0x1111c0, 0x0 },
+	{ 0x2111c0, 0x0 },
+	{ 0x112c0, 0x0 },
+	{ 0x1112c0, 0x0 },
+	{ 0x2112c0, 0x0 },
+	{ 0x113c0, 0x0 },
+	{ 0x1113c0, 0x0 },
+	{ 0x2113c0, 0x0 },
+	{ 0x114c0, 0x0 },
+	{ 0x1114c0, 0x0 },
+	{ 0x2114c0, 0x0 },
+	{ 0x115c0, 0x0 },
+	{ 0x1115c0, 0x0 },
+	{ 0x2115c0, 0x0 },
+	{ 0x116c0, 0x0 },
+	{ 0x1116c0, 0x0 },
+	{ 0x2116c0, 0x0 },
+	{ 0x117c0, 0x0 },
+	{ 0x1117c0, 0x0 },
+	{ 0x2117c0, 0x0 },
+	{ 0x118c0, 0x0 },
+	{ 0x1118c0, 0x0 },
+	{ 0x2118c0, 0x0 },
+	{ 0x120c0, 0x0 },
+	{ 0x1120c0, 0x0 },
+	{ 0x2120c0, 0x0 },
+	{ 0x121c0, 0x0 },
+	{ 0x1121c0, 0x0 },
+	{ 0x2121c0, 0x0 },
+	{ 0x122c0, 0x0 },
+	{ 0x1122c0, 0x0 },
+	{ 0x2122c0, 0x0 },
+	{ 0x123c0, 0x0 },
+	{ 0x1123c0, 0x0 },
+	{ 0x2123c0, 0x0 },
+	{ 0x124c0, 0x0 },
+	{ 0x1124c0, 0x0 },
+	{ 0x2124c0, 0x0 },
+	{ 0x125c0, 0x0 },
+	{ 0x1125c0, 0x0 },
+	{ 0x2125c0, 0x0 },
+	{ 0x126c0, 0x0 },
+	{ 0x1126c0, 0x0 },
+	{ 0x2126c0, 0x0 },
+	{ 0x127c0, 0x0 },
+	{ 0x1127c0, 0x0 },
+	{ 0x2127c0, 0x0 },
+	{ 0x128c0, 0x0 },
+	{ 0x1128c0, 0x0 },
+	{ 0x2128c0, 0x0 },
+	{ 0x130c0, 0x0 },
+	{ 0x1130c0, 0x0 },
+	{ 0x2130c0, 0x0 },
+	{ 0x131c0, 0x0 },
+	{ 0x1131c0, 0x0 },
+	{ 0x2131c0, 0x0 },
+	{ 0x132c0, 0x0 },
+	{ 0x1132c0, 0x0 },
+	{ 0x2132c0, 0x0 },
+	{ 0x133c0, 0x0 },
+	{ 0x1133c0, 0x0 },
+	{ 0x2133c0, 0x0 },
+	{ 0x134c0, 0x0 },
+	{ 0x1134c0, 0x0 },
+	{ 0x2134c0, 0x0 },
+	{ 0x135c0, 0x0 },
+	{ 0x1135c0, 0x0 },
+	{ 0x2135c0, 0x0 },
+	{ 0x136c0, 0x0 },
+	{ 0x1136c0, 0x0 },
+	{ 0x2136c0, 0x0 },
+	{ 0x137c0, 0x0 },
+	{ 0x1137c0, 0x0 },
+	{ 0x2137c0, 0x0 },
+	{ 0x138c0, 0x0 },
+	{ 0x1138c0, 0x0 },
+	{ 0x2138c0, 0x0 },
+	{ 0x100c1, 0x0 },
+	{ 0x1100c1, 0x0 },
+	{ 0x2100c1, 0x0 },
+	{ 0x101c1, 0x0 },
+	{ 0x1101c1, 0x0 },
+	{ 0x2101c1, 0x0 },
+	{ 0x102c1, 0x0 },
+	{ 0x1102c1, 0x0 },
+	{ 0x2102c1, 0x0 },
+	{ 0x103c1, 0x0 },
+	{ 0x1103c1, 0x0 },
+	{ 0x2103c1, 0x0 },
+	{ 0x104c1, 0x0 },
+	{ 0x1104c1, 0x0 },
+	{ 0x2104c1, 0x0 },
+	{ 0x105c1, 0x0 },
+	{ 0x1105c1, 0x0 },
+	{ 0x2105c1, 0x0 },
+	{ 0x106c1, 0x0 },
+	{ 0x1106c1, 0x0 },
+	{ 0x2106c1, 0x0 },
+	{ 0x107c1, 0x0 },
+	{ 0x1107c1, 0x0 },
+	{ 0x2107c1, 0x0 },
+	{ 0x108c1, 0x0 },
+	{ 0x1108c1, 0x0 },
+	{ 0x2108c1, 0x0 },
+	{ 0x110c1, 0x0 },
+	{ 0x1110c1, 0x0 },
+	{ 0x2110c1, 0x0 },
+	{ 0x111c1, 0x0 },
+	{ 0x1111c1, 0x0 },
+	{ 0x2111c1, 0x0 },
+	{ 0x112c1, 0x0 },
+	{ 0x1112c1, 0x0 },
+	{ 0x2112c1, 0x0 },
+	{ 0x113c1, 0x0 },
+	{ 0x1113c1, 0x0 },
+	{ 0x2113c1, 0x0 },
+	{ 0x114c1, 0x0 },
+	{ 0x1114c1, 0x0 },
+	{ 0x2114c1, 0x0 },
+	{ 0x115c1, 0x0 },
+	{ 0x1115c1, 0x0 },
+	{ 0x2115c1, 0x0 },
+	{ 0x116c1, 0x0 },
+	{ 0x1116c1, 0x0 },
+	{ 0x2116c1, 0x0 },
+	{ 0x117c1, 0x0 },
+	{ 0x1117c1, 0x0 },
+	{ 0x2117c1, 0x0 },
+	{ 0x118c1, 0x0 },
+	{ 0x1118c1, 0x0 },
+	{ 0x2118c1, 0x0 },
+	{ 0x120c1, 0x0 },
+	{ 0x1120c1, 0x0 },
+	{ 0x2120c1, 0x0 },
+	{ 0x121c1, 0x0 },
+	{ 0x1121c1, 0x0 },
+	{ 0x2121c1, 0x0 },
+	{ 0x122c1, 0x0 },
+	{ 0x1122c1, 0x0 },
+	{ 0x2122c1, 0x0 },
+	{ 0x123c1, 0x0 },
+	{ 0x1123c1, 0x0 },
+	{ 0x2123c1, 0x0 },
+	{ 0x124c1, 0x0 },
+	{ 0x1124c1, 0x0 },
+	{ 0x2124c1, 0x0 },
+	{ 0x125c1, 0x0 },
+	{ 0x1125c1, 0x0 },
+	{ 0x2125c1, 0x0 },
+	{ 0x126c1, 0x0 },
+	{ 0x1126c1, 0x0 },
+	{ 0x2126c1, 0x0 },
+	{ 0x127c1, 0x0 },
+	{ 0x1127c1, 0x0 },
+	{ 0x2127c1, 0x0 },
+	{ 0x128c1, 0x0 },
+	{ 0x1128c1, 0x0 },
+	{ 0x2128c1, 0x0 },
+	{ 0x130c1, 0x0 },
+	{ 0x1130c1, 0x0 },
+	{ 0x2130c1, 0x0 },
+	{ 0x131c1, 0x0 },
+	{ 0x1131c1, 0x0 },
+	{ 0x2131c1, 0x0 },
+	{ 0x132c1, 0x0 },
+	{ 0x1132c1, 0x0 },
+	{ 0x2132c1, 0x0 },
+	{ 0x133c1, 0x0 },
+	{ 0x1133c1, 0x0 },
+	{ 0x2133c1, 0x0 },
+	{ 0x134c1, 0x0 },
+	{ 0x1134c1, 0x0 },
+	{ 0x2134c1, 0x0 },
+	{ 0x135c1, 0x0 },
+	{ 0x1135c1, 0x0 },
+	{ 0x2135c1, 0x0 },
+	{ 0x136c1, 0x0 },
+	{ 0x1136c1, 0x0 },
+	{ 0x2136c1, 0x0 },
+	{ 0x137c1, 0x0 },
+	{ 0x1137c1, 0x0 },
+	{ 0x2137c1, 0x0 },
+	{ 0x138c1, 0x0 },
+	{ 0x1138c1, 0x0 },
+	{ 0x2138c1, 0x0 },
+	{ 0x10020, 0x0 },
+	{ 0x110020, 0x0 },
+	{ 0x210020, 0x0 },
+	{ 0x11020, 0x0 },
+	{ 0x111020, 0x0 },
+	{ 0x211020, 0x0 },
+	{ 0x12020, 0x0 },
+	{ 0x112020, 0x0 },
+	{ 0x212020, 0x0 },
+	{ 0x13020, 0x0 },
+	{ 0x113020, 0x0 },
+	{ 0x213020, 0x0 },
+	{ 0x20072, 0x0 },
+	{ 0x20073, 0x0 },
+	{ 0x20074, 0x0 },
+	{ 0x100aa, 0x0 },
+	{ 0x110aa, 0x0 },
+	{ 0x120aa, 0x0 },
+	{ 0x130aa, 0x0 },
+	{ 0x20010, 0x0 },
+	{ 0x120010, 0x0 },
+	{ 0x220010, 0x0 },
+	{ 0x20011, 0x0 },
+	{ 0x120011, 0x0 },
+	{ 0x220011, 0x0 },
+	{ 0x100ae, 0x0 },
+	{ 0x1100ae, 0x0 },
+	{ 0x2100ae, 0x0 },
+	{ 0x100af, 0x0 },
+	{ 0x1100af, 0x0 },
+	{ 0x2100af, 0x0 },
+	{ 0x110ae, 0x0 },
+	{ 0x1110ae, 0x0 },
+	{ 0x2110ae, 0x0 },
+	{ 0x110af, 0x0 },
+	{ 0x1110af, 0x0 },
+	{ 0x2110af, 0x0 },
+	{ 0x120ae, 0x0 },
+	{ 0x1120ae, 0x0 },
+	{ 0x2120ae, 0x0 },
+	{ 0x120af, 0x0 },
+	{ 0x1120af, 0x0 },
+	{ 0x2120af, 0x0 },
+	{ 0x130ae, 0x0 },
+	{ 0x1130ae, 0x0 },
+	{ 0x2130ae, 0x0 },
+	{ 0x130af, 0x0 },
+	{ 0x1130af, 0x0 },
+	{ 0x2130af, 0x0 },
+	{ 0x20020, 0x0 },
+	{ 0x120020, 0x0 },
+	{ 0x220020, 0x0 },
+	{ 0x100a0, 0x0 },
+	{ 0x100a1, 0x0 },
+	{ 0x100a2, 0x0 },
+	{ 0x100a3, 0x0 },
+	{ 0x100a4, 0x0 },
+	{ 0x100a5, 0x0 },
+	{ 0x100a6, 0x0 },
+	{ 0x100a7, 0x0 },
+	{ 0x110a0, 0x0 },
+	{ 0x110a1, 0x0 },
+	{ 0x110a2, 0x0 },
+	{ 0x110a3, 0x0 },
+	{ 0x110a4, 0x0 },
+	{ 0x110a5, 0x0 },
+	{ 0x110a6, 0x0 },
+	{ 0x110a7, 0x0 },
+	{ 0x120a0, 0x0 },
+	{ 0x120a1, 0x0 },
+	{ 0x120a2, 0x0 },
+	{ 0x120a3, 0x0 },
+	{ 0x120a4, 0x0 },
+	{ 0x120a5, 0x0 },
+	{ 0x120a6, 0x0 },
+	{ 0x120a7, 0x0 },
+	{ 0x130a0, 0x0 },
+	{ 0x130a1, 0x0 },
+	{ 0x130a2, 0x0 },
+	{ 0x130a3, 0x0 },
+	{ 0x130a4, 0x0 },
+	{ 0x130a5, 0x0 },
+	{ 0x130a6, 0x0 },
+	{ 0x130a7, 0x0 },
+	{ 0x2007c, 0x0 },
+	{ 0x12007c, 0x0 },
+	{ 0x22007c, 0x0 },
+	{ 0x2007d, 0x0 },
+	{ 0x12007d, 0x0 },
+	{ 0x22007d, 0x0 },
+	{ 0x400fd, 0x0 },
+	{ 0x400c0, 0x0 },
+	{ 0x90201, 0x0 },
+	{ 0x190201, 0x0 },
+	{ 0x290201, 0x0 },
+	{ 0x90202, 0x0 },
+	{ 0x190202, 0x0 },
+	{ 0x290202, 0x0 },
+	{ 0x90203, 0x0 },
+	{ 0x190203, 0x0 },
+	{ 0x290203, 0x0 },
+	{ 0x90204, 0x0 },
+	{ 0x190204, 0x0 },
+	{ 0x290204, 0x0 },
+	{ 0x90205, 0x0 },
+	{ 0x190205, 0x0 },
+	{ 0x290205, 0x0 },
+	{ 0x90206, 0x0 },
+	{ 0x190206, 0x0 },
+	{ 0x290206, 0x0 },
+	{ 0x90207, 0x0 },
+	{ 0x190207, 0x0 },
+	{ 0x290207, 0x0 },
+	{ 0x90208, 0x0 },
+	{ 0x190208, 0x0 },
+	{ 0x290208, 0x0 },
+	{ 0x10062, 0x0 },
+	{ 0x10162, 0x0 },
+	{ 0x10262, 0x0 },
+	{ 0x10362, 0x0 },
+	{ 0x10462, 0x0 },
+	{ 0x10562, 0x0 },
+	{ 0x10662, 0x0 },
+	{ 0x10762, 0x0 },
+	{ 0x10862, 0x0 },
+	{ 0x11062, 0x0 },
+	{ 0x11162, 0x0 },
+	{ 0x11262, 0x0 },
+	{ 0x11362, 0x0 },
+	{ 0x11462, 0x0 },
+	{ 0x11562, 0x0 },
+	{ 0x11662, 0x0 },
+	{ 0x11762, 0x0 },
+	{ 0x11862, 0x0 },
+	{ 0x12062, 0x0 },
+	{ 0x12162, 0x0 },
+	{ 0x12262, 0x0 },
+	{ 0x12362, 0x0 },
+	{ 0x12462, 0x0 },
+	{ 0x12562, 0x0 },
+	{ 0x12662, 0x0 },
+	{ 0x12762, 0x0 },
+	{ 0x12862, 0x0 },
+	{ 0x13062, 0x0 },
+	{ 0x13162, 0x0 },
+	{ 0x13262, 0x0 },
+	{ 0x13362, 0x0 },
+	{ 0x13462, 0x0 },
+	{ 0x13562, 0x0 },
+	{ 0x13662, 0x0 },
+	{ 0x13762, 0x0 },
+	{ 0x13862, 0x0 },
+	{ 0x20077, 0x0 },
+	{ 0x10001, 0x0 },
+	{ 0x11001, 0x0 },
+	{ 0x12001, 0x0 },
+	{ 0x13001, 0x0 },
+	{ 0x10040, 0x0 },
+	{ 0x10140, 0x0 },
+	{ 0x10240, 0x0 },
+	{ 0x10340, 0x0 },
+	{ 0x10440, 0x0 },
+	{ 0x10540, 0x0 },
+	{ 0x10640, 0x0 },
+	{ 0x10740, 0x0 },
+	{ 0x10840, 0x0 },
+	{ 0x10030, 0x0 },
+	{ 0x10130, 0x0 },
+	{ 0x10230, 0x0 },
+	{ 0x10330, 0x0 },
+	{ 0x10430, 0x0 },
+	{ 0x10530, 0x0 },
+	{ 0x10630, 0x0 },
+	{ 0x10730, 0x0 },
+	{ 0x10830, 0x0 },
+	{ 0x11040, 0x0 },
+	{ 0x11140, 0x0 },
+	{ 0x11240, 0x0 },
+	{ 0x11340, 0x0 },
+	{ 0x11440, 0x0 },
+	{ 0x11540, 0x0 },
+	{ 0x11640, 0x0 },
+	{ 0x11740, 0x0 },
+	{ 0x11840, 0x0 },
+	{ 0x11030, 0x0 },
+	{ 0x11130, 0x0 },
+	{ 0x11230, 0x0 },
+	{ 0x11330, 0x0 },
+	{ 0x11430, 0x0 },
+	{ 0x11530, 0x0 },
+	{ 0x11630, 0x0 },
+	{ 0x11730, 0x0 },
+	{ 0x11830, 0x0 },
+	{ 0x12040, 0x0 },
+	{ 0x12140, 0x0 },
+	{ 0x12240, 0x0 },
+	{ 0x12340, 0x0 },
+	{ 0x12440, 0x0 },
+	{ 0x12540, 0x0 },
+	{ 0x12640, 0x0 },
+	{ 0x12740, 0x0 },
+	{ 0x12840, 0x0 },
+	{ 0x12030, 0x0 },
+	{ 0x12130, 0x0 },
+	{ 0x12230, 0x0 },
+	{ 0x12330, 0x0 },
+	{ 0x12430, 0x0 },
+	{ 0x12530, 0x0 },
+	{ 0x12630, 0x0 },
+	{ 0x12730, 0x0 },
+	{ 0x12830, 0x0 },
+	{ 0x13040, 0x0 },
+	{ 0x13140, 0x0 },
+	{ 0x13240, 0x0 },
+	{ 0x13340, 0x0 },
+	{ 0x13440, 0x0 },
+	{ 0x13540, 0x0 },
+	{ 0x13640, 0x0 },
+	{ 0x13740, 0x0 },
+	{ 0x13840, 0x0 },
+	{ 0x13030, 0x0 },
+	{ 0x13130, 0x0 },
+	{ 0x13230, 0x0 },
+	{ 0x13330, 0x0 },
+	{ 0x13430, 0x0 },
+	{ 0x13530, 0x0 },
+	{ 0x13630, 0x0 },
+	{ 0x13730, 0x0 },
+	{ 0x13830, 0x0 },
+};
+/* P0 message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp0_cfg_1g_2ch1cs15r10cx32[] = {
+	{0xd0000, 0x0},
+	{0x54003,0x960},
+	{0x54004,0x2},
+	{0x54005,0x2228},
+	{0x54006,0x11},
+	{0x54008,0x131f},
+	{0x54009,0xc8},
+	{0x5400b,0x2},
+	{0x5400d,0x100},
+	{0x54012,0x110},
+	{0x54019,0x24c4},
+	{0x5401a,0x31},
+	{0x5401b,0x4d66},
+	{0x5401c,0x4d00},
+	{0x5401e,0x16},
+	{0x5401f,0x24c4},
+	{0x54020,0x31},
+	{0x54021,0x4d66},
+	{0x54022,0x4d00},
+	{0x54024,0x16},
+	{0x5402b,0x1000},
+	{0x5402c,0x1},
+	{0x54032,0xc400},
+	{0x54033,0x3124},
+	{0x54034,0x6600},
+	{0x54035,0x4d},
+	{0x54036,0x4d},
+	{0x54037,0x1600},
+	{0x54038,0xc400},
+	{0x54039,0x3124},
+	{0x5403a,0x6600},
+	{0x5403b,0x4d},
+	{0x5403c,0x4d},
+	{0x5403d,0x1600},
+	{0xd0000, 0x1},
+};
+
+
+/* P1 message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp1_cfg_1g_2ch1cs15r10cx32[] = {
+	{0xd0000, 0x0},
+	{0x54002,0x101},
+	{0x54003,0x190},
+	{0x54004,0x2},
+	{0x54005,0x2228},
+	{0x54006,0x11},
+	{0x54008,0x121f},
+	{0x54009,0xc8},
+	{0x5400b,0x2},
+	{0x5400d,0x100},
+	{0x54012,0x110},
+	{0x54019,0x84},
+	{0x5401a,0x31},
+	{0x5401b,0x4d66},
+	{0x5401c,0x4d00},
+	{0x5401e,0x16},
+	{0x5401f,0x84},
+	{0x54020,0x31},
+	{0x54021,0x4d66},
+	{0x54022,0x4d00},
+	{0x54024,0x16},
+	{0x5402b,0x1000},
+	{0x5402c,0x1},
+	{0x54032,0x8400},
+	{0x54033,0x3100},
+	{0x54034,0x6600},
+	{0x54035,0x4d},
+	{0x54036,0x4d},
+	{0x54037,0x1600},
+	{0x54038,0x8400},
+	{0x54039,0x3100},
+	{0x5403a,0x6600},
+	{0x5403b,0x4d},
+	{0x5403c,0x4d},
+	{0x5403d,0x1600},
+	{0xd0000, 0x1},
+};
+
+
+/* P2 message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp2_cfg_1g_2ch1cs15r10cx32[] = {
+	{0xd0000, 0x0},
+	{0x54002,0x102},
+	{0x54003,0x64},
+	{0x54004,0x2},
+	{0x54005,0x2228},
+	{0x54006,0x11},
+	{0x54008,0x121f},
+	{0x54009,0xc8},
+	{0x5400b,0x2},
+	{0x5400d,0x100},
+	{0x54012,0x110},
+	{0x54019,0x84},
+	{0x5401a,0x31},
+	{0x5401b,0x4d66},
+	{0x5401c,0x4d00},
+	{0x5401e,0x16},
+	{0x5401f,0x84},
+	{0x54020,0x31},
+	{0x54021,0x4d66},
+	{0x54022,0x4d00},
+	{0x54024,0x16},
+	{0x5402b,0x1000},
+	{0x5402c,0x1},
+	{0x54032,0x8400},
+	{0x54033,0x3100},
+	{0x54034,0x6600},
+	{0x54035,0x4d},
+	{0x54036,0x4d},
+	{0x54037,0x1600},
+	{0x54038,0x8400},
+	{0x54039,0x3100},
+	{0x5403a,0x6600},
+	{0x5403b,0x4d},
+	{0x5403c,0x4d},
+	{0x5403d,0x1600},
+	{0xd0000, 0x1},
+};
+
+
+/* P0 2D message block paremeter for training firmware */
+static struct dram_cfg_param ddr_fsp0_2d_cfg_1g_2ch1cs15r10cx32[] = {
+	{0xd0000, 0x0},
+	{0x54003,0x960},
+	{0x54004,0x2},
+	{0x54005,0x2228},
+	{0x54006,0x11},
+	{0x54008,0x61},
+	{0x54009,0xc8},
+	{0x5400b,0x2},
+	{0x5400f,0x100},
+	{0x54010,0x1f7f},
+	{0x54012,0x110},
+	{0x54019,0x24c4},
+	{0x5401a,0x31},
+	{0x5401b,0x4d66},
+	{0x5401c,0x4d00},
+	{0x5401e,0x16},
+	{0x5401f,0x24c4},
+	{0x54020,0x31},
+	{0x54021,0x4d66},
+	{0x54022,0x4d00},
+	{0x54024,0x16},
+	{0x5402b,0x1000},
+	{0x5402c,0x1},
+	{0x54032,0xc400},
+	{0x54033,0x3124},
+	{0x54034,0x6600},
+	{0x54035,0x4d},
+	{0x54036,0x4d},
+	{0x54037,0x1600},
+	{0x54038,0xc400},
+	{0x54039,0x3124},
+	{0x5403a,0x6600},
+	{0x5403b,0x4d},
+	{0x5403c,0x4d},
+	{0x5403d,0x1600},
+	{ 0xd0000, 0x1 },
+};
+
+/* DRAM PHY init engine image */
+static struct dram_cfg_param ddr_phy_pie[] = {
+	{0xd0000, 0x0},
+	{0x90000,0x10},
+	{0x90001,0x400},
+	{0x90002,0x10e},
+	{0x90003,0x0},
+	{0x90004,0x0},
+	{0x90005,0x8},
+	{0x90029,0xb},
+	{0x9002a,0x480},
+	{0x9002b,0x109},
+	{0x9002c,0x8},
+	{0x9002d,0x448},
+	{0x9002e,0x139},
+	{0x9002f,0x8},
+	{0x90030,0x478},
+	{0x90031,0x109},
+	{0x90032,0x0},
+	{0x90033,0xe8},
+	{0x90034,0x109},
+	{0x90035,0x2},
+	{0x90036,0x10},
+	{0x90037,0x139},
+	{0x90038,0xf},
+	{0x90039,0x7c0},
+	{0x9003a,0x139},
+	{0x9003b,0x44},
+	{0x9003c,0x630},
+	{0x9003d,0x159},
+	{0x9003e,0x14f},
+	{0x9003f,0x630},
+	{0x90040,0x159},
+	{0x90041,0x47},
+	{0x90042,0x630},
+	{0x90043,0x149},
+	{0x90044,0x4f},
+	{0x90045,0x630},
+	{0x90046,0x179},
+	{0x90047,0x8},
+	{0x90048,0xe0},
+	{0x90049,0x109},
+	{0x9004a,0x0},
+	{0x9004b,0x7c8},
+	{0x9004c,0x109},
+	{0x9004d,0x0},
+	{0x9004e,0x1},
+	{0x9004f,0x8},
+	{0x90050,0x0},
+	{0x90051,0x45a},
+	{0x90052,0x9},
+	{0x90053,0x0},
+	{0x90054,0x448},
+	{0x90055,0x109},
+	{0x90056,0x40},
+	{0x90057,0x630},
+	{0x90058,0x179},
+	{0x90059,0x1},
+	{0x9005a,0x618},
+	{0x9005b,0x109},
+	{0x9005c,0x40c0},
+	{0x9005d,0x630},
+	{0x9005e,0x149},
+	{0x9005f,0x8},
+	{0x90060,0x4},
+	{0x90061,0x48},
+	{0x90062,0x4040},
+	{0x90063,0x630},
+	{0x90064,0x149},
+	{0x90065,0x0},
+	{0x90066,0x4},
+	{0x90067,0x48},
+	{0x90068,0x40},
+	{0x90069,0x630},
+	{0x9006a,0x149},
+	{0x9006b,0x10},
+	{0x9006c,0x4},
+	{0x9006d,0x18},
+	{0x9006e,0x0},
+	{0x9006f,0x4},
+	{0x90070,0x78},
+	{0x90071,0x549},
+	{0x90072,0x630},
+	{0x90073,0x159},
+	{0x90074,0xd49},
+	{0x90075,0x630},
+	{0x90076,0x159},
+	{0x90077,0x94a},
+	{0x90078,0x630},
+	{0x90079,0x159},
+	{0x9007a,0x441},
+	{0x9007b,0x630},
+	{0x9007c,0x149},
+	{0x9007d,0x42},
+	{0x9007e,0x630},
+	{0x9007f,0x149},
+	{0x90080,0x1},
+	{0x90081,0x630},
+	{0x90082,0x149},
+	{0x90083,0x0},
+	{0x90084,0xe0},
+	{0x90085,0x109},
+	{0x90086,0xa},
+	{0x90087,0x10},
+	{0x90088,0x109},
+	{0x90089,0x9},
+	{0x9008a,0x3c0},
+	{0x9008b,0x149},
+	{0x9008c,0x9},
+	{0x9008d,0x3c0},
+	{0x9008e,0x159},
+	{0x9008f,0x18},
+	{0x90090,0x10},
+	{0x90091,0x109},
+	{0x90092,0x0},
+	{0x90093,0x3c0},
+	{0x90094,0x109},
+	{0x90095,0x18},
+	{0x90096,0x4},
+	{0x90097,0x48},
+	{0x90098,0x18},
+	{0x90099,0x4},
+	{0x9009a,0x58},
+	{0x9009b,0xa},
+	{0x9009c,0x10},
+	{0x9009d,0x109},
+	{0x9009e,0x2},
+	{0x9009f,0x10},
+	{0x900a0,0x109},
+	{0x900a1,0x5},
+	{0x900a2,0x7c0},
+	{0x900a3,0x109},
+	{0x900a4,0x10},
+	{0x900a5,0x10},
+	{0x900a6,0x109},
+	{0x40000,0x811},
+	{0x40020,0x880},
+	{0x40040,0x0},
+	{0x40060,0x0},
+	{0x40001,0x4008},
+	{0x40021,0x83},
+	{0x40041,0x4f},
+	{0x40061,0x0},
+	{0x40002,0x4040},
+	{0x40022,0x83},
+	{0x40042,0x51},
+	{0x40062,0x0},
+	{0x40003,0x811},
+	{0x40023,0x880},
+	{0x40043,0x0},
+	{0x40063,0x0},
+	{0x40004,0x720},
+	{0x40024,0xf},
+	{0x40044,0x1740},
+	{0x40064,0x0},
+	{0x40005,0x16},
+	{0x40025,0x83},
+	{0x40045,0x4b},
+	{0x40065,0x0},
+	{0x40006,0x716},
+	{0x40026,0xf},
+	{0x40046,0x2001},
+	{0x40066,0x0},
+	{0x40007,0x716},
+	{0x40027,0xf},
+	{0x40047,0x2800},
+	{0x40067,0x0},
+	{0x40008,0x716},
+	{0x40028,0xf},
+	{0x40048,0xf00},
+	{0x40068,0x0},
+	{0x40009,0x720},
+	{0x40029,0xf},
+	{0x40049,0x1400},
+	{0x40069,0x0},
+	{0x4000a,0xe08},
+	{0x4002a,0xc15},
+	{0x4004a,0x0},
+	{0x4006a,0x0},
+	{0x4000b,0x623},
+	{0x4002b,0x15},
+	{0x4004b,0x0},
+	{0x4006b,0x0},
+	{0x4000c,0x4028},
+	{0x4002c,0x80},
+	{0x4004c,0x0},
+	{0x4006c,0x0},
+	{0x4000d,0xe08},
+	{0x4002d,0xc1a},
+	{0x4004d,0x0},
+	{0x4006d,0x0},
+	{0x4000e,0x623},
+	{0x4002e,0x1a},
+	{0x4004e,0x0},
+	{0x4006e,0x0},
+	{0x4000f,0x4040},
+	{0x4002f,0x80},
+	{0x4004f,0x0},
+	{0x4006f,0x0},
+	{0x40010,0x2604},
+	{0x40030,0x15},
+	{0x40050,0x0},
+	{0x40070,0x0},
+	{0x40011,0x708},
+	{0x40031,0x5},
+	{0x40051,0x0},
+	{0x40071,0x2002},
+	{0x40012,0x8},
+	{0x40032,0x80},
+	{0x40052,0x0},
+	{0x40072,0x0},
+	{0x40013,0x2604},
+	{0x40033,0x1a},
+	{0x40053,0x0},
+	{0x40073,0x0},
+	{0x40014,0x708},
+	{0x40034,0xa},
+	{0x40054,0x0},
+	{0x40074,0x2002},
+	{0x40015,0x4040},
+	{0x40035,0x80},
+	{0x40055,0x0},
+	{0x40075,0x0},
+	{0x40016,0x60a},
+	{0x40036,0x15},
+	{0x40056,0x1200},
+	{0x40076,0x0},
+	{0x40017,0x61a},
+	{0x40037,0x15},
+	{0x40057,0x1300},
+	{0x40077,0x0},
+	{0x40018,0x60a},
+	{0x40038,0x1a},
+	{0x40058,0x1200},
+	{0x40078,0x0},
+	{0x40019,0x642},
+	{0x40039,0x1a},
+	{0x40059,0x1300},
+	{0x40079,0x0},
+	{0x4001a,0x4808},
+	{0x4003a,0x880},
+	{0x4005a,0x0},
+	{0x4007a,0x0},
+	{0x900a7,0x0},
+	{0x900a8,0x790},
+	{0x900a9,0x11a},
+	{0x900aa,0x8},
+	{0x900ab,0x7aa},
+	{0x900ac,0x2a},
+	{0x900ad,0x10},
+	{0x900ae,0x7b2},
+	{0x900af,0x2a},
+	{0x900b0,0x0},
+	{0x900b1,0x7c8},
+	{0x900b2,0x109},
+	{0x900b3,0x10},
+	{0x900b4,0x2a8},
+	{0x900b5,0x129},
+	{0x900b6,0x8},
+	{0x900b7,0x370},
+	{0x900b8,0x129},
+	{0x900b9,0xa},
+	{0x900ba,0x3c8},
+	{0x900bb,0x1a9},
+	{0x900bc,0xc},
+	{0x900bd,0x408},
+	{0x900be,0x199},
+	{0x900bf,0x14},
+	{0x900c0,0x790},
+	{0x900c1,0x11a},
+	{0x900c2,0x8},
+	{0x900c3,0x4},
+	{0x900c4,0x18},
+	{0x900c5,0xe},
+	{0x900c6,0x408},
+	{0x900c7,0x199},
+	{0x900c8,0x8},
+	{0x900c9,0x8568},
+	{0x900ca,0x108},
+	{0x900cb,0x18},
+	{0x900cc,0x790},
+	{0x900cd,0x16a},
+	{0x900ce,0x8},
+	{0x900cf,0x1d8},
+	{0x900d0,0x169},
+	{0x900d1,0x10},
+	{0x900d2,0x8558},
+	{0x900d3,0x168},
+	{0x900d4,0x70},
+	{0x900d5,0x788},
+	{0x900d6,0x16a},
+	{0x900d7,0x1ff8},
+	{0x900d8,0x85a8},
+	{0x900d9,0x1e8},
+	{0x900da,0x50},
+	{0x900db,0x798},
+	{0x900dc,0x16a},
+	{0x900dd,0x60},
+	{0x900de,0x7a0},
+	{0x900df,0x16a},
+	{0x900e0,0x8},
+	{0x900e1,0x8310},
+	{0x900e2,0x168},
+	{0x900e3,0x8},
+	{0x900e4,0xa310},
+	{0x900e5,0x168},
+	{0x900e6,0xa},
+	{0x900e7,0x408},
+	{0x900e8,0x169},
+	{0x900e9,0x6e},
+	{0x900ea,0x0},
+	{0x900eb,0x68},
+	{0x900ec,0x0},
+	{0x900ed,0x408},
+	{0x900ee,0x169},
+	{0x900ef,0x0},
+	{0x900f0,0x8310},
+	{0x900f1,0x168},
+	{0x900f2,0x0},
+	{0x900f3,0xa310},
+	{0x900f4,0x168},
+	{0x900f5,0x1ff8},
+	{0x900f6,0x85a8},
+	{0x900f7,0x1e8},
+	{0x900f8,0x68},
+	{0x900f9,0x798},
+	{0x900fa,0x16a},
+	{0x900fb,0x78},
+	{0x900fc,0x7a0},
+	{0x900fd,0x16a},
+	{0x900fe,0x68},
+	{0x900ff,0x790},
+	{0x90100,0x16a},
+	{0x90101,0x8},
+	{0x90102,0x8b10},
+	{0x90103,0x168},
+	{0x90104,0x8},
+	{0x90105,0xab10},
+	{0x90106,0x168},
+	{0x90107,0xa},
+	{0x90108,0x408},
+	{0x90109,0x169},
+	{0x9010a,0x58},
+	{0x9010b,0x0},
+	{0x9010c,0x68},
+	{0x9010d,0x0},
+	{0x9010e,0x408},
+	{0x9010f,0x169},
+	{0x90110,0x0},
+	{0x90111,0x8b10},
+	{0x90112,0x168},
+	{0x90113,0x0},
+	{0x90114,0xab10},
+	{0x90115,0x168},
+	{0x90116,0x0},
+	{0x90117,0x1d8},
+	{0x90118,0x169},
+	{0x90119,0x80},
+	{0x9011a,0x790},
+	{0x9011b,0x16a},
+	{0x9011c,0x18},
+	{0x9011d,0x7aa},
+	{0x9011e,0x6a},
+	{0x9011f,0xa},
+	{0x90120,0x0},
+	{0x90121,0x1e9},
+	{0x90122,0x8},
+	{0x90123,0x8080},
+	{0x90124,0x108},
+	{0x90125,0xf},
+	{0x90126,0x408},
+	{0x90127,0x169},
+	{0x90128,0xc},
+	{0x90129,0x0},
+	{0x9012a,0x68},
+	{0x9012b,0x9},
+	{0x9012c,0x0},
+	{0x9012d,0x1a9},
+	{0x9012e,0x0},
+	{0x9012f,0x408},
+	{0x90130,0x169},
+	{0x90131,0x0},
+	{0x90132,0x8080},
+	{0x90133,0x108},
+	{0x90134,0x8},
+	{0x90135,0x7aa},
+	{0x90136,0x6a},
+	{0x90137,0x0},
+	{0x90138,0x8568},
+	{0x90139,0x108},
+	{0x9013a,0xb7},
+	{0x9013b,0x790},
+	{0x9013c,0x16a},
+	{0x9013d,0x1f},
+	{0x9013e,0x0},
+	{0x9013f,0x68},
+	{0x90140,0x8},
+	{0x90141,0x8558},
+	{0x90142,0x168},
+	{0x90143,0xf},
+	{0x90144,0x408},
+	{0x90145,0x169},
+	{0x90146,0xc},
+	{0x90147,0x0},
+	{0x90148,0x68},
+	{0x90149,0x0},
+	{0x9014a,0x408},
+	{0x9014b,0x169},
+	{0x9014c,0x0},
+	{0x9014d,0x8558},
+	{0x9014e,0x168},
+	{0x9014f,0x8},
+	{0x90150,0x3c8},
+	{0x90151,0x1a9},
+	{0x90152,0x3},
+	{0x90153,0x370},
+	{0x90154,0x129},
+	{0x90155,0x20},
+	{0x90156,0x2aa},
+	{0x90157,0x9},
+	{0x90158,0x0},
+	{0x90159,0x400},
+	{0x9015a,0x10e},
+	{0x9015b,0x8},
+	{0x9015c,0xe8},
+	{0x9015d,0x109},
+	{0x9015e,0x0},
+	{0x9015f,0x8140},
+	{0x90160,0x10c},
+	{0x90161,0x10},
+	{0x90162,0x8138},
+	{0x90163,0x10c},
+	{0x90164,0x8},
+	{0x90165,0x7c8},
+	{0x90166,0x101},
+	{0x90167,0x8},
+	{0x90168,0x0},
+	{0x90169,0x8},
+	{0x9016a,0x8},
+	{0x9016b,0x448},
+	{0x9016c,0x109},
+	{0x9016d,0xf},
+	{0x9016e,0x7c0},
+	{0x9016f,0x109},
+	{0x90170,0x0},
+	{0x90171,0xe8},
+	{0x90172,0x109},
+	{0x90173,0x47},
+	{0x90174,0x630},
+	{0x90175,0x109},
+	{0x90176,0x8},
+	{0x90177,0x618},
+	{0x90178,0x109},
+	{0x90179,0x8},
+	{0x9017a,0xe0},
+	{0x9017b,0x109},
+	{0x9017c,0x0},
+	{0x9017d,0x7c8},
+	{0x9017e,0x109},
+	{0x9017f,0x8},
+	{0x90180,0x8140},
+	{0x90181,0x10c},
+	{0x90182,0x0},
+	{0x90183,0x1},
+	{0x90184,0x8},
+	{0x90185,0x8},
+	{0x90186,0x4},
+	{0x90187,0x8},
+	{0x90188,0x8},
+	{0x90189,0x7c8},
+	{0x9018a,0x101},
+	{0x90006,0x0},
+	{0x90007,0x0},
+	{0x90008,0x8},
+	{0x90009,0x0},
+	{0x9000a,0x0},
+	{0x9000b,0x0},
+	{0xd00e7,0x400},
+	{0x90017,0x0},
+	{0x9001f,0x2a},
+	{0x90026,0x6a},
+	{0x400d0,0x0},
+	{0x400d1,0x101},
+	{0x400d2,0x105},
+	{0x400d3,0x107},
+	{0x400d4,0x10f},
+	{0x400d5,0x202},
+	{0x400d6,0x20a},
+	{0x400d7,0x20b},
+	{0x2003a,0x2},
+	{0x2000b,0x4b},
+	{0x2000c,0x96},
+	{0x2000d,0x5dc},
+	{0x2000e,0x2c},
+	{0x12000b,0xc},
+	{0x12000c,0x19},
+	{0x12000d,0xfa},
+	{0x12000e,0x10},
+	{0x22000b,0x3},
+	{0x22000c,0x6},
+	{0x22000d,0x3e},
+	{0x22000e,0x10},
+	{0x9000c,0x0},
+	{0x9000d,0x173},
+	{0x9000e,0x60},
+	{0x9000f,0x6110},
+	{0x90010,0x2152},
+	{0x90011,0xdfbd},
+	{0x90012,0x60},
+	{0x90013,0x6152},
+	{0x20010,0x5a},
+	{0x20011,0x3},
+	{0x120010,0x5a},
+	{0x120011,0x3},
+	{0x220010,0x5a},
+	{0x220011,0x3},
+	{0x40080,0xe0},
+	{0x40081,0x12},
+	{0x40082,0xe0},
+	{0x40083,0x12},
+	{0x40084,0xe0},
+	{0x40085,0x12},
+	{0x140080,0xe0},
+	{0x140081,0x12},
+	{0x140082,0xe0},
+	{0x140083,0x12},
+	{0x140084,0xe0},
+	{0x140085,0x12},
+	{0x240080,0xe0},
+	{0x240081,0x12},
+	{0x240082,0xe0},
+	{0x240083,0x12},
+	{0x240084,0xe0},
+	{0x240085,0x12},
+	{0x400fd,0xf},
+	{0x10011,0x1},
+	{0x10012,0x1},
+	{0x10013,0x180},
+	{0x10018,0x1},
+	{0x10002,0x6209},
+	{0x100b2,0x1},
+	{0x101b4,0x1},
+	{0x102b4,0x1},
+	{0x103b4,0x1},
+	{0x104b4,0x1},
+	{0x105b4,0x1},
+	{0x106b4,0x1},
+	{0x107b4,0x1},
+	{0x108b4,0x1},
+	{0x11011,0x1},
+	{0x11012,0x1},
+	{0x11013,0x180},
+	{0x11018,0x1},
+	{0x11002,0x6209},
+	{0x110b2,0x1},
+	{0x111b4,0x1},
+	{0x112b4,0x1},
+	{0x113b4,0x1},
+	{0x114b4,0x1},
+	{0x115b4,0x1},
+	{0x116b4,0x1},
+	{0x117b4,0x1},
+	{0x118b4,0x1},
+	{0x12011,0x1},
+	{0x12012,0x1},
+	{0x12013,0x180},
+	{0x12018,0x1},
+	{0x12002,0x6209},
+	{0x120b2,0x1},
+	{0x121b4,0x1},
+	{0x122b4,0x1},
+	{0x123b4,0x1},
+	{0x124b4,0x1},
+	{0x125b4,0x1},
+	{0x126b4,0x1},
+	{0x127b4,0x1},
+	{0x128b4,0x1},
+	{0x13011,0x1},
+	{0x13012,0x1},
+	{0x13013,0x180},
+	{0x13018,0x1},
+	{0x13002,0x6209},
+	{0x130b2,0x1},
+	{0x131b4,0x1},
+	{0x132b4,0x1},
+	{0x133b4,0x1},
+	{0x134b4,0x1},
+	{0x135b4,0x1},
+	{0x136b4,0x1},
+	{0x137b4,0x1},
+	{0x138b4,0x1},
+	{0x2003a,0x2},
+	{0xc0080,0x2},
+	{0xd0000, 0x1}
+};
+
+static struct dram_fsp_msg ddr_dram_fsp_msg_1g_2ch1cs15r10cx32[] = {
+	{
+		/* P0 2400mts 1D */
+		.drate = 2400,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp0_cfg_1g_2ch1cs15r10cx32,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg_1g_2ch1cs15r10cx32),
+	},
+	{
+		/* P1 400mts 1D */
+		.drate = 400,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp1_cfg_1g_2ch1cs15r10cx32,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg_1g_2ch1cs15r10cx32),
+	},
+	{
+		/* P2 100mts 1D */
+		.drate = 100,
+		.fw_type = FW_1D_IMAGE,
+		.fsp_cfg = ddr_fsp2_cfg_1g_2ch1cs15r10cx32,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg_1g_2ch1cs15r10cx32),
+	},
+	{
+		/* P0 2400mts 2D */
+		.drate = 2400,
+		.fw_type = FW_2D_IMAGE,
+		.fsp_cfg = ddr_fsp0_2d_cfg_1g_2ch1cs15r10cx32,
+		.fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg_1g_2ch1cs15r10cx32),
+	},
+};
+
+/* ddr timing config params */
+struct dram_timing_info innocom_wb15_dram_timing = {
+	.ddrc_cfg = ddr_ddrc_cfg_1g_2ch1cs15r10cx32,
+	.ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg_1g_2ch1cs15r10cx32),
+	.ddrphy_cfg = ddr_ddrphy_cfg,
+	.ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg),
+	.fsp_msg = ddr_dram_fsp_msg_1g_2ch1cs15r10cx32,
+	.fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg_1g_2ch1cs15r10cx32),
+	.ddrphy_trained_csr = ddr_ddrphy_trained_csr,
+	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
+	.ddrphy_pie = ddr_phy_pie,
+	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
+	.fsp_table = { 2400, 400, 100, },
+};
diff --git a/arch/arm/configs/imx_v8_defconfig b/arch/arm/configs/imx_v8_defconfig
index fe6398cc87..65cf81b3e2 100644
--- a/arch/arm/configs/imx_v8_defconfig
+++ b/arch/arm/configs/imx_v8_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARCH_IMX=y
 CONFIG_IMX_MULTI_BOARDS=y
 CONFIG_MACH_PROTONIC_IMX8M=y
+CONFIG_MACH_INNOCOM_WB15=y
 CONFIG_MACH_ZII_IMX8MQ_DEV=y
 CONFIG_MACH_NXP_IMX8MM_EVK=y
 CONFIG_MACH_NXP_IMX8MN_EVK=y
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 97374edc4c..939e5bfc5a 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -145,6 +145,7 @@ lwl-$(CONFIG_MACH_NXP_IMX8MM_EVK) += imx8mm-evk.dtb.o
 lwl-$(CONFIG_MACH_NXP_IMX8MN_EVK) += imx8mn-evk.dtb.o imx8mn-ddr4-evk.dtb.o
 lwl-$(CONFIG_MACH_NXP_IMX8MP_EVK) += imx8mp-evk.dtb.o
 lwl-$(CONFIG_MACH_NXP_IMX8MQ_EVK) += imx8mq-evk.dtb.o
+lwl-$(CONFIG_MACH_INNOCOM_WB15) += imx8mm-innocom-wb15-evk.dtb.o
 lwl-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o
 lwl-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o
 lwl-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o
diff --git a/arch/arm/dts/imx8mm-innocom-wb15-evk-upstream.dts b/arch/arm/dts/imx8mm-innocom-wb15-evk-upstream.dts
new file mode 100644
index 0000000000..ba880c2459
--- /dev/null
+++ b/arch/arm/dts/imx8mm-innocom-wb15-evk-upstream.dts
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018 Bang & Olufsen
+ * Copyright 2022 Pengutronix
+ */
+
+/dts-v1/;
+
+#include "imx8mm-innocom-wb15.dtsi"
+
+/ {
+	model = "Innocom WB15-EVK";
+	compatible = "innocom,wb15-evk", "fsl,imx8mm";
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_leds>;
+		status = "okay";
+
+		led-0 {
+			label = "debug";
+			gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+
+	reg_vsd_3v3: regulator-vsd-3v3 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_vsd_3v3>;
+		regulator-name = "VSD_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_ethphy: regulator-eth-phy {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_fec_phy_reg>;
+		regulator-name = "PHY_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec>;
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethphy0>;
+	fsl,magic-packet;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy at 1 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <0x1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_fec_phy>;
+			reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+			phy-supply = <&reg_ethphy>;
+		};
+	};
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usbotg1 {
+	dr_mode = "otg";
+	samsung,picophy-pre-emp-curr-control = <3>;
+	samsung,picophy-dc-vol-level-adjust = <7>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg2 {
+	dr_mode = "host";
+	samsung,picophy-pre-emp-curr-control = <3>;
+	samsung,picophy-dc-vol-level-adjust = <7>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc2 {
+	cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&reg_vsd_3v3>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_fec: fecgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_ENET_MDC_ENET1_MDC			0x03
+			MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO		0x03
+			MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3		0x1f
+			MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2		0x1f
+			MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1		0x1f
+			MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0		0x1f
+			MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3		0x91
+			MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2		0x91
+			MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1		0x91
+			MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0		0x91
+			MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC		0x1f
+			MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC		0x91
+			MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL	0x91
+			MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL	0x1f
+		>;
+	};
+
+	pinctrl_fec_phy: fecphygrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9		0x19
+		>;
+	};
+
+	pinctrl_fec_phy_reg: fecphyreggrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10		0x16
+		>;
+	};
+
+	pinctrl_gpio_leds: led_grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3	0xd6
+		>;
+	};
+
+	pinctrl_reg_vsd_3v3: reg-vsd-3v3-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19	0x41
+		>;
+	};
+};
diff --git a/arch/arm/dts/imx8mm-innocom-wb15-evk.dts b/arch/arm/dts/imx8mm-innocom-wb15-evk.dts
new file mode 100644
index 0000000000..5bac39c376
--- /dev/null
+++ b/arch/arm/dts/imx8mm-innocom-wb15-evk.dts
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/dts-v1/;
+
+#include "imx8mm-innocom-wb15-evk-upstream.dts"
+
+/ {
+	chosen {
+		environment-emmc {
+			compatible = "barebox,environment";
+			device-path = &usdhc1, "partname:barebox-environment";
+			status = "disabled";
+		};
+		environment-sd {
+			compatible = "barebox,environment";
+			device-path = &usdhc2, "partname:barebox-environment";
+			status = "disabled";
+		};
+	};
+};
+
+&ocotp {
+	barebox,provide-mac-address = <&fec1 0x640>;
+};
+
+&usdhc1 {
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		partition at 0 {
+			label = "barebox";
+			reg = <0x0 0x0 0x0 0x100000>;
+		};
+
+		partition at e0000 {
+			label = "barebox-environment";
+			reg = <0x0 0x100000 0x0 0x100000>;
+		};
+	};
+};
+
+&usdhc2 {
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		partition at 0 {
+			label = "barebox";
+			reg = <0x0 0x0 0x0 0x100000>;
+		};
+
+		partition at e0000 {
+			label = "barebox-environment";
+			reg = <0x0 0x100000 0x0 0x100000>;
+		};
+	};
+};
diff --git a/arch/arm/dts/imx8mm-innocom-wb15.dtsi b/arch/arm/dts/imx8mm-innocom-wb15.dtsi
new file mode 100644
index 0000000000..7e25450362
--- /dev/null
+++ b/arch/arm/dts/imx8mm-innocom-wb15.dtsi
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018 Bang & Olufsen
+ */
+
+#include <arm64/freescale/imx8mm.dtsi>
+#include "imx8mm.dtsi"
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+
+/ {
+	reg_modem: regulator-modem {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_modem_regulator>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-name = "epdev_on";
+		gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-always-on;
+	};
+
+	reg_3v3_out: regulator-3v3-out {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3_OUT";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&cpu_alert0 {
+	temperature = <95000>;
+};
+
+&cpu_crit0 {
+	temperature = <105000>;
+};
+
+&ddrc {
+	operating-points-v2 = <&ddrc_opp_table>;
+
+	ddrc_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp-25000000 {
+			opp-hz = /bits/ 64 <25000000>;
+		};
+
+		opp-100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	status = "okay";
+
+	pmic at 4b {
+		compatible = "rohm,bd71847";
+		reg = <0x4b>;
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <3 GPIO_ACTIVE_LOW>;
+		rohm,reset-snvs-powered;
+
+		regulators {
+			buck1_reg: BUCK1 {
+				regulator-name = "buck1";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <1250>;
+				rohm,dvs-run-voltage = <850000>;
+				rohm,dvs-idle-voltage = <850000>;
+				rohm,dvs-suspend-voltage = <850000>;
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "buck2";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <1250>;
+				rohm,dvs-run-voltage = <1000000>;
+				rohm,dvs-idle-voltage = <900000>;
+			};
+
+			buck3_reg: BUCK3 {
+				// buck5 in datasheet
+				regulator-name = "buck3";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck4_reg: BUCK4 {
+				// buck6 in datasheet
+				regulator-name = "buck4";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck5_reg: BUCK5 {
+				// buck7 in datasheet
+				regulator-name = "buck5";
+				regulator-min-microvolt = <1605000>;
+				regulator-max-microvolt = <1995000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck6_reg: BUCK6 {
+				// buck8 in datasheet
+				regulator-name = "buck6";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1_reg: LDO1 {
+				regulator-name = "ldo1";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "ldo2";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3_reg: LDO3 {
+				regulator-name = "ldo3";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4_reg: LDO4 {
+				regulator-name = "ldo4";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo5_reg: LDO5 {
+				regulator-name = "ldo5";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo6_reg: LDO6 {
+				regulator-name = "ldo6";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	pinctrl-1 = <&pinctrl_i2c2_gpio>;
+	scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	status = "okay";
+};
+
+&i2c3 {
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	pinctrl-1 = <&pinctrl_i2c3_gpio>;
+	scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+};
+
+&pcie_phy {
+	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>;
+	fsl,tx-deemph-gen1 = <0x2d>;
+	fsl,tx-deemph-gen2 = <0xf>;
+	status = "okay";
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie0>;
+	reset-gpio = <&gpio5 21 GPIO_ACTIVE_LOW>;
+	clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_PHY>,
+		 <&clk IMX8MM_CLK_PCIE1_AUX>;
+	clock-names = "pcie", "pcie_bus", "pcie_aux";
+	fsl,max-link-speed = <1>;
+	assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>, <&clk IMX8MM_CLK_PCIE1_CTRL>;
+	assigned-clock-rates = <10000000>, <250000000>;
+	assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>, <&clk IMX8MM_SYS_PLL2_250M>;
+	status = "okay";
+};
+
+&uart1 { /* BT */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	assigned-clocks = <&clk IMX8MM_CLK_UART1>;
+	assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+
+	bluetooth {
+		compatible = "brcm,bcm4349-bt";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_modem_bt>;
+		device-wakeup-gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
+		host-wakeup-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
+		shutdown-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>;
+		vbat-supply = <&reg_3v3_out>;
+		vddio-supply = <&reg_3v3_out>;
+		clocks = <&osc_32k>;
+		max-speed = <3000000>;
+		clock-names = "extclk";
+	};
+};
+
+&uart2 { /* console */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	bus-width = <8>;
+	no-sd;
+	no-sdio;
+	non-removable;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+	bus-width = <4>;
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+	status = "okay";
+};
+
+&A53_0 {
+	cpu-supply = <&buck2_reg>;
+};
+
+&A53_1 {
+	cpu-supply = <&buck2_reg>;
+};
+
+&A53_2 {
+	cpu-supply = <&buck2_reg>;
+};
+
+&A53_3 {
+	cpu-supply = <&buck2_reg>;
+};
+
+/delete-node/ &sec_jr1; /* Job ring in use by OP-TEE */
+
+&iomuxc {
+	pinctrl_i2c1: i2c1-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL	0x400001c3
+			MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA	0x400001c3
+		>;
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14	0x400001c3
+			MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15	0x400001c3
+		>;
+	};
+
+	pinctrl_i2c2: i2c2-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL	0x400001c3
+			MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA	0x400001c3
+		>;
+	};
+
+	pinctrl_i2c2_gpio: i2c2-gpio-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16	0x400001c3
+			MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17	0x400001c3
+		>;
+	};
+
+	pinctrl_i2c3: i2c3-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL		0x400001c3
+			MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA		0x400001c3
+		>;
+	};
+
+	pinctrl_i2c3_gpio: i2c3-gpio-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18	0x400001c3
+			MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19	0x400001c3
+		>;
+	};
+
+	pinctrl_pcie0: pcie0-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C4_SCL_PCIE1_CLKREQ_B	0x61
+			MX8MM_IOMUXC_I2C4_SDA_GPIO5_IO21	0x6
+		>;
+	};
+
+	pinctrl_modem_bt: modembt-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_NAND_CLE_GPIO3_IO5			0x19
+			MX8MM_IOMUXC_NAND_CE2_B_GPIO3_IO3		0x19
+			MX8MM_IOMUXC_NAND_CE3_B_GPIO3_IO4		0x19
+			MX8MM_IOMUXC_NAND_RE_B_GPIO3_IO15		0x19
+			MX8MM_IOMUXC_GPIO1_IO00_ANAMIX_REF_CLK_32K	0x141
+		>;
+	};
+
+	pinctrl_modem_regulator: modemreg-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16    0x41
+		>;
+	};
+
+	pinctrl_pmic: pmicirq-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3	0x41
+		>;
+	};
+
+	pinctrl_uart1: uart1-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX	0x140
+			MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX	0x140
+			MX8MM_IOMUXC_UART3_RXD_UART1_DCE_CTS_B	0x140
+			MX8MM_IOMUXC_UART3_TXD_UART1_DCE_RTS_B	0x140
+		>;
+	};
+
+	pinctrl_uart2: uart2-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX	0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX	0x140
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK		0x40000190
+			MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD		0x1d0
+			MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0	0x1d0
+			MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1	0x1d0
+			MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2	0x1d0
+			MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3	0x1d0
+			MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4	0x1d0
+			MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5	0x1d0
+			MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6	0x1d0
+			MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7	0x1d0
+			MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE	0x190
+			MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B	0x1d0
+		>;
+	};
+
+	pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK		0x40000194
+			MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD		0x1d4
+			MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0	0x1d4
+			MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1	0x1d4
+			MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2	0x1d4
+			MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3	0x1d4
+			MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4	0x1d4
+			MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5	0x1d4
+			MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6	0x1d4
+			MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7	0x1d4
+			MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE	0x194
+			MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B	0x1d4
+		>;
+	};
+
+	pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK		0x40000196
+			MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD		0x1d6
+			MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0	0x1d6
+			MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1	0x1d6
+			MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2	0x1d6
+			MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3	0x1d6
+			MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4	0x1d6
+			MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5	0x1d6
+			MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6	0x1d6
+			MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7	0x1d6
+			MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE	0x196
+			MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B	0x1d6
+		>;
+	};
+
+	pinctrl_usdhc2_gpio: usdhc2-gpio-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19	0x1d0
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK		0x190
+			MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD		0x1d0
+			MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0	0x1d0
+			MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1	0x1d0
+			MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2	0x1d0
+			MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3	0x1d0
+			MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT	0x1d0
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK		0x194
+			MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD		0x1d4
+			MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0	0x1d4
+			MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1	0x1d4
+			MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2	0x1d4
+			MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3	0x1d4
+			MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT	0x1d0
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK		0x196
+			MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD		0x1d6
+			MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0	0x1d6
+			MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1	0x1d6
+			MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2	0x1d6
+			MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3	0x1d6
+			MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT	0x1d0
+		>;
+	};
+
+	pinctrl_wdog: wdog-grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B	0xc6
+		>;
+	};
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 356a916445..f18d7c81ea 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -361,6 +361,17 @@ config MACH_PROTONIC_IMX8M
 	select IMX8M_DRAM
 	select USB_GADGET_DRIVER_ARC_PBL
 
+config MACH_INNOCOM_WB15
+	bool "Innocom WB15 (i.MX8MM) EVK"
+	select ARCH_IMX8MM
+	select FIRMWARE_IMX_LPDDR4_PMU_TRAIN
+	select FIRMWARE_IMX8MM_ATF
+	select ARM_SMCCC
+	select MCI_IMX_ESDHC_PBL
+	select IMX8M_DRAM
+	select I2C_IMX_EARLY
+	select USB_GADGET_DRIVER_ARC_PBL
+
 config MACH_KONTRON_SAMX6I
         bool "Kontron sAMX6i"
         select ARCH_IMX6
diff --git a/images/Makefile.imx b/images/Makefile.imx
index a19e0ff1c7..60973b6003 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -439,6 +439,11 @@ CFG_start_prt_prt8mm.pblb.imximg = $(board)/protonic-imx8m/flash-header-prt8mm.i
 FILE_barebox-prt-prt8mm.img = start_prt_prt8mm.pblb.pimximg
 image-$(CONFIG_MACH_PROTONIC_IMX8M) += barebox-prt-prt8mm.img
 
+pblb-$(CONFIG_MACH_INNOCOM_WB15) += start_innocom_wb15_evk
+CFG_start_innocom_wb15_evk.pblb.imximg = $(board)/innocom-imx8mm-wb15/flash-header-imx8mm-wb15.imxcfg
+FILE_barebox-innocom-imx8mm-wb15-evk.img = start_innocom_wb15_evk.pblb.pimximg
+image-$(CONFIG_MACH_INNOCOM_WB15) += barebox-innocom-imx8mm-wb15-evk.img
+
 # ----------------------- i.MX8mn based boards --------------------------
 pblb-$(CONFIG_MACH_NXP_IMX8MN_EVK) += start_nxp_imx8mn_evk
 CFG_start_nxp_imx8mn_evk.pblb.imximg = $(board)/nxp-imx8mn-evk/flash-header-imx8mn-evk.imxcfg
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep  2 02:54:58 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri,  2 Sep 2022 11:54:58 +0200
Subject: [PATCH master] blspec: fix memory leak handling NFS URLs
Message-ID: <20220902095458.2589252-1-a.fatoum@pengutronix.de>

parse_nfs_url() returns either an allocated string on success or an
error pointer otherwise. blspec_bootentry_provider() will early
exit if the path couldn't be resolved and thus not free() the string.

Fix this memory leak. While at it, change parse_nfs_url() to return NULL
on error. The error code is unused and just returning NULL, simplifies
the code.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/blspec.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/common/blspec.c b/common/blspec.c
index 9bb25ee72123..d391f690ad0c 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -341,10 +341,10 @@ static char *parse_nfs_url(const char *url)
 	int ret;
 
 	if (!IS_ENABLED(CONFIG_FS_NFS))
-		return ERR_PTR(-ENOSYS);
+		return NULL;
 
 	if (strncmp(url, "nfs://", 6))
-		return ERR_PTR(-EINVAL);
+		return NULL;
 
 	url += 6;
 
@@ -413,7 +413,7 @@ out:
 	if (ret)
 		free(mountpath);
 
-	return ret ? ERR_PTR(ret) : mountpath;
+	return ret ? NULL : mountpath;
 }
 
 /*
@@ -824,12 +824,12 @@ static int blspec_bootentry_provider(struct bootentries *bootentries,
 	if (*name == '/' || !strncmp(name, "nfs://", 6)) {
 		char *nfspath = parse_nfs_url(name);
 
-		if (!IS_ERR(nfspath))
+		if (nfspath)
 			name = nfspath;
 
 		ret = stat(name, &s);
 		if (ret)
-			return found;
+			goto out;
 
 		if (S_ISDIR(s.st_mode))
 			ret = blspec_scan_directory(bootentries, name);
@@ -838,8 +838,8 @@ static int blspec_bootentry_provider(struct bootentries *bootentries,
 		if (ret > 0)
 			found += ret;
 
-		if (!IS_ERR(nfspath))
-			free(nfspath);
+out:
+		free(nfspath);
 	}
 
 	return found;
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep  2 03:04:58 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri,  2 Sep 2022 12:04:58 +0200
Subject: [PATCH] commands: mm: don't ignore pread() errors for larger access sizes
Message-ID: <20220902100458.2597350-1-a.fatoum@pengutronix.de>

Error check was before pread was called and because ret was initialized,
compiler didn't warn about it. Fix this.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 commands/mm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/commands/mm.c b/commands/mm.c
index 9ce883964485..8fe87a80a18e 100644
--- a/commands/mm.c
+++ b/commands/mm.c
@@ -16,7 +16,7 @@
 
 static int do_mem_mm(int argc, char *argv[])
 {
-	int ret = 0;
+	int ret;
 	int fd;
 	char *filename = "/dev/mem";
 	int mode = O_RWSIZE_4;
@@ -65,9 +65,9 @@ static int do_mem_mm(int argc, char *argv[])
 			goto out_write;
 		break;
 	case O_RWSIZE_4:
+		ret = pread(fd, &val32, 4, adr);
 		if (ret < 0)
 			goto out_read;
-		ret = pread(fd, &val32, 4, adr);
 		val32 &= ~mask;
 		val32 |= (value & mask);
 		ret = pwrite(fd, &val32, 4, adr);
@@ -75,9 +75,9 @@ static int do_mem_mm(int argc, char *argv[])
 			goto out_write;
 		break;
 	case O_RWSIZE_8:
+		ret = pread(fd, &val64, 8, adr);
 		if (ret < 0)
 			goto out_read;
-		ret = pread(fd, &val64, 8, adr);
 		val64 &= ~mask;
 		val64 |= (value & mask);
 		ret = pwrite(fd, &val64, 8, adr);
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep  2 07:02:32 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 2 Sep 2022 16:02:32 +0200
Subject: [PATCH] clks: imx7: fix initial clock setup with deep probe
 enabled
In-Reply-To: <ea03c971490b991a53b332beaded392862525f50.camel@pengutronix.de>
References: <20220830083937.466171-1-j.zink@pengutronix.de>
 <20220830150522.GI24324@pengutronix.de>
 <ea03c971490b991a53b332beaded392862525f50.camel@pengutronix.de>
Message-ID: <5a0c3e08-e47c-d01c-aa9a-b41da6a3f4af@pengutronix.de>

Hello,

On 31.08.22 10:21, Johannes Zink wrote:
> Hi Sascha,
> 
> On Tue, 2022-08-30 at 17:05 +0200, Sascha Hauer wrote:
>> On Tue, Aug 30, 2022 at 10:39:37AM +0200, Johannes Zink wrote:
>>> We register the i.MX7 clock controller driver at core_initcall
>>> level and
>>> then do some initial clock setup/reparenting at postcore_initcall
>>> level.
>>> This doesn't work as expected when deep probe is enabled, because
>>> while
>>> the driver is registered at core_initcall level, it's only probed
>>> later on, currently at postcore_initcall level because it's a
>>> dependency
>>> of the timer for which of_ensure_device_probed is called.
>>>
>>> As the initial clock setup is also at postcore_initcall level, it's
>>> no
>>> longer guaranteed that the code executes in the same order. Fix
>>> this by
>>> directly doing the setup at the end of the probe function.
>>
>> Does this still work with deep probe disabled?
>>
>> I am asking because this effectively reverts bce79428773 ("clk:
>> i.MX7: do
>> clock reparenting when all clocks are initialized"). Switching all
>> i.MX7 boards to deep probe might be a solution as well.

fixed clocks are registered via CLK_OF_DECLARE, so by the time the
imx7 clock probe runs, they will always be available, independent of
whether deep probe is enabled.

> Though I would not _expect_ any problems here, I would like to check
> that more thoroughly. This will probably take a bit, please stand by.

I looked at this with Johannes and I am puzzled how the problem
that bce79428773 aimed to fix occurred. Could you elaborate?

Thanks,
Ahmad

> 
> Best regards
> Johannes
> 
>>
>>>
>>> Co-developed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
>>> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
>>> Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
>>> ---
>>> ?drivers/clk/imx/clk-imx7.c | 62 +++++++++++++++++-----------------
>>> ----
>>> ?1 file changed, 27 insertions(+), 35 deletions(-)
>>>
>>> diff --git a/drivers/clk/imx/clk-imx7.c b/drivers/clk/imx/clk-
>>> imx7.c
>>> index ffa39d17b0..67876a8404 100644
>>> --- a/drivers/clk/imx/clk-imx7.c
>>> +++ b/drivers/clk/imx/clk-imx7.c
>>> @@ -358,7 +358,32 @@ static int const clks_init_on[] __initconst =
>>> {
>>> ?
>>> ?static struct clk_onecell_data clk_data;
>>> ?
>>> -static int imx7_clk_initialized;
>>> +static void imx7_clk_setup(void)
>>> +{
>>> +???????int i;
>>> +
>>> +???????clks[IMX7D_OSC_24M_CLK] = clk_lookup("osc");
>>> +
>>> +???????for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
>>> +???????????????clk_enable(clks[clks_init_on[i]]);
>>> +
>>> +???????/* use old gpt clk setting, gpt1 root clk must be twice as
>>> gpt counter freq */
>>> +???????clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC],
>>> clks[IMX7D_OSC_24M_CLK]);
>>> +
>>> +???????/* set uart module clock's parent clock source that must be
>>> great then 80MHz */
>>> +???????clk_set_parent(clks[IMX7D_UART1_ROOT_SRC],
>>> clks[IMX7D_OSC_24M_CLK]);
>>> +
>>> +???????clk_set_parent(clks[IMX7D_ENET1_REF_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_125M_CLK]);
>>> +???????clk_set_parent(clks[IMX7D_ENET1_TIME_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_100M_CLK]);
>>> +???????clk_set_parent(clks[IMX7D_ENET2_REF_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_125M_CLK]);
>>> +???????clk_set_parent(clks[IMX7D_ENET2_TIME_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_100M_CLK]);
>>> +
>>> +???????clk_set_rate(clks[IMX7D_PLL_SYS_PFD4_CLK], 392000000);
>>> +???????clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC],
>>> clks[IMX7D_PLL_SYS_PFD4_CLK]);
>>> +???????clk_set_rate(clks[IMX7D_ENET_AXI_ROOT_CLK], 197000000);
>>> +???????clk_set_rate(clks[IMX7D_ENET1_TIME_ROOT_CLK], 25000000);
>>> +???????clk_set_rate(clks[IMX7D_ENET2_TIME_ROOT_CLK], 25000000);
>>> +}
>>> ?
>>> ?static int imx7_ccm_probe(struct device_d *dev)
>>> ?{
>>> @@ -806,43 +831,10 @@ static int imx7_ccm_probe(struct device_d
>>> *dev)
>>> ????????clk_data.clk_num = ARRAY_SIZE(clks);
>>> ????????of_clk_add_provider(dev->device_node,
>>> of_clk_src_onecell_get, &clk_data);
>>> ?
>>> -???????imx7_clk_initialized = 1;
>>> -
>>> -???????return 0;
>>> -}
>>> -
>>> -static int imx7_clk_setup(void)
>>> -{
>>> -???????int i;
>>> -
>>> -???????if (!imx7_clk_initialized)
>>> -???????????????return 0;
>>> -
>>> -???????clks[IMX7D_OSC_24M_CLK] = clk_lookup("osc");
>>> -
>>> -???????for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
>>> -???????????????clk_enable(clks[clks_init_on[i]]);
>>> -
>>> -???????/* use old gpt clk setting, gpt1 root clk must be twice as
>>> gpt counter freq */
>>> -???????clk_set_parent(clks[IMX7D_GPT1_ROOT_SRC],
>>> clks[IMX7D_OSC_24M_CLK]);
>>> -
>>> -???????/* set uart module clock's parent clock source that must be
>>> great then 80MHz */
>>> -???????clk_set_parent(clks[IMX7D_UART1_ROOT_SRC],
>>> clks[IMX7D_OSC_24M_CLK]);
>>> -
>>> -???????clk_set_parent(clks[IMX7D_ENET1_REF_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_125M_CLK]);
>>> -???????clk_set_parent(clks[IMX7D_ENET1_TIME_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_100M_CLK]);
>>> -???????clk_set_parent(clks[IMX7D_ENET2_REF_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_125M_CLK]);
>>> -???????clk_set_parent(clks[IMX7D_ENET2_TIME_ROOT_SRC],
>>> clks[IMX7D_PLL_ENET_MAIN_100M_CLK]);
>>> -
>>> -???????clk_set_rate(clks[IMX7D_PLL_SYS_PFD4_CLK], 392000000);
>>> -???????clk_set_parent(clks[IMX7D_ENET_AXI_ROOT_SRC],
>>> clks[IMX7D_PLL_SYS_PFD4_CLK]);
>>> -???????clk_set_rate(clks[IMX7D_ENET_AXI_ROOT_CLK], 197000000);
>>> -???????clk_set_rate(clks[IMX7D_ENET1_TIME_ROOT_CLK], 25000000);
>>> -???????clk_set_rate(clks[IMX7D_ENET2_TIME_ROOT_CLK], 25000000);
>>> +???????imx7_clk_setup();
>>> ?
>>> ????????return 0;
>>> ?}
>>> -postcore_initcall(imx7_clk_setup);
>>> ?
>>> ?static __maybe_unused struct of_device_id imx7_ccm_dt_ids[] = {
>>> ????????{
>>> -- 
>>> 2.30.2
>>>
>>>
>>>
>>
> 


-- 
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-5555 |


From sha at pengutronix.de  Fri Sep  2 11:38:25 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Fri, 2 Sep 2022 20:38:25 +0200
Subject: [PATCH] clks: imx7: fix initial clock setup with deep probe
 enabled
In-Reply-To: <5a0c3e08-e47c-d01c-aa9a-b41da6a3f4af@pengutronix.de>
References: <20220830083937.466171-1-j.zink@pengutronix.de>
 <20220830150522.GI24324@pengutronix.de>
 <ea03c971490b991a53b332beaded392862525f50.camel@pengutronix.de>
 <5a0c3e08-e47c-d01c-aa9a-b41da6a3f4af@pengutronix.de>
Message-ID: <20220902183825.GW24324@pengutronix.de>

On Fri, Sep 02, 2022 at 04:02:32PM +0200, Ahmad Fatoum wrote:
> Hello,
> 
> On 31.08.22 10:21, Johannes Zink wrote:
> > Hi Sascha,
> > 
> > On Tue, 2022-08-30 at 17:05 +0200, Sascha Hauer wrote:
> >> On Tue, Aug 30, 2022 at 10:39:37AM +0200, Johannes Zink wrote:
> >>> We register the i.MX7 clock controller driver at core_initcall
> >>> level and
> >>> then do some initial clock setup/reparenting at postcore_initcall
> >>> level.
> >>> This doesn't work as expected when deep probe is enabled, because
> >>> while
> >>> the driver is registered at core_initcall level, it's only probed
> >>> later on, currently at postcore_initcall level because it's a
> >>> dependency
> >>> of the timer for which of_ensure_device_probed is called.
> >>>
> >>> As the initial clock setup is also at postcore_initcall level, it's
> >>> no
> >>> longer guaranteed that the code executes in the same order. Fix
> >>> this by
> >>> directly doing the setup at the end of the probe function.
> >>
> >> Does this still work with deep probe disabled?
> >>
> >> I am asking because this effectively reverts bce79428773 ("clk:
> >> i.MX7: do
> >> clock reparenting when all clocks are initialized"). Switching all
> >> i.MX7 boards to deep probe might be a solution as well.
> 
> fixed clocks are registered via CLK_OF_DECLARE, so by the time the
> imx7 clock probe runs, they will always be available, independent of
> whether deep probe is enabled.

So this problem is already fixed, great.

> 
> > Though I would not _expect_ any problems here, I would like to check
> > that more thoroughly. This will probably take a bit, please stand by.
> 
> I looked at this with Johannes and I am puzzled how the problem
> that bce79428773 aimed to fix occurred. Could you elaborate?

Have a look at the tree at bce79428773. Back then the i.MX7 clock driver
was registered at core_initcall level, the same level that of_probe()
was running which first called of_platform_populate() and then
of_clk_init().

Sascha

-- 
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-5555 |


From a.fatoum at pengutronix.de  Mon Sep  5 00:00:32 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 09:00:32 +0200
Subject: [PATCH] tftp: allocate at least 4096 bytes for FIFO
Message-ID: <20220905070032.536912-1-a.fatoum@pengutronix.de>

On one board, boots from /mnt/tftp currently fail for me with:

ERROR: tftp: tftp: not enough room in kfifo (only 1376 out of 1432 written

This is overly annoying, because it doesn't abort the boot and thus an
incomplete image is started, that eventually crashes.

As this didn't happen with the previous hardcoded value of 4096, restore
working order by ensuring we have at least that many bytes in the kfifo.

Fixes: 480ed057aacb ("tftp: allocate buffers and fifo dynamically")
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 fs/tftp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/tftp.c b/fs/tftp.c
index 2bffae2bf36e..e1c1b0e7269f 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -546,7 +546,7 @@ static int tftp_allocate_transfer(struct file_priv *priv)
 
 	/* multiplication is safe; both operands were checked in tftp_parse_oack()
 	   and are small integers */
-	priv->fifo = kfifo_alloc(priv->blocksize * priv->windowsize);
+	priv->fifo = kfifo_alloc(max(priv->blocksize * priv->windowsize, 4096U));
 	if (!priv->fifo)
 		goto err;
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 00:01:25 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 09:01:25 +0200
Subject: [PATCH] test: self: provide selftest_is_running()
Message-ID: <20220905070125.537483-1-a.fatoum@pengutronix.de>

For debugging during self-test run, it can be useful to enable select
logging only when the selftest is running. Provide a selftest_is_running()
function that can be used to determine whether a test is running.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 commands/selftest.c |  2 +-
 include/bselftest.h |  5 +++++
 test/self/core.c    | 26 +++++++++++++++++++++++++-
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/commands/selftest.c b/commands/selftest.c
index a10f1467fece..bb62575aa7bb 100644
--- a/commands/selftest.c
+++ b/commands/selftest.c
@@ -24,7 +24,7 @@ static int run_selftest(const char *match, bool list)
 		if (match && strcmp(test->name, match))
 			continue;
 
-		err |= test->func();
+		err |= selftest_run(test);
 		matches++;
 	}
 
diff --git a/include/bselftest.h b/include/bselftest.h
index 21eeba0526ef..f03c803b6553 100644
--- a/include/bselftest.h
+++ b/include/bselftest.h
@@ -15,6 +15,7 @@ struct selftest {
 	const char *name;
 	int (*func)(void);
 	struct list_head list;
+	bool running;
 };
 
 static inline int selftest_report(unsigned int total_tests, unsigned int failed_tests,
@@ -71,4 +72,8 @@ static inline void selftests_run(void)
 	}							\
 	__bselftest_initcall(_func##_bselftest_register);
 
+
+int selftest_run(struct selftest *test);
+bool selftest_is_running(struct selftest *test);
+
 #endif
diff --git a/test/self/core.c b/test/self/core.c
index caa4c27f6def..40f5ee842d16 100644
--- a/test/self/core.c
+++ b/test/self/core.c
@@ -7,6 +7,30 @@
 
 LIST_HEAD(selftests);
 
+int selftest_run(struct selftest *test)
+{
+	int err;
+
+	test->running = true;
+	err = test->func();
+	test->running = false;
+
+	return err;
+}
+
+bool selftest_is_running(struct selftest *test)
+{
+	if (test)
+		return test->running;
+
+	list_for_each_entry(test, &selftests, list) {
+		if (selftest_is_running(test))
+			return true;
+	}
+
+	return false;
+}
+
 void selftests_run(void)
 {
 	struct selftest *test;
@@ -15,7 +39,7 @@ void selftests_run(void)
 	pr_notice("Configured tests will run now\n");
 
 	list_for_each_entry(test, &selftests, list)
-		err |= test->func();
+		err |= selftest_run(test);
 
 	if (err)
 		pr_err("Some selftests failed\n");
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 00:02:08 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 09:02:08 +0200
Subject: [PATCH] of: of_probe: create board's machine device at the earliest
Message-ID: <20220905070208.538012-1-a.fatoum@pengutronix.de>

We currently create devices for matching reserved memory entries and
firmware before creating the machine device. In a deep probe system, the
machine driver would be probed directly at registration and as such
needs to be probed before other devices are created, so it can disable
other devices if needed. Move the machine device registration to the
top, so board drivers can disabled reserved memory entries and firmware
if they need to.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/base.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 52e6a9294e11..6a51dd71793d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2503,6 +2503,12 @@ int of_probe(void)
 	if(!root_node)
 		return -ENODEV;
 
+	/*
+	 * We do this first thing, so board drivers can patch the device
+	 * tree prior to device creation if needed.
+	 */
+	of_platform_device_create_root(root_node);
+
 	/*
 	 * Handle certain compatibles explicitly, since we don't want to create
 	 * platform_devices for every node in /reserved-memory with a
@@ -2515,8 +2521,6 @@ int of_probe(void)
 	if (node)
 		of_platform_populate(node, NULL, NULL);
 
-	of_platform_device_create_root(root_node);
-
 	of_platform_populate(root_node, of_default_bus_match_table, NULL);
 
 	return 0;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 00:02:47 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 09:02:47 +0200
Subject: [PATCH] blspec: fix memory leak handling NFS URLs
Message-ID: <20220905070247.538308-1-a.fatoum@pengutronix.de>

parse_nfs_url() returns either an allocated string on success or an
error pointer otherwise. blspec_bootentry_provider() will early
exit if the path couldn't be resolved and thus not free() the string.

Fix this memory leak. While at it, change parse_nfs_url() to return NULL
on error. The error code is unused and just returning NULL, simplifies
the code.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/blspec.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/common/blspec.c b/common/blspec.c
index 9bb25ee72123..d391f690ad0c 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -341,10 +341,10 @@ static char *parse_nfs_url(const char *url)
 	int ret;
 
 	if (!IS_ENABLED(CONFIG_FS_NFS))
-		return ERR_PTR(-ENOSYS);
+		return NULL;
 
 	if (strncmp(url, "nfs://", 6))
-		return ERR_PTR(-EINVAL);
+		return NULL;
 
 	url += 6;
 
@@ -413,7 +413,7 @@ out:
 	if (ret)
 		free(mountpath);
 
-	return ret ? ERR_PTR(ret) : mountpath;
+	return ret ? NULL : mountpath;
 }
 
 /*
@@ -824,12 +824,12 @@ static int blspec_bootentry_provider(struct bootentries *bootentries,
 	if (*name == '/' || !strncmp(name, "nfs://", 6)) {
 		char *nfspath = parse_nfs_url(name);
 
-		if (!IS_ERR(nfspath))
+		if (nfspath)
 			name = nfspath;
 
 		ret = stat(name, &s);
 		if (ret)
-			return found;
+			goto out;
 
 		if (S_ISDIR(s.st_mode))
 			ret = blspec_scan_directory(bootentries, name);
@@ -838,8 +838,8 @@ static int blspec_bootentry_provider(struct bootentries *bootentries,
 		if (ret > 0)
 			found += ret;
 
-		if (!IS_ERR(nfspath))
-			free(nfspath);
+out:
+		free(nfspath);
 	}
 
 	return found;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 00:04:06 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 09:04:06 +0200
Subject: [PATCH] soc: imx: gpcv2: make available to all i.MX8M
Message-ID: <20220905070406.539244-1-a.fatoum@pengutronix.de>

Now that the driver supports i.MX8M Mini, Nano and Plus, we should no
longer restrict it to just i.MX7 and i.MX8MQ.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/soc/imx/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
index eabe4a06d22c..624aff2ecae3 100644
--- a/drivers/soc/imx/Kconfig
+++ b/drivers/soc/imx/Kconfig
@@ -3,9 +3,9 @@ menu "i.MX SoC drivers"
 
 config IMX_GPCV2_PM_DOMAINS
         bool "i.MX GPCv2 PM domains"
-	depends on ARCH_IMX7 || ARCH_IMX8MQ
+	depends on ARCH_IMX7 || ARCH_IMX8M
 	select PM_GENERIC_DOMAINS
-	default y if ARCH_IMX7 || ARCH_IMX8MQ
+	default y if ARCH_IMX7 || ARCH_IMX8M
 
 config IMX8M_FEATCTRL
         bool "i.MX8M feature controller"
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 00:04:48 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 09:04:48 +0200
Subject: [PATCH] commands: add pm_domain for listing power domains
Message-ID: <20220905070448.539531-1-a.fatoum@pengutronix.de>

Like the regulator command, this new pm_domain command gives an easy
way for listing registered power domains and whether barebox had them
activated.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 commands/Kconfig     |  8 ++++++++
 commands/Makefile    |  1 +
 commands/pm_domain.c | 18 ++++++++++++++++++
 drivers/base/power.c | 10 ++++++++++
 include/pm_domain.h  |  2 ++
 5 files changed, 39 insertions(+)
 create mode 100644 commands/pm_domain.c

diff --git a/commands/Kconfig b/commands/Kconfig
index 3e21dc4c0500..9894ecb9aa31 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -240,6 +240,14 @@ config CMD_REGULATOR
 	  the regulator command lists the currently registered regulators and
 	  their current state.
 
+config CMD_PM_DOMAIN
+	bool
+	depends on PM_GENERIC_DOMAINS
+	prompt "pm_domain command"
+	help
+	  The pm_domain command lists the currently registered power domains and
+	  their current state.
+
 config CMD_NVMEM
 	bool
 	depends on NVMEM
diff --git a/commands/Makefile b/commands/Makefile
index 0aae8893d696..068fbb32dad7 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -116,6 +116,7 @@ obj-$(CONFIG_CMD_READF)		+= readf.o
 obj-$(CONFIG_CMD_MENUTREE)	+= menutree.o
 obj-$(CONFIG_CMD_2048)		+= 2048.o
 obj-$(CONFIG_CMD_REGULATOR)	+= regulator.o
+obj-$(CONFIG_CMD_PM_DOMAIN)	+= pm_domain.o
 obj-$(CONFIG_CMD_LSPCI)		+= lspci.o
 obj-$(CONFIG_CMD_IMD)		+= imd.o
 obj-$(CONFIG_CMD_HWCLOCK)	+= hwclock.o
diff --git a/commands/pm_domain.c b/commands/pm_domain.c
new file mode 100644
index 000000000000..ec8b769df193
--- /dev/null
+++ b/commands/pm_domain.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <command.h>
+#include <pm_domain.h>
+
+static int do_pm_domain(int argc, char *argv[])
+{
+	pm_genpd_print();
+
+	return 0;
+}
+
+BAREBOX_CMD_START(pm_domain)
+	.cmd		= do_pm_domain,
+	BAREBOX_CMD_DESC("list power domains")
+	BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+BAREBOX_CMD_END
diff --git a/drivers/base/power.c b/drivers/base/power.c
index 4a206051b137..3eabf3c897b2 100644
--- a/drivers/base/power.c
+++ b/drivers/base/power.c
@@ -266,3 +266,13 @@ int genpd_dev_pm_attach(struct device_d *dev)
 	return __genpd_dev_pm_attach(dev, dev->device_node, 0, true);
 }
 EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+
+void pm_genpd_print(void)
+{
+	struct generic_pm_domain *genpd;
+
+	printf("%-20s %6s\n", "name", "active");
+	list_for_each_entry(genpd, &gpd_list, gpd_list_node)
+		printf("%-20s %6s\n", genpd->name,
+		       genpd->status == GPD_STATE_ACTIVE ? "on" : "off");
+}
diff --git a/include/pm_domain.h b/include/pm_domain.h
index 48fd170007fd..ff1aa3751165 100644
--- a/include/pm_domain.h
+++ b/include/pm_domain.h
@@ -54,6 +54,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd, void *gov, bool is_off);
 int of_genpd_add_provider_simple(struct device_node *np,
 				 struct generic_pm_domain *genpd);
 
+void pm_genpd_print(void);
+
 #else
 
 static inline int pm_genpd_init(struct generic_pm_domain *genpd,
-- 
2.30.2



From enrico.scholz at sigma-chemnitz.de  Mon Sep  5 01:56:55 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Mon,  5 Sep 2022 10:56:55 +0200
Subject: [PATCH 0/3] tftp fixups
Message-ID: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>

Fixups for the "tftp" branch in next.

Enrico Scholz (3):
  fixup! tftp: implement 'windowsize' (RFC 7440) support
  fixup! tftp: detect out-of-memory situations
  tftp: make read() fail in error case

 fs/tftp.c | 29 ++++++++++++++++++++++-------
 1 file changed, 22 insertions(+), 7 deletions(-)

-- 
2.37.2



From enrico.scholz at sigma-chemnitz.de  Mon Sep  5 01:56:57 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Mon,  5 Sep 2022 10:56:57 +0200
Subject: [PATCH 2/3] fixup! tftp: detect out-of-memory situations
In-Reply-To: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
References: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
Message-ID: <20220905085658.3854939-3-enrico.scholz@sigma-chemnitz.de>

minor typo fix

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
---
 fs/tftp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/tftp.c b/fs/tftp.c
index a3fe7dfd590e..9a3753e50e37 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -591,7 +591,7 @@ static void tftp_put_data(struct file_priv *priv, uint16_t block,
 	sz = kfifo_put(priv->fifo, pkt, len);
 
 	if (sz != len) {
-		pr_err("tftp: not enough room in kfifo (only %u out of %zu written\n",
+		pr_err("tftp: not enough room in kfifo (only %u out of %zu written)\n",
 		       sz, len);
 		priv->err = -ENOMEM;
 		priv->state = STATE_DONE;
-- 
2.37.2



From enrico.scholz at sigma-chemnitz.de  Mon Sep  5 01:56:58 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Mon,  5 Sep 2022 10:56:58 +0200
Subject: [PATCH 3/3] tftp: make read() fail in error case
In-Reply-To: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
References: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
Message-ID: <20220905085658.3854939-4-enrico.scholz@sigma-chemnitz.de>

when tftp transfer goes in error state e.g. due to error packets sent
from the server or (unexpected) internal problems, let the read() fail
instead of ignoring these errors silently and corrupting the output.

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
---
 fs/tftp.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/fs/tftp.c b/fs/tftp.c
index 9a3753e50e37..2592da94dd34 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -1017,7 +1017,7 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize)
 {
 	struct file_priv *priv = f->priv;
 	size_t outsize = 0, now;
-	int ret;
+	int ret = 0;
 
 	pr_vdebug("%s %zu\n", __func__, insize);
 
@@ -1026,8 +1026,11 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize)
 		outsize += now;
 		buf += now;
 		insize -= now;
-		if (priv->state == STATE_DONE)
-			return outsize;
+
+		if (priv->state == STATE_DONE) {
+			ret = priv->err;
+			break;
+		}
 
 		/* send the ACK only when fifo has been nearly depleted; else,
 		   when tftp_read() is called with small 'insize' values, it
@@ -1041,9 +1044,12 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize)
 		if (ret == TFTP_ERR_RESEND)
 			tftp_send(priv);
 		if (ret < 0)
-			return ret;
+			break;
 	}
 
+	if (ret < 0)
+		return ret;
+
 	return outsize;
 }
 
-- 
2.37.2



From enrico.scholz at sigma-chemnitz.de  Mon Sep  5 01:56:56 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Mon,  5 Sep 2022 10:56:56 +0200
Subject: [PATCH 1/3] fixup! tftp: implement 'windowsize' (RFC 7440) support
In-Reply-To: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
References: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
Message-ID: <20220905085658.3854939-2-enrico.scholz@sigma-chemnitz.de>

avoid fifo overflow on read() with small buffer sizes.

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
---
 fs/tftp.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/fs/tftp.c b/fs/tftp.c
index 2bffae2bf36e..a3fe7dfd590e 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -78,6 +78,9 @@
 /* size of cache which deals with udp reordering */
 #define TFTP_WINDOW_CACHE_NUM	CONFIG_FS_TFTP_REORDER_CACHE_SIZE
 
+/* allocate this number of blocks more than needed in the fifo */
+#define TFTP_EXTRA_BLOCKS	2
+
 /* marker for an emtpy 'tftp_cache' */
 #define TFTP_CACHE_NO_ID	(-1)
 
@@ -546,7 +549,8 @@ static int tftp_allocate_transfer(struct file_priv *priv)
 
 	/* multiplication is safe; both operands were checked in tftp_parse_oack()
 	   and are small integers */
-	priv->fifo = kfifo_alloc(priv->blocksize * priv->windowsize);
+	priv->fifo = kfifo_alloc(priv->blocksize *
+				 (priv->windowsize + TFTP_EXTRA_BLOCKS));
 	if (!priv->fifo)
 		goto err;
 
@@ -1025,7 +1029,12 @@ static int tftp_read(struct device_d *dev, FILE *f, void *buf, size_t insize)
 		if (priv->state == STATE_DONE)
 			return outsize;
 
-		if (priv->last_block == priv->ack_block)
+		/* send the ACK only when fifo has been nearly depleted; else,
+		   when tftp_read() is called with small 'insize' values, it
+		   is possible that there is read more data from the network
+		   than consumed by kfifo_get() and the fifo overflows */
+		if (priv->last_block == priv->ack_block &&
+		    kfifo_len(priv->fifo) <= TFTP_EXTRA_BLOCKS * priv->blocksize)
 			tftp_send(priv);
 
 		ret = tftp_poll(priv);
-- 
2.37.2



From enrico.scholz at sigma-chemnitz.de  Mon Sep  5 02:03:05 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Mon, 05 Sep 2022 11:03:05 +0200
Subject: [PATCH] tftp: allocate at least 4096 bytes for FIFO
In-Reply-To: <20220905070032.536912-1-a.fatoum@pengutronix.de> (Ahmad Fatoum's
	message of "Mon, 5 Sep 2022 09:00:32 +0200")
References: <20220905070032.536912-1-a.fatoum@pengutronix.de>
Message-ID: <ly1qsq2nxy.fsf@ensc-pc.intern.sigma-chemnitz.de>

Ahmad Fatoum <a.fatoum at pengutronix.de> writes:

> On one board, boots from /mnt/tftp currently fail for me with:
>
> ERROR: tftp: tftp: not enough room in kfifo (only 1376 out of 1432 written

Thanks for noticing that; I sent fixups for the recent patchset.

Perhaps, can you test it on your failing platform with changing

| #define TFTP_EXTRA_BLOCKS	2

to

| #define TFTP_EXTRA_BLOCKS	0

?

This should turn off the workaround of over-allocating memory and isolate
(and verify) the fix for the real problem.



Enrico


From a.fatoum at pengutronix.de  Mon Sep  5 02:55:28 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:28 +0200
Subject: [PATCH 03/32] meminfo: support SANDBOX build with DEBUG log level
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-4-a.fatoum@pengutronix.de>

We don't necessarily have _[se]text, __bss_(start|stop) symbols on
sandbox, so we shouldn't reference these there in the debug prints.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/meminfo.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/common/meminfo.c b/common/meminfo.c
index e6b251e5bfee..f4994959b6ae 100644
--- a/common/meminfo.c
+++ b/common/meminfo.c
@@ -12,8 +12,10 @@ static int display_meminfo(void)
 	ulong mend   = mem_malloc_end();
 	ulong msize  = mend - mstart + 1;
 
-	pr_debug("barebox code: 0x%p -> 0x%p\n", _stext, _etext - 1);
-	pr_debug("bss segment:  0x%p -> 0x%p\n", __bss_start, __bss_stop - 1);
+	if (!IS_ENABLED(CONFIG_SANDBOX)) {
+		pr_debug("barebox code: 0x%p -> 0x%p\n", _stext, _etext - 1);
+		pr_debug("bss segment:  0x%p -> 0x%p\n", __bss_start, __bss_stop - 1);
+	}
 	pr_info("malloc space: 0x%08lx -> 0x%08lx (size %s)\n",
 		mstart, mend, size_human_readable(msize));
 	return 0;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:27 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:27 +0200
Subject: [PATCH 02/32] clk: have SCMI and SiFive clock controllers depend on COMMON_CLK
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-3-a.fatoum@pengutronix.de>

Both drivers require CCF support, so move these into a new if
COMMON_CLK. As we already have COMMON_CLK_STM32 with the same
requirement, move it in there as well.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/clk/Kconfig | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 5b5acf4e0656..0faea6488e59 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -20,10 +20,11 @@ config CLK_SOCFPGA
 	select COMMON_CLK_OF_PROVIDER
 	default y if ARCH_SOCFPGA && OFDEVICE
 
+if COMMON_CLK
 
 config COMMON_CLK_STM32F
 	bool "STM32F4 and STM32F7 clock driver" if COMPILE_TEST
-	depends on COMMON_CLK && ARCH_STM32
+	depends on ARCH_STM32
 	help
 	  Support for stm32f4 and stm32f7 SoC families clocks
 
@@ -38,3 +39,5 @@ config COMMON_CLK_SCMI
 	  firmware providing all the clock controls.
 
 source "drivers/clk/sifive/Kconfig"
+
+endif
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:44 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:44 +0200
Subject: [PATCH 19/32] crypto: caam - delete unused variable
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-20-a.fatoum@pengutronix.de>

We don't use nprop anywhere, so drop it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/crypto/caam/jr.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 70e016486a7e..6c4867914753 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -289,7 +289,6 @@ static int caam_jr_init(struct device_d *dev)
  */
 int caam_jr_probe(struct device_d *dev)
 {
-	struct device_node *nprop;
 	struct caam_job_ring __iomem *ctrl;
 	struct caam_drv_private_jr *jrpriv;
 	static int total_jobrs;
@@ -303,7 +302,6 @@ int caam_jr_probe(struct device_d *dev)
 	/* save ring identity relative to detection */
 	jrpriv->ridx = total_jobrs++;
 
-	nprop = dev->device_node;
 	/* Get configuration properties from device tree */
 	/* First, get register page */
 	ctrl = dev_get_mem_region(dev, 0);
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:32 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:32 +0200
Subject: [PATCH 07/32] fs: remove never-read initializer in mount_all()
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-8-a.fatoum@pengutronix.de>

list_for_each_entry will initialize cdev for each iteration, so the
initial assignment is never used, thus drop it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 fs/fs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/fs.c b/fs/fs.c
index 620cd6597a63..14d5f7330457 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -1014,7 +1014,7 @@ void mount_all(void)
 		device_detect(dev);
 
 	for_each_block_device(bdev) {
-		struct cdev *cdev = &bdev->cdev;
+		struct cdev *cdev;
 
 		list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list)
 			cdev_mount_default(cdev, NULL);
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:29 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:29 +0200
Subject: [PATCH 04/32] net: phy: micrel: drop useless assignment of dummy read
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-5-a.fatoum@pengutronix.de>

The result of the PHY read is never used and the comment suggests this
is intentional. Still static analysis warns about this, so remove the
variable assignment and leave the read. We cast it to (void) to avoid
possible future __must_check warnings.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/net/phy/micrel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index cf593ee6a6e6..8a30faa92b8a 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -554,7 +554,7 @@ static int ksz8873mll_read_status(struct phy_device *phydev)
 	int regval;
 
 	/* dummy read */
-	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+	(void)phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
 
 	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:33 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:33 +0200
Subject: [PATCH 08/32] usb: otg: always propagate failure to register parameters
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-9-a.fatoum@pengutronix.de>

We assign the result of the first dev_add_param_enum() to a variable,
but don't use the variable for anything. Refactor device registration
and parameter addition to a new helper function and do error checking
right.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/usb/otg/otgdev.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c
index 129b1cf5e14b..29cb0d362b9b 100644
--- a/drivers/usb/otg/otgdev.c
+++ b/drivers/usb/otg/otgdev.c
@@ -42,6 +42,22 @@ static const char *otg_mode_names[] = {
 	[USB_DR_MODE_OTG] = "otg",
 };
 
+static int register_otg_device(struct device_d *dev, struct otg_mode *otg)
+{
+	struct param_d *param_mode;
+	int ret;
+
+	ret = register_device(dev);
+	if (ret)
+		return ret;
+
+	param_mode = dev_add_param_enum(dev, "mode",
+			otg_set_mode, NULL, &otg->var_mode,
+			otg_mode_names, ARRAY_SIZE(otg_mode_names), otg);
+
+	return PTR_ERR_OR_ZERO(param_mode);
+}
+
 static struct device_d otg_device = {
 	.name = "otg",
 	.id = DEVICE_ID_SINGLE,
@@ -51,7 +67,6 @@ int usb_register_otg_device(struct device_d *parent,
 			    int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx)
 {
 	int ret;
-	struct param_d *param_mode;
 	struct otg_mode *otg;
 
 	otg = xzalloc(sizeof(*otg));
@@ -68,22 +83,10 @@ int usb_register_otg_device(struct device_d *parent,
 	/* register otg.mode as an alias of otg0.mode */
 	if (otg_device.parent == NULL) {
 		otg_device.parent = parent;
-		ret = register_device(&otg_device);
+		ret = register_otg_device(&otg_device, otg);
 		if (ret)
 			return ret;
-
-		param_mode = dev_add_param_enum(&otg_device, "mode",
-				otg_set_mode, NULL, &otg->var_mode,
-				otg_mode_names, ARRAY_SIZE(otg_mode_names), otg);
 	}
 
-	ret = register_device(&otg->dev);
-	if (ret)
-		return ret;
-
-	param_mode = dev_add_param_enum(&otg->dev, "mode",
-			otg_set_mode, NULL, &otg->var_mode,
-			otg_mode_names, ARRAY_SIZE(otg_mode_names), otg);
-
-	return PTR_ERR_OR_ZERO(param_mode);
+	return register_otg_device(&otg->dev, otg);
 }
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:26 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:26 +0200
Subject: [PATCH 01/32] clk: define stub implementation for clk_get_parent
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-2-a.fatoum@pengutronix.de>

To make it easier to build drivers utilizing clk_get_parent on sandbox
for static analysis, provide a stub implementation of the function.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 include/linux/clk.h | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/include/linux/clk.h b/include/linux/clk.h
index 42c64d650d1f..b18fc733843d 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -128,14 +128,6 @@ int clk_hw_set_rate(struct clk_hw *hw, unsigned long rate);
 int clk_set_parent(struct clk *clk, struct clk *parent);
 int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *hwp);
 
-/**
- * clk_get_parent - get the parent clock source for this clock
- * @clk: clock source
- *
- * Returns struct clk corresponding to parent clock source, or
- * valid IS_ERR() condition containing errno.
- */
-struct clk *clk_get_parent(struct clk *clk);
 struct clk_hw *clk_hw_get_parent(struct clk_hw *hw);
 
 int clk_set_phase(struct clk *clk, int degrees);
@@ -658,6 +650,14 @@ struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
 struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
+/**
+ * clk_get_parent - get the parent clock source for this clock
+ * @clk: clock source
+ *
+ * Returns struct clk corresponding to parent clock source, or
+ * valid IS_ERR() condition containing errno.
+ */
+struct clk *clk_get_parent(struct clk *clk);
 unsigned int of_clk_get_parent_count(struct device_node *np);
 int of_clk_parent_fill(struct device_node *np, const char **parents,
 		       unsigned int size);
@@ -717,6 +717,10 @@ static inline unsigned int of_clk_get_parent_count(struct device_node *np)
 {
 	return 0;
 }
+static inline struct clk *clk_get_parent(struct clk *clk)
+{
+	return ERR_PTR(-ENOENT);
+}
 static inline int of_clk_init(struct device_node *root,
 			      const struct of_device_id *matches)
 {
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:47 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:47 +0200
Subject: [PATCH 22/32] of: fdt: gracefully handle out-of-place properties
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-23-a.fatoum@pengutronix.de>

node is initialized by FDT_BEGIN_NODE. In case where a FDT_PROP is
encountered before the first FDT_BEGIN_NODE, we would end up
dereferencing a NULL pointer. Handle such malformed device trees
gracefully by returning with an -ESPIPE error instead.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/fdt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 42f45bbd4fb5..01d7dc37439f 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -212,7 +212,7 @@ static struct device_node *__of_unflatten_dtb(const void *infdt, int size,
 			nodep = fdt_prop->data;
 
 			name = dt_string(&f, dt_strings, fdt32_to_cpu(fdt_prop->nameoff));
-			if (!name) {
+			if (!name || !node) {
 				ret = -ESPIPE;
 				goto err;
 			}
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:53 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:53 +0200
Subject: [PATCH 28/32] fs: fat: propagate f_lseek failure
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-29-a.fatoum@pengutronix.de>

We store an error code to ret, but don't act on it. Fix this.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 fs/fat/fat.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 84bfe69089e5..7d888817c145 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -196,6 +196,11 @@ static int fat_open(struct device_d *dev, FILE *file, const char *filename)
 
 	if (file->flags & O_APPEND) {
 		ret = f_lseek(f_file, f_file->fsize);
+		if (ret) {
+			f_close(f_file);
+			free(f_file);
+			return -EINVAL;
+		}
 	}
 
 	file->priv = f_file;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:49 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:49 +0200
Subject: [PATCH 24/32] of: partition: drop unused variable
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-25-a.fatoum@pengutronix.de>

The name variable is unused anywhere, so just drop it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/partition.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/of/partition.c b/drivers/of/partition.c
index 6c05e28ea9a8..abbda674d6cb 100644
--- a/drivers/of/partition.c
+++ b/drivers/of/partition.c
@@ -31,7 +31,6 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
 	struct cdev *new;
 	const __be32 *reg;
 	u64 offset, size;
-	const char *name;
 	int len;
 	unsigned long flags = 0;
 	int na, ns;
@@ -60,8 +59,6 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
 	if (!partname)
 		return NULL;
 
-	name = (char *)partname;
-
 	debug("add partition: %s.%s 0x%08llx 0x%08llx\n", cdev->name, partname, offset, size);
 
 	if (of_get_property(node, "read-only", NULL))
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:51 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:51 +0200
Subject: [PATCH 26/32] phy: core: drop useless else clause
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-27-a.fatoum@pengutronix.de>

ret is not read below, so we don't need this override.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/phy/phy-core.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 8a57bd1aa9d4..3a36f0a1b26d 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -169,8 +169,6 @@ int phy_power_on(struct phy *phy)
 			dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
 			goto out;
 		}
-	} else {
-		ret = 0; /* Override possible ret == -ENOTSUPP */
 	}
 	++phy->power_count;
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:42 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:42 +0200
Subject: [PATCH 17/32] password: avoid static analyzer false positive
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-18-a.fatoum@pengutronix.de>

default_passwd is a compile-time constant. In case, where it's unset,
the function will early-return and the static analyzer will warn about
len being initialized, but never used, move the length calculation later
to avoid this false positive.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/password.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/password.c b/common/password.c
index aea7c7ff5d21..55b2d1093ab9 100644
--- a/common/password.c
+++ b/common/password.c
@@ -148,8 +148,7 @@ static unsigned char to_hexa(unsigned char c)
 
 static int read_default_passwd(unsigned char *sum, size_t length)
 {
-	int i = 0;
-	int len = strlen(default_passwd);
+	int len, i = 0;
 	unsigned char *buf = (unsigned char *)default_passwd;
 	unsigned char c;
 
@@ -159,6 +158,7 @@ static int read_default_passwd(unsigned char *sum, size_t length)
 	if (!sum || length < 1)
 		return -EINVAL;
 
+	len = strlen(default_passwd);
 	for (i = 0; i < len && length > 0; i++) {
 		c = buf[i];
 		i++;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:46 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:46 +0200
Subject: [PATCH 21/32] nvmem: core: drop always true condition
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-22-a.fatoum@pengutronix.de>

The iterator in a list_for_each_entry's body can never be NULL, so drop
the needless NULL check.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/nvmem/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index c344738abd51..c89ad08f81d8 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -136,7 +136,7 @@ static struct nvmem_cell *nvmem_find_cell(const char *cell_id)
 	struct nvmem_cell *p;
 
 	list_for_each_entry(p, &nvmem_cells, node)
-		if (p && !strcmp(p->name, cell_id))
+		if (!strcmp(p->name, cell_id))
 			return p;
 
 	return NULL;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:43 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:43 +0200
Subject: [PATCH 18/32] regmap-mmio: regmap_mmio_get_min_stride: unify branches for readability
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-19-a.fatoum@pengutronix.de>

We just return min_stride after the switch statement, so instead of
returning 0 directly for 8 bits, just have all code reach the same return
at the end.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/base/regmap/regmap-mmio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index c8422ca46f3c..7b1501df933b 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -46,7 +46,7 @@ static int regmap_mmio_get_min_stride(size_t val_bits)
 	case 8:
 		/* The core treats 0 as 1 */
 		min_stride = 0;
-		return 0;
+		break;
 	case 16:
 		min_stride = 2;
 		break;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:41 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:41 +0200
Subject: [PATCH 16/32] of: refactor for of_fixup_reserved_memory() for clarity
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-17-a.fatoum@pengutronix.de>

pp was never used and the ?: construct made the code needlessly terse.
Use it and make the code a bit clearer.

No functional change.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/oftree.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/common/oftree.c b/common/oftree.c
index e459f84601a3..38752e2c191d 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -292,8 +292,10 @@ int of_fixup_reserved_memory(struct device_node *root, void *_res)
 	if (ret)
 		of_property_write_u32(node, "#size-cells", size_n_cells);
 
-	pp = of_find_property(node, "ranges", &rangelen) ?: of_new_property(node, "ranges", NULL, 0);
-	if (rangelen) {
+	pp = of_find_property(node, "ranges", &rangelen);
+	if (!pp) {
+		of_new_property(node, "ranges", NULL, 0);
+	} else if (rangelen) {
 		pr_warn("reserved-memory ranges not 1:1 mapped. Aborting fixup\n");
 		return -EINVAL;
 	}
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:57 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:57 +0200
Subject: [PATCH 32/32] net: fastboot: keep error message initialized at all times
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-33-a.fatoum@pengutronix.de>

Static analyzer points out that an unfortunate sequence of fastboot
commands can have us end up with an uninitialized error_msg, so
initialize it in that case, so we have something in there at all times.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 net/fastboot.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/fastboot.c b/net/fastboot.c
index aa483f57a74e..932eb05c4341 100644
--- a/net/fastboot.c
+++ b/net/fastboot.c
@@ -126,6 +126,8 @@ static void fastboot_send(struct fastboot_net *fbn,
 
 	if (error_msg)
 		header.id = FASTBOOT_ERROR;
+	else
+		error_msg = "no error";
 
 	/* send header */
 	memcpy(packet, &header, sizeof(header));
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:55 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:55 +0200
Subject: [PATCH 30/32] lib: parse_area_spec: guard against NULL pointer dereference
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-31-a.fatoum@pengutronix.de>

If mem_parse_options is called with an optstr containing x, but with
swab == NULL, we will end up doing a NULL pointer dereference. Add a
check that avoids this from happening.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 lib/misc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/misc.c b/lib/misc.c
index 532f0bfc1eb5..2d5f7c198586 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -159,6 +159,8 @@ int mem_parse_options(int argc, char *argv[], char *optstr, int *mode,
 			*destfile = optarg;
 			break;
 		case 'x':
+			if (!swab)
+				return -EINVAL;
 			*swab = 1;
 			break;
 		default:
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:36 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:36 +0200
Subject: [PATCH 11/32] of: silence warning about never-read error assignment
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-12-a.fatoum@pengutronix.de>

err is assigned specific error codes, but they are not propagated and
instead NULL is returned for error. Make it explicit that we handle all
errors the same by typecasting to (void).

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/resolver.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
index 2457ae96a412..510d36f95192 100644
--- a/drivers/of/resolver.c
+++ b/drivers/of/resolver.c
@@ -272,6 +272,7 @@ out:
 err:
 	of_delete_node(result);
 
+	(void)err;
 	return NULL;
 
 }
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:52 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:52 +0200
Subject: [PATCH 27/32] fs: ext4: ext_barebox: handle ext_get_inode() errors
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-28-a.fatoum@pengutronix.de>

Static analyzer laments ext_get_inode, which can fail not having its
failure condition checked. Fix this.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 fs/ext4/ext_barebox.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/fs/ext4/ext_barebox.c b/fs/ext4/ext_barebox.c
index 8f318a49c008..6c7c9885c48f 100644
--- a/fs/ext4/ext_barebox.c
+++ b/fs/ext4/ext_barebox.c
@@ -127,8 +127,8 @@ static struct dentry *ext_lookup(struct inode *dir, struct dentry *dentry,
 
 	if (ino) {
 		inode = ext_get_inode(dir->i_sb, ino);
-
-		d_add(dentry, inode);
+		if (inode)
+			d_add(dentry, inode);
 	}
 
 	return NULL;
@@ -218,6 +218,8 @@ struct inode *ext_get_inode(struct super_block *sb, int ino)
 	node = container_of(inode, struct ext2fs_node, i);
 
 	ret = ext4fs_read_inode(fs->data, ino, &node->inode);
+	if (ret)
+		return NULL;
 
 	inode->i_ino = ino;
 	inode->i_mode = le16_to_cpu(node->inode.mode);
@@ -262,23 +264,27 @@ static int ext_probe(struct device_d *dev)
 
 	ret = fsdev_open_cdev(fsdev);
 	if (ret)
-		goto err_open;
+		goto err;
 
 	fs->cdev = fsdev->cdev;
 
 	ret = ext4fs_mount(fs);
 	if (ret)
-		goto err_mount;
+		goto err;
 
 	sb->s_op = &ext_ops;
 
 	inode = ext_get_inode(sb, 2);
+	if (!inode) {
+		ret = -EINVAL;
+		goto err;
+	}
+
 	sb->s_root = d_make_root(inode);
 
 	return 0;
 
-err_mount:
-err_open:
+err:
 	free(fs);
 
 	return ret;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:39 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:39 +0200
Subject: [PATCH 14/32] bthread: fix null pointer dereference in error path
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-15-a.fatoum@pengutronix.de>

When borting bthread creation early, we would end up calling
bthread_free on a NULL bthread, causing a NULL pointer dereference.

As it's customary for free functions to gracefully handle a NULL
argument, have bthread_free follow suit.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/bthread.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/common/bthread.c b/common/bthread.c
index 46e6987149bb..d40c0b0f9e3a 100644
--- a/common/bthread.c
+++ b/common/bthread.c
@@ -70,6 +70,8 @@ bool bthread_is_main(struct bthread *bthread)
 
 static void bthread_free(struct bthread *bthread)
 {
+	if (!bthread)
+		return;
 	free(bthread->stack);
 	free(bthread->name);
 	free(bthread);
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:35 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:35 +0200
Subject: [PATCH 10/32] state: propagate failure to fixup enum32 into DT
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-11-a.fatoum@pengutronix.de>

We assign to ret, but don't use the value anywhere laments the static
analyzer. Remedy that.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/state/state_variables.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/common/state/state_variables.c b/common/state/state_variables.c
index f112c60bf602..cb85f3a92602 100644
--- a/common/state/state_variables.c
+++ b/common/state/state_variables.c
@@ -180,6 +180,8 @@ static int state_enum32_export(struct state_variable *var,
 		str += sprintf(str, "%s", enum32->names[i]) + 1;
 
 	ret = of_set_property(node, "names", prop, len, 1);
+	if (ret)
+		return ret;
 
 	free(prop);
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:34 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:34 +0200
Subject: [PATCH 09/32] usb: dwc2: gracefully handle unknown hs_phy_type
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-10-a.fatoum@pengutronix.de>

Static analysis shows that, we may not enter the switch and thus write
an uninitialized value. Warn if we indeed reach this case and handle it
as if the register read GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED for now.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/usb/dwc2/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 8be5c91f98a1..459ebc65372c 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -61,6 +61,9 @@ static void dwc2_set_param_phy_type(struct dwc2 *dwc2)
 	case GHWCFG2_HS_PHY_TYPE_ULPI:
 		val = DWC2_PHY_TYPE_PARAM_ULPI;
 		break;
+	default:
+		dwc2_warn(dwc2, "Unhandled HS PHY type\n");
+		fallthrough;
 	case GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED:
 		val = DWC2_PHY_TYPE_PARAM_FS;
 		break;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:37 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:37 +0200
Subject: [PATCH 12/32] commands: trigger: drop unused variable
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-13-a.fatoum@pengutronix.de>

Static analyzer correctly identifies led as being set, but always
overwritten later on. As the later assignments all have their own
argument count check, so we can just drop the first assignment.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 commands/trigger.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/commands/trigger.c b/commands/trigger.c
index c1402b66f049..d2802080b96f 100644
--- a/commands/trigger.c
+++ b/commands/trigger.c
@@ -16,7 +16,7 @@
 
 static int do_trigger(int argc, char *argv[])
 {
-	struct led *led = NULL;
+	struct led *led;
 	int opt, ret = 0;
 	int cmd = LED_COMMAND_SHOW_INFO;
 	enum led_trigger trigger;
@@ -35,9 +35,6 @@ static int do_trigger(int argc, char *argv[])
 		}
 	}
 
-	if (optind < argc)
-		led = led_by_name_or_number(argv[optind]);
-
 	switch (cmd) {
 	case LED_COMMAND_SHOW_INFO:
 		led_triggers_show_info();
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:50 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:50 +0200
Subject: [PATCH 25/32] serial: ns16550_pci: drop useless assignment
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-26-a.fatoum@pengutronix.de>

Code was imported from the kernel and the kernel had this fixed in the
meantime, so follow suit here.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/serial/serial_ns16550_pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/serial/serial_ns16550_pci.c b/drivers/serial/serial_ns16550_pci.c
index fde8f718dd51..0d7b686fef0a 100644
--- a/drivers/serial/serial_ns16550_pci.c
+++ b/drivers/serial/serial_ns16550_pci.c
@@ -1203,7 +1203,7 @@ static int pci_quatech_init(struct pci_dev *dev)
 			outl(inl(base + 0x38) | 0x00002000, base + 0x38);
 			tmp = inl(base + 0x3c);
 			outl(tmp | 0x01000000, base + 0x3c);
-			outl(tmp &= ~0x01000000, base + 0x3c);
+			outl(tmp & ~0x01000000, base + 0x3c);
 		}
 	}
 	return 0;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:45 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:45 +0200
Subject: [PATCH 20/32] misc: ubootvar: always initialize struct ubootvar_data::flag
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-21-a.fatoum@pengutronix.de>

The flag member is only relevant to redundant environments, still we
shouldn't store garbage there for the non-redundant case. Thus
initialize it to an acceptable default: FLAG_NONE.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/misc/ubootvar.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/ubootvar.c b/drivers/misc/ubootvar.c
index d98a6ed9a742..723e9e2b547a 100644
--- a/drivers/misc/ubootvar.c
+++ b/drivers/misc/ubootvar.c
@@ -181,7 +181,7 @@ static int ubootenv_probe(struct device_d *dev)
 	unsigned int crc_ok = 0;
 	int ret, i, current, count = 0;
 	uint32_t crc[2];
-	uint8_t flag[2];
+	uint8_t flag[2] = { FLAG_NONE, FLAG_NONE };
 	size_t size[2];
 	void *blob[2] = { NULL, NULL };
 	uint8_t *data[2];
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:31 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:31 +0200
Subject: [PATCH 06/32] nvmem: core: propagate read failure
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-7-a.fatoum@pengutronix.de>

The read may fail and we may not depend on v's value then. Propagate the
error correctly to fix this.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/nvmem/core.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index c5fe5f6b767a..c344738abd51 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -591,6 +591,9 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
 
 		/* setup the first byte with lsb bits from nvmem */
 		rc = nvmem->bus->read(nvmem->priv, cell->offset, &v, 1);
+		if (IS_ERR_VALUE(rc))
+			return ERR_PTR(rc);
+
 		*b++ |= GENMASK(bit_offset - 1, 0) & v;
 
 		/* setup rest of the byte if any */
@@ -609,6 +612,9 @@ static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
 		/* setup the last byte with msb bits from nvmem */
 		rc = nvmem->bus->read(nvmem->priv, cell->offset + cell->bytes - 1,
 				      &v, 1);
+		if (IS_ERR_VALUE(rc))
+			return ERR_PTR(rc);
+
 		*p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
 
 	}
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:40 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:40 +0200
Subject: [PATCH 15/32] common: env: drop never-read initialization
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-16-a.fatoum@pengutronix.de>

c is used a temporary variable later on for context pushing and its
initializer is never read, so drop it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/env.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/env.c b/common/env.c
index 5ac1e62b8c79..9e9988e415cf 100644
--- a/common/env.c
+++ b/common/env.c
@@ -80,7 +80,7 @@ int env_push_context(void)
  */
 int env_pop_context(void)
 {
-	struct env_context *c = context;
+	struct env_context *c;
 
 	if (context->parent) {
 		c = context->parent;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:38 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:38 +0200
Subject: [PATCH 13/32] commands: tutorial: fix memory leak
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-14-a.fatoum@pengutronix.de>

We don't need to duplicate argv[i], because it persists for the lieftime
of print_tutorial_step. We can thus drop the strdup and while at it,
just drop the redundant step variable altogether.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 commands/tutorial.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/commands/tutorial.c b/commands/tutorial.c
index 444177764311..afe5b66f0b0a 100644
--- a/commands/tutorial.c
+++ b/commands/tutorial.c
@@ -84,7 +84,6 @@ out:
 static int do_tutorial_next(int argc, char *argv[])
 {
 	int opt, i;
-	char *step = NULL;
 	char *oldcwd;
 	ssize_t ret = 0;
 	bool is_prev = *argv[0] == 'p';
@@ -121,14 +120,12 @@ static int do_tutorial_next(int argc, char *argv[])
 		next_step = next_step > 0 ? next_step - 1 : 0;
 
 	if (optind == argc) {
-		step = steps.gl_pathv[next_step];
-		ret = print_tutorial_step(step);
+		ret = print_tutorial_step(steps.gl_pathv[next_step]);
 		if (ret == 0 && !is_prev)
 			next_step = (next_step + 1) % steps.gl_pathc;
 	} else {
 		for (i = optind; i < argc; i++) {
-			step = strdup(argv[i]);
-			ret = print_tutorial_step(step);
+			ret = print_tutorial_step(argv[i]);
 			if (ret)
 				break;
 		}
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:56 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:56 +0200
Subject: [PATCH 31/32] net: ping: propagate failure
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-32-a.fatoum@pengutronix.de>

We populate ret, but don't do anything with it. Pass it along instead.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 net/net.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/net.c b/net/net.c
index eae45e184359..22931509d0d9 100644
--- a/net/net.c
+++ b/net/net.c
@@ -634,7 +634,7 @@ static int ping_reply(struct eth_device *edev, unsigned char *pkt, int len)
 
 	free(packet);
 
-	return 0;
+	return ret;
 }
 
 static int net_handle_icmp(struct eth_device *edev, unsigned char *pkt, int len)
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:54 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:54 +0200
Subject: [PATCH 29/32] fs: drop duplicate follow_managed() call
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-30-a.fatoum@pengutronix.de>

lookup_fast called above already calls follow_managed with the same
argument, so no need to duplicate the call here.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 fs/fs.c | 13 +++----------
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index 14d5f7330457..78878e7112d5 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -1838,16 +1838,9 @@ static int walk_component(struct nameidata *nd, int flags)
 	if (err < 0)
 		return err;
 
-	if (err == 0) {
-		path.mnt = nd->path.mnt;
-		err = follow_managed(&path, nd);
-		if (err < 0)
-			return err;
-
-		if (d_is_negative(path.dentry)) {
-			path_to_nameidata(&path, nd);
-			return -ENOENT;
-		}
+	if (err == 0 && d_is_negative(path.dentry)) {
+		path_to_nameidata(&path, nd);
+		return -ENOENT;
 	}
 
 	return step_into(nd, &path, flags, d_inode(path.dentry));
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:48 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:48 +0200
Subject: [PATCH 23/32] of: overlay: drop unused variable of_overlay_apply_dir()
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-24-a.fatoum@pengutronix.de>

This seems to be a copy-paste left-over from of_overlay_filter_filename,
which has some actual use for both p and path. We don't though and just
end up leaking the buffer, so drop these variables.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/overlay.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 20a43f5170c8..fff1d6ea028e 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -418,7 +418,6 @@ void of_overlay_set_basedir(const char *path)
 static int of_overlay_apply_dir(struct device_node *root, const char *dirname,
 				bool filter)
 {
-	char *p, *path;
 	int ret = 0;
 	DIR *dir;
 
@@ -431,8 +430,6 @@ static int of_overlay_apply_dir(struct device_node *root, const char *dirname,
 	if (!dir)
 		return -errno;
 
-	p = path = strdup(of_overlay_filepattern);
-
 	while (1) {
 		struct dirent *ent;
 		char *filename;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:30 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:30 +0200
Subject: [PATCH 05/32] mci: core: drop useless assignment
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220905095557.596891-6-a.fatoum@pengutronix.de>

rc is never read afterwards anyway, so no point in setting it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/mci/mci-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 8c08a4f61f63..a1e27b954375 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1722,8 +1722,8 @@ static int mci_register_partition(struct mci_part *part)
 
 	rc = parse_partition_table(&part->blk);
 	if (rc != 0) {
+		/* Lack of partition table is unusual, but not a failure */
 		dev_warn(&mci->dev, "No partition table found\n");
-		rc = 0; /* it's not a failure */
 	}
 
 	if (np) {
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 02:55:25 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 11:55:25 +0200
Subject: [PATCH 00/32] treewide: fix some clang-analyze static analyzer warnings
Message-ID: <20220905095557.596891-1-a.fatoum@pengutronix.de>

I ran scan-build while building barebox for sandbox with clang and
patched some of the reported issues.

Ahmad Fatoum (32):
  clk: define stub implementation for clk_get_parent
  clk: have SCMI and SiFive clock controllers depend on COMMON_CLK
  meminfo: support SANDBOX build with DEBUG log level
  net: phy: micrel: drop useless assignment of dummy read
  mci: core: drop useless assignment
  nvmem: core: propagate read failure
  fs: remove never-read initializer in mount_all()
  usb: otg: always propagate failure to register parameters
  usb: dwc2: gracefully handle unknown hs_phy_type
  state: propagate failure to fixup enum32 into DT
  of: silence warning about never-read error assignment
  commands: trigger: drop unused variable
  commands: tutorial: fix memory leak
  bthread: fix null pointer dereference in error path
  common: env: drop never-read initialization
  of: refactor for of_fixup_reserved_memory() for clarity
  password: avoid static analyzer false positive
  regmap-mmio: regmap_mmio_get_min_stride: unify branches for
    readability
  crypto: caam - delete unused variable
  misc: ubootvar: always initialize struct ubootvar_data::flag
  nvmem: core: drop always true condition
  of: fdt: gracefully handle out-of-place properties
  of: overlay: drop unused variable of_overlay_apply_dir()
  of: partition: drop unused variable
  serial: ns16550_pci: drop useless assignment
  phy: core: drop useless else clause
  fs: ext4: ext_barebox: handle ext_get_inode() errors
  fs: fat: propagate f_lseek failure
  fs: drop duplicate follow_managed() call
  lib: parse_area_spec: guard against NULL pointer dereference
  net: ping: propagate failure
  net: fastboot: keep error message initialized at all times

 commands/trigger.c                  |  5 +----
 commands/tutorial.c                 |  7 ++----
 common/bthread.c                    |  2 ++
 common/env.c                        |  2 +-
 common/meminfo.c                    |  6 ++++--
 common/oftree.c                     |  6 ++++--
 common/password.c                   |  4 ++--
 common/state/state_variables.c      |  2 ++
 drivers/base/regmap/regmap-mmio.c   |  2 +-
 drivers/clk/Kconfig                 |  5 ++++-
 drivers/crypto/caam/jr.c            |  2 --
 drivers/mci/mci-core.c              |  2 +-
 drivers/misc/ubootvar.c             |  2 +-
 drivers/net/phy/micrel.c            |  2 +-
 drivers/nvmem/core.c                |  8 ++++++-
 drivers/of/fdt.c                    |  2 +-
 drivers/of/overlay.c                |  3 ---
 drivers/of/partition.c              |  3 ---
 drivers/of/resolver.c               |  1 +
 drivers/phy/phy-core.c              |  2 --
 drivers/serial/serial_ns16550_pci.c |  2 +-
 drivers/usb/dwc2/core.c             |  3 +++
 drivers/usb/otg/otgdev.c            | 33 ++++++++++++++++-------------
 fs/ext4/ext_barebox.c               | 18 ++++++++++------
 fs/fat/fat.c                        |  5 +++++
 fs/fs.c                             | 15 ++++---------
 include/linux/clk.h                 | 20 ++++++++++-------
 lib/misc.c                          |  2 ++
 net/fastboot.c                      |  2 ++
 net/net.c                           |  2 +-
 30 files changed, 95 insertions(+), 75 deletions(-)

-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep  5 03:07:16 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon,  5 Sep 2022 12:07:16 +0200
Subject: [PATCH 1/2] of: overlay: improve error handling in of_overlay_apply_tree
In-Reply-To: <20220905100717.150557-1-michael.riesch@wolfvision.net>
References: <20220905100717.150557-1-michael.riesch@wolfvision.net>
Message-ID: <20220905100717.150557-2-michael.riesch@wolfvision.net>

Propagate any error from of_overlay_apply_symbols and let the user
know if the provided overlay is not applicable.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 drivers/of/overlay.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 20a43f5170..20686db511 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -115,8 +115,8 @@ static char *of_overlay_fix_path(struct device_node *root,
 	return basprintf("%s%s", target->full_name, path_tail);
 }
 
-static void of_overlay_apply_symbols(struct device_node *root,
-				     struct device_node *overlay)
+static int of_overlay_apply_symbols(struct device_node *root,
+				    struct device_node *overlay)
 {
 	const char *old_path;
 	char *new_path;
@@ -129,12 +129,12 @@ static void of_overlay_apply_symbols(struct device_node *root,
 
 	if (!overlay_symbols) {
 		pr_debug("overlay doesn't have a __symbols__ node\n");
-		return;
+		return -EINVAL;
 	}
 
 	if (!root_symbols) {
 		pr_info("root doesn't have a __symbols__ node\n");
-		return;
+		return -EINVAL;
 	}
 
 	list_for_each_entry(prop, &overlay_symbols->properties, list) {
@@ -148,6 +148,8 @@ static void of_overlay_apply_symbols(struct device_node *root,
 			 prop->name, new_path);
 		of_property_write_string(root_symbols, prop->name, new_path);
 	}
+
+	return 0;
 }
 
 static int of_overlay_apply_fragment(struct device_node *root,
@@ -190,7 +192,9 @@ int of_overlay_apply_tree(struct device_node *root,
 		goto out_err;
 
 	/* Copy symbols from resolved overlay to base device tree */
-	of_overlay_apply_symbols(root, resolved);
+	err = of_overlay_apply_symbols(root, resolved);
+	if (err)
+		goto out_err;
 
 	/* Copy nodes and properties from resolved overlay to root */
 	for_each_child_of_node(resolved, fragment) {
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep  5 03:07:17 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon,  5 Sep 2022 12:07:17 +0200
Subject: [PATCH 2/2] of: overlay: avoid potential null pointer exception
In-Reply-To: <20220905100717.150557-1-michael.riesch@wolfvision.net>
References: <20220905100717.150557-1-michael.riesch@wolfvision.net>
Message-ID: <20220905100717.150557-3-michael.riesch@wolfvision.net>

The function of_overlay_fix_path returns NULL in certain error cases but
of_overlay_apply_symbols (which is the only caller) does not check the
return value. For broken overlays this may result in a null pointer
exception. Fix this by checking the return value and inform the user
what exactly went wrong.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 drivers/of/overlay.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 20686db511..884cdf8928 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -102,8 +102,10 @@ static char *of_overlay_fix_path(struct device_node *root,
 		if (of_get_child_by_name(fragment, "__overlay__"))
 			break;
 	}
-	if (!fragment)
+	if (!fragment) {
+		pr_info("could not find __overlay__ node\n");
 		return NULL;
+	}
 
 	target = find_target(root, fragment);
 	if (!target)
@@ -143,6 +145,8 @@ static int of_overlay_apply_symbols(struct device_node *root,
 
 		old_path = of_property_get_value(prop);
 		new_path = of_overlay_fix_path(root, overlay, old_path);
+		if (!new_path)
+			return -EINVAL;
 
 		pr_debug("add symbol %s with new path %s\n",
 			 prop->name, new_path);
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep  5 03:07:15 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon,  5 Sep 2022 12:07:15 +0200
Subject: [PATCH 0/2] of: overlay: avoid potential null pointer exception
Message-ID: <20220905100717.150557-1-michael.riesch@wolfvision.net>

Hi all,

The function of_overlay_fix_path returns NULL in certain error cases but
of_overlay_apply_symbols (which is the only caller) does not check the
return value. For broken overlays this may result in a null pointer
exception. Fix this by checking the return value and inform the user
what exactly went wrong. To this end, improve the error handling in
of_overlay_apply_tree.

The thread [0] gives a bit more context.

Best regards,
Michael

[0] https://lore.barebox.org/barebox/95ff064f-aa11-c1ce-9d41-e38f2040c565 at wolfvision.net/T/#u

Michael Riesch (2):
  of: overlay: improve error handling in of_overlay_apply_tree
  of: overlay: avoid potential null pointer exception

 drivers/of/overlay.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:35:46 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:35:46 +0200
Subject: [PATCH 5/5] gpiolib: gpioinfo: add optional CONTROLLER command line argument
In-Reply-To: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
Message-ID: <20220905103546.1476277-6-a.fatoum@pengutronix.de>

Like done with gpio setter/getter functions in the previous commit,
extend the gpioinfo command to accept an optional argument that
restricts output to the supplied gpio controller instead of printing
all GPIOs at once.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/gpio/gpiolib.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index cf61213ca12d..7f2070903501 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -675,15 +675,35 @@ struct gpio_chip *gpio_get_chip(int gpio)
 #ifdef CONFIG_CMD_GPIO
 static int do_gpiolib(int argc, char *argv[])
 {
+	struct gpio_chip *chip = NULL;
 	int i;
 
+	if (argc > 2)
+		return COMMAND_ERROR_USAGE;
+
+	if (argc == 1) {
+		struct device_d *dev;
+
+		dev = find_device(argv[1]);
+		if (!dev)
+			return -ENODEV;
+
+		chip = gpio_get_chip_by_dev(dev);
+		if (!chip)
+			return -EINVAL;
+	}
+
 	for (i = 0; i < ARCH_NR_GPIOS; i++) {
 		struct gpio_info *gi = &gpio_desc[i];
 		int val = -1, dir = -1;
+		int idx;
 
 		if (!gi->chip)
 			continue;
 
+		if (chip && chip != gi->chip)
+			continue;
+
 		/* print chip information and header on first gpio */
 		if (gi->chip->base == i) {
 			printf("\nGPIOs %u-%u, chip %s:\n",
@@ -693,14 +713,14 @@ static int do_gpiolib(int argc, char *argv[])
 			printf("             %-3s %-3s %-9s %-20s %-20s\n", "dir", "val", "requested", "name", "label");
 		}
 
+		idx = i - gi->chip->base;
+
 		if (gi->chip->ops->get_direction)
-			dir = gi->chip->ops->get_direction(gi->chip,
-						i - gi->chip->base);
+			dir = gi->chip->ops->get_direction(gi->chip, idx);
 		if (gi->chip->ops->get)
-			val = gi->chip->ops->get(gi->chip,
-						i - gi->chip->base);
+			val = gi->chip->ops->get(gi->chip, idx);
 
-		printf("  GPIO %4d: %-3s %-3s %-9s %-20s %-20s\n", i,
+		printf("  GPIO %4d: %-3s %-3s %-9s %-20s %-20s\n", chip ? idx : i,
 			(dir < 0) ? "unk" : ((dir == GPIOF_DIR_IN) ? "in" : "out"),
 			(val < 0) ? "unk" : ((val == 0) ? "lo" : "hi"),
 		        gi->requested ? (gi->active_low ? "active low" : "true") : "false",
@@ -714,6 +734,7 @@ static int do_gpiolib(int argc, char *argv[])
 BAREBOX_CMD_START(gpioinfo)
 	.cmd		= do_gpiolib,
 	BAREBOX_CMD_DESC("list registered GPIOs")
+	BAREBOX_CMD_OPTS("[CONTROLLER]")
 	BAREBOX_CMD_GROUP(CMD_GRP_INFO)
 	BAREBOX_CMD_COMPLETE(empty_complete)
 BAREBOX_CMD_END
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:35:44 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:35:44 +0200
Subject: [PATCH 3/5] driver: implement find_device() helper
In-Reply-To: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
Message-ID: <20220905103546.1476277-4-a.fatoum@pengutronix.de>

For use in commands like done in the follow-up commits, it can be useful
to have a best effort find_device, that not only finds by device name,
but also by device tree path or alias. Add such a helper.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/base/driver.c | 16 ++++++++++++++++
 include/driver.h      |  5 +++++
 2 files changed, 21 insertions(+)

diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 072870bea444..cbe1c974f4fe 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -46,6 +46,22 @@ LIST_HEAD(active_device_list);
 EXPORT_SYMBOL(active_device_list);
 static LIST_HEAD(deferred);
 
+struct device_d *find_device(const char *str)
+{
+	struct device_d *dev;
+	struct device_node *np;
+
+	dev = get_device_by_name(str);
+	if (dev)
+		return dev;
+
+	np = of_find_node_by_path_or_alias(NULL, str);
+	if (np)
+		return of_find_device_by_node(np);
+
+	return NULL;
+}
+
 struct device_d *get_device_by_name(const char *name)
 {
 	struct device_d *dev;
diff --git a/include/driver.h b/include/driver.h
index 67ffbba6be80..543287a27638 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -169,6 +169,11 @@ struct device_d *get_device_by_type(ulong type, struct device_d *last);
 struct device_d *get_device_by_id(const char *id);
 struct device_d *get_device_by_name(const char *name);
 
+/* Find a device by name and if not found look up by device tree path
+ * or alias
+ */
+struct device_d *find_device(const char *str);
+
 /* Find a free device id from the given template. This is archieved by
  * appending a number to the template. Dynamically created devices should
  * use this function rather than filling the id field themselves.
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:35:42 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:35:42 +0200
Subject: [PATCH 1/5] gpiolib: implement gpio_get_chip_by_dev()
In-Reply-To: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
Message-ID: <20220905103546.1476277-2-a.fatoum@pengutronix.de>

gpio_of_xlate() already needs the ability to find a struct gpio_chip *
via a struct device_d. Exporting this functionality to elsewhere in the
code will allow restricting commands to manipulate only a single GPIO
bank.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/gpio/gpiolib.c | 28 +++++++++++++++++++---------
 include/gpio.h         |  1 +
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 97a99b84e32a..cf61213ca12d 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -636,6 +636,18 @@ static int of_gpio_simple_xlate(struct gpio_chip *chip,
 	return chip->base + gpiospec->args[0];
 }
 
+struct gpio_chip *gpio_get_chip_by_dev(struct device_d *dev)
+{
+	struct gpio_chip *chip;
+
+	list_for_each_entry(chip, &chip_list, list) {
+		if (chip->dev == dev)
+			return chip;
+	}
+
+	return NULL;
+}
+
 int gpio_of_xlate(struct device_d *dev, struct of_phandle_args *gpiospec, int *flags)
 {
 	struct gpio_chip *chip;
@@ -643,16 +655,14 @@ int gpio_of_xlate(struct device_d *dev, struct of_phandle_args *gpiospec, int *f
 	if (!dev)
 		return -ENODEV;
 
-	list_for_each_entry(chip, &chip_list, list) {
-		if (chip->dev != dev)
-			continue;
-		if (chip->ops->of_xlate)
-			return chip->ops->of_xlate(chip, gpiospec, flags);
-		else
-			return of_gpio_simple_xlate(chip, gpiospec, flags);
-	}
+	chip = gpio_get_chip_by_dev(dev);
+	if (!chip)
+		return -EPROBE_DEFER;
 
-	return -EPROBE_DEFER;
+	if (chip->ops->of_xlate)
+		return chip->ops->of_xlate(chip, gpiospec, flags);
+	else
+		return of_gpio_simple_xlate(chip, gpiospec, flags);
 }
 
 struct gpio_chip *gpio_get_chip(int gpio)
diff --git a/include/gpio.h b/include/gpio.h
index 8218722dcbf0..82f2eb6b8a34 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -190,5 +190,6 @@ void gpiochip_remove(struct gpio_chip *chip);
 
 int gpio_of_xlate(struct device_d *dev, struct of_phandle_args *gpiospec, int *flags);
 struct gpio_chip *gpio_get_chip(int gpio);
+struct gpio_chip *gpio_get_chip_by_dev(struct device_d *);
 
 #endif /* __GPIO_H */
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:35:41 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:35:41 +0200
Subject: [PATCH 0/5] commands: gpio: add controller as optional argument
Message-ID: <20220905103546.1476277-1-a.fatoum@pengutronix.de>

gpioinfo currently displays all GPIOs and the rest of the GPIO commands
like gpio_direction_output expects either a GPIO label or a global GPIO
number to act upon.

With this series, the gpio commands now accept an optional argument,
e.g.:

  gpioinfo gpio4
  gpio_direction_output -d gpio4 20 1

Controllers are identified by either device name, full path to the
device tree node backing it or an alias pointing at it.

Ahmad Fatoum (5):
  gpiolib: implement gpio_get_chip_by_dev()
  of: platform: optimize of_find_device_by_node when deep probing
  driver: implement find_device() helper
  commands: gpio: add -d argument to set/get commands
  gpiolib: gpioinfo: add optional CONTROLLER command line argument

 commands/gpio.c        | 51 +++++++++++++++++++++++++++++-------
 drivers/base/driver.c  | 16 ++++++++++++
 drivers/gpio/gpiolib.c | 59 ++++++++++++++++++++++++++++++++----------
 drivers/of/platform.c  |  3 +++
 include/driver.h       |  5 ++++
 include/gpio.h         |  1 +
 6 files changed, 111 insertions(+), 24 deletions(-)

-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:36:13 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:36:13 +0200
Subject: [PATCH 2/2] i2c: implement of_i2c_device_enable_and_register_by_alias()
In-Reply-To: <20220905103613.1750340-1-a.fatoum@pengutronix.de>
References: <20220905103613.1750340-1-a.fatoum@pengutronix.de>
Message-ID: <20220905103613.1750340-2-a.fatoum@pengutronix.de>

This new helper is the i2c equivalent of the existing
of_device_enable_and_register_by_alias(). That function isn't applicable
to i2c devices as it would create a platform device, but we need the
controller to create an i2c device instead.

This function was implemented for board code that uses an I2C EEPROM to
determine whether a specific I2C device is available on the same bus.
As reading the EEPROM requires the i2c controller be probed, there was
no way to reprobe the i2c controller children to create a device for the
previously disabled node. With of_i2c_register_devices_by_node(), this
is now possible and this helper makes it easier to use from board code.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/i2c/i2c.c | 13 +++++++++++++
 include/i2c/i2c.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index e70e51618850..40590b7d11be 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -597,6 +597,19 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
 	return to_i2c_client(dev);
 }
 
+int of_i2c_device_enable_and_register_by_alias(const char *alias)
+{
+	struct device_node *np;
+
+	np = of_find_node_by_alias(NULL, alias);
+	if (!np)
+		return -ENODEV;
+
+	of_device_enable(np);
+	return of_i2c_register_devices_by_node(np->parent);
+}
+
+
 static void i2c_parse_timing(struct device_d *dev, char *prop_name, u32 *cur_val_p,
 			    u32 def_val, bool use_def)
 {
diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index f5e2dc511ed1..e37a1770dc1e 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -297,6 +297,7 @@ struct i2c_adapter *i2c_get_adapter(int busnum);
 struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
 int of_i2c_register_devices_by_node(struct device_node *node);
 struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
+int of_i2c_device_enable_and_register_by_alias(const char *alias);
 
 void i2c_parse_fw_timings(struct device_d *dev, struct i2c_timings *t, bool use_defaults);
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:36:12 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:36:12 +0200
Subject: [PATCH 1/2] i2c: implement of_i2c_register_devices_by_node()
Message-ID: <20220905103613.1750340-1-a.fatoum@pengutronix.de>

i2c controllers probe the devices on their bus themselves, so in the
case the i2c controller was already probed, we currently have no way to
have it reread the device tree after fixing it up or applying an
overlay. Add a new helper that retriggers the device creation.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/i2c/i2c.c | 20 ++++++++++++++++++++
 include/i2c/i2c.h |  1 +
 2 files changed, 21 insertions(+)

diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index b24fd88f5b39..e70e51618850 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -427,6 +427,12 @@ static void of_i2c_register_devices(struct i2c_adapter *adap)
 		const __be32 *addr;
 		int len;
 
+		if (n->dev) {
+			dev_dbg(&adap->dev, "of_i2c: skipping already registered %s\n",
+				dev_name(n->dev));
+			continue;
+		}
+
 		of_modalias_node(n, info.type, I2C_NAME_SIZE);
 
 		info.of_node = n;
@@ -452,6 +458,20 @@ static void of_i2c_register_devices(struct i2c_adapter *adap)
 	}
 }
 
+int of_i2c_register_devices_by_node(struct device_node *node)
+{
+	struct i2c_adapter *adap;
+
+	adap = of_find_i2c_adapter_by_node(node);
+	if (!adap)
+		return -ENODEV;
+	if (IS_ERR(adap))
+		return PTR_ERR(adap);
+
+	of_i2c_register_devices(adap);
+	return 0;
+}
+
 /**
  * i2c_new_dummy - return a new i2c device bound to a dummy driver
  * @adapter: the adapter managing the device
diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index 7207b1180e1d..f5e2dc511ed1 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -295,6 +295,7 @@ static inline int i2c_register_board_info(int busnum,
 extern int i2c_add_numbered_adapter(struct i2c_adapter *adapter);
 struct i2c_adapter *i2c_get_adapter(int busnum);
 struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
+int of_i2c_register_devices_by_node(struct device_node *node);
 struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
 
 void i2c_parse_fw_timings(struct device_d *dev, struct i2c_timings *t, bool use_defaults);
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:36:39 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:36:39 +0200
Subject: [PATCH] of: implement of_rename_property()
Message-ID: <20220905103639.1750714-1-a.fatoum@pengutronix.de>

It's often desirable to have the same barebox binary for multiple
variants. DT-level differences between the variants are often handled
by having extra device tree nodes that are disabled by default and
patched as appropriate by board code. It can be useful to have a finer
granularity for patching though, that covers only a select property, e.g.:

   usbotg1 {
	vbus-supply = <&reg_vbus_common>;
	vendor,specialvariant-vbus-supply = <&reg_vbus_specialvariant>;
   };

The new of_rename_property allows board code to easily activate the
alternative vbus supply on the specialvariant:

  of_rename_property(np, "vendor,specialvariant-vbus-supply",
			 "vbus-supply");

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/base.c             | 16 ++++++++++++++++
 include/of.h                  |  8 ++++++++
 test/self/of_manipulation.c   | 10 ++++++++++
 test/self/of_manipulation.dts |  6 ++++--
 4 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 6a51dd71793d..212b226eb55c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2301,6 +2301,22 @@ void of_delete_property(struct property *pp)
 	free(pp);
 }
 
+struct property *of_rename_property(struct device_node *np,
+				    const char *old_name, const char *new_name)
+{
+	struct property *pp;
+
+	pp = of_find_property(np, old_name, NULL);
+	if (!pp)
+		return NULL;
+
+	of_property_write_bool(np, new_name, false);
+
+	free(pp->name);
+	pp->name = xstrdup(new_name);
+	return pp;
+}
+
 /**
  * of_set_property - create a property for a given node
  * @node - the node
diff --git a/include/of.h b/include/of.h
index 29df7d912b33..153e75d3e51d 100644
--- a/include/of.h
+++ b/include/of.h
@@ -143,6 +143,8 @@ extern struct property *of_new_property_const(struct device_node *node,
 extern struct property *__of_new_property(struct device_node *node,
 					  const char *name, void *data, int len);
 extern void of_delete_property(struct property *pp);
+extern struct property *of_rename_property(struct device_node *np,
+					   const char *old_name, const char *new_name);
 
 extern struct device_node *of_find_node_by_name(struct device_node *from,
 	const char *name);
@@ -550,6 +552,12 @@ static inline void of_delete_property(struct property *pp)
 {
 }
 
+static inline struct property *of_rename_property(struct device_node *np,
+						  const char *old_name, const char *new_name)
+{
+	return NULL;
+}
+
 static inline int of_property_read_u32_index(const struct device_node *np,
 				const char *propname, u32 index, u32 *out_value)
 {
diff --git a/test/self/of_manipulation.c b/test/self/of_manipulation.c
index 6eb6062e126b..7e30a60ca687 100644
--- a/test/self/of_manipulation.c
+++ b/test/self/of_manipulation.c
@@ -57,6 +57,16 @@ static void test_of_basics(struct device_node *root)
 	of_property_write_bool(node1, "property1", true);
 
 	assert_equal(node1, node2);
+
+	of_property_write_bool(node2, "property1", false);
+	of_property_write_u32(node2, "property1", 1);
+	of_property_write_u32(node2, "property2", 2);
+
+	of_property_write_u32(node1, "property3", 1);
+	of_property_write_u32(node1, "property2", 2);
+	of_rename_property(node1, "property3", "property1");
+
+	assert_equal(node1, node2);
 }
 
 static void test_of_property_strings(struct device_node *root)
diff --git a/test/self/of_manipulation.dts b/test/self/of_manipulation.dts
index a69d944c1eb5..2cc6773fa98e 100644
--- a/test/self/of_manipulation.dts
+++ b/test/self/of_manipulation.dts
@@ -4,12 +4,14 @@
 
 / {
 	node1 {
-		property1;
+		property1 = <1>;
+		property2 = <2>;
 		node21 { };
 	};
 
 	node2 {
-		property1;
+		property1 = <1>;
+		property2 = <2>;
 		node21 { };
 	};
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:35:43 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:35:43 +0200
Subject: [PATCH 2/5] of: platform: optimize of_find_device_by_node when deep probing
In-Reply-To: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
Message-ID: <20220905103546.1476277-3-a.fatoum@pengutronix.de>

With deep probe enabled, we are guaranteed that struct device_node::dev
is populated whenever a device had been created for a node, so in that
case, skip the iteration over the linked list of registered devices.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/platform.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 7f377b8b378a..dc784ea8e550 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -28,6 +28,9 @@ struct device_d *of_find_device_by_node(struct device_node *np)
 	if (ret)
 		return NULL;
 
+	if (deep_probe_is_supported())
+		return np->dev;
+
 	for_each_device(dev)
 		if (dev->device_node == np)
 			return dev;
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 03:35:45 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 12:35:45 +0200
Subject: [PATCH 4/5] commands: gpio: add -d argument to set/get commands
In-Reply-To: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
Message-ID: <20220905103546.1476277-5-a.fatoum@pengutronix.de>

For debugging, it can be useful to reference GPIOs relative to a
controller, e.g.:

  gpio_direction_output -d gpio4 20 1

instead of calculating the global gpio number. Extend the GPIO
functions to support that. The argument to -d may be either a device
name, a full path to a device tree node or an alias as in the example
above.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 commands/gpio.c | 51 +++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 10 deletions(-)

diff --git a/commands/gpio.c b/commands/gpio.c
index 955b60e91bce..d04fd65bc8e0 100644
--- a/commands/gpio.c
+++ b/commands/gpio.c
@@ -4,27 +4,58 @@
 #include <command.h>
 #include <errno.h>
 #include <gpio.h>
+#include <getopt.h>
 
 static int get_gpio_and_value(int argc, char *argv[],
 			      int *gpio, int *value)
 {
-	const int count = value ? 3 : 2;
+	struct gpio_chip *chip = NULL;
+	struct device_d *dev;
+	int count = 2;
 	int ret = 0;
+	int opt;
+
+	while ((opt = getopt(argc, argv, "d:")) > 0) {
+		switch (opt) {
+		case 'd':
+			dev = find_device(optarg);
+			if (!dev)
+				return -ENODEV;
+
+			chip = gpio_get_chip_by_dev(dev);
+			if (!chip)
+				return -EINVAL;
+			break;
+		default:
+			return COMMAND_ERROR_USAGE;
+		}
+	}
+
+	if (value)
+		count++;
 
-	if (argc < count)
+	if (optind < count)
 		return COMMAND_ERROR_USAGE;
 
-	*gpio = gpio_find_by_name(argv[1]);
+	*gpio = gpio_find_by_name(argv[optind]);
 	if (*gpio < 0)
-		*gpio = gpio_find_by_label(argv[1]);
+		*gpio = gpio_find_by_label(argv[optind]);
 	if (*gpio < 0) {
-		ret = kstrtoint(argv[1], 0, gpio);
+		ret = kstrtoint(argv[optind], 0, gpio);
 		if (ret < 0)
 			return ret;
+
+		if (chip)
+			*gpio += chip->base;
+	} else if (chip) {
+		if (gpio_get_chip(*gpio) != chip) {
+			printf("%s: not exporting pin %u\n", dev_name(chip->dev), *gpio);
+			return -EINVAL;
+		}
 	}
 
 	if (value)
-		ret = kstrtoint(argv[2], 0, value);
+		ret = kstrtoint(argv[optind + 1], 0, value);
 
 	return ret;
 }
@@ -47,7 +78,7 @@ static int do_gpio_get_value(int argc, char *argv[])
 BAREBOX_CMD_START(gpio_get_value)
 	.cmd		= do_gpio_get_value,
 	BAREBOX_CMD_DESC("return value of a GPIO pin")
-	BAREBOX_CMD_OPTS("GPIO")
+	BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO")
 	BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
 BAREBOX_CMD_END
 
@@ -67,7 +98,7 @@ static int do_gpio_set_value(int argc, char *argv[])
 BAREBOX_CMD_START(gpio_set_value)
 	.cmd		= do_gpio_set_value,
 	BAREBOX_CMD_DESC("set a GPIO's output value")
-	BAREBOX_CMD_OPTS("GPIO VALUE")
+	BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO VALUE")
 	BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
 BAREBOX_CMD_END
 
@@ -89,7 +120,7 @@ static int do_gpio_direction_input(int argc, char *argv[])
 BAREBOX_CMD_START(gpio_direction_input)
 	.cmd		= do_gpio_direction_input,
 	BAREBOX_CMD_DESC("set direction of a GPIO pin to input")
-	BAREBOX_CMD_OPTS("GPIO")
+	BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO")
 	BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
 BAREBOX_CMD_END
 
@@ -111,6 +142,6 @@ static int do_gpio_direction_output(int argc, char *argv[])
 BAREBOX_CMD_START(gpio_direction_output)
 	.cmd		= do_gpio_direction_output,
 	BAREBOX_CMD_DESC("set direction of a GPIO pin to output")
-	BAREBOX_CMD_OPTS("GPIO VALUE")
+	BAREBOX_CMD_OPTS("[-d CONTROLLER] GPIO VALUE")
 	BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
 BAREBOX_CMD_END
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 04:59:44 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  5 Sep 2022 13:59:44 +0200
Subject: [PATCH] of: platform: propagate of_devices_ensure_probed_by(name|property) errors
Message-ID: <20220905115944.1911301-1-a.fatoum@pengutronix.de>

The of_devices_ensure_probed_by functions are expected to return an
error code after iterating over all matching devices should any device
have failed its of_device_ensure_probed. Doing this unearths one common
failure: a matching node has status = "disabled". These will have
of_device_ensure_probed return -ENODEV, which makes sense for users
wanting to ensure a specific device is probed, but doesn't when
iterating over multiple nodes.

We already have of_devices_ensure_probed_by_dev_id, which does an early
of_device_is_available check, so do likewise for the other to
ensure_probed_by_* functions.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/platform.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index dc784ea8e550..a9a5d4c2daf2 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -525,12 +525,15 @@ int of_devices_ensure_probed_by_property(const char *property_name)
 		return 0;
 
 	for_each_node_with_property(node, property_name) {
-		ret = of_device_ensure_probed(node);
+		if (!of_device_is_available(node))
+			continue;
+
+		err = of_device_ensure_probed(node);
 		if (err)
 			ret = err;
 	}
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(of_devices_ensure_probed_by_property);
 
@@ -543,12 +546,15 @@ int of_devices_ensure_probed_by_name(const char *name)
 		return 0;
 
 	for_each_node_by_name(node, name) {
-		ret = of_device_ensure_probed(node);
+		if (!of_device_is_available(node))
+			continue;
+
+		err = of_device_ensure_probed(node);
 		if (err)
 			ret = err;
 	}
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(of_devices_ensure_probed_by_name);
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep  5 05:05:20 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 5 Sep 2022 14:05:20 +0200
Subject: [PATCH 0/3] tftp fixups
In-Reply-To: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
References: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
Message-ID: <3d648a4b-591d-2fb9-a333-ef973a55434c@pengutronix.de>

On 05.09.22 10:56, Enrico Scholz wrote:
> Fixups for the "tftp" branch in next.
> 
> Enrico Scholz (3):
>   fixup! tftp: implement 'windowsize' (RFC 7440) support
>   fixup! tftp: detect out-of-memory situations
>   tftp: make read() fail in error case

This fixes the issue of kfifo underflow I run into.

Tested-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

Thanks,
Ahmad

> 
>  fs/tftp.c | 29 ++++++++++++++++++++++-------
>  1 file changed, 22 insertions(+), 7 deletions(-)
> 


-- 
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-5555 |


From a.fatoum at pengutronix.de  Mon Sep  5 05:07:31 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 5 Sep 2022 14:07:31 +0200
Subject: [PATCH] tftp: allocate at least 4096 bytes for FIFO
In-Reply-To: <ly1qsq2nxy.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <20220905070032.536912-1-a.fatoum@pengutronix.de>
 <ly1qsq2nxy.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <0b0bc5d9-90d7-0fd0-906e-e3a7a893b33b@pengutronix.de>

Hello Enrico,

On 05.09.22 11:03, Enrico Scholz wrote:
> Ahmad Fatoum <a.fatoum at pengutronix.de> writes:
> 
>> On one board, boots from /mnt/tftp currently fail for me with:
>>
>> ERROR: tftp: tftp: not enough room in kfifo (only 1376 out of 1432 written
> 
> Thanks for noticing that; I sent fixups for the recent patchset.

Thanks for the prompt reply and series.

> Perhaps, can you test it on your failing platform with changing
> 
> | #define TFTP_EXTRA_BLOCKS	2
> 
> to
> 
> | #define TFTP_EXTRA_BLOCKS	0
> 
> ?
> 
> This should turn off the workaround of over-allocating memory and isolate
> (and verify) the fix for the real problem.

Issue was not reproducible with TFTP_EXTRA_BLOCKS 0.

FWIW, the same barebox binary only had the issue when booting via USB network adapter
(DUB-E100) on one board, but not when booting from i.MX8MM FEC on another board.

Cheers,
Ahmad

> 
> 
> 
> Enrico
> 


-- 
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-5555 |


From michael.riesch at wolfvision.net  Mon Sep  5 07:52:12 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon,  5 Sep 2022 16:52:12 +0200
Subject: [PATCH 0/2] soc: rockchip: add driver for rockchip io domains
Message-ID: <20220905145214.290551-1-michael.riesch@wolfvision.net>

Hi all,

The IO domains on Rockchip SoCs need to be configured to the correct
bank voltage. In Linux this is achieved by means of a platform driver
that reads the voltage value of the supplies and configures the bits
in the general register file (GRF) accordingly.

This series ports this driver to barebox to provide support for the
Rockchip RK356x SoCs. Please note that I could only test the changes
on RK3568 boards, so I left out the parts for the other SoCs supported
by the Linux driver. Also, it should be noted that the Linux driver
uses notifiers to react to voltage changes. This is not supported by
this barebox driver.

WARNING: Use those patches with care as they have the potential to
fry up your board. That said, testers are very welcome ;-)

Looking forward to your comments!

Best regards,
Michael

Michael Riesch (2):
  soc: rockchip: add driver for rockchip io domains
  arm: rockchip: radxa-rock3: remove io domain configuration

 arch/arm/boards/radxa-rock3/lowlevel.c |   6 -
 drivers/soc/Kconfig                    |   1 +
 drivers/soc/Makefile                   |   1 +
 drivers/soc/rockchip/Kconfig           |  17 ++
 drivers/soc/rockchip/Makefile          |   6 +
 drivers/soc/rockchip/io-domain.c       | 223 +++++++++++++++++++++++++
 6 files changed, 248 insertions(+), 6 deletions(-)
 create mode 100644 drivers/soc/rockchip/Kconfig
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/io-domain.c

-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep  5 07:52:13 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon,  5 Sep 2022 16:52:13 +0200
Subject: [PATCH 1/2] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <20220905145214.290551-1-michael.riesch@wolfvision.net>
References: <20220905145214.290551-1-michael.riesch@wolfvision.net>
Message-ID: <20220905145214.290551-2-michael.riesch@wolfvision.net>

The IO domains on Rockchip SoCs need to be configured to the correct
bank voltage. In Linux this is achieved by means of a platform driver
that reads the voltage value of the supplies and configures the bits
in the general register file (GRF) accordingly. Port this driver to
barebox to provide support for the Rockchip RK356x SoCs.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 drivers/soc/Kconfig              |   1 +
 drivers/soc/Makefile             |   1 +
 drivers/soc/rockchip/Kconfig     |  17 +++
 drivers/soc/rockchip/Makefile    |   6 +
 drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
 5 files changed, 248 insertions(+)
 create mode 100644 drivers/soc/rockchip/Kconfig
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/io-domain.c

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 54b69cc42e..c0fe214429 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,5 +2,6 @@ menu "SoC drivers"
 
 source "drivers/soc/imx/Kconfig"
 source "drivers/soc/kvx/Kconfig"
+source "drivers/soc/rockchip/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index a23e81ffb3..9bff737b78 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,5 +2,6 @@
 
 obj-$(CONFIG_ARCH_IMX)		+= imx/
 obj-$(CONFIG_KVX)		+= kvx/
+obj-$(CONFIG_ARCH_ROCKCHIP)	+= rockchip/
 obj-$(CONFIG_CPU_SIFIVE)	+= sifive/
 obj-$(CONFIG_SOC_STARFIVE)	+= starfive/
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
new file mode 100644
index 0000000000..3484b37e22
--- /dev/null
+++ b/drivers/soc/rockchip/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_ROCKCHIP || COMPILE_TEST
+
+menu "Rockchip SoC drivers"
+
+config ROCKCHIP_IODOMAIN
+	tristate "Rockchip IO domain support"
+	depends on OFDEVICE
+	help
+	  Say y here to enable support io domains on Rockchip SoCs. It is
+	  necessary for the io domain setting of the SoC to match the
+	  voltage supplied by the regulators.
+
+endmenu
+
+endif
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 0000000000..104fad968e
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Rockchip Soc drivers
+#
+
+obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o
diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c
new file mode 100644
index 0000000000..ac5724c0e7
--- /dev/null
+++ b/drivers/soc/rockchip/io-domain.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Rockchip IO Voltage Domain driver
+ *
+ * Copyright 2014 MundoReader S.L.
+ * Copyright 2014 Google, Inc.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <linux/err.h>
+#include <mfd/syscon.h>
+#include <regmap.h>
+#include <regulator.h>
+
+#define MAX_SUPPLIES		16
+
+/*
+ * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
+ * "Recommended Operating Conditions" for "Digital GPIO".   When the typical
+ * is 3.3V the max is 3.6V.  When the typical is 1.8V the max is 1.98V.
+ *
+ * They are used like this:
+ * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
+ *   SoC we're at 3.3.
+ * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
+ *   that to be an error.
+ */
+#define MAX_VOLTAGE_1_8		1980000
+#define MAX_VOLTAGE_3_3		3600000
+
+#define RK3568_PMU_GRF_IO_VSEL0 (0x0140)
+#define RK3568_PMU_GRF_IO_VSEL1 (0x0144)
+#define RK3568_PMU_GRF_IO_VSEL2 (0x0148)
+
+struct rockchip_iodomain;
+
+struct rockchip_iodomain_supply {
+	struct rockchip_iodomain *iod;
+	struct regulator *reg;
+	int idx;
+};
+
+struct rockchip_iodomain_soc_data {
+	int grf_offset;
+	const char *supply_names[MAX_SUPPLIES];
+	void (*init)(struct rockchip_iodomain *iod);
+	int (*write)(struct rockchip_iodomain_supply *supply, int uV);
+};
+
+struct rockchip_iodomain {
+	struct device_d *dev;
+	struct regmap *grf;
+	const struct rockchip_iodomain_soc_data *soc_data;
+	struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
+	int (*write)(struct rockchip_iodomain_supply *supply, int uV);
+};
+
+static int rk3568_iodomain_write(struct rockchip_iodomain_supply *supply,
+				 int uV)
+{
+	struct rockchip_iodomain *iod = supply->iod;
+	u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
+	u32 val0, val1;
+	int b;
+
+	dev_dbg(iod->dev, "set domain %d to %d uV\n", supply->idx, uV);
+
+	switch (supply->idx) {
+	case 0: /* pmuio1 */
+		break;
+	case 1: /* pmuio2 */
+		b = supply->idx;
+		val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+		b = supply->idx + 4;
+		val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val0);
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val1);
+		break;
+	case 3: /* vccio2 */
+		break;
+	case 2: /* vccio1 */
+	case 4: /* vccio3 */
+	case 5: /* vccio4 */
+	case 6: /* vccio5 */
+	case 7: /* vccio6 */
+	case 8: /* vccio7 */
+		b = supply->idx - 1;
+		val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+		val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL0, val0);
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL1, val1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
+	.grf_offset = 0x140,
+	.supply_names = {
+		"pmuio1",
+		"pmuio2",
+		"vccio1",
+		"vccio2",
+		"vccio3",
+		"vccio4",
+		"vccio5",
+		"vccio6",
+		"vccio7",
+	},
+	.write = rk3568_iodomain_write,
+};
+
+static const struct of_device_id rockchip_iodomain_match[] = {
+	{ .compatible = "rockchip,rk3568-pmu-io-voltage-domain",
+	  .data = &soc_data_rk3568_pmu },
+	{ /* sentinel */ },
+};
+
+static int rockchip_iodomain_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node, *parent;
+	struct rockchip_iodomain *iod;
+	int i, ret = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	iod = xzalloc(sizeof(*iod));
+	iod->dev = dev;
+	iod->soc_data = device_get_match_data(dev);
+
+	if (iod->soc_data->write)
+		iod->write = iod->soc_data->write;
+
+	parent = of_get_parent(np);
+	if (parent) {
+		iod->grf = syscon_node_to_regmap(parent);
+	} else {
+		dev_dbg(dev, "falling back to old binding\n");
+		iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	}
+
+	if (IS_ERR(iod->grf)) {
+		dev_err(dev, "couldn't find grf regmap\n");
+		return PTR_ERR(iod->grf);
+	}
+
+	for (i = 0; i < MAX_SUPPLIES; i++) {
+		const char *supply_name = iod->soc_data->supply_names[i];
+		struct rockchip_iodomain_supply *supply = &iod->supplies[i];
+		struct regulator *reg;
+		int uV;
+
+		if (!supply_name)
+			continue;
+
+		reg = regulator_get(dev, supply_name);
+		if (IS_ERR(reg)) {
+			ret = PTR_ERR(reg);
+
+			/* If a supply wasn't specified, that's OK */
+			if (ret == -ENODEV)
+				continue;
+			else if (ret != -EPROBE_DEFER)
+				dev_err(dev, "couldn't get regulator %s\n",
+					supply_name);
+			goto out;
+		}
+
+		/* set initial correct value */
+		uV = regulator_get_voltage(reg);
+
+		/* must be a regulator we can get the voltage of */
+		if (uV < 0) {
+			dev_err(dev, "Can't determine voltage: %s\n",
+				supply_name);
+			ret = uV;
+			goto out;
+		}
+
+		if (uV > MAX_VOLTAGE_3_3) {
+			dev_crit(dev, "%d uV is too high. May damage SoC!\n",
+				 uV);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* setup our supply */
+		supply->idx = i;
+		supply->iod = iod;
+		supply->reg = reg;
+
+		ret = iod->write(supply, uV);
+		if (ret) {
+			supply->reg = NULL;
+			goto out;
+		}
+	}
+
+	if (iod->soc_data->init)
+		iod->soc_data->init(iod);
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static struct driver_d rockchip_iodomain_driver = {
+	.name = "rockchip-iodomain",
+	.probe = rockchip_iodomain_probe,
+	.of_compatible = rockchip_iodomain_match,
+};
+coredevice_platform_driver(rockchip_iodomain_driver);
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep  5 07:52:14 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon,  5 Sep 2022 16:52:14 +0200
Subject: [PATCH 2/2] arm: rockchip: radxa-rock3: remove io domain configuration
In-Reply-To: <20220905145214.290551-1-michael.riesch@wolfvision.net>
References: <20220905145214.290551-1-michael.riesch@wolfvision.net>
Message-ID: <20220905145214.290551-3-michael.riesch@wolfvision.net>

Let the recently added Rockchip IO domain driver configure the IO
domains instead of setting the bits in rk3568_start().

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm/boards/radxa-rock3/lowlevel.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/arch/arm/boards/radxa-rock3/lowlevel.c b/arch/arm/boards/radxa-rock3/lowlevel.c
index 00a68889cd..5c2499362b 100644
--- a/arch/arm/boards/radxa-rock3/lowlevel.c
+++ b/arch/arm/boards/radxa-rock3/lowlevel.c
@@ -23,12 +23,6 @@ static noinline void rk3568_start(void *fdt)
 
 	setup_c();
 
-	/*
-	 * Enable vccio4 1.8V and vccio6 1.8V
-	 * Needed for GMAC to work.
-	 */
-	writel(RK_SETBITS(0x50), 0xfdc20140);
-
 	if (current_el() == 3) {
 		rk3568_lowlevel_init();
 		rk3568_atf_load_bl31(fdt);
-- 
2.30.2



From s.hauer at pengutronix.de  Tue Sep  6 03:20:49 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  6 Sep 2022 12:20:49 +0200
Subject: [PATCH 4/4] ratp: i2c: Do not return error
In-Reply-To: <20220906102049.1364561-1-s.hauer@pengutronix.de>
References: <20220906102049.1364561-1-s.hauer@pengutronix.de>
Message-ID: <20220906102049.1364561-5-s.hauer@pengutronix.de>

The RATP command implementations should only return an error on internal
failures. When an i2c command failed we should return 0 though to
actually send the error message. Without it the remote would just wait
for a response until it times out.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/ratp/i2c.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/ratp/i2c.c b/common/ratp/i2c.c
index c14bbbf9b9..404ddd2ece 100644
--- a/common/ratp/i2c.c
+++ b/common/ratp/i2c.c
@@ -162,7 +162,7 @@ out:
 	*rsp = (struct ratp_bb *)i2c_read_rsp;
 	*rsp_len = i2c_read_rsp_len;
 
-	return ret;
+	return 0;
 }
 
 BAREBOX_RATP_CMD_START(I2C_READ)
@@ -271,7 +271,7 @@ out:
 	*rsp = (struct ratp_bb *)i2c_write_rsp;
 	*rsp_len = sizeof(*i2c_write_rsp);
 
-	return ret;
+	return 0;
 }
 
 BAREBOX_RATP_CMD_START(I2C_WRITE)
-- 
2.30.2



From s.hauer at pengutronix.de  Tue Sep  6 03:20:48 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  6 Sep 2022 12:20:48 +0200
Subject: [PATCH 3/4] ratp: getenv: Do not crash on non-existing variables
In-Reply-To: <20220906102049.1364561-1-s.hauer@pengutronix.de>
References: <20220906102049.1364561-1-s.hauer@pengutronix.de>
Message-ID: <20220906102049.1364561-4-s.hauer@pengutronix.de>

getenv() returns NULL on non-existing variables. Replace result with
empty string to avoid doing strlen() on a NULL pointer.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/ratp/getenv.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/ratp/getenv.c b/common/ratp/getenv.c
index 7b38d2e363..9617ab1b43 100644
--- a/common/ratp/getenv.c
+++ b/common/ratp/getenv.c
@@ -32,6 +32,9 @@ static int ratp_cmd_getenv(const struct ratp_bb *req, int req_len,
 	value = getenv(varname);
 	free(varname);
 
+	if (!value)
+		value = "";
+
 	dlen = strlen(value);
 
 	*rsp_len = sizeof(struct ratp_bb) + dlen;
-- 
2.30.2



From s.hauer at pengutronix.de  Tue Sep  6 03:20:45 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  6 Sep 2022 12:20:45 +0200
Subject: [PATCH 0/4] RATP updates
Message-ID: <20220906102049.1364561-1-s.hauer@pengutronix.de>

This series has some updates for the barebox RATP support, most
importantly the python3 conversion of the host side python scripts.

Sascha Hauer (4):
  remove local pyserial
  bbremote: Convert to python3
  ratp: getenv: Do not crash on non-existing variables
  ratp: i2c: Do not return error

 common/ratp/getenv.c                          |    3 +
 common/ratp/i2c.c                             |    4 +-
 scripts/bbremote                              |    2 +-
 scripts/remote/controller.py                  |   21 +-
 scripts/remote/main.py                        |    8 +-
 scripts/remote/messages.py                    |   15 +-
 scripts/remote/ratp.py                        |    4 +-
 scripts/remote/ratpfs.py                      |    4 +-
 scripts/remote/threadstdio.py                 |    4 +-
 scripts/serial/__init__.py                    |   79 -
 scripts/serial/rfc2217.py                     | 1327 -----------------
 scripts/serial/serialcli.py                   |  284 ----
 scripts/serial/serialposix.py                 |  730 ---------
 scripts/serial/serialutil.py                  |  572 -------
 scripts/serial/tools/__init__.py              |    1 -
 scripts/serial/tools/list_ports.py            |  103 --
 scripts/serial/tools/list_ports_linux.py      |  152 --
 scripts/serial/urlhandler/__init__.py         |    1 -
 scripts/serial/urlhandler/protocol_hwgrep.py  |   45 -
 scripts/serial/urlhandler/protocol_loop.py    |  279 ----
 scripts/serial/urlhandler/protocol_rfc2217.py |   11 -
 scripts/serial/urlhandler/protocol_socket.py  |  291 ----
 22 files changed, 40 insertions(+), 3900 deletions(-)
 delete mode 100644 scripts/serial/__init__.py
 delete mode 100644 scripts/serial/rfc2217.py
 delete mode 100644 scripts/serial/serialcli.py
 delete mode 100644 scripts/serial/serialposix.py
 delete mode 100644 scripts/serial/serialutil.py
 delete mode 100644 scripts/serial/tools/__init__.py
 delete mode 100644 scripts/serial/tools/list_ports.py
 delete mode 100644 scripts/serial/tools/list_ports_linux.py
 delete mode 100644 scripts/serial/urlhandler/__init__.py
 delete mode 100644 scripts/serial/urlhandler/protocol_hwgrep.py
 delete mode 100644 scripts/serial/urlhandler/protocol_loop.py
 delete mode 100644 scripts/serial/urlhandler/protocol_rfc2217.py
 delete mode 100644 scripts/serial/urlhandler/protocol_socket.py

-- 
2.30.2



From s.hauer at pengutronix.de  Tue Sep  6 03:20:47 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  6 Sep 2022 12:20:47 +0200
Subject: [PATCH 2/4] bbremote: Convert to python3
In-Reply-To: <20220906102049.1364561-1-s.hauer@pengutronix.de>
References: <20220906102049.1364561-1-s.hauer@pengutronix.de>
Message-ID: <20220906102049.1364561-3-s.hauer@pengutronix.de>

This is the long overdue conversion from python2 to python3.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 scripts/bbremote              |  2 +-
 scripts/remote/controller.py  | 21 +++++++++++----------
 scripts/remote/main.py        |  8 ++++----
 scripts/remote/messages.py    | 15 +++++++++++++--
 scripts/remote/ratp.py        |  4 ++--
 scripts/remote/ratpfs.py      |  4 ++--
 scripts/remote/threadstdio.py |  4 ++--
 7 files changed, 35 insertions(+), 23 deletions(-)

diff --git a/scripts/bbremote b/scripts/bbremote
index bc5351dbae..1eeabd08d1 100755
--- a/scripts/bbremote
+++ b/scripts/bbremote
@@ -1,3 +1,3 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 
 import remote.main
diff --git a/scripts/remote/controller.py b/scripts/remote/controller.py
index b4493591dd..a3ae260558 100644
--- a/scripts/remote/controller.py
+++ b/scripts/remote/controller.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -8,7 +8,7 @@ import logging
 import sys
 import os
 from threading import Thread
-from Queue import Queue, Empty
+from queue import Queue, Empty
 from .ratpfs import RatpFSServer
 from .messages import *
 from .ratp import RatpError
@@ -105,7 +105,7 @@ class Controller(Thread):
         self.rxq = None
         self.conn.connect(timeout=5.0)
         self._txq = Queue()
-        self._stop = False
+        self._stopit = False
         self.fsserver = RatpFSServer()
 
     def _send(self, bbpkt):
@@ -147,24 +147,24 @@ class Controller(Thread):
             return 0
 
     def command(self, cmd):
-        self._send(BBPacketCommand(cmd=cmd))
+        self._send(BBPacketCommand(cmd=cmd.encode()))
         r = self._expect(BBPacketCommandReturn, timeout=None)
         logging.info("Command: %r", r)
         return r.exit_code
 
     def getenv(self, varname):
-        self._send(BBPacketGetenv(varname=varname))
+        self._send(BBPacketGetenv(varname=varname.encode()))
         r = self._expect(BBPacketGetenvReturn)
         return r.text
 
     def md(self, path, addr, size):
-        self._send(BBPacketMd(path=path, addr=addr, size=size))
+        self._send(BBPacketMd(path=path.encode(), addr=addr, size=size))
         r = self._expect(BBPacketMdReturn)
         logging.info("Md return: %r", r)
         return (r.exit_code,r.data)
 
     def mw(self, path, addr, data):
-        self._send(BBPacketMw(path=path, addr=addr, data=data))
+        self._send(BBPacketMw(path=path.encode(), addr=addr, data=data))
         r = self._expect(BBPacketMwReturn)
         logging.info("Mw return: %r", r)
         return (r.exit_code,r.written)
@@ -208,7 +208,7 @@ class Controller(Thread):
     def run(self):
         assert self.rxq is not None
         try:
-            while not self._stop:
+            while not self._stopit:
                 # receive
                 pkt = self.conn.recv()
                 if pkt:
@@ -235,15 +235,16 @@ class Controller(Thread):
         Thread.start(self)
 
     def stop(self):
-        self._stop = True
+        self._stopit = True
         self.join()
-        self._stop = False
+        self._stopit = False
         self.rxq = None
 
     def send_async(self, pkt):
         self._txq.put(pkt)
 
     def send_async_console(self, text):
+        assert isinstance(text, bytes)
         self._txq.put(BBPacketConsoleMsg(text=text))
 
     def send_async_ping(self):
diff --git a/scripts/remote/main.py b/scripts/remote/main.py
index cef5d92ee2..b99dba180a 100644
--- a/scripts/remote/main.py
+++ b/scripts/remote/main.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 
 from __future__ import absolute_import, division, print_function
 
@@ -7,7 +7,7 @@ import os
 import argparse
 import binascii
 import logging
-from Queue import Queue
+from queue import Queue
 from .ratp import RatpError
 
 try:
@@ -162,8 +162,8 @@ def handle_console(args):
     ctrl = get_controller(args)
     ctrl.export(args.export)
     ctrl.start(queue)
-    ctrl.send_async_console('\r')
-    cons = ConsoleInput(queue, exit='\x14')  # CTRL-T
+    ctrl.send_async_console(b'\r')
+    cons = ConsoleInput(queue, exit=b'\x14')  # CTRL-T
     cons.start()
     try:
         while True:
diff --git a/scripts/remote/messages.py b/scripts/remote/messages.py
index abd331c8b6..ae36189d4c 100644
--- a/scripts/remote/messages.py
+++ b/scripts/remote/messages.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -41,12 +41,13 @@ class BBPacket(object):
         if raw is not None:
             self.unpack(raw)
         else:
-            self.payload = payload
+            self.payload = payload.encode()
 
     def __repr__(self):
         return "BBPacket(%i, %i)" % (self.p_type, self.p_flags)
 
     def _unpack_payload(self, data):
+        assert isinstance(data, bytes)
         self.payload = data
 
     def _pack_payload(self):
@@ -63,6 +64,7 @@ class BBPacket(object):
 
 class BBPacketCommand(BBPacket):
     def __init__(self, raw=None, cmd=None):
+        assert isinstance(cmd, bytes)
         self.cmd = cmd
         super(BBPacketCommand, self).__init__(BBType.command, raw=raw)
 
@@ -70,6 +72,7 @@ class BBPacketCommand(BBPacket):
         return "BBPacketCommand(cmd=%r)" % self.cmd
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.cmd = payload
 
     def _pack_payload(self):
@@ -94,6 +97,8 @@ class BBPacketCommandReturn(BBPacket):
 
 class BBPacketConsoleMsg(BBPacket):
     def __init__(self, raw=None, text=None):
+        if text != None:
+            assert isinstance(text, bytes)
         self.text = text
         super(BBPacketConsoleMsg, self).__init__(BBType.consolemsg, raw=raw)
 
@@ -101,6 +106,7 @@ class BBPacketConsoleMsg(BBPacket):
         return "BBPacketConsoleMsg(text=%r)" % self.text
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.text = payload
 
     def _pack_payload(self):
@@ -125,6 +131,7 @@ class BBPacketPong(BBPacket):
 
 class BBPacketGetenv(BBPacket):
     def __init__(self, raw=None, varname=None):
+        assert isinstance(varname, bytes)
         self.varname = varname
         super(BBPacketGetenv, self).__init__(BBType.getenv, raw=raw)
 
@@ -132,6 +139,7 @@ class BBPacketGetenv(BBPacket):
         return "BBPacketGetenv(varname=%r)" % self.varname
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.varname = payload
 
     def _pack_payload(self):
@@ -148,6 +156,7 @@ class BBPacketGetenvReturn(BBPacket):
         return "BBPacketGetenvReturn(varvalue=%s)" % self.text
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.text = payload
 
     def _pack_payload(self):
@@ -172,6 +181,7 @@ class BBPacketFSReturn(BBPacket):
 
 class BBPacketMd(BBPacket):
     def __init__(self, raw=None, path=None, addr=None, size=None):
+        assert isinstance(path, bytes)
         self.path = path
         self.addr = addr
         self.size = size
@@ -214,6 +224,7 @@ class BBPacketMdReturn(BBPacket):
 
 class BBPacketMw(BBPacket):
     def __init__(self, raw=None, path=None, addr=None, data=None):
+        assert isinstance(path, bytes)
         self.path = path
         self.addr = addr
         self.data = data
diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py
index 44f3e2f40a..25ca442d15 100644
--- a/scripts/remote/ratp.py
+++ b/scripts/remote/ratp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -593,7 +593,7 @@ class RatpConnection(object):
         # reassemble
         if r.c_eor:
             logging.info("Reassembling %i frames", len(self._rx_buf))
-            self._rx_queue.append(''.join(self._rx_buf))
+            self._rx_queue.append(b''.join(self._rx_buf))
             self._rx_buf = []
 
         s = RatpPacket(flags='A')
diff --git a/scripts/remote/ratpfs.py b/scripts/remote/ratpfs.py
index 91ca044540..957628b648 100644
--- a/scripts/remote/ratpfs.py
+++ b/scripts/remote/ratpfs.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -97,7 +97,7 @@ class RatpFSServer(object):
                          os.O_TRUNC)
         path = params[4:]
         try:
-            f = os.open(self._resolve(path), flags, 0666)
+            f = os.open(self._resolve(path), flags, 0o666)
         except OSError as e:
             return struct.pack('!II', 0, e.errno)
         h = self._alloc_handle()
diff --git a/scripts/remote/threadstdio.py b/scripts/remote/threadstdio.py
index db249892ac..d8ad71413c 100644
--- a/scripts/remote/threadstdio.py
+++ b/scripts/remote/threadstdio.py
@@ -1,11 +1,11 @@
-#!/usr/bin/python2
+#!/usr/bin/env python3
 
 import os
 import sys
 import termios
 import atexit
 from threading import Thread
-from Queue import Queue, Empty
+from queue import Queue, Empty
 
 class ConsoleInput(Thread):
     def __init__(self, queue, exit='\x14'):
-- 
2.30.2



From s.hauer at pengutronix.de  Tue Sep  6 03:20:46 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue,  6 Sep 2022 12:20:46 +0200
Subject: [PATCH 1/4] remove local pyserial
In-Reply-To: <20220906102049.1364561-1-s.hauer@pengutronix.de>
References: <20220906102049.1364561-1-s.hauer@pengutronix.de>
Message-ID: <20220906102049.1364561-2-s.hauer@pengutronix.de>

A copy of pyserial has been put into the tree because RFC2217 support
was broken back then. This issue is long fixed, so remove the local
copy.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 scripts/serial/__init__.py                    |   79 -
 scripts/serial/rfc2217.py                     | 1327 -----------------
 scripts/serial/serialcli.py                   |  284 ----
 scripts/serial/serialposix.py                 |  730 ---------
 scripts/serial/serialutil.py                  |  572 -------
 scripts/serial/tools/__init__.py              |    1 -
 scripts/serial/tools/list_ports.py            |  103 --
 scripts/serial/tools/list_ports_linux.py      |  152 --
 scripts/serial/urlhandler/__init__.py         |    1 -
 scripts/serial/urlhandler/protocol_hwgrep.py  |   45 -
 scripts/serial/urlhandler/protocol_loop.py    |  279 ----
 scripts/serial/urlhandler/protocol_rfc2217.py |   11 -
 scripts/serial/urlhandler/protocol_socket.py  |  291 ----
 13 files changed, 3875 deletions(-)
 delete mode 100644 scripts/serial/__init__.py
 delete mode 100644 scripts/serial/rfc2217.py
 delete mode 100644 scripts/serial/serialcli.py
 delete mode 100644 scripts/serial/serialposix.py
 delete mode 100644 scripts/serial/serialutil.py
 delete mode 100644 scripts/serial/tools/__init__.py
 delete mode 100644 scripts/serial/tools/list_ports.py
 delete mode 100644 scripts/serial/tools/list_ports_linux.py
 delete mode 100644 scripts/serial/urlhandler/__init__.py
 delete mode 100644 scripts/serial/urlhandler/protocol_hwgrep.py
 delete mode 100644 scripts/serial/urlhandler/protocol_loop.py
 delete mode 100644 scripts/serial/urlhandler/protocol_rfc2217.py
 delete mode 100644 scripts/serial/urlhandler/protocol_socket.py

diff --git a/scripts/serial/__init__.py b/scripts/serial/__init__.py
deleted file mode 100644
index 33ae52ec11..0000000000
--- a/scripts/serial/__init__.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env python 
-
-# portable serial port access with python
-# this is a wrapper module for different platform implementations
-#
-# (C) 2001-2010 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-VERSION = '2.7'
-
-import sys
-
-if sys.platform == 'cli':
-    from serial.serialcli import *
-else:
-    import os
-    # chose an implementation, depending on os
-    if os.name == 'nt': #sys.platform == 'win32':
-        from serial.serialwin32 import *
-    elif os.name == 'posix':
-        from serial.serialposix import *
-    elif os.name == 'java':
-        from serial.serialjava import *
-    else:
-        raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
-
-
-protocol_handler_packages = [
-        'serial.urlhandler',
-        ]
-
-def serial_for_url(url, *args, **kwargs):
-    """\
-    Get an instance of the Serial class, depending on port/url. The port is not
-    opened when the keyword parameter 'do_not_open' is true, by default it
-    is. All other parameters are directly passed to the __init__ method when
-    the port is instantiated.
-
-    The list of package names that is searched for protocol handlers is kept in
-    ``protocol_handler_packages``.
-
-    e.g. we want to support a URL ``foobar://``. A module
-    ``my_handlers.protocol_foobar`` is provided by the user. Then
-    ``protocol_handler_packages.append("my_handlers")`` would extend the search
-    path so that ``serial_for_url("foobar://"))`` would work.
-    """
-    # check remove extra parameter to not confuse the Serial class
-    do_open = 'do_not_open' not in kwargs or not kwargs['do_not_open']
-    if 'do_not_open' in kwargs: del kwargs['do_not_open']
-    # the default is to use the native version
-    klass = Serial   # 'native' implementation
-    # check port type and get class
-    try:
-        url_nocase = url.lower()
-    except AttributeError:
-        # it's not a string, use default
-        pass
-    else:
-        if '://' in url_nocase:
-            protocol = url_nocase.split('://', 1)[0]
-            for package_name in protocol_handler_packages:
-                module_name = '%s.protocol_%s' % (package_name, protocol,)
-                try:
-                    handler_module = __import__(module_name)
-                except ImportError:
-                    pass
-                else:
-                    klass = sys.modules[module_name].Serial
-                    break
-            else:
-                raise ValueError('invalid URL, protocol %r not known' % (protocol,))
-        else:
-            klass = Serial   # 'native' implementation
-    # instantiate and open when desired
-    instance = klass(None, *args, **kwargs)
-    instance.port = url
-    if do_open:
-        instance.open()
-    return instance
diff --git a/scripts/serial/rfc2217.py b/scripts/serial/rfc2217.py
deleted file mode 100644
index b65edd55c8..0000000000
--- a/scripts/serial/rfc2217.py
+++ /dev/null
@@ -1,1327 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a RFC2217 compatible client. RF2217 descibes a
-# protocol to access serial ports over TCP/IP and allows setting the baud rate,
-# modem control lines etc.
-#
-# (C) 2001-2013 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-# TODO:
-# - setting control line -> answer is not checked (had problems with one of the
-#   severs). consider implementing a compatibility mode flag to make check
-#   conditional
-# - write timeout not implemented at all
-
-##############################################################################
-# observations and issues with servers
-#=============================================================================
-# sredird V2.2.1
-# - http://www.ibiblio.org/pub/Linux/system/serial/   sredird-2.2.2.tar.gz
-# - does not acknowledge SET_CONTROL (RTS/DTR) correctly, always responding
-#   [105 1] instead of the actual value.
-# - SET_BAUDRATE answer contains 4 extra null bytes -> probably for larger
-#   numbers than 2**32?
-# - To get the signature [COM_PORT_OPTION 0] has to be sent.
-# - run a server: while true; do nc -l -p 7000 -c "sredird debug /dev/ttyUSB0 /var/lock/sredir"; done
-#=============================================================================
-# telnetcpcd (untested)
-# - http://ftp.wayne.edu/kermit/sredird/telnetcpcd-1.09.tar.gz
-# - To get the signature [COM_PORT_OPTION] w/o data has to be sent.
-#=============================================================================
-# ser2net
-# - does not negotiate BINARY or COM_PORT_OPTION for his side but at least
-#   acknowledges that the client activates these options
-# - The configuration may be that the server prints a banner. As this client
-#   implementation does a flushInput on connect, this banner is hidden from
-#   the user application.
-# - NOTIFY_MODEMSTATE: the poll interval of the server seems to be one
-#   second.
-# - To get the signature [COM_PORT_OPTION 0] has to be sent.
-# - run a server: run ser2net daemon, in /etc/ser2net.conf:
-#     2000:telnet:0:/dev/ttyS0:9600 remctl banner
-##############################################################################
-
-# How to identify ports? pySerial might want to support other protocols in the
-# future, so lets use an URL scheme.
-# for RFC2217 compliant servers we will use this:
-#    rfc2217://<host>:<port>[/option[/option...]]
-#
-# options:
-# - "debug" print diagnostic messages
-# - "ign_set_control": do not look at the answers to SET_CONTROL
-# - "poll_modem": issue NOTIFY_MODEMSTATE requests when CTS/DTR/RI/CD is read.
-#   Without this option it expects that the server sends notifications
-#   automatically on change (which most servers do and is according to the
-#   RFC).
-# the order of the options is not relevant
-
-from serial.serialutil import *
-import time
-import struct
-import socket
-import threading
-import Queue
-import logging
-
-# port string is expected to be something like this:
-# rfc2217://host:port
-# host may be an IP or including domain, whatever.
-# port is 0...65535
-
-# map log level names to constants. used in fromURL()
-LOGGER_LEVELS = {
-    'debug': logging.DEBUG,
-    'info': logging.INFO,
-    'warning': logging.WARNING,
-    'error': logging.ERROR,
-    }
-
-
-# telnet protocol characters
-IAC  = to_bytes([255]) # Interpret As Command
-DONT = to_bytes([254])
-DO   = to_bytes([253])
-WONT = to_bytes([252])
-WILL = to_bytes([251])
-IAC_DOUBLED = to_bytes([IAC, IAC])
-
-SE  = to_bytes([240])  # Subnegotiation End
-NOP = to_bytes([241])  # No Operation
-DM  = to_bytes([242])  # Data Mark
-BRK = to_bytes([243])  # Break
-IP  = to_bytes([244])  # Interrupt process
-AO  = to_bytes([245])  # Abort output
-AYT = to_bytes([246])  # Are You There
-EC  = to_bytes([247])  # Erase Character
-EL  = to_bytes([248])  # Erase Line
-GA  = to_bytes([249])  # Go Ahead
-SB =  to_bytes([250])  # Subnegotiation Begin
-
-# selected telnet options
-BINARY = to_bytes([0]) # 8-bit data path
-ECHO = to_bytes([1])   # echo
-SGA = to_bytes([3])    # suppress go ahead
-
-# RFC2217
-COM_PORT_OPTION = to_bytes([44])
-
-# Client to Access Server
-SET_BAUDRATE = to_bytes([1])
-SET_DATASIZE = to_bytes([2])
-SET_PARITY = to_bytes([3])
-SET_STOPSIZE = to_bytes([4])
-SET_CONTROL = to_bytes([5])
-NOTIFY_LINESTATE = to_bytes([6])
-NOTIFY_MODEMSTATE = to_bytes([7])
-FLOWCONTROL_SUSPEND = to_bytes([8])
-FLOWCONTROL_RESUME = to_bytes([9])
-SET_LINESTATE_MASK = to_bytes([10])
-SET_MODEMSTATE_MASK = to_bytes([11])
-PURGE_DATA = to_bytes([12])
-
-SERVER_SET_BAUDRATE = to_bytes([101])
-SERVER_SET_DATASIZE = to_bytes([102])
-SERVER_SET_PARITY = to_bytes([103])
-SERVER_SET_STOPSIZE = to_bytes([104])
-SERVER_SET_CONTROL = to_bytes([105])
-SERVER_NOTIFY_LINESTATE = to_bytes([106])
-SERVER_NOTIFY_MODEMSTATE = to_bytes([107])
-SERVER_FLOWCONTROL_SUSPEND = to_bytes([108])
-SERVER_FLOWCONTROL_RESUME = to_bytes([109])
-SERVER_SET_LINESTATE_MASK = to_bytes([110])
-SERVER_SET_MODEMSTATE_MASK = to_bytes([111])
-SERVER_PURGE_DATA = to_bytes([112])
-
-RFC2217_ANSWER_MAP = {
-    SET_BAUDRATE: SERVER_SET_BAUDRATE,
-    SET_DATASIZE: SERVER_SET_DATASIZE,
-    SET_PARITY: SERVER_SET_PARITY,
-    SET_STOPSIZE: SERVER_SET_STOPSIZE,
-    SET_CONTROL: SERVER_SET_CONTROL,
-    NOTIFY_LINESTATE: SERVER_NOTIFY_LINESTATE,
-    NOTIFY_MODEMSTATE: SERVER_NOTIFY_MODEMSTATE,
-    FLOWCONTROL_SUSPEND: SERVER_FLOWCONTROL_SUSPEND,
-    FLOWCONTROL_RESUME: SERVER_FLOWCONTROL_RESUME,
-    SET_LINESTATE_MASK: SERVER_SET_LINESTATE_MASK,
-    SET_MODEMSTATE_MASK: SERVER_SET_MODEMSTATE_MASK,
-    PURGE_DATA: SERVER_PURGE_DATA,
-}
-
-SET_CONTROL_REQ_FLOW_SETTING = to_bytes([0])        # Request Com Port Flow Control Setting (outbound/both)
-SET_CONTROL_USE_NO_FLOW_CONTROL = to_bytes([1])     # Use No Flow Control (outbound/both)
-SET_CONTROL_USE_SW_FLOW_CONTROL = to_bytes([2])     # Use XON/XOFF Flow Control (outbound/both)
-SET_CONTROL_USE_HW_FLOW_CONTROL = to_bytes([3])     # Use HARDWARE Flow Control (outbound/both)
-SET_CONTROL_REQ_BREAK_STATE = to_bytes([4])         # Request BREAK State
-SET_CONTROL_BREAK_ON = to_bytes([5])                # Set BREAK State ON
-SET_CONTROL_BREAK_OFF = to_bytes([6])               # Set BREAK State OFF
-SET_CONTROL_REQ_DTR = to_bytes([7])                 # Request DTR Signal State
-SET_CONTROL_DTR_ON = to_bytes([8])                  # Set DTR Signal State ON
-SET_CONTROL_DTR_OFF = to_bytes([9])                 # Set DTR Signal State OFF
-SET_CONTROL_REQ_RTS = to_bytes([10])                # Request RTS Signal State
-SET_CONTROL_RTS_ON = to_bytes([11])                 # Set RTS Signal State ON
-SET_CONTROL_RTS_OFF = to_bytes([12])                # Set RTS Signal State OFF
-SET_CONTROL_REQ_FLOW_SETTING_IN = to_bytes([13])    # Request Com Port Flow Control Setting (inbound)
-SET_CONTROL_USE_NO_FLOW_CONTROL_IN = to_bytes([14]) # Use No Flow Control (inbound)
-SET_CONTROL_USE_SW_FLOW_CONTOL_IN = to_bytes([15])  # Use XON/XOFF Flow Control (inbound)
-SET_CONTROL_USE_HW_FLOW_CONTOL_IN = to_bytes([16])  # Use HARDWARE Flow Control (inbound)
-SET_CONTROL_USE_DCD_FLOW_CONTROL = to_bytes([17])   # Use DCD Flow Control (outbound/both)
-SET_CONTROL_USE_DTR_FLOW_CONTROL = to_bytes([18])   # Use DTR Flow Control (inbound)
-SET_CONTROL_USE_DSR_FLOW_CONTROL = to_bytes([19])   # Use DSR Flow Control (outbound/both)
-
-LINESTATE_MASK_TIMEOUT = 128                # Time-out Error
-LINESTATE_MASK_SHIFTREG_EMPTY = 64          # Transfer Shift Register Empty
-LINESTATE_MASK_TRANSREG_EMPTY = 32          # Transfer Holding Register Empty
-LINESTATE_MASK_BREAK_DETECT = 16            # Break-detect Error
-LINESTATE_MASK_FRAMING_ERROR = 8            # Framing Error
-LINESTATE_MASK_PARTIY_ERROR = 4             # Parity Error
-LINESTATE_MASK_OVERRUN_ERROR = 2            # Overrun Error
-LINESTATE_MASK_DATA_READY = 1               # Data Ready
-
-MODEMSTATE_MASK_CD = 128                    # Receive Line Signal Detect (also known as Carrier Detect)
-MODEMSTATE_MASK_RI = 64                     # Ring Indicator
-MODEMSTATE_MASK_DSR = 32                    # Data-Set-Ready Signal State
-MODEMSTATE_MASK_CTS = 16                    # Clear-To-Send Signal State
-MODEMSTATE_MASK_CD_CHANGE = 8               # Delta Receive Line Signal Detect
-MODEMSTATE_MASK_RI_CHANGE = 4               # Trailing-edge Ring Detector
-MODEMSTATE_MASK_DSR_CHANGE = 2              # Delta Data-Set-Ready
-MODEMSTATE_MASK_CTS_CHANGE = 1              # Delta Clear-To-Send
-
-PURGE_RECEIVE_BUFFER = to_bytes([1])        # Purge access server receive data buffer
-PURGE_TRANSMIT_BUFFER = to_bytes([2])       # Purge access server transmit data buffer
-PURGE_BOTH_BUFFERS = to_bytes([3])          # Purge both the access server receive data buffer and the access server transmit data buffer
-
-
-RFC2217_PARITY_MAP = {
-    PARITY_NONE: 1,
-    PARITY_ODD: 2,
-    PARITY_EVEN: 3,
-    PARITY_MARK: 4,
-    PARITY_SPACE: 5,
-}
-RFC2217_REVERSE_PARITY_MAP = dict((v,k) for k,v in RFC2217_PARITY_MAP.items())
-
-RFC2217_STOPBIT_MAP = {
-    STOPBITS_ONE: 1,
-    STOPBITS_ONE_POINT_FIVE: 3,
-    STOPBITS_TWO: 2,
-}
-RFC2217_REVERSE_STOPBIT_MAP = dict((v,k) for k,v in RFC2217_STOPBIT_MAP.items())
-
-# Telnet filter states
-M_NORMAL = 0
-M_IAC_SEEN = 1
-M_NEGOTIATE = 2
-
-# TelnetOption and TelnetSubnegotiation states
-REQUESTED = 'REQUESTED'
-ACTIVE = 'ACTIVE'
-INACTIVE = 'INACTIVE'
-REALLY_INACTIVE = 'REALLY_INACTIVE'
-
-class TelnetOption(object):
-    """Manage a single telnet option, keeps track of DO/DONT WILL/WONT."""
-
-    def __init__(self, connection, name, option, send_yes, send_no, ack_yes, ack_no, initial_state, activation_callback=None):
-        """\
-        Initialize option.
-        :param connection: connection used to transmit answers
-        :param name: a readable name for debug outputs
-        :param send_yes: what to send when option is to be enabled.
-        :param send_no: what to send when option is to be disabled.
-        :param ack_yes: what to expect when remote agrees on option.
-        :param ack_no: what to expect when remote disagrees on option.
-        :param initial_state: options initialized with REQUESTED are tried to
-            be enabled on startup. use INACTIVE for all others.
-        """
-        self.connection = connection
-        self.name = name
-        self.option = option
-        self.send_yes = send_yes
-        self.send_no = send_no
-        self.ack_yes = ack_yes
-        self.ack_no = ack_no
-        self.state = initial_state
-        self.active = False
-        self.activation_callback = activation_callback
-
-    def __repr__(self):
-        """String for debug outputs"""
-        return "%s:%s(%s)" % (self.name, self.active, self.state)
-
-    def process_incoming(self, command):
-        """\
-        A DO/DONT/WILL/WONT was received for this option, update state and
-        answer when needed.
-        """
-        if command == self.ack_yes:
-            if self.state is REQUESTED:
-                self.state = ACTIVE
-                self.active = True
-                if self.activation_callback is not None:
-                    self.activation_callback()
-            elif self.state is ACTIVE:
-                pass
-            elif self.state is INACTIVE:
-                self.state = ACTIVE
-                self.connection.telnetSendOption(self.send_yes, self.option)
-                self.active = True
-                if self.activation_callback is not None:
-                    self.activation_callback()
-            elif self.state is REALLY_INACTIVE:
-                self.connection.telnetSendOption(self.send_no, self.option)
-            else:
-                raise ValueError('option in illegal state %r' % self)
-        elif command == self.ack_no:
-            if self.state is REQUESTED:
-                self.state = INACTIVE
-                self.active = False
-            elif self.state is ACTIVE:
-                self.state = INACTIVE
-                self.connection.telnetSendOption(self.send_no, self.option)
-                self.active = False
-            elif self.state is INACTIVE:
-                pass
-            elif self.state is REALLY_INACTIVE:
-                pass
-            else:
-                raise ValueError('option in illegal state %r' % self)
-
-
-class TelnetSubnegotiation(object):
-    """\
-    A object to handle subnegotiation of options. In this case actually
-    sub-sub options for RFC 2217. It is used to track com port options.
-    """
-
-    def __init__(self, connection, name, option, ack_option=None):
-        if ack_option is None: ack_option = option
-        self.connection = connection
-        self.name = name
-        self.option = option
-        self.value = None
-        self.ack_option = ack_option
-        self.state = INACTIVE
-
-    def __repr__(self):
-        """String for debug outputs."""
-        return "%s:%s" % (self.name, self.state)
-
-    def set(self, value):
-        """\
-        Request a change of the value. a request is sent to the server. if
-        the client needs to know if the change is performed he has to check the
-        state of this object.
-        """
-        self.value = value
-        self.state = REQUESTED
-        self.connection.rfc2217SendSubnegotiation(self.option, self.value)
-        if self.connection.logger:
-            self.connection.logger.debug("SB Requesting %s -> %r" % (self.name, self.value))
-
-    def isReady(self):
-        """\
-        Check if answer from server has been received. when server rejects
-        the change, raise a ValueError.
-        """
-        if self.state == REALLY_INACTIVE:
-            raise ValueError("remote rejected value for option %r" % (self.name))
-        return self.state == ACTIVE
-    # add property to have a similar interface as TelnetOption
-    active = property(isReady)
-
-    def wait(self, timeout=3):
-        """\
-        Wait until the subnegotiation has been acknowledged or timeout. It
-        can also throw a value error when the answer from the server does not
-        match the value sent.
-        """
-        timeout_time = time.time() + timeout
-        while time.time() < timeout_time:
-            if self.isReady():
-                break
-            time.sleep(0.001)    # prevent 100% CPU load
-        else:
-            raise SerialException("timeout while waiting for option %r" % (self.name))
-
-    def checkAnswer(self, suboption):
-        """\
-        Check an incoming subnegotiation block. The parameter already has
-        cut off the header like sub option number and com port option value.
-        """
-        if self.value == suboption[:len(self.value)]:
-            self.state = ACTIVE
-        else:
-            # error propagation done in isReady
-            self.state = REALLY_INACTIVE
-        if self.connection.logger:
-            self.connection.logger.debug("SB Answer %s -> %r -> %s" % (self.name, suboption, self.state))
-
-
-class RFC2217Serial(SerialBase):
-    """Serial port implementation for RFC 2217 remote serial ports."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        self.logger = None
-        self._ignore_set_control_answer = False
-        self._poll_modem_state = False
-        self._network_timeout = 3
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        try:
-            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            self._socket.connect(self.fromURL(self.portstr))
-            self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-        except Exception, msg:
-            self._socket = None
-            raise SerialException("Could not open port %s: %s" % (self.portstr, msg))
-
-        self._socket.settimeout(5) # XXX good value?
-
-        # use a thread save queue as buffer. it also simplifies implementing
-        # the read timeout
-        self._read_buffer = Queue.Queue()
-        # to ensure that user writes does not interfere with internal
-        # telnet/rfc2217 options establish a lock
-        self._write_lock = threading.Lock()
-        # name the following separately so that, below, a check can be easily done
-        mandadory_options = [
-            TelnetOption(self, 'we-BINARY', BINARY, WILL, WONT, DO, DONT, INACTIVE),
-            TelnetOption(self, 'we-RFC2217', COM_PORT_OPTION, WILL, WONT, DO, DONT, REQUESTED),
-        ]
-        # all supported telnet options
-        self._telnet_options = [
-            TelnetOption(self, 'ECHO', ECHO, DO, DONT, WILL, WONT, REQUESTED),
-            TelnetOption(self, 'we-SGA', SGA, WILL, WONT, DO, DONT, REQUESTED),
-            TelnetOption(self, 'they-SGA', SGA, DO, DONT, WILL, WONT, REQUESTED),
-            TelnetOption(self, 'they-BINARY', BINARY, DO, DONT, WILL, WONT, INACTIVE),
-            TelnetOption(self, 'they-RFC2217', COM_PORT_OPTION, DO, DONT, WILL, WONT, REQUESTED),
-        ] + mandadory_options
-        # RFC 2217 specific states
-        # COM port settings
-        self._rfc2217_port_settings = {
-            'baudrate': TelnetSubnegotiation(self, 'baudrate', SET_BAUDRATE, SERVER_SET_BAUDRATE),
-            'datasize': TelnetSubnegotiation(self, 'datasize', SET_DATASIZE, SERVER_SET_DATASIZE),
-            'parity':   TelnetSubnegotiation(self, 'parity',   SET_PARITY,   SERVER_SET_PARITY),
-            'stopsize': TelnetSubnegotiation(self, 'stopsize', SET_STOPSIZE, SERVER_SET_STOPSIZE),
-            }
-        # There are more subnegotiation objects, combine all in one dictionary
-        # for easy access
-        self._rfc2217_options = {
-            'purge':    TelnetSubnegotiation(self, 'purge',    PURGE_DATA,   SERVER_PURGE_DATA),
-            'control':  TelnetSubnegotiation(self, 'control',  SET_CONTROL,  SERVER_SET_CONTROL),
-            }
-        self._rfc2217_options.update(self._rfc2217_port_settings)
-        # cache for line and modem states that the server sends to us
-        self._linestate = 0
-        self._modemstate = None
-        self._modemstate_expires = 0
-        # RFC 2217 flow control between server and client
-        self._remote_suspend_flow = False
-
-        self._thread = threading.Thread(target=self._telnetReadLoop)
-        self._thread.setDaemon(True)
-        self._thread.setName('pySerial RFC 2217 reader thread for %s' % (self._port,))
-        self._thread.start()
-
-        # negotiate Telnet/RFC 2217 -> send initial requests
-        for option in self._telnet_options:
-            if option.state is REQUESTED:
-                self.telnetSendOption(option.send_yes, option.option)
-        # now wait until important options are negotiated
-        timeout_time = time.time() + self._network_timeout
-        while time.time() < timeout_time:
-            if sum(o.active for o in mandadory_options) == sum(o.state != INACTIVE for o in mandadory_options):
-                break
-            time.sleep(0.001)    # prevent 100% CPU load
-        else:
-            raise SerialException("Remote does not seem to support RFC2217 or BINARY mode %r" % mandadory_options)
-        if self.logger:
-            self.logger.info("Negotiated options: %s" % self._telnet_options)
-
-        # fine, go on, set RFC 2271 specific things
-        self._reconfigurePort()
-        # all things set up get, now a clean start
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """Set communication parameters on opened port."""
-        if self._socket is None:
-            raise SerialException("Can only operate on open ports")
-
-        # if self._timeout != 0 and self._interCharTimeout is not None:
-            # XXX
-
-        if self._writeTimeout is not None:
-            raise NotImplementedError('writeTimeout is currently not supported')
-            # XXX
-
-        # Setup the connection
-        # to get good performance, all parameter changes are sent first...
-        if not isinstance(self._baudrate, (int, long)) or not 0 < self._baudrate < 2**32:
-            raise ValueError("invalid baudrate: %r" % (self._baudrate))
-        self._rfc2217_port_settings['baudrate'].set(struct.pack('!I', self._baudrate))
-        self._rfc2217_port_settings['datasize'].set(struct.pack('!B', self._bytesize))
-        self._rfc2217_port_settings['parity'].set(struct.pack('!B', RFC2217_PARITY_MAP[self._parity]))
-        self._rfc2217_port_settings['stopsize'].set(struct.pack('!B', RFC2217_STOPBIT_MAP[self._stopbits]))
-
-        # and now wait until parameters are active
-        items = self._rfc2217_port_settings.values()
-        if self.logger:
-            self.logger.debug("Negotiating settings: %s" % (items,))
-        timeout_time = time.time() + self._network_timeout
-        while time.time() < timeout_time:
-            if sum(o.active for o in items) == len(items):
-                break
-            time.sleep(0.001)    # prevent 100% CPU load
-        else:
-            raise SerialException("Remote does not accept parameter change (RFC2217): %r" % items)
-        if self.logger:
-            self.logger.info("Negotiated settings: %s" % (items,))
-
-        if self._rtscts and self._xonxoff:
-            raise ValueError('xonxoff and rtscts together are not supported')
-        elif self._rtscts:
-            self.rfc2217SetControl(SET_CONTROL_USE_HW_FLOW_CONTROL)
-        elif self._xonxoff:
-            self.rfc2217SetControl(SET_CONTROL_USE_SW_FLOW_CONTROL)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_USE_NO_FLOW_CONTROL)
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self._socket:
-                try:
-                    self._socket.shutdown(socket.SHUT_RDWR)
-                    self._socket.close()
-                except:
-                    # ignore errors.
-                    pass
-                self._socket = None
-            if self._thread:
-                self._thread.join()
-            self._isOpen = False
-            # in case of quick reconnects, give the server some time
-            time.sleep(0.3)
-
-    def makeDeviceName(self, port):
-        raise SerialException("there is no sensible way to turn numbers into URLs")
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("rfc2217://"): url = url[10:]
-        try:
-            # is there a "path" (our options)?
-            if '/' in url:
-                # cut away options
-                url, options = url.split('/', 1)
-                # process options now, directly altering self
-                for option in options.split('/'):
-                    if '=' in option:
-                        option, value = option.split('=', 1)
-                    else:
-                        value = None
-                    if option == 'logging':
-                        logging.basicConfig()   # XXX is that good to call it here?
-                        self.logger = logging.getLogger('pySerial.rfc2217')
-                        self.logger.setLevel(LOGGER_LEVELS[value])
-                        self.logger.debug('enabled logging')
-                    elif option == 'ign_set_control':
-                        self._ignore_set_control_answer = True
-                    elif option == 'poll_modem':
-                        self._poll_modem_state = True
-                    elif option == 'timeout':
-                        self._network_timeout = float(value)
-                    else:
-                        raise ValueError('unknown option: %r' % (option,))
-            # get host and port
-            host, port = url.split(':', 1) # may raise ValueError because of unpacking
-            port = int(port)               # and this if it's not a number
-            if not 0 <= port < 65536: raise ValueError("port not in range 0...65535")
-        except ValueError, e:
-            raise SerialException('expected a string in the form "[rfc2217://]<host>:<port>[/option[/option...]]": %s' % e)
-        return (host, port)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._isOpen: raise portNotOpenError
-        return self._read_buffer.qsize()
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        data = bytearray()
-        try:
-            while len(data) < size:
-                if self._thread is None:
-                    raise SerialException('connection failed (reader thread died)')
-                data.append(self._read_buffer.get(True, self._timeout))
-        except Queue.Empty: # -> timeout
-            pass
-        return bytes(data)
-
-    def write(self, data):
-        """\
-        Output the given string over the serial port. Can block if the
-        connection is blocked. May raise SerialException if the connection is
-        closed.
-        """
-        if not self._isOpen: raise portNotOpenError
-        self._write_lock.acquire()
-        try:
-            try:
-                self._socket.sendall(to_bytes(data).replace(IAC, IAC_DOUBLED))
-            except socket.error, e:
-                raise SerialException("connection failed (socket error): %s" % e) # XXX what exception if socket connection fails
-        finally:
-            self._write_lock.release()
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        self.rfc2217SendPurge(PURGE_RECEIVE_BUFFER)
-        # empty read buffer
-        while self._read_buffer.qsize():
-            self._read_buffer.get(False)
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        self.rfc2217SendPurge(PURGE_TRANSMIT_BUFFER)
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-        self.setBreak(True)
-        time.sleep(duration)
-        self.setBreak(False)
-
-    def setBreak(self, level=True):
-        """\
-        Set break: Controls TXD. When active, to transmitting is
-        possible.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('set BREAK to %s' % ('inactive', 'active')[bool(level)])
-        if level:
-            self.rfc2217SetControl(SET_CONTROL_BREAK_ON)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_BREAK_OFF)
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('set RTS to %s' % ('inactive', 'active')[bool(level)])
-        if level:
-            self.rfc2217SetControl(SET_CONTROL_RTS_ON)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_RTS_OFF)
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('set DTR to %s' % ('inactive', 'active')[bool(level)])
-        if level:
-            self.rfc2217SetControl(SET_CONTROL_DTR_ON)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_DTR_OFF)
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_CTS)
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_DSR)
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_RI)
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_CD)
-
-    # - - - platform specific - - -
-    # None so far
-
-    # - - - RFC2217 specific - - -
-
-    def _telnetReadLoop(self):
-        """Read loop for the socket."""
-        mode = M_NORMAL
-        suboption = None
-        try:
-            while self._socket is not None:
-                try:
-                    data = self._socket.recv(1024)
-                except socket.timeout:
-                    # just need to get out of recv form time to time to check if
-                    # still alive
-                    continue
-                except socket.error, e:
-                    # connection fails -> terminate loop
-                    if self.logger:
-                        self.logger.debug("socket error in reader thread: %s" % (e,))
-                    break
-                if not data: break # lost connection
-                for byte in data:
-                    if mode == M_NORMAL:
-                        # interpret as command or as data
-                        if byte == IAC:
-                            mode = M_IAC_SEEN
-                        else:
-                            # store data in read buffer or sub option buffer
-                            # depending on state
-                            if suboption is not None:
-                                suboption.append(byte)
-                            else:
-                                self._read_buffer.put(byte)
-                    elif mode == M_IAC_SEEN:
-                        if byte == IAC:
-                            # interpret as command doubled -> insert character
-                            # itself
-                            if suboption is not None:
-                                suboption.append(IAC)
-                            else:
-                                self._read_buffer.put(IAC)
-                            mode = M_NORMAL
-                        elif byte == SB:
-                            # sub option start
-                            suboption = bytearray()
-                            mode = M_NORMAL
-                        elif byte == SE:
-                            # sub option end -> process it now
-                            self._telnetProcessSubnegotiation(bytes(suboption))
-                            suboption = None
-                            mode = M_NORMAL
-                        elif byte in (DO, DONT, WILL, WONT):
-                            # negotiation
-                            telnet_command = byte
-                            mode = M_NEGOTIATE
-                        else:
-                            # other telnet commands
-                            self._telnetProcessCommand(byte)
-                            mode = M_NORMAL
-                    elif mode == M_NEGOTIATE: # DO, DONT, WILL, WONT was received, option now following
-                        self._telnetNegotiateOption(telnet_command, byte)
-                        mode = M_NORMAL
-        finally:
-            self._thread = None
-            if self.logger:
-                self.logger.debug("read thread terminated")
-
-    # - incoming telnet commands and options
-
-    def _telnetProcessCommand(self, command):
-        """Process commands other than DO, DONT, WILL, WONT."""
-        # Currently none. RFC2217 only uses negotiation and subnegotiation.
-        if self.logger:
-            self.logger.warning("ignoring Telnet command: %r" % (command,))
-
-    def _telnetNegotiateOption(self, command, option):
-        """Process incoming DO, DONT, WILL, WONT."""
-        # check our registered telnet options and forward command to them
-        # they know themselves if they have to answer or not
-        known = False
-        for item in self._telnet_options:
-            # can have more than one match! as some options are duplicated for
-            # 'us' and 'them'
-            if item.option == option:
-                item.process_incoming(command)
-                known = True
-        if not known:
-            # handle unknown options
-            # only answer to positive requests and deny them
-            if command == WILL or command == DO:
-                self.telnetSendOption((command == WILL and DONT or WONT), option)
-                if self.logger:
-                    self.logger.warning("rejected Telnet option: %r" % (option,))
-
-
-    def _telnetProcessSubnegotiation(self, suboption):
-        """Process subnegotiation, the data between IAC SB and IAC SE."""
-        if suboption[0:1] == COM_PORT_OPTION:
-            if suboption[1:2] == SERVER_NOTIFY_LINESTATE and len(suboption) >= 3:
-                self._linestate = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("NOTIFY_LINESTATE: %s" % self._linestate)
-            elif suboption[1:2] == SERVER_NOTIFY_MODEMSTATE and len(suboption) >= 3:
-                self._modemstate = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("NOTIFY_MODEMSTATE: %s" % self._modemstate)
-                # update time when we think that a poll would make sense
-                self._modemstate_expires = time.time() + 0.3
-            elif suboption[1:2] == FLOWCONTROL_SUSPEND:
-                self._remote_suspend_flow = True
-            elif suboption[1:2] == FLOWCONTROL_RESUME:
-                self._remote_suspend_flow = False
-            else:
-                for item in self._rfc2217_options.values():
-                    if item.ack_option == suboption[1:2]:
-                        #~ print "processing COM_PORT_OPTION: %r" % list(suboption[1:])
-                        item.checkAnswer(bytes(suboption[2:]))
-                        break
-                else:
-                    if self.logger:
-                        self.logger.warning("ignoring COM_PORT_OPTION: %r" % (suboption,))
-        else:
-            if self.logger:
-                self.logger.warning("ignoring subnegotiation: %r" % (suboption,))
-
-    # - outgoing telnet commands and options
-
-    def _internal_raw_write(self, data):
-        """internal socket write with no data escaping. used to send telnet stuff."""
-        self._write_lock.acquire()
-        try:
-            self._socket.sendall(data)
-        finally:
-            self._write_lock.release()
-
-    def telnetSendOption(self, action, option):
-        """Send DO, DONT, WILL, WONT."""
-        self._internal_raw_write(to_bytes([IAC, action, option]))
-
-    def rfc2217SendSubnegotiation(self, option, value=''):
-        """Subnegotiation of RFC2217 parameters."""
-        value = value.replace(IAC, IAC_DOUBLED)
-        self._internal_raw_write(to_bytes([IAC, SB, COM_PORT_OPTION, option] + list(value) + [IAC, SE]))
-
-    def rfc2217SendPurge(self, value):
-        item = self._rfc2217_options['purge']
-        item.set(value) # transmit desired purge type
-        item.wait(self._network_timeout) # wait for acknowledge from the server
-
-    def rfc2217SetControl(self, value):
-        item = self._rfc2217_options['control']
-        item.set(value) # transmit desired control type
-        if self._ignore_set_control_answer:
-            # answers are ignored when option is set. compatibility mode for
-            # servers that answer, but not the expected one... (or no answer
-            # at all) i.e. sredird
-            time.sleep(0.1)  # this helps getting the unit tests passed
-        else:
-            item.wait(self._network_timeout)  # wait for acknowledge from the server
-
-    def rfc2217FlowServerReady(self):
-        """\
-        check if server is ready to receive data. block for some time when
-        not.
-        """
-        #~ if self._remote_suspend_flow:
-            #~ wait---
-
-    def getModemState(self):
-        """\
-        get last modem state (cached value. If value is "old", request a new
-        one. This cache helps that we don't issue to many requests when e.g. all
-        status lines, one after the other is queried by the user (getCTS, getDSR
-        etc.)
-        """
-        # active modem state polling enabled? is the value fresh enough?
-        if self._poll_modem_state and self._modemstate_expires < time.time():
-            if self.logger:
-                self.logger.debug('polling modem state')
-            # when it is older, request an update
-            self.rfc2217SendSubnegotiation(NOTIFY_MODEMSTATE)
-            timeout_time = time.time() + self._network_timeout
-            while time.time() < timeout_time:
-                # when expiration time is updated, it means that there is a new
-                # value
-                if self._modemstate_expires > time.time():
-                    if self.logger:
-                        self.logger.warning('poll for modem state failed')
-                    break
-                time.sleep(0.001)    # prevent 100% CPU load
-            # even when there is a timeout, do not generate an error just
-            # return the last known value. this way we can support buggy
-            # servers that do not respond to polls, but send automatic
-            # updates.
-        if self._modemstate is not None:
-            if self.logger:
-                self.logger.debug('using cached modem state')
-            return self._modemstate
-        else:
-            # never received a notification from the server
-            raise SerialException("remote sends no NOTIFY_MODEMSTATE")
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(RFC2217Serial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(RFC2217Serial, io.RawIOBase):
-        pass
-
-
-#############################################################################
-# The following is code that helps implementing an RFC 2217 server.
-
-class PortManager(object):
-    """\
-    This class manages the state of Telnet and RFC 2217. It needs a serial
-    instance and a connection to work with. Connection is expected to implement
-    a (thread safe) write function, that writes the string to the network.
-    """
-
-    def __init__(self, serial_port, connection, logger=None):
-        self.serial = serial_port
-        self.connection = connection
-        self.logger = logger
-        self._client_is_rfc2217 = False
-
-        # filter state machine
-        self.mode = M_NORMAL
-        self.suboption = None
-        self.telnet_command = None
-
-        # states for modem/line control events
-        self.modemstate_mask = 255
-        self.last_modemstate = None
-        self.linstate_mask = 0
-
-        # all supported telnet options
-        self._telnet_options = [
-            TelnetOption(self, 'ECHO', ECHO, WILL, WONT, DO, DONT, REQUESTED),
-            TelnetOption(self, 'we-SGA', SGA, WILL, WONT, DO, DONT, REQUESTED),
-            TelnetOption(self, 'they-SGA', SGA, DO, DONT, WILL, WONT, INACTIVE),
-            TelnetOption(self, 'we-BINARY', BINARY, WILL, WONT, DO, DONT, INACTIVE),
-            TelnetOption(self, 'they-BINARY', BINARY, DO, DONT, WILL, WONT, REQUESTED),
-            TelnetOption(self, 'we-RFC2217', COM_PORT_OPTION, WILL, WONT, DO, DONT, REQUESTED, self._client_ok),
-            TelnetOption(self, 'they-RFC2217', COM_PORT_OPTION, DO, DONT, WILL, WONT, INACTIVE, self._client_ok),
-            ]
-
-        # negotiate Telnet/RFC2217 -> send initial requests
-        if self.logger:
-            self.logger.debug("requesting initial Telnet/RFC 2217 options")
-        for option in self._telnet_options:
-            if option.state is REQUESTED:
-                self.telnetSendOption(option.send_yes, option.option)
-        # issue 1st modem state notification
-
-    def _client_ok(self):
-        """\
-        callback of telnet option. It gets called when option is activated.
-        This one here is used to detect when the client agrees on RFC 2217. A
-        flag is set so that other functions like check_modem_lines know if the
-        client is OK.
-        """
-        # The callback is used for we and they so if one party agrees, we're
-        # already happy. it seems not all servers do the negotiation correctly
-        # and i guess there are incorrect clients too.. so be happy if client
-        # answers one or the other positively.
-        self._client_is_rfc2217 = True
-        if self.logger:
-            self.logger.info("client accepts RFC 2217")
-        # this is to ensure that the client gets a notification, even if there
-        # was no change
-        self.check_modem_lines(force_notification=True)
-
-    # - outgoing telnet commands and options
-
-    def telnetSendOption(self, action, option):
-        """Send DO, DONT, WILL, WONT."""
-        self.connection.write(to_bytes([IAC, action, option]))
-
-    def rfc2217SendSubnegotiation(self, option, value=''):
-        """Subnegotiation of RFC 2217 parameters."""
-        value = value.replace(IAC, IAC_DOUBLED)
-        self.connection.write(to_bytes([IAC, SB, COM_PORT_OPTION, option] + list(value) + [IAC, SE]))
-
-    # - check modem lines, needs to be called periodically from user to
-    # establish polling
-
-    def check_modem_lines(self, force_notification=False):
-        modemstate = (
-            (self.serial.getCTS() and MODEMSTATE_MASK_CTS) |
-            (self.serial.getDSR() and MODEMSTATE_MASK_DSR) |
-            (self.serial.getRI() and MODEMSTATE_MASK_RI) |
-            (self.serial.getCD() and MODEMSTATE_MASK_CD)
-        )
-        # check what has changed
-        deltas = modemstate ^ (self.last_modemstate or 0) # when last is None -> 0
-        if deltas & MODEMSTATE_MASK_CTS:
-            modemstate |= MODEMSTATE_MASK_CTS_CHANGE
-        if deltas & MODEMSTATE_MASK_DSR:
-            modemstate |= MODEMSTATE_MASK_DSR_CHANGE
-        if deltas & MODEMSTATE_MASK_RI:
-            modemstate |= MODEMSTATE_MASK_RI_CHANGE
-        if deltas & MODEMSTATE_MASK_CD:
-            modemstate |= MODEMSTATE_MASK_CD_CHANGE
-        # if new state is different and the mask allows this change, send
-        # notification. suppress notifications when client is not rfc2217
-        if modemstate != self.last_modemstate or force_notification:
-            if (self._client_is_rfc2217 and (modemstate & self.modemstate_mask)) or force_notification:
-                self.rfc2217SendSubnegotiation(
-                    SERVER_NOTIFY_MODEMSTATE,
-                    to_bytes([modemstate & self.modemstate_mask])
-                    )
-                if self.logger:
-                    self.logger.info("NOTIFY_MODEMSTATE: %s" % (modemstate,))
-            # save last state, but forget about deltas.
-            # otherwise it would also notify about changing deltas which is
-            # probably not very useful
-            self.last_modemstate = modemstate & 0xf0
-
-    # - outgoing data escaping
-
-    def escape(self, data):
-        """\
-        This generator function is for the user. All outgoing data has to be
-        properly escaped, so that no IAC character in the data stream messes up
-        the Telnet state machine in the server.
-
-        socket.sendall(escape(data))
-        """
-        for byte in data:
-            if byte == IAC:
-                yield IAC
-                yield IAC
-            else:
-                yield byte
-
-    # - incoming data filter
-
-    def filter(self, data):
-        """\
-        Handle a bunch of incoming bytes. This is a generator. It will yield
-        all characters not of interest for Telnet/RFC 2217.
-
-        The idea is that the reader thread pushes data from the socket through
-        this filter:
-
-        for byte in filter(socket.recv(1024)):
-            # do things like CR/LF conversion/whatever
-            # and write data to the serial port
-            serial.write(byte)
-
-        (socket error handling code left as exercise for the reader)
-        """
-        for byte in data:
-            if self.mode == M_NORMAL:
-                # interpret as command or as data
-                if byte == IAC:
-                    self.mode = M_IAC_SEEN
-                else:
-                    # store data in sub option buffer or pass it to our
-                    # consumer depending on state
-                    if self.suboption is not None:
-                        self.suboption.append(byte)
-                    else:
-                        yield byte
-            elif self.mode == M_IAC_SEEN:
-                if byte == IAC:
-                    # interpret as command doubled -> insert character
-                    # itself
-                    if self.suboption is not None:
-                        self.suboption.append(byte)
-                    else:
-                        yield byte
-                    self.mode = M_NORMAL
-                elif byte == SB:
-                    # sub option start
-                    self.suboption = bytearray()
-                    self.mode = M_NORMAL
-                elif byte == SE:
-                    # sub option end -> process it now
-                    self._telnetProcessSubnegotiation(bytes(self.suboption))
-                    self.suboption = None
-                    self.mode = M_NORMAL
-                elif byte in (DO, DONT, WILL, WONT):
-                    # negotiation
-                    self.telnet_command = byte
-                    self.mode = M_NEGOTIATE
-                else:
-                    # other telnet commands
-                    self._telnetProcessCommand(byte)
-                    self.mode = M_NORMAL
-            elif self.mode == M_NEGOTIATE: # DO, DONT, WILL, WONT was received, option now following
-                self._telnetNegotiateOption(self.telnet_command, byte)
-                self.mode = M_NORMAL
-
-    # - incoming telnet commands and options
-
-    def _telnetProcessCommand(self, command):
-        """Process commands other than DO, DONT, WILL, WONT."""
-        # Currently none. RFC2217 only uses negotiation and subnegotiation.
-        if self.logger:
-            self.logger.warning("ignoring Telnet command: %r" % (command,))
-
-    def _telnetNegotiateOption(self, command, option):
-        """Process incoming DO, DONT, WILL, WONT."""
-        # check our registered telnet options and forward command to them
-        # they know themselves if they have to answer or not
-        known = False
-        for item in self._telnet_options:
-            # can have more than one match! as some options are duplicated for
-            # 'us' and 'them'
-            if item.option == option:
-                item.process_incoming(command)
-                known = True
-        if not known:
-            # handle unknown options
-            # only answer to positive requests and deny them
-            if command == WILL or command == DO:
-                self.telnetSendOption((command == WILL and DONT or WONT), option)
-                if self.logger:
-                    self.logger.warning("rejected Telnet option: %r" % (option,))
-
-
-    def _telnetProcessSubnegotiation(self, suboption):
-        """Process subnegotiation, the data between IAC SB and IAC SE."""
-        if suboption[0:1] == COM_PORT_OPTION:
-            if self.logger:
-                self.logger.debug('received COM_PORT_OPTION: %r' % (suboption,))
-            if suboption[1:2] == SET_BAUDRATE:
-                backup = self.serial.baudrate
-                try:
-                    (baudrate,) = struct.unpack("!I", suboption[2:6])
-                    if baudrate != 0:
-                        self.serial.baudrate = baudrate
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set baud rate: %s" % (e,))
-                    self.serial.baudrate = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s baud rate: %s" % (baudrate and 'set' or 'get', self.serial.baudrate))
-                self.rfc2217SendSubnegotiation(SERVER_SET_BAUDRATE, struct.pack("!I", self.serial.baudrate))
-            elif suboption[1:2] == SET_DATASIZE:
-                backup = self.serial.bytesize
-                try:
-                    (datasize,) = struct.unpack("!B", suboption[2:3])
-                    if datasize != 0:
-                        self.serial.bytesize = datasize
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set data size: %s" % (e,))
-                    self.serial.bytesize = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s data size: %s" % (datasize and 'set' or 'get', self.serial.bytesize))
-                self.rfc2217SendSubnegotiation(SERVER_SET_DATASIZE, struct.pack("!B", self.serial.bytesize))
-            elif suboption[1:2] == SET_PARITY:
-                backup = self.serial.parity
-                try:
-                    parity = struct.unpack("!B", suboption[2:3])[0]
-                    if parity != 0:
-                            self.serial.parity = RFC2217_REVERSE_PARITY_MAP[parity]
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set parity: %s" % (e,))
-                    self.serial.parity = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s parity: %s" % (parity and 'set' or 'get', self.serial.parity))
-                self.rfc2217SendSubnegotiation(
-                    SERVER_SET_PARITY,
-                    struct.pack("!B", RFC2217_PARITY_MAP[self.serial.parity])
-                    )
-            elif suboption[1:2] == SET_STOPSIZE:
-                backup = self.serial.stopbits
-                try:
-                    stopbits = struct.unpack("!B", suboption[2:3])[0]
-                    if stopbits != 0:
-                        self.serial.stopbits = RFC2217_REVERSE_STOPBIT_MAP[stopbits]
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set stop bits: %s" % (e,))
-                    self.serial.stopbits = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s stop bits: %s" % (stopbits and 'set' or 'get', self.serial.stopbits))
-                self.rfc2217SendSubnegotiation(
-                    SERVER_SET_STOPSIZE,
-                    struct.pack("!B", RFC2217_STOPBIT_MAP[self.serial.stopbits])
-                    )
-            elif suboption[1:2] == SET_CONTROL:
-                if suboption[2:3] == SET_CONTROL_REQ_FLOW_SETTING:
-                    if self.serial.xonxoff:
-                        self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_SW_FLOW_CONTROL)
-                    elif self.serial.rtscts:
-                        self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_HW_FLOW_CONTROL)
-                    else:
-                        self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_NO_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_USE_NO_FLOW_CONTROL:
-                    self.serial.xonxoff = False
-                    self.serial.rtscts = False
-                    if self.logger:
-                        self.logger.info("changed flow control to None")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_NO_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_USE_SW_FLOW_CONTROL:
-                    self.serial.xonxoff = True
-                    if self.logger:
-                        self.logger.info("changed flow control to XON/XOFF")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_SW_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_USE_HW_FLOW_CONTROL:
-                    self.serial.rtscts = True
-                    if self.logger:
-                        self.logger.info("changed flow control to RTS/CTS")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_HW_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_REQ_BREAK_STATE:
-                    if self.logger:
-                        self.logger.warning("requested break state - not implemented")
-                    pass # XXX needs cached value
-                elif suboption[2:3] == SET_CONTROL_BREAK_ON:
-                    self.serial.setBreak(True)
-                    if self.logger:
-                        self.logger.info("changed BREAK to active")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_BREAK_ON)
-                elif suboption[2:3] == SET_CONTROL_BREAK_OFF:
-                    self.serial.setBreak(False)
-                    if self.logger:
-                        self.logger.info("changed BREAK to inactive")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_BREAK_OFF)
-                elif suboption[2:3] == SET_CONTROL_REQ_DTR:
-                    if self.logger:
-                        self.logger.warning("requested DTR state - not implemented")
-                    pass # XXX needs cached value
-                elif suboption[2:3] == SET_CONTROL_DTR_ON:
-                    self.serial.setDTR(True)
-                    if self.logger:
-                        self.logger.info("changed DTR to active")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_DTR_ON)
-                elif suboption[2:3] == SET_CONTROL_DTR_OFF:
-                    self.serial.setDTR(False)
-                    if self.logger:
-                        self.logger.info("changed DTR to inactive")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_DTR_OFF)
-                elif suboption[2:3] == SET_CONTROL_REQ_RTS:
-                    if self.logger:
-                        self.logger.warning("requested RTS state - not implemented")
-                    pass # XXX needs cached value
-                    #~ self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_RTS_ON)
-                elif suboption[2:3] == SET_CONTROL_RTS_ON:
-                    self.serial.setRTS(True)
-                    if self.logger:
-                        self.logger.info("changed RTS to active")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_RTS_ON)
-                elif suboption[2:3] == SET_CONTROL_RTS_OFF:
-                    self.serial.setRTS(False)
-                    if self.logger:
-                        self.logger.info("changed RTS to inactive")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_RTS_OFF)
-                #~ elif suboption[2:3] == SET_CONTROL_REQ_FLOW_SETTING_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_NO_FLOW_CONTROL_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_SW_FLOW_CONTOL_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_HW_FLOW_CONTOL_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_DCD_FLOW_CONTROL:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_DTR_FLOW_CONTROL:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_DSR_FLOW_CONTROL:
-            elif suboption[1:2] == NOTIFY_LINESTATE:
-                # client polls for current state
-                self.rfc2217SendSubnegotiation(
-                    SERVER_NOTIFY_LINESTATE,
-                    to_bytes([0])   # sorry, nothing like that implemented
-                    )
-            elif suboption[1:2] == NOTIFY_MODEMSTATE:
-                if self.logger:
-                    self.logger.info("request for modem state")
-                # client polls for current state
-                self.check_modem_lines(force_notification=True)
-            elif suboption[1:2] == FLOWCONTROL_SUSPEND:
-                if self.logger:
-                    self.logger.info("suspend")
-                self._remote_suspend_flow = True
-            elif suboption[1:2] == FLOWCONTROL_RESUME:
-                if self.logger:
-                    self.logger.info("resume")
-                self._remote_suspend_flow = False
-            elif suboption[1:2] == SET_LINESTATE_MASK:
-                self.linstate_mask = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("line state mask: 0x%02x" % (self.linstate_mask,))
-            elif suboption[1:2] == SET_MODEMSTATE_MASK:
-                self.modemstate_mask = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("modem state mask: 0x%02x" % (self.modemstate_mask,))
-            elif suboption[1:2] == PURGE_DATA:
-                if suboption[2:3] == PURGE_RECEIVE_BUFFER:
-                    self.serial.flushInput()
-                    if self.logger:
-                        self.logger.info("purge in")
-                    self.rfc2217SendSubnegotiation(SERVER_PURGE_DATA, PURGE_RECEIVE_BUFFER)
-                elif suboption[2:3] == PURGE_TRANSMIT_BUFFER:
-                    self.serial.flushOutput()
-                    if self.logger:
-                        self.logger.info("purge out")
-                    self.rfc2217SendSubnegotiation(SERVER_PURGE_DATA, PURGE_TRANSMIT_BUFFER)
-                elif suboption[2:3] == PURGE_BOTH_BUFFERS:
-                    self.serial.flushInput()
-                    self.serial.flushOutput()
-                    if self.logger:
-                        self.logger.info("purge both")
-                    self.rfc2217SendSubnegotiation(SERVER_PURGE_DATA, PURGE_BOTH_BUFFERS)
-                else:
-                    if self.logger:
-                        self.logger.error("undefined PURGE_DATA: %r" % list(suboption[2:]))
-            else:
-                if self.logger:
-                    self.logger.error("undefined COM_PORT_OPTION: %r" % list(suboption[1:]))
-        else:
-            if self.logger:
-                self.logger.warning("unknown subnegotiation: %r" % (suboption,))
-
-
-# simple client test
-if __name__ == '__main__':
-    import sys
-    s = Serial('rfc2217://localhost:7000', 115200)
-    sys.stdout.write('%s\n' % s)
-
-    #~ s.baudrate = 1898
-
-    sys.stdout.write("write...\n")
-    s.write("hello\n")
-    s.flush()
-    sys.stdout.write("read: %s\n" % s.read(5))
-
-    #~ s.baudrate = 19200
-    #~ s.databits = 7
-    s.close()
diff --git a/scripts/serial/serialcli.py b/scripts/serial/serialcli.py
deleted file mode 100644
index 9ab3876206..0000000000
--- a/scripts/serial/serialcli.py
+++ /dev/null
@@ -1,284 +0,0 @@
-#! python
-# Python Serial Port Extension for Win32, Linux, BSD, Jython and .NET/Mono
-# serial driver for .NET/Mono (IronPython), .NET >= 2
-# see __init__.py
-#
-# (C) 2008 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-import clr
-import System
-import System.IO.Ports
-from serial.serialutil import *
-
-
-def device(portnum):
-    """Turn a port number into a device name"""
-    return System.IO.Ports.SerialPort.GetPortNames()[portnum]
-
-
-# must invoke function with byte array, make a helper to convert strings
-# to byte arrays
-sab = System.Array[System.Byte]
-def as_byte_array(string):
-    return sab([ord(x) for x in string])  # XXX will require adaption when run with a 3.x compatible IronPython
-
-class IronSerial(SerialBase):
-    """Serial port implementation for .NET/Mono."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        try:
-            self._port_handle = System.IO.Ports.SerialPort(self.portstr)
-        except Exception, msg:
-            self._port_handle = None
-            raise SerialException("could not open port %s: %s" % (self.portstr, msg))
-
-        self._reconfigurePort()
-        self._port_handle.Open()
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """Set communication parameters on opened port."""
-        if not self._port_handle:
-            raise SerialException("Can only operate on a valid port handle")
-
-        #~ self._port_handle.ReceivedBytesThreshold = 1
-
-        if self._timeout is None:
-            self._port_handle.ReadTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
-        else:
-            self._port_handle.ReadTimeout = int(self._timeout*1000)
-
-        # if self._timeout != 0 and self._interCharTimeout is not None:
-            # timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
-
-        if self._writeTimeout is None:
-            self._port_handle.WriteTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
-        else:
-            self._port_handle.WriteTimeout = int(self._writeTimeout*1000)
-
-
-        # Setup the connection info.
-        try:
-            self._port_handle.BaudRate = self._baudrate
-        except IOError, e:
-            # catch errors from illegal baudrate settings
-            raise ValueError(str(e))
-
-        if self._bytesize == FIVEBITS:
-            self._port_handle.DataBits     = 5
-        elif self._bytesize == SIXBITS:
-            self._port_handle.DataBits     = 6
-        elif self._bytesize == SEVENBITS:
-            self._port_handle.DataBits     = 7
-        elif self._bytesize == EIGHTBITS:
-            self._port_handle.DataBits     = 8
-        else:
-            raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
-
-        if self._parity == PARITY_NONE:
-            self._port_handle.Parity       = getattr(System.IO.Ports.Parity, 'None') # reserved keyword in Py3k
-        elif self._parity == PARITY_EVEN:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Even
-        elif self._parity == PARITY_ODD:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Odd
-        elif self._parity == PARITY_MARK:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Mark
-        elif self._parity == PARITY_SPACE:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Space
-        else:
-            raise ValueError("Unsupported parity mode: %r" % self._parity)
-
-        if self._stopbits == STOPBITS_ONE:
-            self._port_handle.StopBits     = System.IO.Ports.StopBits.One
-        elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
-            self._port_handle.StopBits     = System.IO.Ports.StopBits.OnePointFive
-        elif self._stopbits == STOPBITS_TWO:
-            self._port_handle.StopBits     = System.IO.Ports.StopBits.Two
-        else:
-            raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
-
-        if self._rtscts and self._xonxoff:
-            self._port_handle.Handshake  = System.IO.Ports.Handshake.RequestToSendXOnXOff
-        elif self._rtscts:
-            self._port_handle.Handshake  = System.IO.Ports.Handshake.RequestToSend
-        elif self._xonxoff:
-            self._port_handle.Handshake  = System.IO.Ports.Handshake.XOnXOff
-        else:
-            self._port_handle.Handshake  = getattr(System.IO.Ports.Handshake, 'None')   # reserved keyword in Py3k
-
-    #~ def __del__(self):
-        #~ self.close()
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self._port_handle:
-                try:
-                    self._port_handle.Close()
-                except System.IO.Ports.InvalidOperationException:
-                    # ignore errors. can happen for unplugged USB serial devices
-                    pass
-                self._port_handle = None
-            self._isOpen = False
-
-    def makeDeviceName(self, port):
-        try:
-            return device(port)
-        except TypeError, e:
-            raise SerialException(str(e))
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.BytesToRead
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._port_handle: raise portNotOpenError
-        # must use single byte reads as this is the only way to read
-        # without applying encodings
-        data = bytearray()
-        while size:
-            try:
-                data.append(self._port_handle.ReadByte())
-            except System.TimeoutException, e:
-                break
-            else:
-                size -= 1
-        return bytes(data)
-
-    def write(self, data):
-        """Output the given string over the serial port."""
-        if not self._port_handle: raise portNotOpenError
-        #~ if not isinstance(data, (bytes, bytearray)):
-            #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
-        try:
-            # must call overloaded method with byte array argument
-            # as this is the only one not applying encodings
-            self._port_handle.Write(as_byte_array(data), 0, len(data))
-        except System.TimeoutException, e:
-            raise writeTimeoutError
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.DiscardInBuffer()
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.DiscardOutBuffer()
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._port_handle: raise portNotOpenError
-        import time
-        self._port_handle.BreakState = True
-        time.sleep(duration)
-        self._port_handle.BreakState = False
-
-    def setBreak(self, level=True):
-        """
-        Set break: Controls TXD. When active, to transmitting is possible.
-        """
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.BreakState = bool(level)
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send"""
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.RtsEnable = bool(level)
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.DtrEnable = bool(level)
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.CtsHolding
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.DsrHolding
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._port_handle: raise portNotOpenError
-        #~ return self._port_handle.XXX
-        return False #XXX an error would be better
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.CDHolding
-
-    # - - platform specific - - - -
-    # none
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(IronSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(IronSerial, io.RawIOBase):
-        pass
-
-
-# Nur Testfunktion!!
-if __name__ == '__main__':
-    import sys
-
-    s = Serial(0)
-    sys.stdio.write('%s\n' % s)
-
-    s = Serial()
-    sys.stdio.write('%s\n' % s)
-
-
-    s.baudrate = 19200
-    s.databits = 7
-    s.close()
-    s.port = 0
-    s.open()
-    sys.stdio.write('%s\n' % s)
-
diff --git a/scripts/serial/serialposix.py b/scripts/serial/serialposix.py
deleted file mode 100644
index 359ad1b877..0000000000
--- a/scripts/serial/serialposix.py
+++ /dev/null
@@ -1,730 +0,0 @@
-#!/usr/bin/env python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# module for serial IO for POSIX compatible systems, like Linux
-# see __init__.py
-#
-# (C) 2001-2010 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# parts based on code from Grant B. Edwards  <grante at visi.com>:
-#  ftp://ftp.visi.com/users/grante/python/PosixSerial.py
-#
-# references: http://www.easysw.com/~mike/serial/serial.html
-
-import sys, os, fcntl, termios, struct, select, errno, time
-from serial.serialutil import *
-
-# Do check the Python version as some constants have moved.
-if (sys.hexversion < 0x020100f0):
-    import TERMIOS
-else:
-    TERMIOS = termios
-
-if (sys.hexversion < 0x020200f0):
-    import FCNTL
-else:
-    FCNTL = fcntl
-
-# try to detect the OS so that a device can be selected...
-# this code block should supply a device() and set_special_baudrate() function
-# for the platform
-plat = sys.platform.lower()
-
-if   plat[:5] == 'linux':    # Linux (confirmed)
-
-    def device(port):
-        return '/dev/ttyS%d' % port
-
-    TCGETS2 = 0x802C542A
-    TCSETS2 = 0x402C542B
-    BOTHER = 0o010000
-
-    def set_special_baudrate(port, baudrate):
-        # right size is 44 on x86_64, allow for some growth
-        import array
-        buf = array.array('i', [0] * 64)
-
-        try:
-            # get serial_struct
-            FCNTL.ioctl(port.fd, TCGETS2, buf)
-            # set custom speed
-            buf[2] &= ~TERMIOS.CBAUD
-            buf[2] |= BOTHER
-            buf[9] = buf[10] = baudrate
-
-            # set serial_struct
-            res = FCNTL.ioctl(port.fd, TCSETS2, buf)
-        except IOError, e:
-            raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
-
-    baudrate_constants = {
-        0:       0000000,  # hang up
-        50:      0000001,
-        75:      0000002,
-        110:     0000003,
-        134:     0000004,
-        150:     0000005,
-        200:     0000006,
-        300:     0000007,
-        600:     0000010,
-        1200:    0000011,
-        1800:    0000012,
-        2400:    0000013,
-        4800:    0000014,
-        9600:    0000015,
-        19200:   0000016,
-        38400:   0000017,
-        57600:   0010001,
-        115200:  0010002,
-        230400:  0010003,
-        460800:  0010004,
-        500000:  0010005,
-        576000:  0010006,
-        921600:  0010007,
-        1000000: 0010010,
-        1152000: 0010011,
-        1500000: 0010012,
-        2000000: 0010013,
-        2500000: 0010014,
-        3000000: 0010015,
-        3500000: 0010016,
-        4000000: 0010017
-    }
-
-elif plat == 'cygwin':       # cygwin/win32 (confirmed)
-
-    def device(port):
-        return '/dev/com%d' % (port + 1)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {
-        128000: 0x01003,
-        256000: 0x01005,
-        500000: 0x01007,
-        576000: 0x01008,
-        921600: 0x01009,
-        1000000: 0x0100a,
-        1152000: 0x0100b,
-        1500000: 0x0100c,
-        2000000: 0x0100d,
-        2500000: 0x0100e,
-        3000000: 0x0100f
-    }
-
-elif plat[:7] == 'openbsd':    # OpenBSD
-
-    def device(port):
-        return '/dev/cua%02d' % port
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:3] == 'bsd' or  \
-    plat[:7] == 'freebsd':
-
-    def device(port):
-        return '/dev/cuad%d' % port
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:6] == 'darwin':   # OS X
-
-    version = os.uname()[2].split('.')
-    # Tiger or above can support arbitrary serial speeds
-    if int(version[0]) >= 8:
-        def set_special_baudrate(port, baudrate):
-            # use IOKit-specific call to set up high speeds
-            import array, fcntl
-            buf = array.array('i', [baudrate])
-            IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
-            fcntl.ioctl(port.fd, IOSSIOSPEED, buf, 1)
-    else: # version < 8
-        def set_special_baudrate(port, baudrate):
-            raise ValueError("baud rate not supported")
-
-    def device(port):
-        return '/dev/cuad%d' % port
-
-    baudrate_constants = {}
-
-
-elif plat[:6] == 'netbsd':   # NetBSD 1.6 testing by Erk
-
-    def device(port):
-        return '/dev/dty%02d' % port
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:4] == 'irix':     # IRIX (partially tested)
-
-    def device(port):
-        return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:2] == 'hp':       # HP-UX (not tested)
-
-    def device(port):
-        return '/dev/tty%dp0' % (port+1)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:5] == 'sunos':    # Solaris/SunOS (confirmed)
-
-    def device(port):
-        return '/dev/tty%c' % (ord('a')+port)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:3] == 'aix':      # AIX
-
-    def device(port):
-        return '/dev/tty%d' % (port)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-else:
-    # platform detection has failed...
-    sys.stderr.write("""\
-don't know how to number ttys on this system.
-! Use an explicit path (eg /dev/ttyS1) or send this information to
-! the author of this module:
-
-sys.platform = %r
-os.name = %r
-serialposix.py version = %s
-
-also add the device name of the serial port and where the
-counting starts for the first serial port.
-e.g. 'first serial port: /dev/ttyS0'
-and with a bit luck you can get this module running...
-""" % (sys.platform, os.name, VERSION))
-    # no exception, just continue with a brave attempt to build a device name
-    # even if the device name is not correct for the platform it has chances
-    # to work using a string with the real device name as port parameter.
-    def device(portum):
-        return '/dev/ttyS%d' % portnum
-    def set_special_baudrate(port, baudrate):
-        raise SerialException("sorry don't know how to handle non standard baud rate on this platform")
-    baudrate_constants = {}
-    #~ raise Exception, "this module does not run on this platform, sorry."
-
-# whats up with "aix", "beos", ....
-# they should work, just need to know the device names.
-
-
-# load some constants for later use.
-# try to use values from TERMIOS, use defaults from linux otherwise
-TIOCMGET  = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415
-TIOCMBIS  = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416
-TIOCMBIC  = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417
-TIOCMSET  = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418
-
-#TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001
-TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002
-TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004
-#TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008
-#TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010
-
-TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020
-TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040
-TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080
-TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100
-TIOCM_CD  = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR
-TIOCM_RI  = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG
-#TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000
-#TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000
-if hasattr(TERMIOS, 'TIOCINQ'):
-    TIOCINQ = TERMIOS.TIOCINQ
-else:
-    TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B
-TIOCOUTQ   = hasattr(TERMIOS, 'TIOCOUTQ') and TERMIOS.TIOCOUTQ or 0x5411
-
-TIOCM_zero_str = struct.pack('I', 0)
-TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
-TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
-
-TIOCSBRK  = hasattr(TERMIOS, 'TIOCSBRK') and TERMIOS.TIOCSBRK or 0x5427
-TIOCCBRK  = hasattr(TERMIOS, 'TIOCCBRK') and TERMIOS.TIOCCBRK or 0x5428
-
-CMSPAR = 010000000000 # Use "stick" (mark/space) parity
-
-
-class PosixSerial(SerialBase):
-    """\
-    Serial port class POSIX implementation. Serial port configuration is 
-    done with termios and fcntl. Runs on Linux and many other Un*x like
-    systems.
-    """
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened."""
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        self.fd = None
-        # open
-        try:
-            self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
-        except OSError, msg:
-            self.fd = None
-            raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
-        #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0)  # set blocking
-
-        try:
-            self._reconfigurePort()
-        except:
-            try:
-                os.close(self.fd)
-            except:
-                # ignore any exception when closing the port
-                # also to keep original exception that happened when setting up
-                pass
-            self.fd = None
-            raise
-        else:
-            self._isOpen = True
-        self.flushInput()
-
-
-    def _reconfigurePort(self):
-        """Set communication parameters on opened port."""
-        if self.fd is None:
-            raise SerialException("Can only operate on a valid file descriptor")
-        custom_baud = None
-
-        vmin = vtime = 0                # timeout is done via select
-        if self._interCharTimeout is not None:
-            vmin = 1
-            vtime = int(self._interCharTimeout * 10)
-        try:
-            orig_attr = termios.tcgetattr(self.fd)
-            iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
-        except termios.error, msg:      # if a port is nonexistent but has a /dev file, it'll fail here
-            raise SerialException("Could not configure port: %s" % msg)
-        # set up raw mode / no echo / binary
-        cflag |=  (TERMIOS.CLOCAL|TERMIOS.CREAD)
-        lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL|
-                     TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT
-        for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
-            if hasattr(TERMIOS, flag):
-                lflag &= ~getattr(TERMIOS, flag)
-
-        oflag &= ~(TERMIOS.OPOST)
-        iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK)
-        if hasattr(TERMIOS, 'IUCLC'):
-            iflag &= ~TERMIOS.IUCLC
-        if hasattr(TERMIOS, 'PARMRK'):
-            iflag &= ~TERMIOS.PARMRK
-
-        # setup baud rate
-        try:
-            ispeed = ospeed = getattr(TERMIOS, 'B%s' % (self._baudrate))
-        except AttributeError:
-            try:
-                ispeed = ospeed = baudrate_constants[self._baudrate]
-            except KeyError:
-                #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
-                # may need custom baud rate, it isn't in our list.
-                ispeed = ospeed = getattr(TERMIOS, 'B38400')
-                try:
-                    custom_baud = int(self._baudrate) # store for later
-                except ValueError:
-                    raise ValueError('Invalid baud rate: %r' % self._baudrate)
-                else:
-                    if custom_baud < 0:
-                        raise ValueError('Invalid baud rate: %r' % self._baudrate)
-
-        # setup char len
-        cflag &= ~TERMIOS.CSIZE
-        if self._bytesize == 8:
-            cflag |= TERMIOS.CS8
-        elif self._bytesize == 7:
-            cflag |= TERMIOS.CS7
-        elif self._bytesize == 6:
-            cflag |= TERMIOS.CS6
-        elif self._bytesize == 5:
-            cflag |= TERMIOS.CS5
-        else:
-            raise ValueError('Invalid char len: %r' % self._bytesize)
-        # setup stop bits
-        if self._stopbits == STOPBITS_ONE:
-            cflag &= ~(TERMIOS.CSTOPB)
-        elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
-            cflag |=  (TERMIOS.CSTOPB)  # XXX same as TWO.. there is no POSIX support for 1.5
-        elif self._stopbits == STOPBITS_TWO:
-            cflag |=  (TERMIOS.CSTOPB)
-        else:
-            raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
-        # setup parity
-        iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP)
-        if self._parity == PARITY_NONE:
-            cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD)
-        elif self._parity == PARITY_EVEN:
-            cflag &= ~(TERMIOS.PARODD)
-            cflag |=  (TERMIOS.PARENB)
-        elif self._parity == PARITY_ODD:
-            cflag |=  (TERMIOS.PARENB|TERMIOS.PARODD)
-        elif self._parity == PARITY_MARK and plat[:5] == 'linux':
-            cflag |=  (TERMIOS.PARENB|CMSPAR|TERMIOS.PARODD)
-        elif self._parity == PARITY_SPACE and plat[:5] == 'linux':
-            cflag |=  (TERMIOS.PARENB|CMSPAR)
-            cflag &= ~(TERMIOS.PARODD)
-        else:
-            raise ValueError('Invalid parity: %r' % self._parity)
-        # setup flow control
-        # xonxoff
-        if hasattr(TERMIOS, 'IXANY'):
-            if self._xonxoff:
-                iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY)
-            else:
-                iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY)
-        else:
-            if self._xonxoff:
-                iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF)
-            else:
-                iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF)
-        # rtscts
-        if hasattr(TERMIOS, 'CRTSCTS'):
-            if self._rtscts:
-                cflag |=  (TERMIOS.CRTSCTS)
-            else:
-                cflag &= ~(TERMIOS.CRTSCTS)
-        elif hasattr(TERMIOS, 'CNEW_RTSCTS'):   # try it with alternate constant name
-            if self._rtscts:
-                cflag |=  (TERMIOS.CNEW_RTSCTS)
-            else:
-                cflag &= ~(TERMIOS.CNEW_RTSCTS)
-        # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
-
-        # buffer
-        # vmin "minimal number of characters to be read. 0 for non blocking"
-        if vmin < 0 or vmin > 255:
-            raise ValueError('Invalid vmin: %r ' % vmin)
-        cc[TERMIOS.VMIN] = vmin
-        # vtime
-        if vtime < 0 or vtime > 255:
-            raise ValueError('Invalid vtime: %r' % vtime)
-        cc[TERMIOS.VTIME] = vtime
-        # activate settings
-        if [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
-            termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
-
-        # apply custom baud rate, if any
-        if custom_baud is not None:
-            set_special_baudrate(self, custom_baud)
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self.fd is not None:
-                os.close(self.fd)
-                self.fd = None
-            self._isOpen = False
-
-    def makeDeviceName(self, port):
-        return device(port)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
-        s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
-        return struct.unpack('I',s)[0]
-
-    # select based implementation, proved to work on many systems
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        read = bytearray()
-        while len(read) < size:
-            try:
-                ready,_,_ = select.select([self.fd],[],[], self._timeout)
-                # If select was used with a timeout, and the timeout occurs, it
-                # returns with empty lists -> thus abort read operation.
-                # For timeout == 0 (non-blocking operation) also abort when there
-                # is nothing to read.
-                if not ready:
-                    break   # timeout
-                buf = os.read(self.fd, size-len(read))
-                # read should always return some data as select reported it was
-                # ready to read when we get to this point.
-                if not buf:
-                    # Disconnected devices, at least on Linux, show the
-                    # behavior that they are always ready to read immediately
-                    # but reading returns nothing.
-                    raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
-                read.extend(buf)
-            except OSError, e:
-                # this is for Python 3.x where select.error is a subclass of OSError
-                # ignore EAGAIN errors. all other errors are shown
-                if e.errno != errno.EAGAIN:
-                    raise SerialException('read failed: %s' % (e,))
-            except select.error, e:
-                # this is for Python 2.x
-                # ignore EAGAIN errors. all other errors are shown
-                # see also http://www.python.org/dev/peps/pep-3151/#select
-                if e[0] != errno.EAGAIN:
-                    raise SerialException('read failed: %s' % (e,))
-        return bytes(read)
-
-    def write(self, data):
-        """Output the given string over the serial port."""
-        if not self._isOpen: raise portNotOpenError
-        d = to_bytes(data)
-        tx_len = len(d)
-        if self._writeTimeout is not None and self._writeTimeout > 0:
-            timeout = time.time() + self._writeTimeout
-        else:
-            timeout = None
-        while tx_len > 0:
-            try:
-                n = os.write(self.fd, d)
-                if timeout:
-                    # when timeout is set, use select to wait for being ready
-                    # with the time left as timeout
-                    timeleft = timeout - time.time()
-                    if timeleft < 0:
-                        raise writeTimeoutError
-                    _, ready, _ = select.select([], [self.fd], [], timeleft)
-                    if not ready:
-                        raise writeTimeoutError
-                else:
-                    # wait for write operation
-                    _, ready, _ = select.select([], [self.fd], [], None)
-                    if not ready:
-                        raise SerialException('write failed (select)')
-                d = d[n:]
-                tx_len -= n
-            except OSError, v:
-                if v.errno != errno.EAGAIN:
-                    raise SerialException('write failed: %s' % (v,))
-        return len(data)
-
-    def flush(self):
-        """\
-        Flush of file like objects. In this case, wait until all data
-        is written.
-        """
-        self.drainOutput()
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        termios.tcflush(self.fd, TERMIOS.TCIFLUSH)
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and discarding all
-        that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        termios.tcflush(self.fd, TERMIOS.TCOFLUSH)
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-        termios.tcsendbreak(self.fd, int(duration/0.25))
-
-    def setBreak(self, level=1):
-        """\
-        Set break: Controls TXD. When active, no transmitting is possible.
-        """
-        if self.fd is None: raise portNotOpenError
-        if level:
-            fcntl.ioctl(self.fd, TIOCSBRK)
-        else:
-            fcntl.ioctl(self.fd, TIOCCBRK)
-
-    def setRTS(self, level=1):
-        """Set terminal status line: Request To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if level:
-            fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
-        else:
-            fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
-
-    def setDTR(self, level=1):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if level:
-            fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
-        else:
-            fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_CTS != 0
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_DSR != 0
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_RI != 0
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_CD != 0
-
-    # - - platform specific - - - -
-
-    def outWaiting(self):
-        """Return the number of characters currently in the output buffer."""
-        #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
-        s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
-        return struct.unpack('I',s)[0]
-
-    def drainOutput(self):
-        """internal - not portable!"""
-        if not self._isOpen: raise portNotOpenError
-        termios.tcdrain(self.fd)
-
-    def nonblocking(self):
-        """internal - not portable!"""
-        if not self._isOpen: raise portNotOpenError
-        fcntl.fcntl(self.fd, FCNTL.F_SETFL, os.O_NONBLOCK)
-
-    def fileno(self):
-        """\
-        For easier use of the serial port instance with select.
-        WARNING: this function is not portable to different platforms!
-        """
-        if not self._isOpen: raise portNotOpenError
-        return self.fd
-
-    def setXON(self, level=True):
-        """\
-        Manually control flow - when software flow control is enabled.
-        This will send XON (true) and XOFF (false) to the other device.
-        WARNING: this function is not portable to different platforms!
-        """
-        if not self.hComPort: raise portNotOpenError
-        if enable:
-            termios.tcflow(self.fd, TERMIOS.TCION)
-        else:
-            termios.tcflow(self.fd, TERMIOS.TCIOFF)
-
-    def flowControlOut(self, enable):
-        """\
-        Manually control flow of outgoing data - when hardware or software flow
-        control is enabled.
-        WARNING: this function is not portable to different platforms!
-        """
-        if not self._isOpen: raise portNotOpenError
-        if enable:
-            termios.tcflow(self.fd, TERMIOS.TCOON)
-        else:
-            termios.tcflow(self.fd, TERMIOS.TCOOFF)
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(PosixSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(PosixSerial, io.RawIOBase):
-        pass
-
-class PosixPollSerial(Serial):
-    """\
-    Poll based read implementation. Not all systems support poll properly.
-    However this one has better handling of errors, such as a device
-    disconnecting while it's in use (e.g. USB-serial unplugged).
-    """
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if self.fd is None: raise portNotOpenError
-        read = bytearray()
-        poll = select.poll()
-        poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
-        if size > 0:
-            while len(read) < size:
-                # print "\tread(): size",size, "have", len(read)    #debug
-                # wait until device becomes ready to read (or something fails)
-                for fd, event in poll.poll(self._timeout*1000):
-                    if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
-                        raise SerialException('device reports error (poll)')
-                    #  we don't care if it is select.POLLIN or timeout, that's
-                    #  handled below
-                buf = os.read(self.fd, size - len(read))
-                read.extend(buf)
-                if ((self._timeout is not None and self._timeout >= 0) or 
-                    (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
-                    break   # early abort on timeout
-        return bytes(read)
-
-
-if __name__ == '__main__':
-    s = Serial(0,
-                 baudrate=19200,        # baud rate
-                 bytesize=EIGHTBITS,    # number of data bits
-                 parity=PARITY_EVEN,    # enable parity checking
-                 stopbits=STOPBITS_ONE, # number of stop bits
-                 timeout=3,             # set a timeout value, None for waiting forever
-                 xonxoff=0,             # enable software flow control
-                 rtscts=0,              # enable RTS/CTS flow control
-               )
-    s.setRTS(1)
-    s.setDTR(1)
-    s.flushInput()
-    s.flushOutput()
-    s.write('hello')
-    sys.stdout.write('%r\n' % s.read(5))
-    sys.stdout.write('%s\n' % s.inWaiting())
-    del s
-
diff --git a/scripts/serial/serialutil.py b/scripts/serial/serialutil.py
deleted file mode 100644
index af0d2f6402..0000000000
--- a/scripts/serial/serialutil.py
+++ /dev/null
@@ -1,572 +0,0 @@
-#! python
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# (C) 2001-2010 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-# compatibility for older Python < 2.6
-try:
-    bytes
-    bytearray
-except (NameError, AttributeError):
-    # Python older than 2.6 do not have these types. Like for Python 2.6 they
-    # should behave like str. For Python older than 3.0 we want to work with
-    # strings anyway, only later versions have a true bytes type.
-    bytes = str
-    # bytearray is a mutable type that is easily turned into an instance of
-    # bytes
-    class bytearray(list):
-        # for bytes(bytearray()) usage
-        def __str__(self): return ''.join(self)
-        def __repr__(self): return 'bytearray(%r)' % ''.join(self)
-        # append automatically converts integers to characters
-        def append(self, item):
-            if isinstance(item, str):
-                list.append(self, item)
-            else:
-                list.append(self, chr(item))
-        # +=
-        def __iadd__(self, other):
-            for byte in other:
-                self.append(byte)
-            return self
-
-        def __getslice__(self, i, j):
-            return bytearray(list.__getslice__(self, i, j))
-
-        def __getitem__(self, item):
-            if isinstance(item, slice):
-                return bytearray(list.__getitem__(self, item))
-            else:
-                return ord(list.__getitem__(self, item))
-
-        def __eq__(self, other):
-            if isinstance(other, basestring):
-                other = bytearray(other)
-            return list.__eq__(self, other)
-
-# ``memoryview`` was introduced in Python 2.7 and ``bytes(some_memoryview)``
-# isn't returning the contents (very unfortunate). Therefore we need special
-# cases and test for it. Ensure that there is a ``memoryview`` object for older
-# Python versions. This is easier than making every test dependent on its
-# existence.
-try:
-    memoryview
-except (NameError, AttributeError):
-    # implementation does not matter as we do not realy use it.
-    # it just must not inherit from something else we might care for.
-    class memoryview:
-        pass
-
-
-# all Python versions prior 3.x convert ``str([17])`` to '[17]' instead of '\x11'
-# so a simple ``bytes(sequence)`` doesn't work for all versions
-def to_bytes(seq):
-    """convert a sequence to a bytes type"""
-    if isinstance(seq, bytes):
-        return seq
-    elif isinstance(seq, bytearray):
-        return bytes(seq)
-    elif isinstance(seq, memoryview):
-        return seq.tobytes()
-    else:
-        b = bytearray()
-        for item in seq:
-            b.append(item)  # this one handles int and str for our emulation and ints for Python 3.x
-        return bytes(b)
-
-# create control bytes
-XON  = to_bytes([17])
-XOFF = to_bytes([19])
-
-CR = to_bytes([13])
-LF = to_bytes([10])
-
-
-PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
-STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
-FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
-
-PARITY_NAMES = {
-    PARITY_NONE:  'None',
-    PARITY_EVEN:  'Even',
-    PARITY_ODD:   'Odd',
-    PARITY_MARK:  'Mark',
-    PARITY_SPACE: 'Space',
-}
-
-
-class SerialException(IOError):
-    """Base class for serial port related exceptions."""
-
-
-class SerialTimeoutException(SerialException):
-    """Write timeouts give an exception"""
-
-
-writeTimeoutError = SerialTimeoutException('Write timeout')
-portNotOpenError = SerialException('Attempting to use a port that is not open')
-
-
-class FileLike(object):
-    """\
-    An abstract file like class.
-
-    This class implements readline and readlines based on read and
-    writelines based on write.
-    This class is used to provide the above functions for to Serial
-    port objects.
-
-    Note that when the serial port was opened with _NO_ timeout that
-    readline blocks until it sees a newline (or the specified size is
-    reached) and that readlines would never return and therefore
-    refuses to work (it raises an exception in this case)!
-    """
-
-    def __init__(self):
-        self.closed = True
-
-    def close(self):
-        self.closed = True
-
-    # so that ports are closed when objects are discarded
-    def __del__(self):
-        """Destructor.  Calls close()."""
-        # The try/except block is in case this is called at program
-        # exit time, when it's possible that globals have already been
-        # deleted, and then the close() call might fail.  Since
-        # there's nothing we can do about such failures and they annoy
-        # the end users, we suppress the traceback.
-        try:
-            self.close()
-        except:
-            pass
-
-    def writelines(self, sequence):
-        for line in sequence:
-            self.write(line)
-
-    def flush(self):
-        """flush of file like objects"""
-        pass
-
-    # iterator for e.g. "for line in Serial(0): ..." usage
-    def next(self):
-        line = self.readline()
-        if not line: raise StopIteration
-        return line
-
-    def __iter__(self):
-        return self
-
-    def readline(self, size=None, eol=LF):
-        """\
-        Read a line which is terminated with end-of-line (eol) character
-        ('\n' by default) or until timeout.
-        """
-        leneol = len(eol)
-        line = bytearray()
-        while True:
-            c = self.read(1)
-            if c:
-                line += c
-                if line[-leneol:] == eol:
-                    break
-                if size is not None and len(line) >= size:
-                    break
-            else:
-                break
-        return bytes(line)
-
-    def readlines(self, sizehint=None, eol=LF):
-        """\
-        Read a list of lines, until timeout.
-        sizehint is ignored.
-        """
-        if self.timeout is None:
-            raise ValueError("Serial port MUST have enabled timeout for this function!")
-        leneol = len(eol)
-        lines = []
-        while True:
-            line = self.readline(eol=eol)
-            if line:
-                lines.append(line)
-                if line[-leneol:] != eol:    # was the line received with a timeout?
-                    break
-            else:
-                break
-        return lines
-
-    def xreadlines(self, sizehint=None):
-        """\
-        Read lines, implemented as generator. It will raise StopIteration on
-        timeout (empty read). sizehint is ignored.
-        """
-        while True:
-            line = self.readline()
-            if not line: break
-            yield line
-
-    # other functions of file-likes - not used by pySerial
-
-    #~ readinto(b)
-
-    def seek(self, pos, whence=0):
-        raise IOError("file is not seekable")
-
-    def tell(self):
-        raise IOError("file is not seekable")
-
-    def truncate(self, n=None):
-        raise IOError("file is not seekable")
-
-    def isatty(self):
-        return False
-
-
-class SerialBase(object):
-    """\
-    Serial port base class. Provides __init__ function and properties to
-    get/set port settings.
-    """
-
-    # default values, may be overridden in subclasses that do not support all values
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
-                 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
-                 3000000, 3500000, 4000000)
-    BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
-    PARITIES  = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
-    STOPBITS  = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
-
-    def __init__(self,
-                 port = None,           # number of device, numbering starts at
-                                        # zero. if everything fails, the user
-                                        # can specify a device string, note
-                                        # that this isn't portable anymore
-                                        # port will be opened if one is specified
-                 baudrate=9600,         # baud rate
-                 bytesize=EIGHTBITS,    # number of data bits
-                 parity=PARITY_NONE,    # enable parity checking
-                 stopbits=STOPBITS_ONE, # number of stop bits
-                 timeout=None,          # set a timeout value, None to wait forever
-                 xonxoff=False,         # enable software flow control
-                 rtscts=False,          # enable RTS/CTS flow control
-                 writeTimeout=None,     # set a timeout for writes
-                 dsrdtr=False,          # None: use rtscts setting, dsrdtr override if True or False
-                 interCharTimeout=None  # Inter-character timeout, None to disable
-                 ):
-        """\
-        Initialize comm port object. If a port is given, then the port will be
-        opened immediately. Otherwise a Serial port object in closed state
-        is returned.
-        """
-
-        self._isOpen   = False
-        self._port     = None           # correct value is assigned below through properties
-        self._baudrate = None           # correct value is assigned below through properties
-        self._bytesize = None           # correct value is assigned below through properties
-        self._parity   = None           # correct value is assigned below through properties
-        self._stopbits = None           # correct value is assigned below through properties
-        self._timeout  = None           # correct value is assigned below through properties
-        self._writeTimeout = None       # correct value is assigned below through properties
-        self._xonxoff  = None           # correct value is assigned below through properties
-        self._rtscts   = None           # correct value is assigned below through properties
-        self._dsrdtr   = None           # correct value is assigned below through properties
-        self._interCharTimeout = None   # correct value is assigned below through properties
-
-        # assign values using get/set methods using the properties feature
-        self.port     = port
-        self.baudrate = baudrate
-        self.bytesize = bytesize
-        self.parity   = parity
-        self.stopbits = stopbits
-        self.timeout  = timeout
-        self.writeTimeout = writeTimeout
-        self.xonxoff  = xonxoff
-        self.rtscts   = rtscts
-        self.dsrdtr   = dsrdtr
-        self.interCharTimeout = interCharTimeout
-
-        if port is not None:
-            self.open()
-
-    def isOpen(self):
-        """Check if the port is opened."""
-        return self._isOpen
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    # TODO: these are not really needed as the is the BAUDRATES etc. attribute...
-    # maybe i remove them before the final release...
-
-    def getSupportedBaudrates(self):
-        return [(str(b), b) for b in self.BAUDRATES]
-
-    def getSupportedByteSizes(self):
-        return [(str(b), b) for b in self.BYTESIZES]
-
-    def getSupportedStopbits(self):
-        return [(str(b), b) for b in self.STOPBITS]
-
-    def getSupportedParities(self):
-        return [(PARITY_NAMES[b], b) for b in self.PARITIES]
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def setPort(self, port):
-        """\
-        Change the port. The attribute portstr is set to a string that
-        contains the name of the port.
-        """
-
-        was_open = self._isOpen
-        if was_open: self.close()
-        if port is not None:
-            if isinstance(port, basestring):
-                self.portstr = port
-            else:
-                self.portstr = self.makeDeviceName(port)
-        else:
-            self.portstr = None
-        self._port = port
-        self.name = self.portstr
-        if was_open: self.open()
-
-    def getPort(self):
-        """\
-        Get the current port setting. The value that was passed on init or using
-        setPort() is passed back. See also the attribute portstr which contains
-        the name of the port as a string.
-        """
-        return self._port
-
-    port = property(getPort, setPort, doc="Port setting")
-
-
-    def setBaudrate(self, baudrate):
-        """\
-        Change baud rate. It raises a ValueError if the port is open and the
-        baud rate is not possible. If the port is closed, then the value is
-        accepted and the exception is raised when the port is opened.
-        """
-        try:
-            b = int(baudrate)
-        except TypeError:
-            raise ValueError("Not a valid baudrate: %r" % (baudrate,))
-        else:
-            if b <= 0:
-                raise ValueError("Not a valid baudrate: %r" % (baudrate,))
-            self._baudrate = b
-            if self._isOpen:  self._reconfigurePort()
-
-    def getBaudrate(self):
-        """Get the current baud rate setting."""
-        return self._baudrate
-
-    baudrate = property(getBaudrate, setBaudrate, doc="Baud rate setting")
-
-
-    def setByteSize(self, bytesize):
-        """Change byte size."""
-        if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
-        self._bytesize = bytesize
-        if self._isOpen: self._reconfigurePort()
-
-    def getByteSize(self):
-        """Get the current byte size setting."""
-        return self._bytesize
-
-    bytesize = property(getByteSize, setByteSize, doc="Byte size setting")
-
-
-    def setParity(self, parity):
-        """Change parity setting."""
-        if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
-        self._parity = parity
-        if self._isOpen: self._reconfigurePort()
-
-    def getParity(self):
-        """Get the current parity setting."""
-        return self._parity
-
-    parity = property(getParity, setParity, doc="Parity setting")
-
-
-    def setStopbits(self, stopbits):
-        """Change stop bits size."""
-        if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
-        self._stopbits = stopbits
-        if self._isOpen: self._reconfigurePort()
-
-    def getStopbits(self):
-        """Get the current stop bits setting."""
-        return self._stopbits
-
-    stopbits = property(getStopbits, setStopbits, doc="Stop bits setting")
-
-
-    def setTimeout(self, timeout):
-        """Change timeout setting."""
-        if timeout is not None:
-            try:
-                timeout + 1     # test if it's a number, will throw a TypeError if not...
-            except TypeError:
-                raise ValueError("Not a valid timeout: %r" % (timeout,))
-            if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
-        self._timeout = timeout
-        if self._isOpen: self._reconfigurePort()
-
-    def getTimeout(self):
-        """Get the current timeout setting."""
-        return self._timeout
-
-    timeout = property(getTimeout, setTimeout, doc="Timeout setting for read()")
-
-
-    def setWriteTimeout(self, timeout):
-        """Change timeout setting."""
-        if timeout is not None:
-            if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
-            try:
-                timeout + 1     #test if it's a number, will throw a TypeError if not...
-            except TypeError:
-                raise ValueError("Not a valid timeout: %r" % timeout)
-
-        self._writeTimeout = timeout
-        if self._isOpen: self._reconfigurePort()
-
-    def getWriteTimeout(self):
-        """Get the current timeout setting."""
-        return self._writeTimeout
-
-    writeTimeout = property(getWriteTimeout, setWriteTimeout, doc="Timeout setting for write()")
-
-
-    def setXonXoff(self, xonxoff):
-        """Change XON/XOFF setting."""
-        self._xonxoff = xonxoff
-        if self._isOpen: self._reconfigurePort()
-
-    def getXonXoff(self):
-        """Get the current XON/XOFF setting."""
-        return self._xonxoff
-
-    xonxoff = property(getXonXoff, setXonXoff, doc="XON/XOFF setting")
-
-    def setRtsCts(self, rtscts):
-        """Change RTS/CTS flow control setting."""
-        self._rtscts = rtscts
-        if self._isOpen: self._reconfigurePort()
-
-    def getRtsCts(self):
-        """Get the current RTS/CTS flow control setting."""
-        return self._rtscts
-
-    rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting")
-
-    def setDsrDtr(self, dsrdtr=None):
-        """Change DsrDtr flow control setting."""
-        if dsrdtr is None:
-            # if not set, keep backwards compatibility and follow rtscts setting
-            self._dsrdtr = self._rtscts
-        else:
-            # if defined independently, follow its value
-            self._dsrdtr = dsrdtr
-        if self._isOpen: self._reconfigurePort()
-
-    def getDsrDtr(self):
-        """Get the current DSR/DTR flow control setting."""
-        return self._dsrdtr
-
-    dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting")
-
-    def setInterCharTimeout(self, interCharTimeout):
-        """Change inter-character timeout setting."""
-        if interCharTimeout is not None:
-            if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
-            try:
-                interCharTimeout + 1     # test if it's a number, will throw a TypeError if not...
-            except TypeError:
-                raise ValueError("Not a valid timeout: %r" % interCharTimeout)
-
-        self._interCharTimeout = interCharTimeout
-        if self._isOpen: self._reconfigurePort()
-
-    def getInterCharTimeout(self):
-        """Get the current inter-character timeout setting."""
-        return self._interCharTimeout
-
-    interCharTimeout = property(getInterCharTimeout, setInterCharTimeout, doc="Inter-character timeout setting for read()")
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
-            'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
-
-    def getSettingsDict(self):
-        """\
-        Get current port settings as a dictionary. For use with
-        applySettingsDict.
-        """
-        return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
-
-    def applySettingsDict(self, d):
-        """\
-        apply stored settings from a dictionary returned from
-        getSettingsDict. it's allowed to delete keys from the dictionary. these
-        values will simply left unchanged.
-        """
-        for key in self._SETTINGS:
-            if d[key] != getattr(self, '_'+key):   # check against internal "_" value
-                setattr(self, key, d[key])          # set non "_" value to use properties write function
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def __repr__(self):
-        """String representation of the current port settings and its state."""
-        return "%s<id=0x%x, open=%s>(port=%r, baudrate=%r, bytesize=%r, parity=%r, stopbits=%r, timeout=%r, xonxoff=%r, rtscts=%r, dsrdtr=%r)" % (
-            self.__class__.__name__,
-            id(self),
-            self._isOpen,
-            self.portstr,
-            self.baudrate,
-            self.bytesize,
-            self.parity,
-            self.stopbits,
-            self.timeout,
-            self.xonxoff,
-            self.rtscts,
-            self.dsrdtr,
-        )
-
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-    # compatibility with io library
-
-    def readable(self): return True
-    def writable(self): return True
-    def seekable(self): return False
-    def readinto(self, b):
-        data = self.read(len(b))
-        n = len(data)
-        try:
-            b[:n] = data
-        except TypeError, err:
-            import array
-            if not isinstance(b, array.array):
-                raise err
-            b[:n] = array.array('b', data)
-        return n
-
-
-if __name__ == '__main__':
-    import sys
-    s = SerialBase()
-    sys.stdout.write('port name:  %s\n' % s.portstr)
-    sys.stdout.write('baud rates: %s\n' % s.getSupportedBaudrates())
-    sys.stdout.write('byte sizes: %s\n' % s.getSupportedByteSizes())
-    sys.stdout.write('parities:   %s\n' % s.getSupportedParities())
-    sys.stdout.write('stop bits:  %s\n' % s.getSupportedStopbits())
-    sys.stdout.write('%s\n' % s)
diff --git a/scripts/serial/tools/__init__.py b/scripts/serial/tools/__init__.py
deleted file mode 100644
index 0efe34b218..0000000000
--- a/scripts/serial/tools/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# empty #
\ No newline at end of file
diff --git a/scripts/serial/tools/list_ports.py b/scripts/serial/tools/list_ports.py
deleted file mode 100644
index d373a5566d..0000000000
--- a/scripts/serial/tools/list_ports.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python
-
-# portable serial port access with python
-# this is a wrapper module for different platform implementations of the
-# port enumeration feature
-#
-# (C) 2011-2013 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-"""\
-This module will provide a function called comports that returns an
-iterable (generator or list) that will enumerate available com ports. Note that
-on some systems non-existent ports may be listed.
-
-Additionally a grep function is supplied that can be used to search for ports
-based on their descriptions or hardware ID.
-"""
-
-import sys, os, re
-
-# chose an implementation, depending on os
-#~ if sys.platform == 'cli':
-#~ else:
-import os
-# chose an implementation, depending on os
-if os.name == 'nt': #sys.platform == 'win32':
-    from serial.tools.list_ports_windows import *
-elif os.name == 'posix':
-    from serial.tools.list_ports_posix import *
-#~ elif os.name == 'java':
-else:
-    raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-def grep(regexp):
-    """\
-    Search for ports using a regular expression. Port name, description and
-    hardware ID are searched. The function returns an iterable that returns the
-    same tuples as comport() would do.
-    """
-    r = re.compile(regexp, re.I)
-    for port, desc, hwid in comports():
-        if r.search(port) or r.search(desc) or r.search(hwid):
-            yield port, desc, hwid
-
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-def main():
-    import optparse
-
-    parser = optparse.OptionParser(
-        usage = "%prog [options] [<regexp>]",
-        description = "Miniterm - A simple terminal program for the serial port."
-    )
-
-    parser.add_option("--debug",
-            help="print debug messages and tracebacks (development mode)",
-            dest="debug",
-            default=False,
-            action='store_true')
-
-    parser.add_option("-v", "--verbose",
-            help="show more messages (can be given multiple times)",
-            dest="verbose",
-            default=1,
-            action='count')
-
-    parser.add_option("-q", "--quiet",
-            help="suppress all messages",
-            dest="verbose",
-            action='store_const',
-            const=0)
-
-    (options, args) = parser.parse_args()
-
-
-    hits = 0
-    # get iteraror w/ or w/o filter
-    if args:
-        if len(args) > 1:
-            parser.error('more than one regexp not supported')
-        print "Filtered list with regexp: %r" % (args[0],)
-        iterator = sorted(grep(args[0]))
-    else:
-        iterator = sorted(comports())
-    # list them
-    for port, desc, hwid in iterator:
-        print("%-20s" % (port,))
-        if options.verbose > 1:
-            print("    desc: %s" % (desc,))
-            print("    hwid: %s" % (hwid,))
-        hits += 1
-    if options.verbose:
-        if hits:
-            print("%d ports found" % (hits,))
-        else:
-            print("no ports found")
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# test
-if __name__ == '__main__':
-    main()
diff --git a/scripts/serial/tools/list_ports_linux.py b/scripts/serial/tools/list_ports_linux.py
deleted file mode 100644
index 955761eaa4..0000000000
--- a/scripts/serial/tools/list_ports_linux.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/env python
-
-# portable serial port access with python
-#
-# This is a module that gathers a list of serial ports including details on
-# GNU/Linux systems
-#
-# (C) 2011-2013 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-import glob
-import sys
-import os
-import re
-
-try:
-    import subprocess
-except ImportError:
-    def popen(argv):
-        try:
-            si, so =  os.popen4(' '.join(argv))
-            return so.read().strip()
-        except:
-            raise IOError('lsusb failed')
-else:
-    def popen(argv):
-        try:
-            return subprocess.check_output(argv, stderr=subprocess.STDOUT).strip()
-        except:
-            raise IOError('lsusb failed')
-
-
-# The comports function is expected to return an iterable that yields tuples of
-# 3 strings: port name, human readable description and a hardware ID.
-#
-# as currently no method is known to get the second two strings easily, they
-# are currently just identical to the port name.
-
-# try to detect the OS so that a device can be selected...
-plat = sys.platform.lower()
-
-def read_line(filename):
-    """\
-    Helper function to read a single line from a file.
-    Returns None on errors..
-    """
-    try:
-        f = open(filename)
-        line = f.readline().strip()
-        f.close()
-        return line
-    except IOError:
-        return None
-
-def re_group(regexp, text):
-    """search for regexp in text, return 1st group on match"""
-    if sys.version < '3':
-        m = re.search(regexp, text)
-    else:
-        # text is bytes-like
-        m = re.search(regexp, text.decode('ascii', 'replace'))
-    if m: return m.group(1)
-
-
-# try to extract descriptions from sysfs. this was done by experimenting,
-# no guarantee that it works for all devices or in the future...
-
-def usb_sysfs_hw_string(sysfs_path):
-    """given a path to a usb device in sysfs, return a string describing it"""
-    bus, dev = os.path.basename(os.path.realpath(sysfs_path)).split('-')
-    snr = read_line(sysfs_path+'/serial')
-    if snr:
-        snr_txt = ' SNR=%s' % (snr,)
-    else:
-        snr_txt = ''
-    return 'USB VID:PID=%s:%s%s' % (
-            read_line(sysfs_path+'/idVendor'),
-            read_line(sysfs_path+'/idProduct'),
-            snr_txt
-            )
-
-def usb_lsusb_string(sysfs_path):
-    base = os.path.basename(os.path.realpath(sysfs_path))
-    bus = base.split('-')[0]
-    try:
-        dev = int(read_line(os.path.join(sysfs_path, 'devnum')))
-        desc = popen(['lsusb', '-v', '-s', '%s:%s' % (bus, dev)])
-        # descriptions from device
-        iManufacturer = re_group('iManufacturer\s+\w+ (.+)', desc)
-        iProduct = re_group('iProduct\s+\w+ (.+)', desc)
-        iSerial = re_group('iSerial\s+\w+ (.+)', desc) or ''
-        # descriptions from kernel
-        idVendor = re_group('idVendor\s+0x\w+ (.+)', desc)
-        idProduct = re_group('idProduct\s+0x\w+ (.+)', desc)
-        # create descriptions. prefer text from device, fall back to the others
-        return '%s %s %s' % (iManufacturer or idVendor, iProduct or idProduct, iSerial)
-    except IOError:
-        return base
-
-def describe(device):
-    """\
-    Get a human readable description.
-    For USB-Serial devices try to run lsusb to get a human readable description.
-    For USB-CDC devices read the description from sysfs.
-    """
-    base = os.path.basename(device)
-    # USB-Serial devices
-    sys_dev_path = '/sys/class/tty/%s/device/driver/%s' % (base, base)
-    if os.path.exists(sys_dev_path):
-        sys_usb = os.path.dirname(os.path.dirname(os.path.realpath(sys_dev_path)))
-        return usb_lsusb_string(sys_usb)
-    # USB-CDC devices
-    sys_dev_path = '/sys/class/tty/%s/device/interface' % (base,)
-    if os.path.exists(sys_dev_path):
-        return read_line(sys_dev_path)
-    # USB Product Information
-    sys_dev_path = '/sys/class/tty/%s/device' % (base,)
-    if os.path.exists(sys_dev_path):
-        product_name_file = os.path.dirname(os.path.realpath(sys_dev_path)) + "/product"
-        if os.path.exists(product_name_file):
-            return read_line(product_name_file)
-    return base
-
-def hwinfo(device):
-    """Try to get a HW identification using sysfs"""
-    base = os.path.basename(device)
-    if os.path.exists('/sys/class/tty/%s/device' % (base,)):
-        # PCI based devices
-        sys_id_path = '/sys/class/tty/%s/device/id' % (base,)
-        if os.path.exists(sys_id_path):
-            return read_line(sys_id_path)
-        # USB-Serial devices
-        sys_dev_path = '/sys/class/tty/%s/device/driver/%s' % (base, base)
-        if os.path.exists(sys_dev_path):
-            sys_usb = os.path.dirname(os.path.dirname(os.path.realpath(sys_dev_path)))
-            return usb_sysfs_hw_string(sys_usb)
-        # USB-CDC devices
-        if base.startswith('ttyACM'):
-            sys_dev_path = '/sys/class/tty/%s/device' % (base,)
-            if os.path.exists(sys_dev_path):
-                return usb_sysfs_hw_string(sys_dev_path + '/..')
-    return 'n/a'    # XXX directly remove these from the list?
-
-def comports():
-    devices = glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*')
-    return [(d, describe(d), hwinfo(d)) for d in devices]
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# test
-if __name__ == '__main__':
-    for port, desc, hwid in sorted(comports()):
-        print "%s: %s [%s]" % (port, desc, hwid)
diff --git a/scripts/serial/urlhandler/__init__.py b/scripts/serial/urlhandler/__init__.py
deleted file mode 100644
index 0efe34b218..0000000000
--- a/scripts/serial/urlhandler/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# empty #
\ No newline at end of file
diff --git a/scripts/serial/urlhandler/protocol_hwgrep.py b/scripts/serial/urlhandler/protocol_hwgrep.py
deleted file mode 100644
index 62cda43aa7..0000000000
--- a/scripts/serial/urlhandler/protocol_hwgrep.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a special URL handler that uses the port listing to
-# find ports by searching the string descriptions.
-#
-# (C) 2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# URL format:    hwgrep://regexp
-
-import serial
-import serial.tools.list_ports
-
-class Serial(serial.Serial):
-    """Just inherit the native Serial port implementation and patch the open function."""
-
-    def setPort(self, value):
-        """translate port name before storing it"""
-        if isinstance(value, basestring) and value.startswith('hwgrep://'):
-            serial.Serial.setPort(self, self.fromURL(value))
-        else:
-            serial.Serial.setPort(self, value)
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("hwgrep://"): url = url[9:]
-        # use a for loop to get the 1st element from the generator
-        for port, desc, hwid in serial.tools.list_ports.grep(url):
-            return port
-        else:
-            raise serial.SerialException('no ports found matching regexp %r' % (url,))
-
-    # override property
-    port = property(serial.Serial.getPort, setPort, doc="Port setting")
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-if __name__ == '__main__':
-    #~ s = Serial('hwgrep://ttyS0')
-    s = Serial(None)
-    s.port = 'hwgrep://ttyS0'
-    print s
-
diff --git a/scripts/serial/urlhandler/protocol_loop.py b/scripts/serial/urlhandler/protocol_loop.py
deleted file mode 100644
index a414839761..0000000000
--- a/scripts/serial/urlhandler/protocol_loop.py
+++ /dev/null
@@ -1,279 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a loop back connection receiving itself what it sent.
-#
-# The purpose of this module is.. well... You can run the unit tests with it.
-# and it was so easy to implement ;-)
-#
-# (C) 2001-2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# URL format:    loop://[option[/option...]]
-# options:
-# - "debug" print diagnostic messages
-
-from serial.serialutil import *
-import threading
-import time
-import logging
-
-# map log level names to constants. used in fromURL()
-LOGGER_LEVELS = {
-    'debug': logging.DEBUG,
-    'info': logging.INFO,
-    'warning': logging.WARNING,
-    'error': logging.ERROR,
-    }
-
-
-class LoopbackSerial(SerialBase):
-    """Serial port implementation that simulates a loop back connection in plain software."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        self.logger = None
-        self.buffer_lock = threading.Lock()
-        self.loop_buffer = bytearray()
-        self.cts = False
-        self.dsr = False
-
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        # not that there is anything to open, but the function applies the
-        # options found in the URL
-        self.fromURL(self.port)
-
-        # not that there anything to configure...
-        self._reconfigurePort()
-        # all things set up get, now a clean start
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """\
-        Set communication parameters on opened port. For the loop://
-        protocol all settings are ignored!
-        """
-        # not that's it of any real use, but it helps in the unit tests
-        if not isinstance(self._baudrate, (int, long)) or not 0 < self._baudrate < 2**32:
-            raise ValueError("invalid baudrate: %r" % (self._baudrate))
-        if self.logger:
-            self.logger.info('_reconfigurePort()')
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            self._isOpen = False
-            # in case of quick reconnects, give the server some time
-            time.sleep(0.3)
-
-    def makeDeviceName(self, port):
-        raise SerialException("there is no sensible way to turn numbers into URLs")
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("loop://"): url = url[7:]
-        try:
-            # process options now, directly altering self
-            for option in url.split('/'):
-                if '=' in option:
-                    option, value = option.split('=', 1)
-                else:
-                    value = None
-                if not option:
-                    pass
-                elif option == 'logging':
-                    logging.basicConfig()   # XXX is that good to call it here?
-                    self.logger = logging.getLogger('pySerial.loop')
-                    self.logger.setLevel(LOGGER_LEVELS[value])
-                    self.logger.debug('enabled logging')
-                else:
-                    raise ValueError('unknown option: %r' % (option,))
-        except ValueError, e:
-            raise SerialException('expected a string in the form "[loop://][option[/option...]]": %s' % e)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            # attention the logged value can differ from return value in
-            # threaded environments...
-            self.logger.debug('inWaiting() -> %d' % (len(self.loop_buffer),))
-        return len(self.loop_buffer)
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self._timeout is not None:
-            timeout = time.time() + self._timeout
-        else:
-            timeout = None
-        data = bytearray()
-        while size > 0:
-            self.buffer_lock.acquire()
-            try:
-                block = to_bytes(self.loop_buffer[:size])
-                del self.loop_buffer[:size]
-            finally:
-                self.buffer_lock.release()
-            data += block
-            size -= len(block)
-            # check for timeout now, after data has been read.
-            # useful for timeout = 0 (non blocking) read
-            if timeout and time.time() > timeout:
-                break
-        return bytes(data)
-
-    def write(self, data):
-        """\
-        Output the given string over the serial port. Can block if the
-        connection is blocked. May raise SerialException if the connection is
-        closed.
-        """
-        if not self._isOpen: raise portNotOpenError
-        # ensure we're working with bytes
-        data = to_bytes(data)
-        # calculate aprox time that would be used to send the data
-        time_used_to_send = 10.0*len(data) / self._baudrate
-        # when a write timeout is configured check if we would be successful
-        # (not sending anything, not even the part that would have time)
-        if self._writeTimeout is not None and time_used_to_send > self._writeTimeout:
-            time.sleep(self._writeTimeout) # must wait so that unit test succeeds
-            raise writeTimeoutError
-        self.buffer_lock.acquire()
-        try:
-            self.loop_buffer += data
-        finally:
-            self.buffer_lock.release()
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('flushInput()')
-        self.buffer_lock.acquire()
-        try:
-            del self.loop_buffer[:]
-        finally:
-            self.buffer_lock.release()
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('flushOutput()')
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-
-    def setBreak(self, level=True):
-        """\
-        Set break: Controls TXD. When active, to transmitting is
-        possible.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('setBreak(%r)' % (level,))
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('setRTS(%r) -> state of CTS' % (level,))
-        self.cts = level
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('setDTR(%r) -> state of DSR' % (level,))
-        self.dsr = level
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('getCTS() -> state of RTS (%r)' % (self.cts,))
-        return self.cts
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('getDSR() -> state of DTR (%r)' % (self.dsr,))
-        return self.dsr
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getRI()')
-        return False
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getCD()')
-        return True
-
-    # - - - platform specific - - -
-    # None so far
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(LoopbackSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(LoopbackSerial, io.RawIOBase):
-        pass
-
-
-# simple client test
-if __name__ == '__main__':
-    import sys
-    s = Serial('loop://')
-    sys.stdout.write('%s\n' % s)
-
-    sys.stdout.write("write...\n")
-    s.write("hello\n")
-    s.flush()
-    sys.stdout.write("read: %s\n" % s.read(5))
-
-    s.close()
diff --git a/scripts/serial/urlhandler/protocol_rfc2217.py b/scripts/serial/urlhandler/protocol_rfc2217.py
deleted file mode 100644
index 981ba45fea..0000000000
--- a/scripts/serial/urlhandler/protocol_rfc2217.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see ../__init__.py
-#
-# This is a thin wrapper to load the rfc2271 implementation.
-#
-# (C) 2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-from serial.rfc2217 import Serial
diff --git a/scripts/serial/urlhandler/protocol_socket.py b/scripts/serial/urlhandler/protocol_socket.py
deleted file mode 100644
index dc5992342c..0000000000
--- a/scripts/serial/urlhandler/protocol_socket.py
+++ /dev/null
@@ -1,291 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a simple socket based client.
-# It does not support changing any port parameters and will silently ignore any
-# requests to do so.
-#
-# The purpose of this module is that applications using pySerial can connect to
-# TCP/IP to serial port converters that do not support RFC 2217.
-#
-# (C) 2001-2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# URL format:    socket://<host>:<port>[/option[/option...]]
-# options:
-# - "debug" print diagnostic messages
-
-from serial.serialutil import *
-import time
-import socket
-import select
-import logging
-
-# map log level names to constants. used in fromURL()
-LOGGER_LEVELS = {
-    'debug': logging.DEBUG,
-    'info': logging.INFO,
-    'warning': logging.WARNING,
-    'error': logging.ERROR,
-    }
-
-POLL_TIMEOUT = 2
-
-class SocketSerial(SerialBase):
-    """Serial port implementation for plain sockets."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        self.logger = None
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        try:
-            # XXX in future replace with create_connection (py >=2.6)
-            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            self._socket.connect(self.fromURL(self.portstr))
-        except Exception, msg:
-            self._socket = None
-            raise SerialException("Could not open port %s: %s" % (self.portstr, msg))
-
-        self._socket.settimeout(POLL_TIMEOUT) # used for write timeout support :/
-
-        # not that there anything to configure...
-        self._reconfigurePort()
-        # all things set up get, now a clean start
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """\
-        Set communication parameters on opened port. For the socket://
-        protocol all settings are ignored!
-        """
-        if self._socket is None:
-            raise SerialException("Can only operate on open ports")
-        if self.logger:
-            self.logger.info('ignored port configuration change')
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self._socket:
-                try:
-                    self._socket.shutdown(socket.SHUT_RDWR)
-                    self._socket.close()
-                except:
-                    # ignore errors.
-                    pass
-                self._socket = None
-            self._isOpen = False
-            # in case of quick reconnects, give the server some time
-            time.sleep(0.3)
-
-    def makeDeviceName(self, port):
-        raise SerialException("there is no sensible way to turn numbers into URLs")
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("socket://"): url = url[9:]
-        try:
-            # is there a "path" (our options)?
-            if '/' in url:
-                # cut away options
-                url, options = url.split('/', 1)
-                # process options now, directly altering self
-                for option in options.split('/'):
-                    if '=' in option:
-                        option, value = option.split('=', 1)
-                    else:
-                        value = None
-                    if option == 'logging':
-                        logging.basicConfig()   # XXX is that good to call it here?
-                        self.logger = logging.getLogger('pySerial.socket')
-                        self.logger.setLevel(LOGGER_LEVELS[value])
-                        self.logger.debug('enabled logging')
-                    else:
-                        raise ValueError('unknown option: %r' % (option,))
-            # get host and port
-            host, port = url.split(':', 1) # may raise ValueError because of unpacking
-            port = int(port)               # and this if it's not a number
-            if not 0 <= port < 65536: raise ValueError("port not in range 0...65535")
-        except ValueError, e:
-            raise SerialException('expected a string in the form "[rfc2217://]<host>:<port>[/option[/option...]]": %s' % e)
-        return (host, port)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._isOpen: raise portNotOpenError
-        # Poll the socket to see if it is ready for reading.
-        # If ready, at least one byte will be to read.
-        lr, lw, lx = select.select([self._socket], [], [], 0)
-        return len(lr)
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        data = bytearray()
-        if self._timeout is not None:
-            timeout = time.time() + self._timeout
-        else:
-            timeout = None
-        while len(data) < size and (timeout is None or time.time() < timeout):
-            try:
-                # an implementation with internal buffer would be better
-                # performing...
-                t = time.time()
-                block = self._socket.recv(size - len(data))
-                duration = time.time() - t
-                if block:
-                    data.extend(block)
-                else:
-                    # no data -> EOF (connection probably closed)
-                    break
-            except socket.timeout:
-                # just need to get out of recv from time to time to check if
-                # still alive
-                continue
-            except socket.error, e:
-                # connection fails -> terminate loop
-                raise SerialException('connection failed (%s)' % e)
-        return bytes(data)
-
-    def write(self, data):
-        """\
-        Output the given string over the serial port. Can block if the
-        connection is blocked. May raise SerialException if the connection is
-        closed.
-        """
-        if not self._isOpen: raise portNotOpenError
-        try:
-            self._socket.sendall(to_bytes(data))
-        except socket.error, e:
-            # XXX what exception if socket connection fails
-            raise SerialException("socket connection failed: %s" % e)
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored flushInput')
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored flushOutput')
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored sendBreak(%r)' % (duration,))
-
-    def setBreak(self, level=True):
-        """Set break: Controls TXD. When active, to transmitting is
-        possible."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored setBreak(%r)' % (level,))
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored setRTS(%r)' % (level,))
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored setDTR(%r)' % (level,))
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getCTS()')
-        return True
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getDSR()')
-        return True
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getRI()')
-        return False
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getCD()')
-        return True
-
-    # - - - platform specific - - -
-
-    # works on Linux and probably all the other POSIX systems
-    def fileno(self):
-        """Get the file handle of the underlying socket for use with select"""
-        return self._socket.fileno()
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(SocketSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(SocketSerial, io.RawIOBase):
-        pass
-
-
-# simple client test
-if __name__ == '__main__':
-    import sys
-    s = Serial('socket://localhost:7000')
-    sys.stdout.write('%s\n' % s)
-
-    sys.stdout.write("write...\n")
-    s.write("hello\n")
-    s.flush()
-    sys.stdout.write("read: %s\n" % s.read(5))
-
-    s.close()
-- 
2.30.2



From jlu at pengutronix.de  Tue Sep  6 06:02:34 2022
From: jlu at pengutronix.de (Jan =?ISO-8859-1?Q?L=FCbbe?=)
Date: Tue, 06 Sep 2022 15:02:34 +0200
Subject: [PATCH 2/4] bbremote: Convert to python3
In-Reply-To: <20220906102049.1364561-3-s.hauer@pengutronix.de>
References: <20220906102049.1364561-1-s.hauer@pengutronix.de>
	 <20220906102049.1364561-3-s.hauer@pengutronix.de>
Message-ID: <1019c1be5617830df3edd0a47b7f7fbd9bc2a311.camel@pengutronix.de>

On Tue, 2022-09-06 at 12:20 +0200, Sascha Hauer wrote:
> This is the long overdue conversion from python2 to python3.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
> ?scripts/bbremote????????????? |? 2 +-
> ?scripts/remote/controller.py? | 21 +++++++++++----------
> ?scripts/remote/main.py??????? |? 8 ++++----
> ?scripts/remote/messages.py??? | 15 +++++++++++++--
> ?scripts/remote/ratp.py??????? |? 4 ++--
> ?scripts/remote/ratpfs.py????? |? 4 ++--
> ?scripts/remote/threadstdio.py |? 4 ++--
> ?7 files changed, 35 insertions(+), 23 deletions(-)
> 
> diff --git a/scripts/bbremote b/scripts/bbremote
> index bc5351dbae..1eeabd08d1 100755
> --- a/scripts/bbremote
> +++ b/scripts/bbremote
> @@ -1,3 +1,3 @@
> -#!/usr/bin/env python2
> +#!/usr/bin/env python3
> ?
> ?import remote.main
> diff --git a/scripts/remote/controller.py b/scripts/remote/controller.py
> index b4493591dd..a3ae260558 100644
> --- a/scripts/remote/controller.py
> +++ b/scripts/remote/controller.py
> @@ -1,4 +1,4 @@
> -#!/usr/bin/env python2
> +#!/usr/bin/env python3
> ?# -*- coding: utf-8 -*-
> ?
> ?from __future__ import absolute_import, division, print_function
> @@ -8,7 +8,7 @@ import logging
> ?import sys
> ?import os
> ?from threading import Thread
> -from Queue import Queue, Empty
> +from queue import Queue, Empty
> ?from .ratpfs import RatpFSServer
> ?from .messages import *
> ?from .ratp import RatpError
> @@ -105,7 +105,7 @@ class Controller(Thread):
> ???????? self.rxq = None
> ???????? self.conn.connect(timeout=5.0)
> ???????? self._txq = Queue()
> -??????? self._stop = False
> +??????? self._stopit = False

Is this rename needed?

> ???????? self.fsserver = RatpFSServer()
> ?
> ???? def _send(self, bbpkt):
> @@ -147,24 +147,24 @@ class Controller(Thread):
> ???????????? return 0
> ?
> ???? def command(self, cmd):
> -??????? self._send(BBPacketCommand(cmd=cmd))
> +??????? self._send(BBPacketCommand(cmd=cmd.encode()))
> ???????? r = self._expect(BBPacketCommandReturn, timeout=None)
> ???????? logging.info("Command: %r", r)
> ???????? return r.exit_code
> ?
> ???? def getenv(self, varname):
> -??????? self._send(BBPacketGetenv(varname=varname))
> +??????? self._send(BBPacketGetenv(varname=varname.encode()))
> ???????? r = self._expect(BBPacketGetenvReturn)
> ???????? return r.text
> ?
> ???? def md(self, path, addr, size):
> -??????? self._send(BBPacketMd(path=path, addr=addr, size=size))
> +??????? self._send(BBPacketMd(path=path.encode(), addr=addr, size=size))
> ???????? r = self._expect(BBPacketMdReturn)
> ???????? logging.info("Md return: %r", r)
> ???????? return (r.exit_code,r.data)
> ?
> ???? def mw(self, path, addr, data):
> -??????? self._send(BBPacketMw(path=path, addr=addr, data=data))
> +??????? self._send(BBPacketMw(path=path.encode(), addr=addr, data=data))
> ???????? r = self._expect(BBPacketMwReturn)
> ???????? logging.info("Mw return: %r", r)
> ???????? return (r.exit_code,r.written)
> @@ -208,7 +208,7 @@ class Controller(Thread):
> ???? def run(self):
> ???????? assert self.rxq is not None
> ???????? try:
> -??????????? while not self._stop:
> +??????????? while not self._stopit:
> ???????????????? # receive
> ???????????????? pkt = self.conn.recv()
> ???????????????? if pkt:
> @@ -235,15 +235,16 @@ class Controller(Thread):
> ???????? Thread.start(self)
> ?
> ???? def stop(self):
> -??????? self._stop = True
> +??????? self._stopit = True
> ???????? self.join()
> -??????? self._stop = False
> +??????? self._stopit = False
> ???????? self.rxq = None
> ?
> ???? def send_async(self, pkt):
> ???????? self._txq.put(pkt)
> ?
> ???? def send_async_console(self, text):
> +??????? assert isinstance(text, bytes)
> ???????? self._txq.put(BBPacketConsoleMsg(text=text))
> ?
> ???? def send_async_ping(self):
> diff --git a/scripts/remote/main.py b/scripts/remote/main.py
> index cef5d92ee2..b99dba180a 100644
> --- a/scripts/remote/main.py
> +++ b/scripts/remote/main.py
> @@ -1,4 +1,4 @@
> -#!/usr/bin/env python2
> +#!/usr/bin/env python3
> ?
> ?from __future__ import absolute_import, division, print_function
> ?
> @@ -7,7 +7,7 @@ import os
> ?import argparse
> ?import binascii
> ?import logging
> -from Queue import Queue
> +from queue import Queue
> ?from .ratp import RatpError
> ?
> ?try:
> @@ -162,8 +162,8 @@ def handle_console(args):
> ???? ctrl = get_controller(args)
> ???? ctrl.export(args.export)
> ???? ctrl.start(queue)
> -??? ctrl.send_async_console('\r')
> -??? cons = ConsoleInput(queue, exit='\x14')? # CTRL-T
> +??? ctrl.send_async_console(b'\r')
> +??? cons = ConsoleInput(queue, exit=b'\x14')? # CTRL-T
> ???? cons.start()
> ???? try:
> ???????? while True:
> diff --git a/scripts/remote/messages.py b/scripts/remote/messages.py
> index abd331c8b6..ae36189d4c 100644
> --- a/scripts/remote/messages.py
> +++ b/scripts/remote/messages.py
> @@ -1,4 +1,4 @@
> -#!/usr/bin/env python2
> +#!/usr/bin/env python3
> ?# -*- coding: utf-8 -*-
> ?
> ?from __future__ import absolute_import, division, print_function
> @@ -41,12 +41,13 @@ class BBPacket(object):
> ???????? if raw is not None:
> ???????????? self.unpack(raw)
> ???????? else:
> -??????????? self.payload = payload
> +??????????? self.payload = payload.encode()
> ?
> ???? def __repr__(self):
> ???????? return "BBPacket(%i, %i)" % (self.p_type, self.p_flags)
> ?
> ???? def _unpack_payload(self, data):
> +??????? assert isinstance(data, bytes)
> ???????? self.payload = data
> ?
> ???? def _pack_payload(self):
> @@ -63,6 +64,7 @@ class BBPacket(object):
> ?
> ?class BBPacketCommand(BBPacket):
> ???? def __init__(self, raw=None, cmd=None):
> +??????? assert isinstance(cmd, bytes)
> ???????? self.cmd = cmd
> ???????? super(BBPacketCommand, self).__init__(BBType.command, raw=raw)
> ?
> @@ -70,6 +72,7 @@ class BBPacketCommand(BBPacket):
> ???????? return "BBPacketCommand(cmd=%r)" % self.cmd
> ?
> ???? def _unpack_payload(self, payload):
> +??????? assert isinstance(payload, bytes)
> ???????? self.cmd = payload
> ?
> ???? def _pack_payload(self):
> @@ -94,6 +97,8 @@ class BBPacketCommandReturn(BBPacket):
> ?
> ?class BBPacketConsoleMsg(BBPacket):
> ???? def __init__(self, raw=None, text=None):
> +??????? if text != None:

Use 'if text is not None:'.

> +??????????? assert isinstance(text, bytes)
> ???????? self.text = text
> ???????? super(BBPacketConsoleMsg, self).__init__(BBType.consolemsg, raw=raw)
> ?
> @@ -101,6 +106,7 @@ class BBPacketConsoleMsg(BBPacket):
> ???????? return "BBPacketConsoleMsg(text=%r)" % self.text
> ?
> ???? def _unpack_payload(self, payload):
> +??????? assert isinstance(payload, bytes)
> ???????? self.text = payload
> ?
> ???? def _pack_payload(self):
> @@ -125,6 +131,7 @@ class BBPacketPong(BBPacket):
> ?
> ?class BBPacketGetenv(BBPacket):
> ???? def __init__(self, raw=None, varname=None):
> +??????? assert isinstance(varname, bytes)
> ???????? self.varname = varname
> ???????? super(BBPacketGetenv, self).__init__(BBType.getenv, raw=raw)
> ?
> @@ -132,6 +139,7 @@ class BBPacketGetenv(BBPacket):
> ???????? return "BBPacketGetenv(varname=%r)" % self.varname
> ?
> ???? def _unpack_payload(self, payload):
> +??????? assert isinstance(payload, bytes)
> ???????? self.varname = payload
> ?
> ???? def _pack_payload(self):
> @@ -148,6 +156,7 @@ class BBPacketGetenvReturn(BBPacket):
> ???????? return "BBPacketGetenvReturn(varvalue=%s)" % self.text
> ?
> ???? def _unpack_payload(self, payload):
> +??????? assert isinstance(payload, bytes)
> ???????? self.text = payload
> ?
> ???? def _pack_payload(self):
> @@ -172,6 +181,7 @@ class BBPacketFSReturn(BBPacket):
> ?
> ?class BBPacketMd(BBPacket):
> ???? def __init__(self, raw=None, path=None, addr=None, size=None):
> +??????? assert isinstance(path, bytes)
> ???????? self.path = path
> ???????? self.addr = addr
> ???????? self.size = size
> @@ -214,6 +224,7 @@ class BBPacketMdReturn(BBPacket):
> ?
> ?class BBPacketMw(BBPacket):
> ???? def __init__(self, raw=None, path=None, addr=None, data=None):
> +??????? assert isinstance(path, bytes)
> ???????? self.path = path
> ???????? self.addr = addr
> ???????? self.data = data
> diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py
> index 44f3e2f40a..25ca442d15 100644
> --- a/scripts/remote/ratp.py
> +++ b/scripts/remote/ratp.py
> @@ -1,4 +1,4 @@
> -#!/usr/bin/env python2
> +#!/usr/bin/env python3
> ?# -*- coding: utf-8 -*-
> ?
> ?from __future__ import absolute_import, division, print_function
> @@ -593,7 +593,7 @@ class RatpConnection(object):
> ???????? # reassemble
> ???????? if r.c_eor:
> ???????????? logging.info("Reassembling %i frames", len(self._rx_buf))
> -??????????? self._rx_queue.append(''.join(self._rx_buf))
> +??????????? self._rx_queue.append(b''.join(self._rx_buf))
> ???????????? self._rx_buf = []
> ?
> ???????? s = RatpPacket(flags='A')
> diff --git a/scripts/remote/ratpfs.py b/scripts/remote/ratpfs.py
> index 91ca044540..957628b648 100644
> --- a/scripts/remote/ratpfs.py
> +++ b/scripts/remote/ratpfs.py
> @@ -1,4 +1,4 @@
> -#!/usr/bin/env python2
> +#!/usr/bin/env python3
> ?# -*- coding: utf-8 -*-
> ?
> ?from __future__ import absolute_import, division, print_function
> @@ -97,7 +97,7 @@ class RatpFSServer(object):
> ????????????????????????? os.O_TRUNC)
> ???????? path = params[4:]
> ???????? try:
> -??????????? f = os.open(self._resolve(path), flags, 0666)
> +??????????? f = os.open(self._resolve(path), flags, 0o666)

This looks like an unrelated fix.

> ???????? except OSError as e:
> ???????????? return struct.pack('!II', 0, e.errno)
> ???????? h = self._alloc_handle()
> diff --git a/scripts/remote/threadstdio.py b/scripts/remote/threadstdio.py
> index db249892ac..d8ad71413c 100644
> --- a/scripts/remote/threadstdio.py
> +++ b/scripts/remote/threadstdio.py
> @@ -1,11 +1,11 @@
> -#!/usr/bin/python2
> +#!/usr/bin/env python3
> ?
> ?import os
> ?import sys
> ?import termios
> ?import atexit
> ?from threading import Thread
> -from Queue import Queue, Empty
> +from queue import Queue, Empty
> ?
> ?class ConsoleInput(Thread):
> ???? def __init__(self, queue, exit='\x14'):

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



From antonynpavlov at gmail.com  Wed Sep  7 01:21:18 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Wed, 7 Sep 2022 11:21:18 +0300
Subject: Makefile.lib: cmd_dtc: warning: missing whitespace after the macro
 name
Message-ID: <20220907112118.71575e3650222736432b3086@gmail.com>

Hi Everyone!

During MIPS ath79_defconfig build I have a 'missing whitespace after the macro name' warning:

  AS [P]  arch/mips/dts/ar9331_tl_mr3020.dtb.pbl.o
  DTC     arch/mips/dts/ar9344-tl-wdr4300-v1.7.dtb
<stdin>:1:9: warning: missing whitespace after the macro name
  XZKERN  arch/mips/dts/ar9344-tl-wdr4300-v1.7.dtb.z

E.g. see https://gitlab.com/frantony/barebox/-/jobs/2969826747#L47

The reason is the scripts/Makefile.lib generates a C macro with the point symbol in the macro name because the arch/mips/dts/ar9344-tl-wdr4300-v1.7.dts file name contains the point symbol before '.dts', as a result we have:

  #define ar9344_tl_wdr4300_v1.7_dts 1

e.g.

  barebox$ grep -RHn -o "define ar9344_tl_wdr4300_v1.* 1" . 2>/dev/null
  ./arch/mips/dts/.ar9344-tl-wdr4300-v1.7.dtb.cmd:1:define ar9344_tl_wdr4300_v1.7_dts 1

cmd_dtc in scripts/Makefile.lib substitutes the '-' symbols with the '_' symbols but do nothing with other unwanted C preprocessor macro name symbols.

It looks like the linux kernel has no problems with extra point symbols in dts file names, there are several files with extra dot in dts:

  barebox$ find dts/ -iname '*.*.dts' | wc -l
  33

So we have to fix Makefile.lib.

This simple patch fixes the warning problem:

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 16308497b84..2f79656c1e9 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -363,7 +363,7 @@ $(obj)/%.dtb.z: $(obj)/%.dtb FORCE
 dts-frags = $(subst $(quote),,$(CONFIG_EXTERNAL_DTS_FRAGMENTS))
 quiet_cmd_dtc = DTC     $@
 # For compatibility between make 4.2 and 4.3
-cmd_dtc = /usr/bin/env echo -e '$(pound)define $(subst -,_,$(*F))_dts 1\n'$(foreach f,$< $(dts-frags),'$(pound)include "$(f)"\n') | \
+cmd_dtc = /usr/bin/env echo -e '$(pound)define $(subst -,_,$(subst .,_,$(*F)))_dts 1\n'$(foreach f,$< $(dts-frags),'$(pound)include "$(f)"\n') | \
 	$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) - ; \
 	$(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
 		-i $(srctree)/arch/$(SRCARCH)/dts $(DTC_FLAGS) \

I suppose that this simple patch may lead to some undesirable side effects.

Any suggestions?

-- 
Best regards,
? Antony Pavlov


From a.fatoum at pengutronix.de  Wed Sep  7 01:37:33 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 7 Sep 2022 10:37:33 +0200
Subject: [PATCH v2] mci: add new MCI_BROKEN_CD option for testing
In-Reply-To: <20220808135527.GU31528@pengutronix.de>
References: <20220725115856.1288819-1-a.fatoum@pengutronix.de>
 <20220808134048.GS31528@pengutronix.de>
 <c8b16aab-e4a1-3ed3-1502-ac5e16884311@pengutronix.de>
 <20220808135527.GU31528@pengutronix.de>
Message-ID: <558b762f-18d7-7e4a-2f05-464e522f32d8@pengutronix.de>

Hi,

On 08.08.22 15:55, Sascha Hauer wrote:
> On Mon, Aug 08, 2022 at 03:43:17PM +0200, Ahmad Fatoum wrote:
>> Hello Sascha,
>>
>> On 08.08.22 15:40, Sascha Hauer wrote:
>>> On Mon, Jul 25, 2022 at 01:58:56PM +0200, Ahmad Fatoum wrote:
>>>> In remote labs co-located with other hardware, we've observed card
>>>> detect levers of different boards to sporadically fail to detect
>>>> the card, e.g. because the cable on the usbsdmux was yanked around
>>>> by accident. When this happens, barebox usually boots up normally as
>>>> the card detect is ignored and then Linux waits indefinitely for
>>>> the card-detect to turn active. Add a new config option that can be
>>>> enabled to avoid these issues altogether.
>>>>
>>>> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
>>>> ---
>>>> v1 -> v2:
>>>>   - use early exit instead of if-else
>>>>   - don't fail mci_card_probe if of_register_fixup fails
>>>> ---
>>>>  drivers/mci/Kconfig    | 15 +++++++++++++++
>>>>  drivers/mci/mci-core.c | 36 ++++++++++++++++++++++++++++++++----
>>>>  2 files changed, 47 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
>>>> index 21d53c0c3f0b..651e59259790 100644
>>>> --- a/drivers/mci/Kconfig
>>>> +++ b/drivers/mci/Kconfig
>>>> @@ -56,6 +56,21 @@ config MCI_MMC_GPP_PARTITIONS
>>>>  	  Note: by default, 'MMC' devices have no 'general purpose partitions',
>>>>  	  it requires a special one-time configuration step to enable them.
>>>>  
>>>> +config MCI_BROKEN_CD
>>>> +	bool "ignore card-detect pin on boot and in OS"
>>>> +	help
>>>> +	  Say 'y' here to have barebox unconditionally ignore the
>>>> +	  card-detect pin for its own operation and manipulate the
>>>> +	  kernel DT, so all detected MCI cards are polled instead
>>>> +	  of expecting the card detect lever to behave correctly.
>>>> +	  If you need more fine grained control use of_property
>>>> +	  in an init script:
>>>> +
>>>> +	    of_property -fd mmc0 cd-gpios
>>>> +	    of_property -fs mmc0 broken-cd
>>>> +
>>>> +	  If unsure, say 'n' here.
>>>> +
>>>>  comment "--- MCI host drivers ---"
>>>>  
>>>>  config MCI_DW
>>>> diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
>>>> index 82e2f82f5377..4db2253c3a80 100644
>>>> --- a/drivers/mci/mci-core.c
>>>> +++ b/drivers/mci/mci-core.c
>>>> @@ -1727,6 +1727,27 @@ static int mci_register_partition(struct mci_part *part)
>>>>  	return 0;
>>>>  }
>>>>  
>>>> +static int of_broken_cd_fixup(struct device_node *root, void *ctx)
>>>> +{
>>>> +	struct device_d *hw_dev = ctx;
>>>> +	struct device_node *np;
>>>> +	char *name;
>>>> +
>>>> +	name = of_get_reproducible_name(hw_dev->device_node);
>>>> +	np = of_find_node_by_reproducible_name(root, name);
>>>> +	free(name);
>>>> +	if (!np) {
>>>> +		dev_warn(hw_dev, "Cannot find nodepath %s, cannot fixup\n",
>>>> +			 hw_dev->device_node->full_name);
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	of_property_write_bool(np, "cd-gpios", false);
>>>> +	of_property_write_bool(np, "broken-cd", true);
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>>  /**
>>>>   * Probe an MCI card at the given host interface
>>>>   * @param mci MCI device instance
>>>> @@ -1737,10 +1758,13 @@ static int mci_card_probe(struct mci *mci)
>>>>  	struct mci_host *host = mci->host;
>>>>  	int i, rc, disknum, ret;
>>>>  
>>>> -	if (host->card_present && !host->card_present(host) &&
>>>> -	    !host->non_removable) {
>>>> -		dev_err(&mci->dev, "no card inserted\n");
>>>> -		return -ENODEV;
>>>> +	if (host->card_present && !host->card_present(host) && !host->non_removable) {
>>>> +		if (!IS_ENABLED(CONFIG_MCI_BROKEN_CD)) {
>>>> +			dev_err(&mci->dev, "no card inserted\n");
>>>> +			return -ENODEV;
>>>> +		}
>>>> +
>>>> +		dev_info(&mci->dev, "no card inserted (ignoring)\n");
>>>>  	}
>>>>  
>>>>  	ret = regulator_enable(host->supply);
>>>> @@ -1818,6 +1842,10 @@ static int mci_card_probe(struct mci *mci)
>>>>  		}
>>>>  	}
>>>>  
>>>> +	if (IS_ENABLED(CONFIG_MCI_BROKEN_CD) && !host->no_sd &&
>>>> +	    dev_of_node(host->hw_dev))
>>>> +		of_register_fixup(of_broken_cd_fixup, host->hw_dev);
>>>
>>> This fixup is only registered when the card is probed, i.e. when it's
>>> used in barebox. Shouldn't it be registered in mci_register() instead?
>>
>> This is intentional. We only know that cards barebox successfully probed
>> are indeed available.
> 
> I don't get this argument. If card detect is broken then why can't we
> let Linux go through the same steps as barebox when barebox hasn't done
> so?
> 
> Letting the card work in Linux only when it was previously used in barebox
> is surprising to me.

I'll change it into a device parameter applicable to all cards in v3.

Cheers,
Ahmad

> 
> Sascha
> 


-- 
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-5555 |


From s.hauer at pengutronix.de  Thu Sep  8 01:16:33 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 8 Sep 2022 10:16:33 +0200
Subject: [PATCH 2/4] bbremote: Convert to python3
In-Reply-To: <1019c1be5617830df3edd0a47b7f7fbd9bc2a311.camel@pengutronix.de>
References: <20220906102049.1364561-1-s.hauer@pengutronix.de>
 <20220906102049.1364561-3-s.hauer@pengutronix.de>
 <1019c1be5617830df3edd0a47b7f7fbd9bc2a311.camel@pengutronix.de>
Message-ID: <20220908081633.GA24324@pengutronix.de>

On Tue, Sep 06, 2022 at 03:02:34PM +0200, Jan L?bbe wrote:
> On Tue, 2022-09-06 at 12:20 +0200, Sascha Hauer wrote:
> > This is the long overdue conversion from python2 to python3.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > ---
> > ?scripts/bbremote????????????? |? 2 +-
> > ?scripts/remote/controller.py? | 21 +++++++++++----------
> > ?scripts/remote/main.py??????? |? 8 ++++----
> > ?scripts/remote/messages.py??? | 15 +++++++++++++--
> > ?scripts/remote/ratp.py??????? |? 4 ++--
> > ?scripts/remote/ratpfs.py????? |? 4 ++--
> > ?scripts/remote/threadstdio.py |? 4 ++--
> > ?7 files changed, 35 insertions(+), 23 deletions(-)
> > 
> > diff --git a/scripts/bbremote b/scripts/bbremote
> > index bc5351dbae..1eeabd08d1 100755
> > --- a/scripts/bbremote
> > +++ b/scripts/bbremote
> > @@ -1,3 +1,3 @@
> > -#!/usr/bin/env python2
> > +#!/usr/bin/env python3
> > ?
> > ?import remote.main
> > diff --git a/scripts/remote/controller.py b/scripts/remote/controller.py
> > index b4493591dd..a3ae260558 100644
> > --- a/scripts/remote/controller.py
> > +++ b/scripts/remote/controller.py
> > @@ -1,4 +1,4 @@
> > -#!/usr/bin/env python2
> > +#!/usr/bin/env python3
> > ?# -*- coding: utf-8 -*-
> > ?
> > ?from __future__ import absolute_import, division, print_function
> > @@ -8,7 +8,7 @@ import logging
> > ?import sys
> > ?import os
> > ?from threading import Thread
> > -from Queue import Queue, Empty
> > +from queue import Queue, Empty
> > ?from .ratpfs import RatpFSServer
> > ?from .messages import *
> > ?from .ratp import RatpError
> > @@ -105,7 +105,7 @@ class Controller(Thread):
> > ???????? self.rxq = None
> > ???????? self.conn.connect(timeout=5.0)
> > ???????? self._txq = Queue()
> > -??????? self._stop = False
> > +??????? self._stopit = False
> 
> Is this rename needed?

Yes. It seems the Thread class now has a member _stop itself, see:

https://github.com/python/cpython/blob/3.10/Lib/threading.py#L1028

Without this rename we get:

Traceback (most recent call last):
  File "/ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/./scripts/bbremote", line 3, in <module>
    import remote.main
  File "/ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/scripts/remote/main.py", line 281, in <module>
    res = args.func(args)
  File "/ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/scripts/remote/main.py", line 185, in handle_console
    ctrl.stop()
  File "/ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/scripts/remote/controller.py", line 239, in stop
    self.join()
  File "/usr/lib/python3.9/threading.py", line 1033, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.9/threading.py", line 1051, in _wait_for_tstate_lock
    self._stop()
TypeError: 'bool' object is not callable

> > ?
> > ???? def _unpack_payload(self, payload):
> > +??????? assert isinstance(payload, bytes)
> > ???????? self.cmd = payload
> > ?
> > ???? def _pack_payload(self):
> > @@ -94,6 +97,8 @@ class BBPacketCommandReturn(BBPacket):
> > ?
> > ?class BBPacketConsoleMsg(BBPacket):
> > ???? def __init__(self, raw=None, text=None):
> > +??????? if text != None:
> 
> Use 'if text is not None:'.

Ok.

> > +++ b/scripts/remote/ratpfs.py
> > @@ -1,4 +1,4 @@
> > -#!/usr/bin/env python2
> > +#!/usr/bin/env python3
> > ?# -*- coding: utf-8 -*-
> > ?
> > ?from __future__ import absolute_import, division, print_function
> > @@ -97,7 +97,7 @@ class RatpFSServer(object):
> > ????????????????????????? os.O_TRUNC)
> > ???????? path = params[4:]
> > ???????? try:
> > -??????????? f = os.open(self._resolve(path), flags, 0666)
> > +??????????? f = os.open(self._resolve(path), flags, 0o666)
> 
> This looks like an unrelated fix.

It depends how you see it. This was accepted in python2, but no longer in python3,
so this is a step to python3 conversion.

Sascha

-- 
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-5555 |


From s.hauer at pengutronix.de  Thu Sep  8 02:30:04 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu,  8 Sep 2022 11:30:04 +0200
Subject: [PATCH v2 4/5] ratp: i2c: Do not return error
In-Reply-To: <20220908093005.3035259-1-s.hauer@pengutronix.de>
References: <20220908093005.3035259-1-s.hauer@pengutronix.de>
Message-ID: <20220908093005.3035259-5-s.hauer@pengutronix.de>

The RATP command implementations should only return an error on internal
failures. When an i2c command failed we should return 0 though to
actually send the error message. Without it the remote would just wait
for a response until it times out.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/ratp/i2c.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/ratp/i2c.c b/common/ratp/i2c.c
index c14bbbf9b9..404ddd2ece 100644
--- a/common/ratp/i2c.c
+++ b/common/ratp/i2c.c
@@ -162,7 +162,7 @@ out:
 	*rsp = (struct ratp_bb *)i2c_read_rsp;
 	*rsp_len = i2c_read_rsp_len;
 
-	return ret;
+	return 0;
 }
 
 BAREBOX_RATP_CMD_START(I2C_READ)
@@ -271,7 +271,7 @@ out:
 	*rsp = (struct ratp_bb *)i2c_write_rsp;
 	*rsp_len = sizeof(*i2c_write_rsp);
 
-	return ret;
+	return 0;
 }
 
 BAREBOX_RATP_CMD_START(I2C_WRITE)
-- 
2.30.2



From s.hauer at pengutronix.de  Thu Sep  8 02:30:03 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu,  8 Sep 2022 11:30:03 +0200
Subject: [PATCH v2 3/5] ratp: getenv: Do not crash on non-existing variables
In-Reply-To: <20220908093005.3035259-1-s.hauer@pengutronix.de>
References: <20220908093005.3035259-1-s.hauer@pengutronix.de>
Message-ID: <20220908093005.3035259-4-s.hauer@pengutronix.de>

getenv() returns NULL on non-existing variables. Replace result with
empty string to avoid doing strlen() on a NULL pointer.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/ratp/getenv.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/ratp/getenv.c b/common/ratp/getenv.c
index 7b38d2e363..9617ab1b43 100644
--- a/common/ratp/getenv.c
+++ b/common/ratp/getenv.c
@@ -32,6 +32,9 @@ static int ratp_cmd_getenv(const struct ratp_bb *req, int req_len,
 	value = getenv(varname);
 	free(varname);
 
+	if (!value)
+		value = "";
+
 	dlen = strlen(value);
 
 	*rsp_len = sizeof(struct ratp_bb) + dlen;
-- 
2.30.2



From s.hauer at pengutronix.de  Thu Sep  8 02:30:00 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu,  8 Sep 2022 11:30:00 +0200
Subject: [PATCH v2 0/5] bbremote: Convert to python3
Message-ID: <20220908093005.3035259-1-s.hauer@pengutronix.de>

Fix some things forgotten in v1;
- Update documentation
- Also convert ratpfs

Sascha Hauer (5):
  remove local pyserial
  bbremote: Convert to python3
  ratp: getenv: Do not crash on non-existing variables
  ratp: i2c: Do not return error
  bbremote: Print usage when no command is given

 Documentation/user/remote-control.rst         |   10 +-
 common/ratp/getenv.c                          |    3 +
 common/ratp/i2c.c                             |    4 +-
 scripts/bbremote                              |    2 +-
 scripts/remote/controller.py                  |   21 +-
 scripts/remote/main.py                        |   18 +-
 scripts/remote/messages.py                    |   13 +-
 scripts/remote/missing.py                     |    2 +-
 scripts/remote/ratp.py                        |    4 +-
 scripts/remote/ratpfs.py                      |   27 +-
 scripts/remote/threadstdio.py                 |    4 +-
 scripts/serial/__init__.py                    |   79 -
 scripts/serial/rfc2217.py                     | 1327 -----------------
 scripts/serial/serialcli.py                   |  284 ----
 scripts/serial/serialposix.py                 |  730 ---------
 scripts/serial/serialutil.py                  |  572 -------
 scripts/serial/tools/__init__.py              |    1 -
 scripts/serial/tools/list_ports.py            |  103 --
 scripts/serial/tools/list_ports_linux.py      |  152 --
 scripts/serial/urlhandler/__init__.py         |    1 -
 scripts/serial/urlhandler/protocol_hwgrep.py  |   45 -
 scripts/serial/urlhandler/protocol_loop.py    |  279 ----
 scripts/serial/urlhandler/protocol_rfc2217.py |   11 -
 scripts/serial/urlhandler/protocol_socket.py  |  291 ----
 24 files changed, 67 insertions(+), 3916 deletions(-)
 delete mode 100644 scripts/serial/__init__.py
 delete mode 100644 scripts/serial/rfc2217.py
 delete mode 100644 scripts/serial/serialcli.py
 delete mode 100644 scripts/serial/serialposix.py
 delete mode 100644 scripts/serial/serialutil.py
 delete mode 100644 scripts/serial/tools/__init__.py
 delete mode 100644 scripts/serial/tools/list_ports.py
 delete mode 100644 scripts/serial/tools/list_ports_linux.py
 delete mode 100644 scripts/serial/urlhandler/__init__.py
 delete mode 100644 scripts/serial/urlhandler/protocol_hwgrep.py
 delete mode 100644 scripts/serial/urlhandler/protocol_loop.py
 delete mode 100644 scripts/serial/urlhandler/protocol_rfc2217.py
 delete mode 100644 scripts/serial/urlhandler/protocol_socket.py

-- 
2.30.2



From s.hauer at pengutronix.de  Thu Sep  8 02:30:02 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu,  8 Sep 2022 11:30:02 +0200
Subject: [PATCH v2 2/5] bbremote: Convert to python3
In-Reply-To: <20220908093005.3035259-1-s.hauer@pengutronix.de>
References: <20220908093005.3035259-1-s.hauer@pengutronix.de>
Message-ID: <20220908093005.3035259-3-s.hauer@pengutronix.de>

This is the long overdue conversion from python2 to python3.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---

Notes:
    Changes since v1:
    - Also convert and test ratpfs
    - Update documentation

 Documentation/user/remote-control.rst | 10 ++++------
 scripts/bbremote                      |  2 +-
 scripts/remote/controller.py          | 21 +++++++++++----------
 scripts/remote/main.py                | 12 ++++++------
 scripts/remote/messages.py            | 13 ++++++++++++-
 scripts/remote/missing.py             |  2 +-
 scripts/remote/ratp.py                |  4 ++--
 scripts/remote/ratpfs.py              | 27 +++++++++++++++++----------
 scripts/remote/threadstdio.py         |  4 ++--
 9 files changed, 56 insertions(+), 39 deletions(-)

diff --git a/Documentation/user/remote-control.rst b/Documentation/user/remote-control.rst
index 43f1fb3118..b285c2297b 100644
--- a/Documentation/user/remote-control.rst
+++ b/Documentation/user/remote-control.rst
@@ -35,17 +35,15 @@ can also be enabled.
 Running the bbremote tool
 -------------------------
 
-The bbremote host tool is written in python. To run it python2 has to be
+The bbremote host tool is written in python. To run it python3 has to be
 installed with the following additional packages:
 
 +----------------+---------------------+
 | python package | Debian package name |
 +================+=====================+
-| crcmod         | python-crcmod       |
+| crcmod         | python3-crcmod      |
 +----------------+---------------------+
-| enum           | python-enum         |
-+----------------+---------------------+
-| enum34         | python-enum34       |
+| pyserial       | python3-serial      |
 +----------------+---------------------+
 
 If your distribution does not provide aforementioned packages, you can
@@ -54,7 +52,7 @@ account via:
 
 .. code-block:: sh
 
-  python2 -m pip install --user crcmod enum enum34
+  python -m pip install --user crcmod pyserial
 
 configuring bbremote
 ^^^^^^^^^^^^^^^^^^^^
diff --git a/scripts/bbremote b/scripts/bbremote
index bc5351dbae..1eeabd08d1 100755
--- a/scripts/bbremote
+++ b/scripts/bbremote
@@ -1,3 +1,3 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 
 import remote.main
diff --git a/scripts/remote/controller.py b/scripts/remote/controller.py
index b4493591dd..a3ae260558 100644
--- a/scripts/remote/controller.py
+++ b/scripts/remote/controller.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -8,7 +8,7 @@ import logging
 import sys
 import os
 from threading import Thread
-from Queue import Queue, Empty
+from queue import Queue, Empty
 from .ratpfs import RatpFSServer
 from .messages import *
 from .ratp import RatpError
@@ -105,7 +105,7 @@ class Controller(Thread):
         self.rxq = None
         self.conn.connect(timeout=5.0)
         self._txq = Queue()
-        self._stop = False
+        self._stopit = False
         self.fsserver = RatpFSServer()
 
     def _send(self, bbpkt):
@@ -147,24 +147,24 @@ class Controller(Thread):
             return 0
 
     def command(self, cmd):
-        self._send(BBPacketCommand(cmd=cmd))
+        self._send(BBPacketCommand(cmd=cmd.encode()))
         r = self._expect(BBPacketCommandReturn, timeout=None)
         logging.info("Command: %r", r)
         return r.exit_code
 
     def getenv(self, varname):
-        self._send(BBPacketGetenv(varname=varname))
+        self._send(BBPacketGetenv(varname=varname.encode()))
         r = self._expect(BBPacketGetenvReturn)
         return r.text
 
     def md(self, path, addr, size):
-        self._send(BBPacketMd(path=path, addr=addr, size=size))
+        self._send(BBPacketMd(path=path.encode(), addr=addr, size=size))
         r = self._expect(BBPacketMdReturn)
         logging.info("Md return: %r", r)
         return (r.exit_code,r.data)
 
     def mw(self, path, addr, data):
-        self._send(BBPacketMw(path=path, addr=addr, data=data))
+        self._send(BBPacketMw(path=path.encode(), addr=addr, data=data))
         r = self._expect(BBPacketMwReturn)
         logging.info("Mw return: %r", r)
         return (r.exit_code,r.written)
@@ -208,7 +208,7 @@ class Controller(Thread):
     def run(self):
         assert self.rxq is not None
         try:
-            while not self._stop:
+            while not self._stopit:
                 # receive
                 pkt = self.conn.recv()
                 if pkt:
@@ -235,15 +235,16 @@ class Controller(Thread):
         Thread.start(self)
 
     def stop(self):
-        self._stop = True
+        self._stopit = True
         self.join()
-        self._stop = False
+        self._stopit = False
         self.rxq = None
 
     def send_async(self, pkt):
         self._txq.put(pkt)
 
     def send_async_console(self, text):
+        assert isinstance(text, bytes)
         self._txq.put(BBPacketConsoleMsg(text=text))
 
     def send_async_ping(self):
diff --git a/scripts/remote/main.py b/scripts/remote/main.py
index cef5d92ee2..2f3ce370ae 100644
--- a/scripts/remote/main.py
+++ b/scripts/remote/main.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 
 from __future__ import absolute_import, division, print_function
 
@@ -7,7 +7,7 @@ import os
 import argparse
 import binascii
 import logging
-from Queue import Queue
+from queue import Queue
 from .ratp import RatpError
 
 try:
@@ -48,7 +48,7 @@ def get_controller(args):
 
 def handle_run(args):
     ctrl = get_controller(args)
-    ctrl.export(args.export)
+    ctrl.export(args.export.encode())
     res = ctrl.command(' '.join(args.arg))
     if res:
         res = 1
@@ -160,10 +160,10 @@ def handle_listen(args):
 def handle_console(args):
     queue = Queue()
     ctrl = get_controller(args)
-    ctrl.export(args.export)
+    ctrl.export(args.export.encode())
     ctrl.start(queue)
-    ctrl.send_async_console('\r')
-    cons = ConsoleInput(queue, exit='\x14')  # CTRL-T
+    ctrl.send_async_console(b'\r')
+    cons = ConsoleInput(queue, exit=b'\x14')  # CTRL-T
     cons.start()
     try:
         while True:
diff --git a/scripts/remote/messages.py b/scripts/remote/messages.py
index abd331c8b6..76cccad393 100644
--- a/scripts/remote/messages.py
+++ b/scripts/remote/messages.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -47,6 +47,7 @@ class BBPacket(object):
         return "BBPacket(%i, %i)" % (self.p_type, self.p_flags)
 
     def _unpack_payload(self, data):
+        assert isinstance(data, bytes)
         self.payload = data
 
     def _pack_payload(self):
@@ -63,6 +64,7 @@ class BBPacket(object):
 
 class BBPacketCommand(BBPacket):
     def __init__(self, raw=None, cmd=None):
+        assert isinstance(cmd, bytes)
         self.cmd = cmd
         super(BBPacketCommand, self).__init__(BBType.command, raw=raw)
 
@@ -70,6 +72,7 @@ class BBPacketCommand(BBPacket):
         return "BBPacketCommand(cmd=%r)" % self.cmd
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.cmd = payload
 
     def _pack_payload(self):
@@ -94,6 +97,8 @@ class BBPacketCommandReturn(BBPacket):
 
 class BBPacketConsoleMsg(BBPacket):
     def __init__(self, raw=None, text=None):
+        if text is not None:
+            assert isinstance(text, bytes)
         self.text = text
         super(BBPacketConsoleMsg, self).__init__(BBType.consolemsg, raw=raw)
 
@@ -101,6 +106,7 @@ class BBPacketConsoleMsg(BBPacket):
         return "BBPacketConsoleMsg(text=%r)" % self.text
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.text = payload
 
     def _pack_payload(self):
@@ -125,6 +131,7 @@ class BBPacketPong(BBPacket):
 
 class BBPacketGetenv(BBPacket):
     def __init__(self, raw=None, varname=None):
+        assert isinstance(varname, bytes)
         self.varname = varname
         super(BBPacketGetenv, self).__init__(BBType.getenv, raw=raw)
 
@@ -132,6 +139,7 @@ class BBPacketGetenv(BBPacket):
         return "BBPacketGetenv(varname=%r)" % self.varname
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.varname = payload
 
     def _pack_payload(self):
@@ -148,6 +156,7 @@ class BBPacketGetenvReturn(BBPacket):
         return "BBPacketGetenvReturn(varvalue=%s)" % self.text
 
     def _unpack_payload(self, payload):
+        assert isinstance(payload, bytes)
         self.text = payload
 
     def _pack_payload(self):
@@ -172,6 +181,7 @@ class BBPacketFSReturn(BBPacket):
 
 class BBPacketMd(BBPacket):
     def __init__(self, raw=None, path=None, addr=None, size=None):
+        assert isinstance(path, bytes)
         self.path = path
         self.addr = addr
         self.size = size
@@ -214,6 +224,7 @@ class BBPacketMdReturn(BBPacket):
 
 class BBPacketMw(BBPacket):
     def __init__(self, raw=None, path=None, addr=None, data=None):
+        assert isinstance(path, bytes)
         self.path = path
         self.addr = addr
         self.data = data
diff --git a/scripts/remote/missing.py b/scripts/remote/missing.py
index 67c2dfa8c0..9ed86bc10e 100644
--- a/scripts/remote/missing.py
+++ b/scripts/remote/missing.py
@@ -25,4 +25,4 @@ def monotonic():
     return t.tv_sec + t.tv_nsec * 1e-9
 
 if __name__ == "__main__":
-    print monotonic()
+    print(monotonic())
diff --git a/scripts/remote/ratp.py b/scripts/remote/ratp.py
index 44f3e2f40a..25ca442d15 100644
--- a/scripts/remote/ratp.py
+++ b/scripts/remote/ratp.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -593,7 +593,7 @@ class RatpConnection(object):
         # reassemble
         if r.c_eor:
             logging.info("Reassembling %i frames", len(self._rx_buf))
-            self._rx_queue.append(''.join(self._rx_buf))
+            self._rx_queue.append(b''.join(self._rx_buf))
             self._rx_buf = []
 
         s = RatpPacket(flags='A')
diff --git a/scripts/remote/ratpfs.py b/scripts/remote/ratpfs.py
index 91ca044540..3e05cf2418 100644
--- a/scripts/remote/ratpfs.py
+++ b/scripts/remote/ratpfs.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
 from __future__ import absolute_import, division, print_function
@@ -36,7 +36,9 @@ class RatpFSError(ValueError):
 
 
 class RatpFSPacket(object):
-    def __init__(self, type=RatpFSType.invalid, payload="", raw=None):
+    def __init__(self, type=RatpFSType.invalid, payload=b'', raw=None):
+        if payload is not None:
+            assert isinstance(payload, bytes)
         if raw is not None:
             type, = struct.unpack('!B', raw[:1])
             self.type = RatpFSType(type)
@@ -57,9 +59,11 @@ class RatpFSPacket(object):
 
 class RatpFSServer(object):
     def __init__(self, path=None):
-        self.path = path
         if path:
+            assert isinstance(path, bytes)
             self.path = os.path.abspath(os.path.expanduser(path))
+        else:
+            self.path = path
         self.next_handle = 1  # 0 is invalid
         self.files = {}
         self.mounted = False
@@ -71,11 +75,13 @@ class RatpFSServer(object):
         return handle
 
     def _resolve(self, path):
-        components = path.split('/')
+        assert isinstance(path, bytes)
+        components = path.split(b'/')
         components = [x for x in components if x and x != '..']
         return os.path.join(self.path, *components)
 
     def handle_stat(self, path):
+        assert isinstance(path, bytes)
 
         try:
             logging.info("path: %r", path)
@@ -97,7 +103,7 @@ class RatpFSServer(object):
                          os.O_TRUNC)
         path = params[4:]
         try:
-            f = os.open(self._resolve(path), flags, 0666)
+            f = os.open(self._resolve(path), flags, 0o666)
         except OSError as e:
             return struct.pack('!II', 0, e.errno)
         h = self._alloc_handle()
@@ -118,24 +124,25 @@ class RatpFSServer(object):
         f = self.files[h]
         pos = os.lseek(f, pos, os.SEEK_SET)
         assert os.write(f, payload) == len(payload)
-        return ""
+        return b""
 
     def handle_readdir(self, path):
-        res = ""
+        assert isinstance(path, bytes)
+        res = b""
         for x in os.listdir(self._resolve(path)):
-            res += x+'\0'
+            res += x+b'\0'
         return res
 
     def handle_close(self, params):
         h, = struct.unpack('!I', params[:4])
         os.close(self.files.pop(h))
-        return ""
+        return b""
 
     def handle_truncate(self, params):
         h, size = struct.unpack('!II', params)
         f = self.files[h]
         os.ftruncate(f, size)
-        return ""
+        return b""
 
     def handle(self, bbcall):
         assert isinstance(bbcall, BBPacketFS)
diff --git a/scripts/remote/threadstdio.py b/scripts/remote/threadstdio.py
index db249892ac..d8ad71413c 100644
--- a/scripts/remote/threadstdio.py
+++ b/scripts/remote/threadstdio.py
@@ -1,11 +1,11 @@
-#!/usr/bin/python2
+#!/usr/bin/env python3
 
 import os
 import sys
 import termios
 import atexit
 from threading import Thread
-from Queue import Queue, Empty
+from queue import Queue, Empty
 
 class ConsoleInput(Thread):
     def __init__(self, queue, exit='\x14'):
-- 
2.30.2



From s.hauer at pengutronix.de  Thu Sep  8 02:30:01 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu,  8 Sep 2022 11:30:01 +0200
Subject: [PATCH v2 1/5] remove local pyserial
In-Reply-To: <20220908093005.3035259-1-s.hauer@pengutronix.de>
References: <20220908093005.3035259-1-s.hauer@pengutronix.de>
Message-ID: <20220908093005.3035259-2-s.hauer@pengutronix.de>

A copy of pyserial has been put into the tree because RFC2217 support
was broken back then. This issue is long fixed, so remove the local
copy.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 scripts/serial/__init__.py                    |   79 -
 scripts/serial/rfc2217.py                     | 1327 -----------------
 scripts/serial/serialcli.py                   |  284 ----
 scripts/serial/serialposix.py                 |  730 ---------
 scripts/serial/serialutil.py                  |  572 -------
 scripts/serial/tools/__init__.py              |    1 -
 scripts/serial/tools/list_ports.py            |  103 --
 scripts/serial/tools/list_ports_linux.py      |  152 --
 scripts/serial/urlhandler/__init__.py         |    1 -
 scripts/serial/urlhandler/protocol_hwgrep.py  |   45 -
 scripts/serial/urlhandler/protocol_loop.py    |  279 ----
 scripts/serial/urlhandler/protocol_rfc2217.py |   11 -
 scripts/serial/urlhandler/protocol_socket.py  |  291 ----
 13 files changed, 3875 deletions(-)
 delete mode 100644 scripts/serial/__init__.py
 delete mode 100644 scripts/serial/rfc2217.py
 delete mode 100644 scripts/serial/serialcli.py
 delete mode 100644 scripts/serial/serialposix.py
 delete mode 100644 scripts/serial/serialutil.py
 delete mode 100644 scripts/serial/tools/__init__.py
 delete mode 100644 scripts/serial/tools/list_ports.py
 delete mode 100644 scripts/serial/tools/list_ports_linux.py
 delete mode 100644 scripts/serial/urlhandler/__init__.py
 delete mode 100644 scripts/serial/urlhandler/protocol_hwgrep.py
 delete mode 100644 scripts/serial/urlhandler/protocol_loop.py
 delete mode 100644 scripts/serial/urlhandler/protocol_rfc2217.py
 delete mode 100644 scripts/serial/urlhandler/protocol_socket.py

diff --git a/scripts/serial/__init__.py b/scripts/serial/__init__.py
deleted file mode 100644
index 33ae52ec11..0000000000
--- a/scripts/serial/__init__.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env python 
-
-# portable serial port access with python
-# this is a wrapper module for different platform implementations
-#
-# (C) 2001-2010 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-VERSION = '2.7'
-
-import sys
-
-if sys.platform == 'cli':
-    from serial.serialcli import *
-else:
-    import os
-    # chose an implementation, depending on os
-    if os.name == 'nt': #sys.platform == 'win32':
-        from serial.serialwin32 import *
-    elif os.name == 'posix':
-        from serial.serialposix import *
-    elif os.name == 'java':
-        from serial.serialjava import *
-    else:
-        raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
-
-
-protocol_handler_packages = [
-        'serial.urlhandler',
-        ]
-
-def serial_for_url(url, *args, **kwargs):
-    """\
-    Get an instance of the Serial class, depending on port/url. The port is not
-    opened when the keyword parameter 'do_not_open' is true, by default it
-    is. All other parameters are directly passed to the __init__ method when
-    the port is instantiated.
-
-    The list of package names that is searched for protocol handlers is kept in
-    ``protocol_handler_packages``.
-
-    e.g. we want to support a URL ``foobar://``. A module
-    ``my_handlers.protocol_foobar`` is provided by the user. Then
-    ``protocol_handler_packages.append("my_handlers")`` would extend the search
-    path so that ``serial_for_url("foobar://"))`` would work.
-    """
-    # check remove extra parameter to not confuse the Serial class
-    do_open = 'do_not_open' not in kwargs or not kwargs['do_not_open']
-    if 'do_not_open' in kwargs: del kwargs['do_not_open']
-    # the default is to use the native version
-    klass = Serial   # 'native' implementation
-    # check port type and get class
-    try:
-        url_nocase = url.lower()
-    except AttributeError:
-        # it's not a string, use default
-        pass
-    else:
-        if '://' in url_nocase:
-            protocol = url_nocase.split('://', 1)[0]
-            for package_name in protocol_handler_packages:
-                module_name = '%s.protocol_%s' % (package_name, protocol,)
-                try:
-                    handler_module = __import__(module_name)
-                except ImportError:
-                    pass
-                else:
-                    klass = sys.modules[module_name].Serial
-                    break
-            else:
-                raise ValueError('invalid URL, protocol %r not known' % (protocol,))
-        else:
-            klass = Serial   # 'native' implementation
-    # instantiate and open when desired
-    instance = klass(None, *args, **kwargs)
-    instance.port = url
-    if do_open:
-        instance.open()
-    return instance
diff --git a/scripts/serial/rfc2217.py b/scripts/serial/rfc2217.py
deleted file mode 100644
index b65edd55c8..0000000000
--- a/scripts/serial/rfc2217.py
+++ /dev/null
@@ -1,1327 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a RFC2217 compatible client. RF2217 descibes a
-# protocol to access serial ports over TCP/IP and allows setting the baud rate,
-# modem control lines etc.
-#
-# (C) 2001-2013 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-# TODO:
-# - setting control line -> answer is not checked (had problems with one of the
-#   severs). consider implementing a compatibility mode flag to make check
-#   conditional
-# - write timeout not implemented at all
-
-##############################################################################
-# observations and issues with servers
-#=============================================================================
-# sredird V2.2.1
-# - http://www.ibiblio.org/pub/Linux/system/serial/   sredird-2.2.2.tar.gz
-# - does not acknowledge SET_CONTROL (RTS/DTR) correctly, always responding
-#   [105 1] instead of the actual value.
-# - SET_BAUDRATE answer contains 4 extra null bytes -> probably for larger
-#   numbers than 2**32?
-# - To get the signature [COM_PORT_OPTION 0] has to be sent.
-# - run a server: while true; do nc -l -p 7000 -c "sredird debug /dev/ttyUSB0 /var/lock/sredir"; done
-#=============================================================================
-# telnetcpcd (untested)
-# - http://ftp.wayne.edu/kermit/sredird/telnetcpcd-1.09.tar.gz
-# - To get the signature [COM_PORT_OPTION] w/o data has to be sent.
-#=============================================================================
-# ser2net
-# - does not negotiate BINARY or COM_PORT_OPTION for his side but at least
-#   acknowledges that the client activates these options
-# - The configuration may be that the server prints a banner. As this client
-#   implementation does a flushInput on connect, this banner is hidden from
-#   the user application.
-# - NOTIFY_MODEMSTATE: the poll interval of the server seems to be one
-#   second.
-# - To get the signature [COM_PORT_OPTION 0] has to be sent.
-# - run a server: run ser2net daemon, in /etc/ser2net.conf:
-#     2000:telnet:0:/dev/ttyS0:9600 remctl banner
-##############################################################################
-
-# How to identify ports? pySerial might want to support other protocols in the
-# future, so lets use an URL scheme.
-# for RFC2217 compliant servers we will use this:
-#    rfc2217://<host>:<port>[/option[/option...]]
-#
-# options:
-# - "debug" print diagnostic messages
-# - "ign_set_control": do not look at the answers to SET_CONTROL
-# - "poll_modem": issue NOTIFY_MODEMSTATE requests when CTS/DTR/RI/CD is read.
-#   Without this option it expects that the server sends notifications
-#   automatically on change (which most servers do and is according to the
-#   RFC).
-# the order of the options is not relevant
-
-from serial.serialutil import *
-import time
-import struct
-import socket
-import threading
-import Queue
-import logging
-
-# port string is expected to be something like this:
-# rfc2217://host:port
-# host may be an IP or including domain, whatever.
-# port is 0...65535
-
-# map log level names to constants. used in fromURL()
-LOGGER_LEVELS = {
-    'debug': logging.DEBUG,
-    'info': logging.INFO,
-    'warning': logging.WARNING,
-    'error': logging.ERROR,
-    }
-
-
-# telnet protocol characters
-IAC  = to_bytes([255]) # Interpret As Command
-DONT = to_bytes([254])
-DO   = to_bytes([253])
-WONT = to_bytes([252])
-WILL = to_bytes([251])
-IAC_DOUBLED = to_bytes([IAC, IAC])
-
-SE  = to_bytes([240])  # Subnegotiation End
-NOP = to_bytes([241])  # No Operation
-DM  = to_bytes([242])  # Data Mark
-BRK = to_bytes([243])  # Break
-IP  = to_bytes([244])  # Interrupt process
-AO  = to_bytes([245])  # Abort output
-AYT = to_bytes([246])  # Are You There
-EC  = to_bytes([247])  # Erase Character
-EL  = to_bytes([248])  # Erase Line
-GA  = to_bytes([249])  # Go Ahead
-SB =  to_bytes([250])  # Subnegotiation Begin
-
-# selected telnet options
-BINARY = to_bytes([0]) # 8-bit data path
-ECHO = to_bytes([1])   # echo
-SGA = to_bytes([3])    # suppress go ahead
-
-# RFC2217
-COM_PORT_OPTION = to_bytes([44])
-
-# Client to Access Server
-SET_BAUDRATE = to_bytes([1])
-SET_DATASIZE = to_bytes([2])
-SET_PARITY = to_bytes([3])
-SET_STOPSIZE = to_bytes([4])
-SET_CONTROL = to_bytes([5])
-NOTIFY_LINESTATE = to_bytes([6])
-NOTIFY_MODEMSTATE = to_bytes([7])
-FLOWCONTROL_SUSPEND = to_bytes([8])
-FLOWCONTROL_RESUME = to_bytes([9])
-SET_LINESTATE_MASK = to_bytes([10])
-SET_MODEMSTATE_MASK = to_bytes([11])
-PURGE_DATA = to_bytes([12])
-
-SERVER_SET_BAUDRATE = to_bytes([101])
-SERVER_SET_DATASIZE = to_bytes([102])
-SERVER_SET_PARITY = to_bytes([103])
-SERVER_SET_STOPSIZE = to_bytes([104])
-SERVER_SET_CONTROL = to_bytes([105])
-SERVER_NOTIFY_LINESTATE = to_bytes([106])
-SERVER_NOTIFY_MODEMSTATE = to_bytes([107])
-SERVER_FLOWCONTROL_SUSPEND = to_bytes([108])
-SERVER_FLOWCONTROL_RESUME = to_bytes([109])
-SERVER_SET_LINESTATE_MASK = to_bytes([110])
-SERVER_SET_MODEMSTATE_MASK = to_bytes([111])
-SERVER_PURGE_DATA = to_bytes([112])
-
-RFC2217_ANSWER_MAP = {
-    SET_BAUDRATE: SERVER_SET_BAUDRATE,
-    SET_DATASIZE: SERVER_SET_DATASIZE,
-    SET_PARITY: SERVER_SET_PARITY,
-    SET_STOPSIZE: SERVER_SET_STOPSIZE,
-    SET_CONTROL: SERVER_SET_CONTROL,
-    NOTIFY_LINESTATE: SERVER_NOTIFY_LINESTATE,
-    NOTIFY_MODEMSTATE: SERVER_NOTIFY_MODEMSTATE,
-    FLOWCONTROL_SUSPEND: SERVER_FLOWCONTROL_SUSPEND,
-    FLOWCONTROL_RESUME: SERVER_FLOWCONTROL_RESUME,
-    SET_LINESTATE_MASK: SERVER_SET_LINESTATE_MASK,
-    SET_MODEMSTATE_MASK: SERVER_SET_MODEMSTATE_MASK,
-    PURGE_DATA: SERVER_PURGE_DATA,
-}
-
-SET_CONTROL_REQ_FLOW_SETTING = to_bytes([0])        # Request Com Port Flow Control Setting (outbound/both)
-SET_CONTROL_USE_NO_FLOW_CONTROL = to_bytes([1])     # Use No Flow Control (outbound/both)
-SET_CONTROL_USE_SW_FLOW_CONTROL = to_bytes([2])     # Use XON/XOFF Flow Control (outbound/both)
-SET_CONTROL_USE_HW_FLOW_CONTROL = to_bytes([3])     # Use HARDWARE Flow Control (outbound/both)
-SET_CONTROL_REQ_BREAK_STATE = to_bytes([4])         # Request BREAK State
-SET_CONTROL_BREAK_ON = to_bytes([5])                # Set BREAK State ON
-SET_CONTROL_BREAK_OFF = to_bytes([6])               # Set BREAK State OFF
-SET_CONTROL_REQ_DTR = to_bytes([7])                 # Request DTR Signal State
-SET_CONTROL_DTR_ON = to_bytes([8])                  # Set DTR Signal State ON
-SET_CONTROL_DTR_OFF = to_bytes([9])                 # Set DTR Signal State OFF
-SET_CONTROL_REQ_RTS = to_bytes([10])                # Request RTS Signal State
-SET_CONTROL_RTS_ON = to_bytes([11])                 # Set RTS Signal State ON
-SET_CONTROL_RTS_OFF = to_bytes([12])                # Set RTS Signal State OFF
-SET_CONTROL_REQ_FLOW_SETTING_IN = to_bytes([13])    # Request Com Port Flow Control Setting (inbound)
-SET_CONTROL_USE_NO_FLOW_CONTROL_IN = to_bytes([14]) # Use No Flow Control (inbound)
-SET_CONTROL_USE_SW_FLOW_CONTOL_IN = to_bytes([15])  # Use XON/XOFF Flow Control (inbound)
-SET_CONTROL_USE_HW_FLOW_CONTOL_IN = to_bytes([16])  # Use HARDWARE Flow Control (inbound)
-SET_CONTROL_USE_DCD_FLOW_CONTROL = to_bytes([17])   # Use DCD Flow Control (outbound/both)
-SET_CONTROL_USE_DTR_FLOW_CONTROL = to_bytes([18])   # Use DTR Flow Control (inbound)
-SET_CONTROL_USE_DSR_FLOW_CONTROL = to_bytes([19])   # Use DSR Flow Control (outbound/both)
-
-LINESTATE_MASK_TIMEOUT = 128                # Time-out Error
-LINESTATE_MASK_SHIFTREG_EMPTY = 64          # Transfer Shift Register Empty
-LINESTATE_MASK_TRANSREG_EMPTY = 32          # Transfer Holding Register Empty
-LINESTATE_MASK_BREAK_DETECT = 16            # Break-detect Error
-LINESTATE_MASK_FRAMING_ERROR = 8            # Framing Error
-LINESTATE_MASK_PARTIY_ERROR = 4             # Parity Error
-LINESTATE_MASK_OVERRUN_ERROR = 2            # Overrun Error
-LINESTATE_MASK_DATA_READY = 1               # Data Ready
-
-MODEMSTATE_MASK_CD = 128                    # Receive Line Signal Detect (also known as Carrier Detect)
-MODEMSTATE_MASK_RI = 64                     # Ring Indicator
-MODEMSTATE_MASK_DSR = 32                    # Data-Set-Ready Signal State
-MODEMSTATE_MASK_CTS = 16                    # Clear-To-Send Signal State
-MODEMSTATE_MASK_CD_CHANGE = 8               # Delta Receive Line Signal Detect
-MODEMSTATE_MASK_RI_CHANGE = 4               # Trailing-edge Ring Detector
-MODEMSTATE_MASK_DSR_CHANGE = 2              # Delta Data-Set-Ready
-MODEMSTATE_MASK_CTS_CHANGE = 1              # Delta Clear-To-Send
-
-PURGE_RECEIVE_BUFFER = to_bytes([1])        # Purge access server receive data buffer
-PURGE_TRANSMIT_BUFFER = to_bytes([2])       # Purge access server transmit data buffer
-PURGE_BOTH_BUFFERS = to_bytes([3])          # Purge both the access server receive data buffer and the access server transmit data buffer
-
-
-RFC2217_PARITY_MAP = {
-    PARITY_NONE: 1,
-    PARITY_ODD: 2,
-    PARITY_EVEN: 3,
-    PARITY_MARK: 4,
-    PARITY_SPACE: 5,
-}
-RFC2217_REVERSE_PARITY_MAP = dict((v,k) for k,v in RFC2217_PARITY_MAP.items())
-
-RFC2217_STOPBIT_MAP = {
-    STOPBITS_ONE: 1,
-    STOPBITS_ONE_POINT_FIVE: 3,
-    STOPBITS_TWO: 2,
-}
-RFC2217_REVERSE_STOPBIT_MAP = dict((v,k) for k,v in RFC2217_STOPBIT_MAP.items())
-
-# Telnet filter states
-M_NORMAL = 0
-M_IAC_SEEN = 1
-M_NEGOTIATE = 2
-
-# TelnetOption and TelnetSubnegotiation states
-REQUESTED = 'REQUESTED'
-ACTIVE = 'ACTIVE'
-INACTIVE = 'INACTIVE'
-REALLY_INACTIVE = 'REALLY_INACTIVE'
-
-class TelnetOption(object):
-    """Manage a single telnet option, keeps track of DO/DONT WILL/WONT."""
-
-    def __init__(self, connection, name, option, send_yes, send_no, ack_yes, ack_no, initial_state, activation_callback=None):
-        """\
-        Initialize option.
-        :param connection: connection used to transmit answers
-        :param name: a readable name for debug outputs
-        :param send_yes: what to send when option is to be enabled.
-        :param send_no: what to send when option is to be disabled.
-        :param ack_yes: what to expect when remote agrees on option.
-        :param ack_no: what to expect when remote disagrees on option.
-        :param initial_state: options initialized with REQUESTED are tried to
-            be enabled on startup. use INACTIVE for all others.
-        """
-        self.connection = connection
-        self.name = name
-        self.option = option
-        self.send_yes = send_yes
-        self.send_no = send_no
-        self.ack_yes = ack_yes
-        self.ack_no = ack_no
-        self.state = initial_state
-        self.active = False
-        self.activation_callback = activation_callback
-
-    def __repr__(self):
-        """String for debug outputs"""
-        return "%s:%s(%s)" % (self.name, self.active, self.state)
-
-    def process_incoming(self, command):
-        """\
-        A DO/DONT/WILL/WONT was received for this option, update state and
-        answer when needed.
-        """
-        if command == self.ack_yes:
-            if self.state is REQUESTED:
-                self.state = ACTIVE
-                self.active = True
-                if self.activation_callback is not None:
-                    self.activation_callback()
-            elif self.state is ACTIVE:
-                pass
-            elif self.state is INACTIVE:
-                self.state = ACTIVE
-                self.connection.telnetSendOption(self.send_yes, self.option)
-                self.active = True
-                if self.activation_callback is not None:
-                    self.activation_callback()
-            elif self.state is REALLY_INACTIVE:
-                self.connection.telnetSendOption(self.send_no, self.option)
-            else:
-                raise ValueError('option in illegal state %r' % self)
-        elif command == self.ack_no:
-            if self.state is REQUESTED:
-                self.state = INACTIVE
-                self.active = False
-            elif self.state is ACTIVE:
-                self.state = INACTIVE
-                self.connection.telnetSendOption(self.send_no, self.option)
-                self.active = False
-            elif self.state is INACTIVE:
-                pass
-            elif self.state is REALLY_INACTIVE:
-                pass
-            else:
-                raise ValueError('option in illegal state %r' % self)
-
-
-class TelnetSubnegotiation(object):
-    """\
-    A object to handle subnegotiation of options. In this case actually
-    sub-sub options for RFC 2217. It is used to track com port options.
-    """
-
-    def __init__(self, connection, name, option, ack_option=None):
-        if ack_option is None: ack_option = option
-        self.connection = connection
-        self.name = name
-        self.option = option
-        self.value = None
-        self.ack_option = ack_option
-        self.state = INACTIVE
-
-    def __repr__(self):
-        """String for debug outputs."""
-        return "%s:%s" % (self.name, self.state)
-
-    def set(self, value):
-        """\
-        Request a change of the value. a request is sent to the server. if
-        the client needs to know if the change is performed he has to check the
-        state of this object.
-        """
-        self.value = value
-        self.state = REQUESTED
-        self.connection.rfc2217SendSubnegotiation(self.option, self.value)
-        if self.connection.logger:
-            self.connection.logger.debug("SB Requesting %s -> %r" % (self.name, self.value))
-
-    def isReady(self):
-        """\
-        Check if answer from server has been received. when server rejects
-        the change, raise a ValueError.
-        """
-        if self.state == REALLY_INACTIVE:
-            raise ValueError("remote rejected value for option %r" % (self.name))
-        return self.state == ACTIVE
-    # add property to have a similar interface as TelnetOption
-    active = property(isReady)
-
-    def wait(self, timeout=3):
-        """\
-        Wait until the subnegotiation has been acknowledged or timeout. It
-        can also throw a value error when the answer from the server does not
-        match the value sent.
-        """
-        timeout_time = time.time() + timeout
-        while time.time() < timeout_time:
-            if self.isReady():
-                break
-            time.sleep(0.001)    # prevent 100% CPU load
-        else:
-            raise SerialException("timeout while waiting for option %r" % (self.name))
-
-    def checkAnswer(self, suboption):
-        """\
-        Check an incoming subnegotiation block. The parameter already has
-        cut off the header like sub option number and com port option value.
-        """
-        if self.value == suboption[:len(self.value)]:
-            self.state = ACTIVE
-        else:
-            # error propagation done in isReady
-            self.state = REALLY_INACTIVE
-        if self.connection.logger:
-            self.connection.logger.debug("SB Answer %s -> %r -> %s" % (self.name, suboption, self.state))
-
-
-class RFC2217Serial(SerialBase):
-    """Serial port implementation for RFC 2217 remote serial ports."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        self.logger = None
-        self._ignore_set_control_answer = False
-        self._poll_modem_state = False
-        self._network_timeout = 3
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        try:
-            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            self._socket.connect(self.fromURL(self.portstr))
-            self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-        except Exception, msg:
-            self._socket = None
-            raise SerialException("Could not open port %s: %s" % (self.portstr, msg))
-
-        self._socket.settimeout(5) # XXX good value?
-
-        # use a thread save queue as buffer. it also simplifies implementing
-        # the read timeout
-        self._read_buffer = Queue.Queue()
-        # to ensure that user writes does not interfere with internal
-        # telnet/rfc2217 options establish a lock
-        self._write_lock = threading.Lock()
-        # name the following separately so that, below, a check can be easily done
-        mandadory_options = [
-            TelnetOption(self, 'we-BINARY', BINARY, WILL, WONT, DO, DONT, INACTIVE),
-            TelnetOption(self, 'we-RFC2217', COM_PORT_OPTION, WILL, WONT, DO, DONT, REQUESTED),
-        ]
-        # all supported telnet options
-        self._telnet_options = [
-            TelnetOption(self, 'ECHO', ECHO, DO, DONT, WILL, WONT, REQUESTED),
-            TelnetOption(self, 'we-SGA', SGA, WILL, WONT, DO, DONT, REQUESTED),
-            TelnetOption(self, 'they-SGA', SGA, DO, DONT, WILL, WONT, REQUESTED),
-            TelnetOption(self, 'they-BINARY', BINARY, DO, DONT, WILL, WONT, INACTIVE),
-            TelnetOption(self, 'they-RFC2217', COM_PORT_OPTION, DO, DONT, WILL, WONT, REQUESTED),
-        ] + mandadory_options
-        # RFC 2217 specific states
-        # COM port settings
-        self._rfc2217_port_settings = {
-            'baudrate': TelnetSubnegotiation(self, 'baudrate', SET_BAUDRATE, SERVER_SET_BAUDRATE),
-            'datasize': TelnetSubnegotiation(self, 'datasize', SET_DATASIZE, SERVER_SET_DATASIZE),
-            'parity':   TelnetSubnegotiation(self, 'parity',   SET_PARITY,   SERVER_SET_PARITY),
-            'stopsize': TelnetSubnegotiation(self, 'stopsize', SET_STOPSIZE, SERVER_SET_STOPSIZE),
-            }
-        # There are more subnegotiation objects, combine all in one dictionary
-        # for easy access
-        self._rfc2217_options = {
-            'purge':    TelnetSubnegotiation(self, 'purge',    PURGE_DATA,   SERVER_PURGE_DATA),
-            'control':  TelnetSubnegotiation(self, 'control',  SET_CONTROL,  SERVER_SET_CONTROL),
-            }
-        self._rfc2217_options.update(self._rfc2217_port_settings)
-        # cache for line and modem states that the server sends to us
-        self._linestate = 0
-        self._modemstate = None
-        self._modemstate_expires = 0
-        # RFC 2217 flow control between server and client
-        self._remote_suspend_flow = False
-
-        self._thread = threading.Thread(target=self._telnetReadLoop)
-        self._thread.setDaemon(True)
-        self._thread.setName('pySerial RFC 2217 reader thread for %s' % (self._port,))
-        self._thread.start()
-
-        # negotiate Telnet/RFC 2217 -> send initial requests
-        for option in self._telnet_options:
-            if option.state is REQUESTED:
-                self.telnetSendOption(option.send_yes, option.option)
-        # now wait until important options are negotiated
-        timeout_time = time.time() + self._network_timeout
-        while time.time() < timeout_time:
-            if sum(o.active for o in mandadory_options) == sum(o.state != INACTIVE for o in mandadory_options):
-                break
-            time.sleep(0.001)    # prevent 100% CPU load
-        else:
-            raise SerialException("Remote does not seem to support RFC2217 or BINARY mode %r" % mandadory_options)
-        if self.logger:
-            self.logger.info("Negotiated options: %s" % self._telnet_options)
-
-        # fine, go on, set RFC 2271 specific things
-        self._reconfigurePort()
-        # all things set up get, now a clean start
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """Set communication parameters on opened port."""
-        if self._socket is None:
-            raise SerialException("Can only operate on open ports")
-
-        # if self._timeout != 0 and self._interCharTimeout is not None:
-            # XXX
-
-        if self._writeTimeout is not None:
-            raise NotImplementedError('writeTimeout is currently not supported')
-            # XXX
-
-        # Setup the connection
-        # to get good performance, all parameter changes are sent first...
-        if not isinstance(self._baudrate, (int, long)) or not 0 < self._baudrate < 2**32:
-            raise ValueError("invalid baudrate: %r" % (self._baudrate))
-        self._rfc2217_port_settings['baudrate'].set(struct.pack('!I', self._baudrate))
-        self._rfc2217_port_settings['datasize'].set(struct.pack('!B', self._bytesize))
-        self._rfc2217_port_settings['parity'].set(struct.pack('!B', RFC2217_PARITY_MAP[self._parity]))
-        self._rfc2217_port_settings['stopsize'].set(struct.pack('!B', RFC2217_STOPBIT_MAP[self._stopbits]))
-
-        # and now wait until parameters are active
-        items = self._rfc2217_port_settings.values()
-        if self.logger:
-            self.logger.debug("Negotiating settings: %s" % (items,))
-        timeout_time = time.time() + self._network_timeout
-        while time.time() < timeout_time:
-            if sum(o.active for o in items) == len(items):
-                break
-            time.sleep(0.001)    # prevent 100% CPU load
-        else:
-            raise SerialException("Remote does not accept parameter change (RFC2217): %r" % items)
-        if self.logger:
-            self.logger.info("Negotiated settings: %s" % (items,))
-
-        if self._rtscts and self._xonxoff:
-            raise ValueError('xonxoff and rtscts together are not supported')
-        elif self._rtscts:
-            self.rfc2217SetControl(SET_CONTROL_USE_HW_FLOW_CONTROL)
-        elif self._xonxoff:
-            self.rfc2217SetControl(SET_CONTROL_USE_SW_FLOW_CONTROL)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_USE_NO_FLOW_CONTROL)
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self._socket:
-                try:
-                    self._socket.shutdown(socket.SHUT_RDWR)
-                    self._socket.close()
-                except:
-                    # ignore errors.
-                    pass
-                self._socket = None
-            if self._thread:
-                self._thread.join()
-            self._isOpen = False
-            # in case of quick reconnects, give the server some time
-            time.sleep(0.3)
-
-    def makeDeviceName(self, port):
-        raise SerialException("there is no sensible way to turn numbers into URLs")
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("rfc2217://"): url = url[10:]
-        try:
-            # is there a "path" (our options)?
-            if '/' in url:
-                # cut away options
-                url, options = url.split('/', 1)
-                # process options now, directly altering self
-                for option in options.split('/'):
-                    if '=' in option:
-                        option, value = option.split('=', 1)
-                    else:
-                        value = None
-                    if option == 'logging':
-                        logging.basicConfig()   # XXX is that good to call it here?
-                        self.logger = logging.getLogger('pySerial.rfc2217')
-                        self.logger.setLevel(LOGGER_LEVELS[value])
-                        self.logger.debug('enabled logging')
-                    elif option == 'ign_set_control':
-                        self._ignore_set_control_answer = True
-                    elif option == 'poll_modem':
-                        self._poll_modem_state = True
-                    elif option == 'timeout':
-                        self._network_timeout = float(value)
-                    else:
-                        raise ValueError('unknown option: %r' % (option,))
-            # get host and port
-            host, port = url.split(':', 1) # may raise ValueError because of unpacking
-            port = int(port)               # and this if it's not a number
-            if not 0 <= port < 65536: raise ValueError("port not in range 0...65535")
-        except ValueError, e:
-            raise SerialException('expected a string in the form "[rfc2217://]<host>:<port>[/option[/option...]]": %s' % e)
-        return (host, port)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._isOpen: raise portNotOpenError
-        return self._read_buffer.qsize()
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        data = bytearray()
-        try:
-            while len(data) < size:
-                if self._thread is None:
-                    raise SerialException('connection failed (reader thread died)')
-                data.append(self._read_buffer.get(True, self._timeout))
-        except Queue.Empty: # -> timeout
-            pass
-        return bytes(data)
-
-    def write(self, data):
-        """\
-        Output the given string over the serial port. Can block if the
-        connection is blocked. May raise SerialException if the connection is
-        closed.
-        """
-        if not self._isOpen: raise portNotOpenError
-        self._write_lock.acquire()
-        try:
-            try:
-                self._socket.sendall(to_bytes(data).replace(IAC, IAC_DOUBLED))
-            except socket.error, e:
-                raise SerialException("connection failed (socket error): %s" % e) # XXX what exception if socket connection fails
-        finally:
-            self._write_lock.release()
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        self.rfc2217SendPurge(PURGE_RECEIVE_BUFFER)
-        # empty read buffer
-        while self._read_buffer.qsize():
-            self._read_buffer.get(False)
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        self.rfc2217SendPurge(PURGE_TRANSMIT_BUFFER)
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-        self.setBreak(True)
-        time.sleep(duration)
-        self.setBreak(False)
-
-    def setBreak(self, level=True):
-        """\
-        Set break: Controls TXD. When active, to transmitting is
-        possible.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('set BREAK to %s' % ('inactive', 'active')[bool(level)])
-        if level:
-            self.rfc2217SetControl(SET_CONTROL_BREAK_ON)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_BREAK_OFF)
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('set RTS to %s' % ('inactive', 'active')[bool(level)])
-        if level:
-            self.rfc2217SetControl(SET_CONTROL_RTS_ON)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_RTS_OFF)
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('set DTR to %s' % ('inactive', 'active')[bool(level)])
-        if level:
-            self.rfc2217SetControl(SET_CONTROL_DTR_ON)
-        else:
-            self.rfc2217SetControl(SET_CONTROL_DTR_OFF)
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_CTS)
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_DSR)
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_RI)
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect."""
-        if not self._isOpen: raise portNotOpenError
-        return bool(self.getModemState() & MODEMSTATE_MASK_CD)
-
-    # - - - platform specific - - -
-    # None so far
-
-    # - - - RFC2217 specific - - -
-
-    def _telnetReadLoop(self):
-        """Read loop for the socket."""
-        mode = M_NORMAL
-        suboption = None
-        try:
-            while self._socket is not None:
-                try:
-                    data = self._socket.recv(1024)
-                except socket.timeout:
-                    # just need to get out of recv form time to time to check if
-                    # still alive
-                    continue
-                except socket.error, e:
-                    # connection fails -> terminate loop
-                    if self.logger:
-                        self.logger.debug("socket error in reader thread: %s" % (e,))
-                    break
-                if not data: break # lost connection
-                for byte in data:
-                    if mode == M_NORMAL:
-                        # interpret as command or as data
-                        if byte == IAC:
-                            mode = M_IAC_SEEN
-                        else:
-                            # store data in read buffer or sub option buffer
-                            # depending on state
-                            if suboption is not None:
-                                suboption.append(byte)
-                            else:
-                                self._read_buffer.put(byte)
-                    elif mode == M_IAC_SEEN:
-                        if byte == IAC:
-                            # interpret as command doubled -> insert character
-                            # itself
-                            if suboption is not None:
-                                suboption.append(IAC)
-                            else:
-                                self._read_buffer.put(IAC)
-                            mode = M_NORMAL
-                        elif byte == SB:
-                            # sub option start
-                            suboption = bytearray()
-                            mode = M_NORMAL
-                        elif byte == SE:
-                            # sub option end -> process it now
-                            self._telnetProcessSubnegotiation(bytes(suboption))
-                            suboption = None
-                            mode = M_NORMAL
-                        elif byte in (DO, DONT, WILL, WONT):
-                            # negotiation
-                            telnet_command = byte
-                            mode = M_NEGOTIATE
-                        else:
-                            # other telnet commands
-                            self._telnetProcessCommand(byte)
-                            mode = M_NORMAL
-                    elif mode == M_NEGOTIATE: # DO, DONT, WILL, WONT was received, option now following
-                        self._telnetNegotiateOption(telnet_command, byte)
-                        mode = M_NORMAL
-        finally:
-            self._thread = None
-            if self.logger:
-                self.logger.debug("read thread terminated")
-
-    # - incoming telnet commands and options
-
-    def _telnetProcessCommand(self, command):
-        """Process commands other than DO, DONT, WILL, WONT."""
-        # Currently none. RFC2217 only uses negotiation and subnegotiation.
-        if self.logger:
-            self.logger.warning("ignoring Telnet command: %r" % (command,))
-
-    def _telnetNegotiateOption(self, command, option):
-        """Process incoming DO, DONT, WILL, WONT."""
-        # check our registered telnet options and forward command to them
-        # they know themselves if they have to answer or not
-        known = False
-        for item in self._telnet_options:
-            # can have more than one match! as some options are duplicated for
-            # 'us' and 'them'
-            if item.option == option:
-                item.process_incoming(command)
-                known = True
-        if not known:
-            # handle unknown options
-            # only answer to positive requests and deny them
-            if command == WILL or command == DO:
-                self.telnetSendOption((command == WILL and DONT or WONT), option)
-                if self.logger:
-                    self.logger.warning("rejected Telnet option: %r" % (option,))
-
-
-    def _telnetProcessSubnegotiation(self, suboption):
-        """Process subnegotiation, the data between IAC SB and IAC SE."""
-        if suboption[0:1] == COM_PORT_OPTION:
-            if suboption[1:2] == SERVER_NOTIFY_LINESTATE and len(suboption) >= 3:
-                self._linestate = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("NOTIFY_LINESTATE: %s" % self._linestate)
-            elif suboption[1:2] == SERVER_NOTIFY_MODEMSTATE and len(suboption) >= 3:
-                self._modemstate = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("NOTIFY_MODEMSTATE: %s" % self._modemstate)
-                # update time when we think that a poll would make sense
-                self._modemstate_expires = time.time() + 0.3
-            elif suboption[1:2] == FLOWCONTROL_SUSPEND:
-                self._remote_suspend_flow = True
-            elif suboption[1:2] == FLOWCONTROL_RESUME:
-                self._remote_suspend_flow = False
-            else:
-                for item in self._rfc2217_options.values():
-                    if item.ack_option == suboption[1:2]:
-                        #~ print "processing COM_PORT_OPTION: %r" % list(suboption[1:])
-                        item.checkAnswer(bytes(suboption[2:]))
-                        break
-                else:
-                    if self.logger:
-                        self.logger.warning("ignoring COM_PORT_OPTION: %r" % (suboption,))
-        else:
-            if self.logger:
-                self.logger.warning("ignoring subnegotiation: %r" % (suboption,))
-
-    # - outgoing telnet commands and options
-
-    def _internal_raw_write(self, data):
-        """internal socket write with no data escaping. used to send telnet stuff."""
-        self._write_lock.acquire()
-        try:
-            self._socket.sendall(data)
-        finally:
-            self._write_lock.release()
-
-    def telnetSendOption(self, action, option):
-        """Send DO, DONT, WILL, WONT."""
-        self._internal_raw_write(to_bytes([IAC, action, option]))
-
-    def rfc2217SendSubnegotiation(self, option, value=''):
-        """Subnegotiation of RFC2217 parameters."""
-        value = value.replace(IAC, IAC_DOUBLED)
-        self._internal_raw_write(to_bytes([IAC, SB, COM_PORT_OPTION, option] + list(value) + [IAC, SE]))
-
-    def rfc2217SendPurge(self, value):
-        item = self._rfc2217_options['purge']
-        item.set(value) # transmit desired purge type
-        item.wait(self._network_timeout) # wait for acknowledge from the server
-
-    def rfc2217SetControl(self, value):
-        item = self._rfc2217_options['control']
-        item.set(value) # transmit desired control type
-        if self._ignore_set_control_answer:
-            # answers are ignored when option is set. compatibility mode for
-            # servers that answer, but not the expected one... (or no answer
-            # at all) i.e. sredird
-            time.sleep(0.1)  # this helps getting the unit tests passed
-        else:
-            item.wait(self._network_timeout)  # wait for acknowledge from the server
-
-    def rfc2217FlowServerReady(self):
-        """\
-        check if server is ready to receive data. block for some time when
-        not.
-        """
-        #~ if self._remote_suspend_flow:
-            #~ wait---
-
-    def getModemState(self):
-        """\
-        get last modem state (cached value. If value is "old", request a new
-        one. This cache helps that we don't issue to many requests when e.g. all
-        status lines, one after the other is queried by the user (getCTS, getDSR
-        etc.)
-        """
-        # active modem state polling enabled? is the value fresh enough?
-        if self._poll_modem_state and self._modemstate_expires < time.time():
-            if self.logger:
-                self.logger.debug('polling modem state')
-            # when it is older, request an update
-            self.rfc2217SendSubnegotiation(NOTIFY_MODEMSTATE)
-            timeout_time = time.time() + self._network_timeout
-            while time.time() < timeout_time:
-                # when expiration time is updated, it means that there is a new
-                # value
-                if self._modemstate_expires > time.time():
-                    if self.logger:
-                        self.logger.warning('poll for modem state failed')
-                    break
-                time.sleep(0.001)    # prevent 100% CPU load
-            # even when there is a timeout, do not generate an error just
-            # return the last known value. this way we can support buggy
-            # servers that do not respond to polls, but send automatic
-            # updates.
-        if self._modemstate is not None:
-            if self.logger:
-                self.logger.debug('using cached modem state')
-            return self._modemstate
-        else:
-            # never received a notification from the server
-            raise SerialException("remote sends no NOTIFY_MODEMSTATE")
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(RFC2217Serial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(RFC2217Serial, io.RawIOBase):
-        pass
-
-
-#############################################################################
-# The following is code that helps implementing an RFC 2217 server.
-
-class PortManager(object):
-    """\
-    This class manages the state of Telnet and RFC 2217. It needs a serial
-    instance and a connection to work with. Connection is expected to implement
-    a (thread safe) write function, that writes the string to the network.
-    """
-
-    def __init__(self, serial_port, connection, logger=None):
-        self.serial = serial_port
-        self.connection = connection
-        self.logger = logger
-        self._client_is_rfc2217 = False
-
-        # filter state machine
-        self.mode = M_NORMAL
-        self.suboption = None
-        self.telnet_command = None
-
-        # states for modem/line control events
-        self.modemstate_mask = 255
-        self.last_modemstate = None
-        self.linstate_mask = 0
-
-        # all supported telnet options
-        self._telnet_options = [
-            TelnetOption(self, 'ECHO', ECHO, WILL, WONT, DO, DONT, REQUESTED),
-            TelnetOption(self, 'we-SGA', SGA, WILL, WONT, DO, DONT, REQUESTED),
-            TelnetOption(self, 'they-SGA', SGA, DO, DONT, WILL, WONT, INACTIVE),
-            TelnetOption(self, 'we-BINARY', BINARY, WILL, WONT, DO, DONT, INACTIVE),
-            TelnetOption(self, 'they-BINARY', BINARY, DO, DONT, WILL, WONT, REQUESTED),
-            TelnetOption(self, 'we-RFC2217', COM_PORT_OPTION, WILL, WONT, DO, DONT, REQUESTED, self._client_ok),
-            TelnetOption(self, 'they-RFC2217', COM_PORT_OPTION, DO, DONT, WILL, WONT, INACTIVE, self._client_ok),
-            ]
-
-        # negotiate Telnet/RFC2217 -> send initial requests
-        if self.logger:
-            self.logger.debug("requesting initial Telnet/RFC 2217 options")
-        for option in self._telnet_options:
-            if option.state is REQUESTED:
-                self.telnetSendOption(option.send_yes, option.option)
-        # issue 1st modem state notification
-
-    def _client_ok(self):
-        """\
-        callback of telnet option. It gets called when option is activated.
-        This one here is used to detect when the client agrees on RFC 2217. A
-        flag is set so that other functions like check_modem_lines know if the
-        client is OK.
-        """
-        # The callback is used for we and they so if one party agrees, we're
-        # already happy. it seems not all servers do the negotiation correctly
-        # and i guess there are incorrect clients too.. so be happy if client
-        # answers one or the other positively.
-        self._client_is_rfc2217 = True
-        if self.logger:
-            self.logger.info("client accepts RFC 2217")
-        # this is to ensure that the client gets a notification, even if there
-        # was no change
-        self.check_modem_lines(force_notification=True)
-
-    # - outgoing telnet commands and options
-
-    def telnetSendOption(self, action, option):
-        """Send DO, DONT, WILL, WONT."""
-        self.connection.write(to_bytes([IAC, action, option]))
-
-    def rfc2217SendSubnegotiation(self, option, value=''):
-        """Subnegotiation of RFC 2217 parameters."""
-        value = value.replace(IAC, IAC_DOUBLED)
-        self.connection.write(to_bytes([IAC, SB, COM_PORT_OPTION, option] + list(value) + [IAC, SE]))
-
-    # - check modem lines, needs to be called periodically from user to
-    # establish polling
-
-    def check_modem_lines(self, force_notification=False):
-        modemstate = (
-            (self.serial.getCTS() and MODEMSTATE_MASK_CTS) |
-            (self.serial.getDSR() and MODEMSTATE_MASK_DSR) |
-            (self.serial.getRI() and MODEMSTATE_MASK_RI) |
-            (self.serial.getCD() and MODEMSTATE_MASK_CD)
-        )
-        # check what has changed
-        deltas = modemstate ^ (self.last_modemstate or 0) # when last is None -> 0
-        if deltas & MODEMSTATE_MASK_CTS:
-            modemstate |= MODEMSTATE_MASK_CTS_CHANGE
-        if deltas & MODEMSTATE_MASK_DSR:
-            modemstate |= MODEMSTATE_MASK_DSR_CHANGE
-        if deltas & MODEMSTATE_MASK_RI:
-            modemstate |= MODEMSTATE_MASK_RI_CHANGE
-        if deltas & MODEMSTATE_MASK_CD:
-            modemstate |= MODEMSTATE_MASK_CD_CHANGE
-        # if new state is different and the mask allows this change, send
-        # notification. suppress notifications when client is not rfc2217
-        if modemstate != self.last_modemstate or force_notification:
-            if (self._client_is_rfc2217 and (modemstate & self.modemstate_mask)) or force_notification:
-                self.rfc2217SendSubnegotiation(
-                    SERVER_NOTIFY_MODEMSTATE,
-                    to_bytes([modemstate & self.modemstate_mask])
-                    )
-                if self.logger:
-                    self.logger.info("NOTIFY_MODEMSTATE: %s" % (modemstate,))
-            # save last state, but forget about deltas.
-            # otherwise it would also notify about changing deltas which is
-            # probably not very useful
-            self.last_modemstate = modemstate & 0xf0
-
-    # - outgoing data escaping
-
-    def escape(self, data):
-        """\
-        This generator function is for the user. All outgoing data has to be
-        properly escaped, so that no IAC character in the data stream messes up
-        the Telnet state machine in the server.
-
-        socket.sendall(escape(data))
-        """
-        for byte in data:
-            if byte == IAC:
-                yield IAC
-                yield IAC
-            else:
-                yield byte
-
-    # - incoming data filter
-
-    def filter(self, data):
-        """\
-        Handle a bunch of incoming bytes. This is a generator. It will yield
-        all characters not of interest for Telnet/RFC 2217.
-
-        The idea is that the reader thread pushes data from the socket through
-        this filter:
-
-        for byte in filter(socket.recv(1024)):
-            # do things like CR/LF conversion/whatever
-            # and write data to the serial port
-            serial.write(byte)
-
-        (socket error handling code left as exercise for the reader)
-        """
-        for byte in data:
-            if self.mode == M_NORMAL:
-                # interpret as command or as data
-                if byte == IAC:
-                    self.mode = M_IAC_SEEN
-                else:
-                    # store data in sub option buffer or pass it to our
-                    # consumer depending on state
-                    if self.suboption is not None:
-                        self.suboption.append(byte)
-                    else:
-                        yield byte
-            elif self.mode == M_IAC_SEEN:
-                if byte == IAC:
-                    # interpret as command doubled -> insert character
-                    # itself
-                    if self.suboption is not None:
-                        self.suboption.append(byte)
-                    else:
-                        yield byte
-                    self.mode = M_NORMAL
-                elif byte == SB:
-                    # sub option start
-                    self.suboption = bytearray()
-                    self.mode = M_NORMAL
-                elif byte == SE:
-                    # sub option end -> process it now
-                    self._telnetProcessSubnegotiation(bytes(self.suboption))
-                    self.suboption = None
-                    self.mode = M_NORMAL
-                elif byte in (DO, DONT, WILL, WONT):
-                    # negotiation
-                    self.telnet_command = byte
-                    self.mode = M_NEGOTIATE
-                else:
-                    # other telnet commands
-                    self._telnetProcessCommand(byte)
-                    self.mode = M_NORMAL
-            elif self.mode == M_NEGOTIATE: # DO, DONT, WILL, WONT was received, option now following
-                self._telnetNegotiateOption(self.telnet_command, byte)
-                self.mode = M_NORMAL
-
-    # - incoming telnet commands and options
-
-    def _telnetProcessCommand(self, command):
-        """Process commands other than DO, DONT, WILL, WONT."""
-        # Currently none. RFC2217 only uses negotiation and subnegotiation.
-        if self.logger:
-            self.logger.warning("ignoring Telnet command: %r" % (command,))
-
-    def _telnetNegotiateOption(self, command, option):
-        """Process incoming DO, DONT, WILL, WONT."""
-        # check our registered telnet options and forward command to them
-        # they know themselves if they have to answer or not
-        known = False
-        for item in self._telnet_options:
-            # can have more than one match! as some options are duplicated for
-            # 'us' and 'them'
-            if item.option == option:
-                item.process_incoming(command)
-                known = True
-        if not known:
-            # handle unknown options
-            # only answer to positive requests and deny them
-            if command == WILL or command == DO:
-                self.telnetSendOption((command == WILL and DONT or WONT), option)
-                if self.logger:
-                    self.logger.warning("rejected Telnet option: %r" % (option,))
-
-
-    def _telnetProcessSubnegotiation(self, suboption):
-        """Process subnegotiation, the data between IAC SB and IAC SE."""
-        if suboption[0:1] == COM_PORT_OPTION:
-            if self.logger:
-                self.logger.debug('received COM_PORT_OPTION: %r' % (suboption,))
-            if suboption[1:2] == SET_BAUDRATE:
-                backup = self.serial.baudrate
-                try:
-                    (baudrate,) = struct.unpack("!I", suboption[2:6])
-                    if baudrate != 0:
-                        self.serial.baudrate = baudrate
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set baud rate: %s" % (e,))
-                    self.serial.baudrate = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s baud rate: %s" % (baudrate and 'set' or 'get', self.serial.baudrate))
-                self.rfc2217SendSubnegotiation(SERVER_SET_BAUDRATE, struct.pack("!I", self.serial.baudrate))
-            elif suboption[1:2] == SET_DATASIZE:
-                backup = self.serial.bytesize
-                try:
-                    (datasize,) = struct.unpack("!B", suboption[2:3])
-                    if datasize != 0:
-                        self.serial.bytesize = datasize
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set data size: %s" % (e,))
-                    self.serial.bytesize = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s data size: %s" % (datasize and 'set' or 'get', self.serial.bytesize))
-                self.rfc2217SendSubnegotiation(SERVER_SET_DATASIZE, struct.pack("!B", self.serial.bytesize))
-            elif suboption[1:2] == SET_PARITY:
-                backup = self.serial.parity
-                try:
-                    parity = struct.unpack("!B", suboption[2:3])[0]
-                    if parity != 0:
-                            self.serial.parity = RFC2217_REVERSE_PARITY_MAP[parity]
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set parity: %s" % (e,))
-                    self.serial.parity = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s parity: %s" % (parity and 'set' or 'get', self.serial.parity))
-                self.rfc2217SendSubnegotiation(
-                    SERVER_SET_PARITY,
-                    struct.pack("!B", RFC2217_PARITY_MAP[self.serial.parity])
-                    )
-            elif suboption[1:2] == SET_STOPSIZE:
-                backup = self.serial.stopbits
-                try:
-                    stopbits = struct.unpack("!B", suboption[2:3])[0]
-                    if stopbits != 0:
-                        self.serial.stopbits = RFC2217_REVERSE_STOPBIT_MAP[stopbits]
-                except ValueError, e:
-                    if self.logger:
-                        self.logger.error("failed to set stop bits: %s" % (e,))
-                    self.serial.stopbits = backup
-                else:
-                    if self.logger:
-                        self.logger.info("%s stop bits: %s" % (stopbits and 'set' or 'get', self.serial.stopbits))
-                self.rfc2217SendSubnegotiation(
-                    SERVER_SET_STOPSIZE,
-                    struct.pack("!B", RFC2217_STOPBIT_MAP[self.serial.stopbits])
-                    )
-            elif suboption[1:2] == SET_CONTROL:
-                if suboption[2:3] == SET_CONTROL_REQ_FLOW_SETTING:
-                    if self.serial.xonxoff:
-                        self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_SW_FLOW_CONTROL)
-                    elif self.serial.rtscts:
-                        self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_HW_FLOW_CONTROL)
-                    else:
-                        self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_NO_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_USE_NO_FLOW_CONTROL:
-                    self.serial.xonxoff = False
-                    self.serial.rtscts = False
-                    if self.logger:
-                        self.logger.info("changed flow control to None")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_NO_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_USE_SW_FLOW_CONTROL:
-                    self.serial.xonxoff = True
-                    if self.logger:
-                        self.logger.info("changed flow control to XON/XOFF")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_SW_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_USE_HW_FLOW_CONTROL:
-                    self.serial.rtscts = True
-                    if self.logger:
-                        self.logger.info("changed flow control to RTS/CTS")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_USE_HW_FLOW_CONTROL)
-                elif suboption[2:3] == SET_CONTROL_REQ_BREAK_STATE:
-                    if self.logger:
-                        self.logger.warning("requested break state - not implemented")
-                    pass # XXX needs cached value
-                elif suboption[2:3] == SET_CONTROL_BREAK_ON:
-                    self.serial.setBreak(True)
-                    if self.logger:
-                        self.logger.info("changed BREAK to active")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_BREAK_ON)
-                elif suboption[2:3] == SET_CONTROL_BREAK_OFF:
-                    self.serial.setBreak(False)
-                    if self.logger:
-                        self.logger.info("changed BREAK to inactive")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_BREAK_OFF)
-                elif suboption[2:3] == SET_CONTROL_REQ_DTR:
-                    if self.logger:
-                        self.logger.warning("requested DTR state - not implemented")
-                    pass # XXX needs cached value
-                elif suboption[2:3] == SET_CONTROL_DTR_ON:
-                    self.serial.setDTR(True)
-                    if self.logger:
-                        self.logger.info("changed DTR to active")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_DTR_ON)
-                elif suboption[2:3] == SET_CONTROL_DTR_OFF:
-                    self.serial.setDTR(False)
-                    if self.logger:
-                        self.logger.info("changed DTR to inactive")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_DTR_OFF)
-                elif suboption[2:3] == SET_CONTROL_REQ_RTS:
-                    if self.logger:
-                        self.logger.warning("requested RTS state - not implemented")
-                    pass # XXX needs cached value
-                    #~ self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_RTS_ON)
-                elif suboption[2:3] == SET_CONTROL_RTS_ON:
-                    self.serial.setRTS(True)
-                    if self.logger:
-                        self.logger.info("changed RTS to active")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_RTS_ON)
-                elif suboption[2:3] == SET_CONTROL_RTS_OFF:
-                    self.serial.setRTS(False)
-                    if self.logger:
-                        self.logger.info("changed RTS to inactive")
-                    self.rfc2217SendSubnegotiation(SERVER_SET_CONTROL, SET_CONTROL_RTS_OFF)
-                #~ elif suboption[2:3] == SET_CONTROL_REQ_FLOW_SETTING_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_NO_FLOW_CONTROL_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_SW_FLOW_CONTOL_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_HW_FLOW_CONTOL_IN:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_DCD_FLOW_CONTROL:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_DTR_FLOW_CONTROL:
-                #~ elif suboption[2:3] == SET_CONTROL_USE_DSR_FLOW_CONTROL:
-            elif suboption[1:2] == NOTIFY_LINESTATE:
-                # client polls for current state
-                self.rfc2217SendSubnegotiation(
-                    SERVER_NOTIFY_LINESTATE,
-                    to_bytes([0])   # sorry, nothing like that implemented
-                    )
-            elif suboption[1:2] == NOTIFY_MODEMSTATE:
-                if self.logger:
-                    self.logger.info("request for modem state")
-                # client polls for current state
-                self.check_modem_lines(force_notification=True)
-            elif suboption[1:2] == FLOWCONTROL_SUSPEND:
-                if self.logger:
-                    self.logger.info("suspend")
-                self._remote_suspend_flow = True
-            elif suboption[1:2] == FLOWCONTROL_RESUME:
-                if self.logger:
-                    self.logger.info("resume")
-                self._remote_suspend_flow = False
-            elif suboption[1:2] == SET_LINESTATE_MASK:
-                self.linstate_mask = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("line state mask: 0x%02x" % (self.linstate_mask,))
-            elif suboption[1:2] == SET_MODEMSTATE_MASK:
-                self.modemstate_mask = ord(suboption[2:3]) # ensure it is a number
-                if self.logger:
-                    self.logger.info("modem state mask: 0x%02x" % (self.modemstate_mask,))
-            elif suboption[1:2] == PURGE_DATA:
-                if suboption[2:3] == PURGE_RECEIVE_BUFFER:
-                    self.serial.flushInput()
-                    if self.logger:
-                        self.logger.info("purge in")
-                    self.rfc2217SendSubnegotiation(SERVER_PURGE_DATA, PURGE_RECEIVE_BUFFER)
-                elif suboption[2:3] == PURGE_TRANSMIT_BUFFER:
-                    self.serial.flushOutput()
-                    if self.logger:
-                        self.logger.info("purge out")
-                    self.rfc2217SendSubnegotiation(SERVER_PURGE_DATA, PURGE_TRANSMIT_BUFFER)
-                elif suboption[2:3] == PURGE_BOTH_BUFFERS:
-                    self.serial.flushInput()
-                    self.serial.flushOutput()
-                    if self.logger:
-                        self.logger.info("purge both")
-                    self.rfc2217SendSubnegotiation(SERVER_PURGE_DATA, PURGE_BOTH_BUFFERS)
-                else:
-                    if self.logger:
-                        self.logger.error("undefined PURGE_DATA: %r" % list(suboption[2:]))
-            else:
-                if self.logger:
-                    self.logger.error("undefined COM_PORT_OPTION: %r" % list(suboption[1:]))
-        else:
-            if self.logger:
-                self.logger.warning("unknown subnegotiation: %r" % (suboption,))
-
-
-# simple client test
-if __name__ == '__main__':
-    import sys
-    s = Serial('rfc2217://localhost:7000', 115200)
-    sys.stdout.write('%s\n' % s)
-
-    #~ s.baudrate = 1898
-
-    sys.stdout.write("write...\n")
-    s.write("hello\n")
-    s.flush()
-    sys.stdout.write("read: %s\n" % s.read(5))
-
-    #~ s.baudrate = 19200
-    #~ s.databits = 7
-    s.close()
diff --git a/scripts/serial/serialcli.py b/scripts/serial/serialcli.py
deleted file mode 100644
index 9ab3876206..0000000000
--- a/scripts/serial/serialcli.py
+++ /dev/null
@@ -1,284 +0,0 @@
-#! python
-# Python Serial Port Extension for Win32, Linux, BSD, Jython and .NET/Mono
-# serial driver for .NET/Mono (IronPython), .NET >= 2
-# see __init__.py
-#
-# (C) 2008 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-import clr
-import System
-import System.IO.Ports
-from serial.serialutil import *
-
-
-def device(portnum):
-    """Turn a port number into a device name"""
-    return System.IO.Ports.SerialPort.GetPortNames()[portnum]
-
-
-# must invoke function with byte array, make a helper to convert strings
-# to byte arrays
-sab = System.Array[System.Byte]
-def as_byte_array(string):
-    return sab([ord(x) for x in string])  # XXX will require adaption when run with a 3.x compatible IronPython
-
-class IronSerial(SerialBase):
-    """Serial port implementation for .NET/Mono."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        try:
-            self._port_handle = System.IO.Ports.SerialPort(self.portstr)
-        except Exception, msg:
-            self._port_handle = None
-            raise SerialException("could not open port %s: %s" % (self.portstr, msg))
-
-        self._reconfigurePort()
-        self._port_handle.Open()
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """Set communication parameters on opened port."""
-        if not self._port_handle:
-            raise SerialException("Can only operate on a valid port handle")
-
-        #~ self._port_handle.ReceivedBytesThreshold = 1
-
-        if self._timeout is None:
-            self._port_handle.ReadTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
-        else:
-            self._port_handle.ReadTimeout = int(self._timeout*1000)
-
-        # if self._timeout != 0 and self._interCharTimeout is not None:
-            # timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
-
-        if self._writeTimeout is None:
-            self._port_handle.WriteTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
-        else:
-            self._port_handle.WriteTimeout = int(self._writeTimeout*1000)
-
-
-        # Setup the connection info.
-        try:
-            self._port_handle.BaudRate = self._baudrate
-        except IOError, e:
-            # catch errors from illegal baudrate settings
-            raise ValueError(str(e))
-
-        if self._bytesize == FIVEBITS:
-            self._port_handle.DataBits     = 5
-        elif self._bytesize == SIXBITS:
-            self._port_handle.DataBits     = 6
-        elif self._bytesize == SEVENBITS:
-            self._port_handle.DataBits     = 7
-        elif self._bytesize == EIGHTBITS:
-            self._port_handle.DataBits     = 8
-        else:
-            raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
-
-        if self._parity == PARITY_NONE:
-            self._port_handle.Parity       = getattr(System.IO.Ports.Parity, 'None') # reserved keyword in Py3k
-        elif self._parity == PARITY_EVEN:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Even
-        elif self._parity == PARITY_ODD:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Odd
-        elif self._parity == PARITY_MARK:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Mark
-        elif self._parity == PARITY_SPACE:
-            self._port_handle.Parity       = System.IO.Ports.Parity.Space
-        else:
-            raise ValueError("Unsupported parity mode: %r" % self._parity)
-
-        if self._stopbits == STOPBITS_ONE:
-            self._port_handle.StopBits     = System.IO.Ports.StopBits.One
-        elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
-            self._port_handle.StopBits     = System.IO.Ports.StopBits.OnePointFive
-        elif self._stopbits == STOPBITS_TWO:
-            self._port_handle.StopBits     = System.IO.Ports.StopBits.Two
-        else:
-            raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
-
-        if self._rtscts and self._xonxoff:
-            self._port_handle.Handshake  = System.IO.Ports.Handshake.RequestToSendXOnXOff
-        elif self._rtscts:
-            self._port_handle.Handshake  = System.IO.Ports.Handshake.RequestToSend
-        elif self._xonxoff:
-            self._port_handle.Handshake  = System.IO.Ports.Handshake.XOnXOff
-        else:
-            self._port_handle.Handshake  = getattr(System.IO.Ports.Handshake, 'None')   # reserved keyword in Py3k
-
-    #~ def __del__(self):
-        #~ self.close()
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self._port_handle:
-                try:
-                    self._port_handle.Close()
-                except System.IO.Ports.InvalidOperationException:
-                    # ignore errors. can happen for unplugged USB serial devices
-                    pass
-                self._port_handle = None
-            self._isOpen = False
-
-    def makeDeviceName(self, port):
-        try:
-            return device(port)
-        except TypeError, e:
-            raise SerialException(str(e))
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.BytesToRead
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._port_handle: raise portNotOpenError
-        # must use single byte reads as this is the only way to read
-        # without applying encodings
-        data = bytearray()
-        while size:
-            try:
-                data.append(self._port_handle.ReadByte())
-            except System.TimeoutException, e:
-                break
-            else:
-                size -= 1
-        return bytes(data)
-
-    def write(self, data):
-        """Output the given string over the serial port."""
-        if not self._port_handle: raise portNotOpenError
-        #~ if not isinstance(data, (bytes, bytearray)):
-            #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
-        try:
-            # must call overloaded method with byte array argument
-            # as this is the only one not applying encodings
-            self._port_handle.Write(as_byte_array(data), 0, len(data))
-        except System.TimeoutException, e:
-            raise writeTimeoutError
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.DiscardInBuffer()
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.DiscardOutBuffer()
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._port_handle: raise portNotOpenError
-        import time
-        self._port_handle.BreakState = True
-        time.sleep(duration)
-        self._port_handle.BreakState = False
-
-    def setBreak(self, level=True):
-        """
-        Set break: Controls TXD. When active, to transmitting is possible.
-        """
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.BreakState = bool(level)
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send"""
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.RtsEnable = bool(level)
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._port_handle: raise portNotOpenError
-        self._port_handle.DtrEnable = bool(level)
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.CtsHolding
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.DsrHolding
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._port_handle: raise portNotOpenError
-        #~ return self._port_handle.XXX
-        return False #XXX an error would be better
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._port_handle: raise portNotOpenError
-        return self._port_handle.CDHolding
-
-    # - - platform specific - - - -
-    # none
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(IronSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(IronSerial, io.RawIOBase):
-        pass
-
-
-# Nur Testfunktion!!
-if __name__ == '__main__':
-    import sys
-
-    s = Serial(0)
-    sys.stdio.write('%s\n' % s)
-
-    s = Serial()
-    sys.stdio.write('%s\n' % s)
-
-
-    s.baudrate = 19200
-    s.databits = 7
-    s.close()
-    s.port = 0
-    s.open()
-    sys.stdio.write('%s\n' % s)
-
diff --git a/scripts/serial/serialposix.py b/scripts/serial/serialposix.py
deleted file mode 100644
index 359ad1b877..0000000000
--- a/scripts/serial/serialposix.py
+++ /dev/null
@@ -1,730 +0,0 @@
-#!/usr/bin/env python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# module for serial IO for POSIX compatible systems, like Linux
-# see __init__.py
-#
-# (C) 2001-2010 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# parts based on code from Grant B. Edwards  <grante at visi.com>:
-#  ftp://ftp.visi.com/users/grante/python/PosixSerial.py
-#
-# references: http://www.easysw.com/~mike/serial/serial.html
-
-import sys, os, fcntl, termios, struct, select, errno, time
-from serial.serialutil import *
-
-# Do check the Python version as some constants have moved.
-if (sys.hexversion < 0x020100f0):
-    import TERMIOS
-else:
-    TERMIOS = termios
-
-if (sys.hexversion < 0x020200f0):
-    import FCNTL
-else:
-    FCNTL = fcntl
-
-# try to detect the OS so that a device can be selected...
-# this code block should supply a device() and set_special_baudrate() function
-# for the platform
-plat = sys.platform.lower()
-
-if   plat[:5] == 'linux':    # Linux (confirmed)
-
-    def device(port):
-        return '/dev/ttyS%d' % port
-
-    TCGETS2 = 0x802C542A
-    TCSETS2 = 0x402C542B
-    BOTHER = 0o010000
-
-    def set_special_baudrate(port, baudrate):
-        # right size is 44 on x86_64, allow for some growth
-        import array
-        buf = array.array('i', [0] * 64)
-
-        try:
-            # get serial_struct
-            FCNTL.ioctl(port.fd, TCGETS2, buf)
-            # set custom speed
-            buf[2] &= ~TERMIOS.CBAUD
-            buf[2] |= BOTHER
-            buf[9] = buf[10] = baudrate
-
-            # set serial_struct
-            res = FCNTL.ioctl(port.fd, TCSETS2, buf)
-        except IOError, e:
-            raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
-
-    baudrate_constants = {
-        0:       0000000,  # hang up
-        50:      0000001,
-        75:      0000002,
-        110:     0000003,
-        134:     0000004,
-        150:     0000005,
-        200:     0000006,
-        300:     0000007,
-        600:     0000010,
-        1200:    0000011,
-        1800:    0000012,
-        2400:    0000013,
-        4800:    0000014,
-        9600:    0000015,
-        19200:   0000016,
-        38400:   0000017,
-        57600:   0010001,
-        115200:  0010002,
-        230400:  0010003,
-        460800:  0010004,
-        500000:  0010005,
-        576000:  0010006,
-        921600:  0010007,
-        1000000: 0010010,
-        1152000: 0010011,
-        1500000: 0010012,
-        2000000: 0010013,
-        2500000: 0010014,
-        3000000: 0010015,
-        3500000: 0010016,
-        4000000: 0010017
-    }
-
-elif plat == 'cygwin':       # cygwin/win32 (confirmed)
-
-    def device(port):
-        return '/dev/com%d' % (port + 1)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {
-        128000: 0x01003,
-        256000: 0x01005,
-        500000: 0x01007,
-        576000: 0x01008,
-        921600: 0x01009,
-        1000000: 0x0100a,
-        1152000: 0x0100b,
-        1500000: 0x0100c,
-        2000000: 0x0100d,
-        2500000: 0x0100e,
-        3000000: 0x0100f
-    }
-
-elif plat[:7] == 'openbsd':    # OpenBSD
-
-    def device(port):
-        return '/dev/cua%02d' % port
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:3] == 'bsd' or  \
-    plat[:7] == 'freebsd':
-
-    def device(port):
-        return '/dev/cuad%d' % port
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:6] == 'darwin':   # OS X
-
-    version = os.uname()[2].split('.')
-    # Tiger or above can support arbitrary serial speeds
-    if int(version[0]) >= 8:
-        def set_special_baudrate(port, baudrate):
-            # use IOKit-specific call to set up high speeds
-            import array, fcntl
-            buf = array.array('i', [baudrate])
-            IOSSIOSPEED = 0x80045402 #_IOW('T', 2, speed_t)
-            fcntl.ioctl(port.fd, IOSSIOSPEED, buf, 1)
-    else: # version < 8
-        def set_special_baudrate(port, baudrate):
-            raise ValueError("baud rate not supported")
-
-    def device(port):
-        return '/dev/cuad%d' % port
-
-    baudrate_constants = {}
-
-
-elif plat[:6] == 'netbsd':   # NetBSD 1.6 testing by Erk
-
-    def device(port):
-        return '/dev/dty%02d' % port
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:4] == 'irix':     # IRIX (partially tested)
-
-    def device(port):
-        return '/dev/ttyf%d' % (port+1) #XXX different device names depending on flow control
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:2] == 'hp':       # HP-UX (not tested)
-
-    def device(port):
-        return '/dev/tty%dp0' % (port+1)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:5] == 'sunos':    # Solaris/SunOS (confirmed)
-
-    def device(port):
-        return '/dev/tty%c' % (ord('a')+port)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-elif plat[:3] == 'aix':      # AIX
-
-    def device(port):
-        return '/dev/tty%d' % (port)
-
-    def set_special_baudrate(port, baudrate):
-        raise ValueError("sorry don't know how to handle non standard baud rate on this platform")
-
-    baudrate_constants = {}
-
-else:
-    # platform detection has failed...
-    sys.stderr.write("""\
-don't know how to number ttys on this system.
-! Use an explicit path (eg /dev/ttyS1) or send this information to
-! the author of this module:
-
-sys.platform = %r
-os.name = %r
-serialposix.py version = %s
-
-also add the device name of the serial port and where the
-counting starts for the first serial port.
-e.g. 'first serial port: /dev/ttyS0'
-and with a bit luck you can get this module running...
-""" % (sys.platform, os.name, VERSION))
-    # no exception, just continue with a brave attempt to build a device name
-    # even if the device name is not correct for the platform it has chances
-    # to work using a string with the real device name as port parameter.
-    def device(portum):
-        return '/dev/ttyS%d' % portnum
-    def set_special_baudrate(port, baudrate):
-        raise SerialException("sorry don't know how to handle non standard baud rate on this platform")
-    baudrate_constants = {}
-    #~ raise Exception, "this module does not run on this platform, sorry."
-
-# whats up with "aix", "beos", ....
-# they should work, just need to know the device names.
-
-
-# load some constants for later use.
-# try to use values from TERMIOS, use defaults from linux otherwise
-TIOCMGET  = hasattr(TERMIOS, 'TIOCMGET') and TERMIOS.TIOCMGET or 0x5415
-TIOCMBIS  = hasattr(TERMIOS, 'TIOCMBIS') and TERMIOS.TIOCMBIS or 0x5416
-TIOCMBIC  = hasattr(TERMIOS, 'TIOCMBIC') and TERMIOS.TIOCMBIC or 0x5417
-TIOCMSET  = hasattr(TERMIOS, 'TIOCMSET') and TERMIOS.TIOCMSET or 0x5418
-
-#TIOCM_LE = hasattr(TERMIOS, 'TIOCM_LE') and TERMIOS.TIOCM_LE or 0x001
-TIOCM_DTR = hasattr(TERMIOS, 'TIOCM_DTR') and TERMIOS.TIOCM_DTR or 0x002
-TIOCM_RTS = hasattr(TERMIOS, 'TIOCM_RTS') and TERMIOS.TIOCM_RTS or 0x004
-#TIOCM_ST = hasattr(TERMIOS, 'TIOCM_ST') and TERMIOS.TIOCM_ST or 0x008
-#TIOCM_SR = hasattr(TERMIOS, 'TIOCM_SR') and TERMIOS.TIOCM_SR or 0x010
-
-TIOCM_CTS = hasattr(TERMIOS, 'TIOCM_CTS') and TERMIOS.TIOCM_CTS or 0x020
-TIOCM_CAR = hasattr(TERMIOS, 'TIOCM_CAR') and TERMIOS.TIOCM_CAR or 0x040
-TIOCM_RNG = hasattr(TERMIOS, 'TIOCM_RNG') and TERMIOS.TIOCM_RNG or 0x080
-TIOCM_DSR = hasattr(TERMIOS, 'TIOCM_DSR') and TERMIOS.TIOCM_DSR or 0x100
-TIOCM_CD  = hasattr(TERMIOS, 'TIOCM_CD') and TERMIOS.TIOCM_CD or TIOCM_CAR
-TIOCM_RI  = hasattr(TERMIOS, 'TIOCM_RI') and TERMIOS.TIOCM_RI or TIOCM_RNG
-#TIOCM_OUT1 = hasattr(TERMIOS, 'TIOCM_OUT1') and TERMIOS.TIOCM_OUT1 or 0x2000
-#TIOCM_OUT2 = hasattr(TERMIOS, 'TIOCM_OUT2') and TERMIOS.TIOCM_OUT2 or 0x4000
-if hasattr(TERMIOS, 'TIOCINQ'):
-    TIOCINQ = TERMIOS.TIOCINQ
-else:
-    TIOCINQ = hasattr(TERMIOS, 'FIONREAD') and TERMIOS.FIONREAD or 0x541B
-TIOCOUTQ   = hasattr(TERMIOS, 'TIOCOUTQ') and TERMIOS.TIOCOUTQ or 0x5411
-
-TIOCM_zero_str = struct.pack('I', 0)
-TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
-TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
-
-TIOCSBRK  = hasattr(TERMIOS, 'TIOCSBRK') and TERMIOS.TIOCSBRK or 0x5427
-TIOCCBRK  = hasattr(TERMIOS, 'TIOCCBRK') and TERMIOS.TIOCCBRK or 0x5428
-
-CMSPAR = 010000000000 # Use "stick" (mark/space) parity
-
-
-class PosixSerial(SerialBase):
-    """\
-    Serial port class POSIX implementation. Serial port configuration is 
-    done with termios and fcntl. Runs on Linux and many other Un*x like
-    systems.
-    """
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened."""
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        self.fd = None
-        # open
-        try:
-            self.fd = os.open(self.portstr, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK)
-        except OSError, msg:
-            self.fd = None
-            raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
-        #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0)  # set blocking
-
-        try:
-            self._reconfigurePort()
-        except:
-            try:
-                os.close(self.fd)
-            except:
-                # ignore any exception when closing the port
-                # also to keep original exception that happened when setting up
-                pass
-            self.fd = None
-            raise
-        else:
-            self._isOpen = True
-        self.flushInput()
-
-
-    def _reconfigurePort(self):
-        """Set communication parameters on opened port."""
-        if self.fd is None:
-            raise SerialException("Can only operate on a valid file descriptor")
-        custom_baud = None
-
-        vmin = vtime = 0                # timeout is done via select
-        if self._interCharTimeout is not None:
-            vmin = 1
-            vtime = int(self._interCharTimeout * 10)
-        try:
-            orig_attr = termios.tcgetattr(self.fd)
-            iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
-        except termios.error, msg:      # if a port is nonexistent but has a /dev file, it'll fail here
-            raise SerialException("Could not configure port: %s" % msg)
-        # set up raw mode / no echo / binary
-        cflag |=  (TERMIOS.CLOCAL|TERMIOS.CREAD)
-        lflag &= ~(TERMIOS.ICANON|TERMIOS.ECHO|TERMIOS.ECHOE|TERMIOS.ECHOK|TERMIOS.ECHONL|
-                     TERMIOS.ISIG|TERMIOS.IEXTEN) #|TERMIOS.ECHOPRT
-        for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
-            if hasattr(TERMIOS, flag):
-                lflag &= ~getattr(TERMIOS, flag)
-
-        oflag &= ~(TERMIOS.OPOST)
-        iflag &= ~(TERMIOS.INLCR|TERMIOS.IGNCR|TERMIOS.ICRNL|TERMIOS.IGNBRK)
-        if hasattr(TERMIOS, 'IUCLC'):
-            iflag &= ~TERMIOS.IUCLC
-        if hasattr(TERMIOS, 'PARMRK'):
-            iflag &= ~TERMIOS.PARMRK
-
-        # setup baud rate
-        try:
-            ispeed = ospeed = getattr(TERMIOS, 'B%s' % (self._baudrate))
-        except AttributeError:
-            try:
-                ispeed = ospeed = baudrate_constants[self._baudrate]
-            except KeyError:
-                #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
-                # may need custom baud rate, it isn't in our list.
-                ispeed = ospeed = getattr(TERMIOS, 'B38400')
-                try:
-                    custom_baud = int(self._baudrate) # store for later
-                except ValueError:
-                    raise ValueError('Invalid baud rate: %r' % self._baudrate)
-                else:
-                    if custom_baud < 0:
-                        raise ValueError('Invalid baud rate: %r' % self._baudrate)
-
-        # setup char len
-        cflag &= ~TERMIOS.CSIZE
-        if self._bytesize == 8:
-            cflag |= TERMIOS.CS8
-        elif self._bytesize == 7:
-            cflag |= TERMIOS.CS7
-        elif self._bytesize == 6:
-            cflag |= TERMIOS.CS6
-        elif self._bytesize == 5:
-            cflag |= TERMIOS.CS5
-        else:
-            raise ValueError('Invalid char len: %r' % self._bytesize)
-        # setup stop bits
-        if self._stopbits == STOPBITS_ONE:
-            cflag &= ~(TERMIOS.CSTOPB)
-        elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
-            cflag |=  (TERMIOS.CSTOPB)  # XXX same as TWO.. there is no POSIX support for 1.5
-        elif self._stopbits == STOPBITS_TWO:
-            cflag |=  (TERMIOS.CSTOPB)
-        else:
-            raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
-        # setup parity
-        iflag &= ~(TERMIOS.INPCK|TERMIOS.ISTRIP)
-        if self._parity == PARITY_NONE:
-            cflag &= ~(TERMIOS.PARENB|TERMIOS.PARODD)
-        elif self._parity == PARITY_EVEN:
-            cflag &= ~(TERMIOS.PARODD)
-            cflag |=  (TERMIOS.PARENB)
-        elif self._parity == PARITY_ODD:
-            cflag |=  (TERMIOS.PARENB|TERMIOS.PARODD)
-        elif self._parity == PARITY_MARK and plat[:5] == 'linux':
-            cflag |=  (TERMIOS.PARENB|CMSPAR|TERMIOS.PARODD)
-        elif self._parity == PARITY_SPACE and plat[:5] == 'linux':
-            cflag |=  (TERMIOS.PARENB|CMSPAR)
-            cflag &= ~(TERMIOS.PARODD)
-        else:
-            raise ValueError('Invalid parity: %r' % self._parity)
-        # setup flow control
-        # xonxoff
-        if hasattr(TERMIOS, 'IXANY'):
-            if self._xonxoff:
-                iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY)
-            else:
-                iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY)
-        else:
-            if self._xonxoff:
-                iflag |=  (TERMIOS.IXON|TERMIOS.IXOFF)
-            else:
-                iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF)
-        # rtscts
-        if hasattr(TERMIOS, 'CRTSCTS'):
-            if self._rtscts:
-                cflag |=  (TERMIOS.CRTSCTS)
-            else:
-                cflag &= ~(TERMIOS.CRTSCTS)
-        elif hasattr(TERMIOS, 'CNEW_RTSCTS'):   # try it with alternate constant name
-            if self._rtscts:
-                cflag |=  (TERMIOS.CNEW_RTSCTS)
-            else:
-                cflag &= ~(TERMIOS.CNEW_RTSCTS)
-        # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
-
-        # buffer
-        # vmin "minimal number of characters to be read. 0 for non blocking"
-        if vmin < 0 or vmin > 255:
-            raise ValueError('Invalid vmin: %r ' % vmin)
-        cc[TERMIOS.VMIN] = vmin
-        # vtime
-        if vtime < 0 or vtime > 255:
-            raise ValueError('Invalid vtime: %r' % vtime)
-        cc[TERMIOS.VTIME] = vtime
-        # activate settings
-        if [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
-            termios.tcsetattr(self.fd, TERMIOS.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
-
-        # apply custom baud rate, if any
-        if custom_baud is not None:
-            set_special_baudrate(self, custom_baud)
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self.fd is not None:
-                os.close(self.fd)
-                self.fd = None
-            self._isOpen = False
-
-    def makeDeviceName(self, port):
-        return device(port)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
-        s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
-        return struct.unpack('I',s)[0]
-
-    # select based implementation, proved to work on many systems
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        read = bytearray()
-        while len(read) < size:
-            try:
-                ready,_,_ = select.select([self.fd],[],[], self._timeout)
-                # If select was used with a timeout, and the timeout occurs, it
-                # returns with empty lists -> thus abort read operation.
-                # For timeout == 0 (non-blocking operation) also abort when there
-                # is nothing to read.
-                if not ready:
-                    break   # timeout
-                buf = os.read(self.fd, size-len(read))
-                # read should always return some data as select reported it was
-                # ready to read when we get to this point.
-                if not buf:
-                    # Disconnected devices, at least on Linux, show the
-                    # behavior that they are always ready to read immediately
-                    # but reading returns nothing.
-                    raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
-                read.extend(buf)
-            except OSError, e:
-                # this is for Python 3.x where select.error is a subclass of OSError
-                # ignore EAGAIN errors. all other errors are shown
-                if e.errno != errno.EAGAIN:
-                    raise SerialException('read failed: %s' % (e,))
-            except select.error, e:
-                # this is for Python 2.x
-                # ignore EAGAIN errors. all other errors are shown
-                # see also http://www.python.org/dev/peps/pep-3151/#select
-                if e[0] != errno.EAGAIN:
-                    raise SerialException('read failed: %s' % (e,))
-        return bytes(read)
-
-    def write(self, data):
-        """Output the given string over the serial port."""
-        if not self._isOpen: raise portNotOpenError
-        d = to_bytes(data)
-        tx_len = len(d)
-        if self._writeTimeout is not None and self._writeTimeout > 0:
-            timeout = time.time() + self._writeTimeout
-        else:
-            timeout = None
-        while tx_len > 0:
-            try:
-                n = os.write(self.fd, d)
-                if timeout:
-                    # when timeout is set, use select to wait for being ready
-                    # with the time left as timeout
-                    timeleft = timeout - time.time()
-                    if timeleft < 0:
-                        raise writeTimeoutError
-                    _, ready, _ = select.select([], [self.fd], [], timeleft)
-                    if not ready:
-                        raise writeTimeoutError
-                else:
-                    # wait for write operation
-                    _, ready, _ = select.select([], [self.fd], [], None)
-                    if not ready:
-                        raise SerialException('write failed (select)')
-                d = d[n:]
-                tx_len -= n
-            except OSError, v:
-                if v.errno != errno.EAGAIN:
-                    raise SerialException('write failed: %s' % (v,))
-        return len(data)
-
-    def flush(self):
-        """\
-        Flush of file like objects. In this case, wait until all data
-        is written.
-        """
-        self.drainOutput()
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        termios.tcflush(self.fd, TERMIOS.TCIFLUSH)
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and discarding all
-        that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        termios.tcflush(self.fd, TERMIOS.TCOFLUSH)
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-        termios.tcsendbreak(self.fd, int(duration/0.25))
-
-    def setBreak(self, level=1):
-        """\
-        Set break: Controls TXD. When active, no transmitting is possible.
-        """
-        if self.fd is None: raise portNotOpenError
-        if level:
-            fcntl.ioctl(self.fd, TIOCSBRK)
-        else:
-            fcntl.ioctl(self.fd, TIOCCBRK)
-
-    def setRTS(self, level=1):
-        """Set terminal status line: Request To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if level:
-            fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
-        else:
-            fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
-
-    def setDTR(self, level=1):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if level:
-            fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
-        else:
-            fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_CTS != 0
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_DSR != 0
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_RI != 0
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._isOpen: raise portNotOpenError
-        s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
-        return struct.unpack('I',s)[0] & TIOCM_CD != 0
-
-    # - - platform specific - - - -
-
-    def outWaiting(self):
-        """Return the number of characters currently in the output buffer."""
-        #~ s = fcntl.ioctl(self.fd, TERMIOS.FIONREAD, TIOCM_zero_str)
-        s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
-        return struct.unpack('I',s)[0]
-
-    def drainOutput(self):
-        """internal - not portable!"""
-        if not self._isOpen: raise portNotOpenError
-        termios.tcdrain(self.fd)
-
-    def nonblocking(self):
-        """internal - not portable!"""
-        if not self._isOpen: raise portNotOpenError
-        fcntl.fcntl(self.fd, FCNTL.F_SETFL, os.O_NONBLOCK)
-
-    def fileno(self):
-        """\
-        For easier use of the serial port instance with select.
-        WARNING: this function is not portable to different platforms!
-        """
-        if not self._isOpen: raise portNotOpenError
-        return self.fd
-
-    def setXON(self, level=True):
-        """\
-        Manually control flow - when software flow control is enabled.
-        This will send XON (true) and XOFF (false) to the other device.
-        WARNING: this function is not portable to different platforms!
-        """
-        if not self.hComPort: raise portNotOpenError
-        if enable:
-            termios.tcflow(self.fd, TERMIOS.TCION)
-        else:
-            termios.tcflow(self.fd, TERMIOS.TCIOFF)
-
-    def flowControlOut(self, enable):
-        """\
-        Manually control flow of outgoing data - when hardware or software flow
-        control is enabled.
-        WARNING: this function is not portable to different platforms!
-        """
-        if not self._isOpen: raise portNotOpenError
-        if enable:
-            termios.tcflow(self.fd, TERMIOS.TCOON)
-        else:
-            termios.tcflow(self.fd, TERMIOS.TCOOFF)
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(PosixSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(PosixSerial, io.RawIOBase):
-        pass
-
-class PosixPollSerial(Serial):
-    """\
-    Poll based read implementation. Not all systems support poll properly.
-    However this one has better handling of errors, such as a device
-    disconnecting while it's in use (e.g. USB-serial unplugged).
-    """
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if self.fd is None: raise portNotOpenError
-        read = bytearray()
-        poll = select.poll()
-        poll.register(self.fd, select.POLLIN|select.POLLERR|select.POLLHUP|select.POLLNVAL)
-        if size > 0:
-            while len(read) < size:
-                # print "\tread(): size",size, "have", len(read)    #debug
-                # wait until device becomes ready to read (or something fails)
-                for fd, event in poll.poll(self._timeout*1000):
-                    if event & (select.POLLERR|select.POLLHUP|select.POLLNVAL):
-                        raise SerialException('device reports error (poll)')
-                    #  we don't care if it is select.POLLIN or timeout, that's
-                    #  handled below
-                buf = os.read(self.fd, size - len(read))
-                read.extend(buf)
-                if ((self._timeout is not None and self._timeout >= 0) or 
-                    (self._interCharTimeout is not None and self._interCharTimeout > 0)) and not buf:
-                    break   # early abort on timeout
-        return bytes(read)
-
-
-if __name__ == '__main__':
-    s = Serial(0,
-                 baudrate=19200,        # baud rate
-                 bytesize=EIGHTBITS,    # number of data bits
-                 parity=PARITY_EVEN,    # enable parity checking
-                 stopbits=STOPBITS_ONE, # number of stop bits
-                 timeout=3,             # set a timeout value, None for waiting forever
-                 xonxoff=0,             # enable software flow control
-                 rtscts=0,              # enable RTS/CTS flow control
-               )
-    s.setRTS(1)
-    s.setDTR(1)
-    s.flushInput()
-    s.flushOutput()
-    s.write('hello')
-    sys.stdout.write('%r\n' % s.read(5))
-    sys.stdout.write('%s\n' % s.inWaiting())
-    del s
-
diff --git a/scripts/serial/serialutil.py b/scripts/serial/serialutil.py
deleted file mode 100644
index af0d2f6402..0000000000
--- a/scripts/serial/serialutil.py
+++ /dev/null
@@ -1,572 +0,0 @@
-#! python
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# (C) 2001-2010 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-# compatibility for older Python < 2.6
-try:
-    bytes
-    bytearray
-except (NameError, AttributeError):
-    # Python older than 2.6 do not have these types. Like for Python 2.6 they
-    # should behave like str. For Python older than 3.0 we want to work with
-    # strings anyway, only later versions have a true bytes type.
-    bytes = str
-    # bytearray is a mutable type that is easily turned into an instance of
-    # bytes
-    class bytearray(list):
-        # for bytes(bytearray()) usage
-        def __str__(self): return ''.join(self)
-        def __repr__(self): return 'bytearray(%r)' % ''.join(self)
-        # append automatically converts integers to characters
-        def append(self, item):
-            if isinstance(item, str):
-                list.append(self, item)
-            else:
-                list.append(self, chr(item))
-        # +=
-        def __iadd__(self, other):
-            for byte in other:
-                self.append(byte)
-            return self
-
-        def __getslice__(self, i, j):
-            return bytearray(list.__getslice__(self, i, j))
-
-        def __getitem__(self, item):
-            if isinstance(item, slice):
-                return bytearray(list.__getitem__(self, item))
-            else:
-                return ord(list.__getitem__(self, item))
-
-        def __eq__(self, other):
-            if isinstance(other, basestring):
-                other = bytearray(other)
-            return list.__eq__(self, other)
-
-# ``memoryview`` was introduced in Python 2.7 and ``bytes(some_memoryview)``
-# isn't returning the contents (very unfortunate). Therefore we need special
-# cases and test for it. Ensure that there is a ``memoryview`` object for older
-# Python versions. This is easier than making every test dependent on its
-# existence.
-try:
-    memoryview
-except (NameError, AttributeError):
-    # implementation does not matter as we do not realy use it.
-    # it just must not inherit from something else we might care for.
-    class memoryview:
-        pass
-
-
-# all Python versions prior 3.x convert ``str([17])`` to '[17]' instead of '\x11'
-# so a simple ``bytes(sequence)`` doesn't work for all versions
-def to_bytes(seq):
-    """convert a sequence to a bytes type"""
-    if isinstance(seq, bytes):
-        return seq
-    elif isinstance(seq, bytearray):
-        return bytes(seq)
-    elif isinstance(seq, memoryview):
-        return seq.tobytes()
-    else:
-        b = bytearray()
-        for item in seq:
-            b.append(item)  # this one handles int and str for our emulation and ints for Python 3.x
-        return bytes(b)
-
-# create control bytes
-XON  = to_bytes([17])
-XOFF = to_bytes([19])
-
-CR = to_bytes([13])
-LF = to_bytes([10])
-
-
-PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
-STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
-FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
-
-PARITY_NAMES = {
-    PARITY_NONE:  'None',
-    PARITY_EVEN:  'Even',
-    PARITY_ODD:   'Odd',
-    PARITY_MARK:  'Mark',
-    PARITY_SPACE: 'Space',
-}
-
-
-class SerialException(IOError):
-    """Base class for serial port related exceptions."""
-
-
-class SerialTimeoutException(SerialException):
-    """Write timeouts give an exception"""
-
-
-writeTimeoutError = SerialTimeoutException('Write timeout')
-portNotOpenError = SerialException('Attempting to use a port that is not open')
-
-
-class FileLike(object):
-    """\
-    An abstract file like class.
-
-    This class implements readline and readlines based on read and
-    writelines based on write.
-    This class is used to provide the above functions for to Serial
-    port objects.
-
-    Note that when the serial port was opened with _NO_ timeout that
-    readline blocks until it sees a newline (or the specified size is
-    reached) and that readlines would never return and therefore
-    refuses to work (it raises an exception in this case)!
-    """
-
-    def __init__(self):
-        self.closed = True
-
-    def close(self):
-        self.closed = True
-
-    # so that ports are closed when objects are discarded
-    def __del__(self):
-        """Destructor.  Calls close()."""
-        # The try/except block is in case this is called at program
-        # exit time, when it's possible that globals have already been
-        # deleted, and then the close() call might fail.  Since
-        # there's nothing we can do about such failures and they annoy
-        # the end users, we suppress the traceback.
-        try:
-            self.close()
-        except:
-            pass
-
-    def writelines(self, sequence):
-        for line in sequence:
-            self.write(line)
-
-    def flush(self):
-        """flush of file like objects"""
-        pass
-
-    # iterator for e.g. "for line in Serial(0): ..." usage
-    def next(self):
-        line = self.readline()
-        if not line: raise StopIteration
-        return line
-
-    def __iter__(self):
-        return self
-
-    def readline(self, size=None, eol=LF):
-        """\
-        Read a line which is terminated with end-of-line (eol) character
-        ('\n' by default) or until timeout.
-        """
-        leneol = len(eol)
-        line = bytearray()
-        while True:
-            c = self.read(1)
-            if c:
-                line += c
-                if line[-leneol:] == eol:
-                    break
-                if size is not None and len(line) >= size:
-                    break
-            else:
-                break
-        return bytes(line)
-
-    def readlines(self, sizehint=None, eol=LF):
-        """\
-        Read a list of lines, until timeout.
-        sizehint is ignored.
-        """
-        if self.timeout is None:
-            raise ValueError("Serial port MUST have enabled timeout for this function!")
-        leneol = len(eol)
-        lines = []
-        while True:
-            line = self.readline(eol=eol)
-            if line:
-                lines.append(line)
-                if line[-leneol:] != eol:    # was the line received with a timeout?
-                    break
-            else:
-                break
-        return lines
-
-    def xreadlines(self, sizehint=None):
-        """\
-        Read lines, implemented as generator. It will raise StopIteration on
-        timeout (empty read). sizehint is ignored.
-        """
-        while True:
-            line = self.readline()
-            if not line: break
-            yield line
-
-    # other functions of file-likes - not used by pySerial
-
-    #~ readinto(b)
-
-    def seek(self, pos, whence=0):
-        raise IOError("file is not seekable")
-
-    def tell(self):
-        raise IOError("file is not seekable")
-
-    def truncate(self, n=None):
-        raise IOError("file is not seekable")
-
-    def isatty(self):
-        return False
-
-
-class SerialBase(object):
-    """\
-    Serial port base class. Provides __init__ function and properties to
-    get/set port settings.
-    """
-
-    # default values, may be overridden in subclasses that do not support all values
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
-                 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
-                 3000000, 3500000, 4000000)
-    BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
-    PARITIES  = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
-    STOPBITS  = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
-
-    def __init__(self,
-                 port = None,           # number of device, numbering starts at
-                                        # zero. if everything fails, the user
-                                        # can specify a device string, note
-                                        # that this isn't portable anymore
-                                        # port will be opened if one is specified
-                 baudrate=9600,         # baud rate
-                 bytesize=EIGHTBITS,    # number of data bits
-                 parity=PARITY_NONE,    # enable parity checking
-                 stopbits=STOPBITS_ONE, # number of stop bits
-                 timeout=None,          # set a timeout value, None to wait forever
-                 xonxoff=False,         # enable software flow control
-                 rtscts=False,          # enable RTS/CTS flow control
-                 writeTimeout=None,     # set a timeout for writes
-                 dsrdtr=False,          # None: use rtscts setting, dsrdtr override if True or False
-                 interCharTimeout=None  # Inter-character timeout, None to disable
-                 ):
-        """\
-        Initialize comm port object. If a port is given, then the port will be
-        opened immediately. Otherwise a Serial port object in closed state
-        is returned.
-        """
-
-        self._isOpen   = False
-        self._port     = None           # correct value is assigned below through properties
-        self._baudrate = None           # correct value is assigned below through properties
-        self._bytesize = None           # correct value is assigned below through properties
-        self._parity   = None           # correct value is assigned below through properties
-        self._stopbits = None           # correct value is assigned below through properties
-        self._timeout  = None           # correct value is assigned below through properties
-        self._writeTimeout = None       # correct value is assigned below through properties
-        self._xonxoff  = None           # correct value is assigned below through properties
-        self._rtscts   = None           # correct value is assigned below through properties
-        self._dsrdtr   = None           # correct value is assigned below through properties
-        self._interCharTimeout = None   # correct value is assigned below through properties
-
-        # assign values using get/set methods using the properties feature
-        self.port     = port
-        self.baudrate = baudrate
-        self.bytesize = bytesize
-        self.parity   = parity
-        self.stopbits = stopbits
-        self.timeout  = timeout
-        self.writeTimeout = writeTimeout
-        self.xonxoff  = xonxoff
-        self.rtscts   = rtscts
-        self.dsrdtr   = dsrdtr
-        self.interCharTimeout = interCharTimeout
-
-        if port is not None:
-            self.open()
-
-    def isOpen(self):
-        """Check if the port is opened."""
-        return self._isOpen
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    # TODO: these are not really needed as the is the BAUDRATES etc. attribute...
-    # maybe i remove them before the final release...
-
-    def getSupportedBaudrates(self):
-        return [(str(b), b) for b in self.BAUDRATES]
-
-    def getSupportedByteSizes(self):
-        return [(str(b), b) for b in self.BYTESIZES]
-
-    def getSupportedStopbits(self):
-        return [(str(b), b) for b in self.STOPBITS]
-
-    def getSupportedParities(self):
-        return [(PARITY_NAMES[b], b) for b in self.PARITIES]
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def setPort(self, port):
-        """\
-        Change the port. The attribute portstr is set to a string that
-        contains the name of the port.
-        """
-
-        was_open = self._isOpen
-        if was_open: self.close()
-        if port is not None:
-            if isinstance(port, basestring):
-                self.portstr = port
-            else:
-                self.portstr = self.makeDeviceName(port)
-        else:
-            self.portstr = None
-        self._port = port
-        self.name = self.portstr
-        if was_open: self.open()
-
-    def getPort(self):
-        """\
-        Get the current port setting. The value that was passed on init or using
-        setPort() is passed back. See also the attribute portstr which contains
-        the name of the port as a string.
-        """
-        return self._port
-
-    port = property(getPort, setPort, doc="Port setting")
-
-
-    def setBaudrate(self, baudrate):
-        """\
-        Change baud rate. It raises a ValueError if the port is open and the
-        baud rate is not possible. If the port is closed, then the value is
-        accepted and the exception is raised when the port is opened.
-        """
-        try:
-            b = int(baudrate)
-        except TypeError:
-            raise ValueError("Not a valid baudrate: %r" % (baudrate,))
-        else:
-            if b <= 0:
-                raise ValueError("Not a valid baudrate: %r" % (baudrate,))
-            self._baudrate = b
-            if self._isOpen:  self._reconfigurePort()
-
-    def getBaudrate(self):
-        """Get the current baud rate setting."""
-        return self._baudrate
-
-    baudrate = property(getBaudrate, setBaudrate, doc="Baud rate setting")
-
-
-    def setByteSize(self, bytesize):
-        """Change byte size."""
-        if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
-        self._bytesize = bytesize
-        if self._isOpen: self._reconfigurePort()
-
-    def getByteSize(self):
-        """Get the current byte size setting."""
-        return self._bytesize
-
-    bytesize = property(getByteSize, setByteSize, doc="Byte size setting")
-
-
-    def setParity(self, parity):
-        """Change parity setting."""
-        if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
-        self._parity = parity
-        if self._isOpen: self._reconfigurePort()
-
-    def getParity(self):
-        """Get the current parity setting."""
-        return self._parity
-
-    parity = property(getParity, setParity, doc="Parity setting")
-
-
-    def setStopbits(self, stopbits):
-        """Change stop bits size."""
-        if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
-        self._stopbits = stopbits
-        if self._isOpen: self._reconfigurePort()
-
-    def getStopbits(self):
-        """Get the current stop bits setting."""
-        return self._stopbits
-
-    stopbits = property(getStopbits, setStopbits, doc="Stop bits setting")
-
-
-    def setTimeout(self, timeout):
-        """Change timeout setting."""
-        if timeout is not None:
-            try:
-                timeout + 1     # test if it's a number, will throw a TypeError if not...
-            except TypeError:
-                raise ValueError("Not a valid timeout: %r" % (timeout,))
-            if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
-        self._timeout = timeout
-        if self._isOpen: self._reconfigurePort()
-
-    def getTimeout(self):
-        """Get the current timeout setting."""
-        return self._timeout
-
-    timeout = property(getTimeout, setTimeout, doc="Timeout setting for read()")
-
-
-    def setWriteTimeout(self, timeout):
-        """Change timeout setting."""
-        if timeout is not None:
-            if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
-            try:
-                timeout + 1     #test if it's a number, will throw a TypeError if not...
-            except TypeError:
-                raise ValueError("Not a valid timeout: %r" % timeout)
-
-        self._writeTimeout = timeout
-        if self._isOpen: self._reconfigurePort()
-
-    def getWriteTimeout(self):
-        """Get the current timeout setting."""
-        return self._writeTimeout
-
-    writeTimeout = property(getWriteTimeout, setWriteTimeout, doc="Timeout setting for write()")
-
-
-    def setXonXoff(self, xonxoff):
-        """Change XON/XOFF setting."""
-        self._xonxoff = xonxoff
-        if self._isOpen: self._reconfigurePort()
-
-    def getXonXoff(self):
-        """Get the current XON/XOFF setting."""
-        return self._xonxoff
-
-    xonxoff = property(getXonXoff, setXonXoff, doc="XON/XOFF setting")
-
-    def setRtsCts(self, rtscts):
-        """Change RTS/CTS flow control setting."""
-        self._rtscts = rtscts
-        if self._isOpen: self._reconfigurePort()
-
-    def getRtsCts(self):
-        """Get the current RTS/CTS flow control setting."""
-        return self._rtscts
-
-    rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting")
-
-    def setDsrDtr(self, dsrdtr=None):
-        """Change DsrDtr flow control setting."""
-        if dsrdtr is None:
-            # if not set, keep backwards compatibility and follow rtscts setting
-            self._dsrdtr = self._rtscts
-        else:
-            # if defined independently, follow its value
-            self._dsrdtr = dsrdtr
-        if self._isOpen: self._reconfigurePort()
-
-    def getDsrDtr(self):
-        """Get the current DSR/DTR flow control setting."""
-        return self._dsrdtr
-
-    dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting")
-
-    def setInterCharTimeout(self, interCharTimeout):
-        """Change inter-character timeout setting."""
-        if interCharTimeout is not None:
-            if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
-            try:
-                interCharTimeout + 1     # test if it's a number, will throw a TypeError if not...
-            except TypeError:
-                raise ValueError("Not a valid timeout: %r" % interCharTimeout)
-
-        self._interCharTimeout = interCharTimeout
-        if self._isOpen: self._reconfigurePort()
-
-    def getInterCharTimeout(self):
-        """Get the current inter-character timeout setting."""
-        return self._interCharTimeout
-
-    interCharTimeout = property(getInterCharTimeout, setInterCharTimeout, doc="Inter-character timeout setting for read()")
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
-            'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
-
-    def getSettingsDict(self):
-        """\
-        Get current port settings as a dictionary. For use with
-        applySettingsDict.
-        """
-        return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
-
-    def applySettingsDict(self, d):
-        """\
-        apply stored settings from a dictionary returned from
-        getSettingsDict. it's allowed to delete keys from the dictionary. these
-        values will simply left unchanged.
-        """
-        for key in self._SETTINGS:
-            if d[key] != getattr(self, '_'+key):   # check against internal "_" value
-                setattr(self, key, d[key])          # set non "_" value to use properties write function
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def __repr__(self):
-        """String representation of the current port settings and its state."""
-        return "%s<id=0x%x, open=%s>(port=%r, baudrate=%r, bytesize=%r, parity=%r, stopbits=%r, timeout=%r, xonxoff=%r, rtscts=%r, dsrdtr=%r)" % (
-            self.__class__.__name__,
-            id(self),
-            self._isOpen,
-            self.portstr,
-            self.baudrate,
-            self.bytesize,
-            self.parity,
-            self.stopbits,
-            self.timeout,
-            self.xonxoff,
-            self.rtscts,
-            self.dsrdtr,
-        )
-
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-    # compatibility with io library
-
-    def readable(self): return True
-    def writable(self): return True
-    def seekable(self): return False
-    def readinto(self, b):
-        data = self.read(len(b))
-        n = len(data)
-        try:
-            b[:n] = data
-        except TypeError, err:
-            import array
-            if not isinstance(b, array.array):
-                raise err
-            b[:n] = array.array('b', data)
-        return n
-
-
-if __name__ == '__main__':
-    import sys
-    s = SerialBase()
-    sys.stdout.write('port name:  %s\n' % s.portstr)
-    sys.stdout.write('baud rates: %s\n' % s.getSupportedBaudrates())
-    sys.stdout.write('byte sizes: %s\n' % s.getSupportedByteSizes())
-    sys.stdout.write('parities:   %s\n' % s.getSupportedParities())
-    sys.stdout.write('stop bits:  %s\n' % s.getSupportedStopbits())
-    sys.stdout.write('%s\n' % s)
diff --git a/scripts/serial/tools/__init__.py b/scripts/serial/tools/__init__.py
deleted file mode 100644
index 0efe34b218..0000000000
--- a/scripts/serial/tools/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# empty #
\ No newline at end of file
diff --git a/scripts/serial/tools/list_ports.py b/scripts/serial/tools/list_ports.py
deleted file mode 100644
index d373a5566d..0000000000
--- a/scripts/serial/tools/list_ports.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python
-
-# portable serial port access with python
-# this is a wrapper module for different platform implementations of the
-# port enumeration feature
-#
-# (C) 2011-2013 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-"""\
-This module will provide a function called comports that returns an
-iterable (generator or list) that will enumerate available com ports. Note that
-on some systems non-existent ports may be listed.
-
-Additionally a grep function is supplied that can be used to search for ports
-based on their descriptions or hardware ID.
-"""
-
-import sys, os, re
-
-# chose an implementation, depending on os
-#~ if sys.platform == 'cli':
-#~ else:
-import os
-# chose an implementation, depending on os
-if os.name == 'nt': #sys.platform == 'win32':
-    from serial.tools.list_ports_windows import *
-elif os.name == 'posix':
-    from serial.tools.list_ports_posix import *
-#~ elif os.name == 'java':
-else:
-    raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-def grep(regexp):
-    """\
-    Search for ports using a regular expression. Port name, description and
-    hardware ID are searched. The function returns an iterable that returns the
-    same tuples as comport() would do.
-    """
-    r = re.compile(regexp, re.I)
-    for port, desc, hwid in comports():
-        if r.search(port) or r.search(desc) or r.search(hwid):
-            yield port, desc, hwid
-
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-def main():
-    import optparse
-
-    parser = optparse.OptionParser(
-        usage = "%prog [options] [<regexp>]",
-        description = "Miniterm - A simple terminal program for the serial port."
-    )
-
-    parser.add_option("--debug",
-            help="print debug messages and tracebacks (development mode)",
-            dest="debug",
-            default=False,
-            action='store_true')
-
-    parser.add_option("-v", "--verbose",
-            help="show more messages (can be given multiple times)",
-            dest="verbose",
-            default=1,
-            action='count')
-
-    parser.add_option("-q", "--quiet",
-            help="suppress all messages",
-            dest="verbose",
-            action='store_const',
-            const=0)
-
-    (options, args) = parser.parse_args()
-
-
-    hits = 0
-    # get iteraror w/ or w/o filter
-    if args:
-        if len(args) > 1:
-            parser.error('more than one regexp not supported')
-        print "Filtered list with regexp: %r" % (args[0],)
-        iterator = sorted(grep(args[0]))
-    else:
-        iterator = sorted(comports())
-    # list them
-    for port, desc, hwid in iterator:
-        print("%-20s" % (port,))
-        if options.verbose > 1:
-            print("    desc: %s" % (desc,))
-            print("    hwid: %s" % (hwid,))
-        hits += 1
-    if options.verbose:
-        if hits:
-            print("%d ports found" % (hits,))
-        else:
-            print("no ports found")
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# test
-if __name__ == '__main__':
-    main()
diff --git a/scripts/serial/tools/list_ports_linux.py b/scripts/serial/tools/list_ports_linux.py
deleted file mode 100644
index 955761eaa4..0000000000
--- a/scripts/serial/tools/list_ports_linux.py
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/bin/env python
-
-# portable serial port access with python
-#
-# This is a module that gathers a list of serial ports including details on
-# GNU/Linux systems
-#
-# (C) 2011-2013 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-import glob
-import sys
-import os
-import re
-
-try:
-    import subprocess
-except ImportError:
-    def popen(argv):
-        try:
-            si, so =  os.popen4(' '.join(argv))
-            return so.read().strip()
-        except:
-            raise IOError('lsusb failed')
-else:
-    def popen(argv):
-        try:
-            return subprocess.check_output(argv, stderr=subprocess.STDOUT).strip()
-        except:
-            raise IOError('lsusb failed')
-
-
-# The comports function is expected to return an iterable that yields tuples of
-# 3 strings: port name, human readable description and a hardware ID.
-#
-# as currently no method is known to get the second two strings easily, they
-# are currently just identical to the port name.
-
-# try to detect the OS so that a device can be selected...
-plat = sys.platform.lower()
-
-def read_line(filename):
-    """\
-    Helper function to read a single line from a file.
-    Returns None on errors..
-    """
-    try:
-        f = open(filename)
-        line = f.readline().strip()
-        f.close()
-        return line
-    except IOError:
-        return None
-
-def re_group(regexp, text):
-    """search for regexp in text, return 1st group on match"""
-    if sys.version < '3':
-        m = re.search(regexp, text)
-    else:
-        # text is bytes-like
-        m = re.search(regexp, text.decode('ascii', 'replace'))
-    if m: return m.group(1)
-
-
-# try to extract descriptions from sysfs. this was done by experimenting,
-# no guarantee that it works for all devices or in the future...
-
-def usb_sysfs_hw_string(sysfs_path):
-    """given a path to a usb device in sysfs, return a string describing it"""
-    bus, dev = os.path.basename(os.path.realpath(sysfs_path)).split('-')
-    snr = read_line(sysfs_path+'/serial')
-    if snr:
-        snr_txt = ' SNR=%s' % (snr,)
-    else:
-        snr_txt = ''
-    return 'USB VID:PID=%s:%s%s' % (
-            read_line(sysfs_path+'/idVendor'),
-            read_line(sysfs_path+'/idProduct'),
-            snr_txt
-            )
-
-def usb_lsusb_string(sysfs_path):
-    base = os.path.basename(os.path.realpath(sysfs_path))
-    bus = base.split('-')[0]
-    try:
-        dev = int(read_line(os.path.join(sysfs_path, 'devnum')))
-        desc = popen(['lsusb', '-v', '-s', '%s:%s' % (bus, dev)])
-        # descriptions from device
-        iManufacturer = re_group('iManufacturer\s+\w+ (.+)', desc)
-        iProduct = re_group('iProduct\s+\w+ (.+)', desc)
-        iSerial = re_group('iSerial\s+\w+ (.+)', desc) or ''
-        # descriptions from kernel
-        idVendor = re_group('idVendor\s+0x\w+ (.+)', desc)
-        idProduct = re_group('idProduct\s+0x\w+ (.+)', desc)
-        # create descriptions. prefer text from device, fall back to the others
-        return '%s %s %s' % (iManufacturer or idVendor, iProduct or idProduct, iSerial)
-    except IOError:
-        return base
-
-def describe(device):
-    """\
-    Get a human readable description.
-    For USB-Serial devices try to run lsusb to get a human readable description.
-    For USB-CDC devices read the description from sysfs.
-    """
-    base = os.path.basename(device)
-    # USB-Serial devices
-    sys_dev_path = '/sys/class/tty/%s/device/driver/%s' % (base, base)
-    if os.path.exists(sys_dev_path):
-        sys_usb = os.path.dirname(os.path.dirname(os.path.realpath(sys_dev_path)))
-        return usb_lsusb_string(sys_usb)
-    # USB-CDC devices
-    sys_dev_path = '/sys/class/tty/%s/device/interface' % (base,)
-    if os.path.exists(sys_dev_path):
-        return read_line(sys_dev_path)
-    # USB Product Information
-    sys_dev_path = '/sys/class/tty/%s/device' % (base,)
-    if os.path.exists(sys_dev_path):
-        product_name_file = os.path.dirname(os.path.realpath(sys_dev_path)) + "/product"
-        if os.path.exists(product_name_file):
-            return read_line(product_name_file)
-    return base
-
-def hwinfo(device):
-    """Try to get a HW identification using sysfs"""
-    base = os.path.basename(device)
-    if os.path.exists('/sys/class/tty/%s/device' % (base,)):
-        # PCI based devices
-        sys_id_path = '/sys/class/tty/%s/device/id' % (base,)
-        if os.path.exists(sys_id_path):
-            return read_line(sys_id_path)
-        # USB-Serial devices
-        sys_dev_path = '/sys/class/tty/%s/device/driver/%s' % (base, base)
-        if os.path.exists(sys_dev_path):
-            sys_usb = os.path.dirname(os.path.dirname(os.path.realpath(sys_dev_path)))
-            return usb_sysfs_hw_string(sys_usb)
-        # USB-CDC devices
-        if base.startswith('ttyACM'):
-            sys_dev_path = '/sys/class/tty/%s/device' % (base,)
-            if os.path.exists(sys_dev_path):
-                return usb_sysfs_hw_string(sys_dev_path + '/..')
-    return 'n/a'    # XXX directly remove these from the list?
-
-def comports():
-    devices = glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*')
-    return [(d, describe(d), hwinfo(d)) for d in devices]
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-# test
-if __name__ == '__main__':
-    for port, desc, hwid in sorted(comports()):
-        print "%s: %s [%s]" % (port, desc, hwid)
diff --git a/scripts/serial/urlhandler/__init__.py b/scripts/serial/urlhandler/__init__.py
deleted file mode 100644
index 0efe34b218..0000000000
--- a/scripts/serial/urlhandler/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# empty #
\ No newline at end of file
diff --git a/scripts/serial/urlhandler/protocol_hwgrep.py b/scripts/serial/urlhandler/protocol_hwgrep.py
deleted file mode 100644
index 62cda43aa7..0000000000
--- a/scripts/serial/urlhandler/protocol_hwgrep.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a special URL handler that uses the port listing to
-# find ports by searching the string descriptions.
-#
-# (C) 2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# URL format:    hwgrep://regexp
-
-import serial
-import serial.tools.list_ports
-
-class Serial(serial.Serial):
-    """Just inherit the native Serial port implementation and patch the open function."""
-
-    def setPort(self, value):
-        """translate port name before storing it"""
-        if isinstance(value, basestring) and value.startswith('hwgrep://'):
-            serial.Serial.setPort(self, self.fromURL(value))
-        else:
-            serial.Serial.setPort(self, value)
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("hwgrep://"): url = url[9:]
-        # use a for loop to get the 1st element from the generator
-        for port, desc, hwid in serial.tools.list_ports.grep(url):
-            return port
-        else:
-            raise serial.SerialException('no ports found matching regexp %r' % (url,))
-
-    # override property
-    port = property(serial.Serial.getPort, setPort, doc="Port setting")
-
-# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-if __name__ == '__main__':
-    #~ s = Serial('hwgrep://ttyS0')
-    s = Serial(None)
-    s.port = 'hwgrep://ttyS0'
-    print s
-
diff --git a/scripts/serial/urlhandler/protocol_loop.py b/scripts/serial/urlhandler/protocol_loop.py
deleted file mode 100644
index a414839761..0000000000
--- a/scripts/serial/urlhandler/protocol_loop.py
+++ /dev/null
@@ -1,279 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a loop back connection receiving itself what it sent.
-#
-# The purpose of this module is.. well... You can run the unit tests with it.
-# and it was so easy to implement ;-)
-#
-# (C) 2001-2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# URL format:    loop://[option[/option...]]
-# options:
-# - "debug" print diagnostic messages
-
-from serial.serialutil import *
-import threading
-import time
-import logging
-
-# map log level names to constants. used in fromURL()
-LOGGER_LEVELS = {
-    'debug': logging.DEBUG,
-    'info': logging.INFO,
-    'warning': logging.WARNING,
-    'error': logging.ERROR,
-    }
-
-
-class LoopbackSerial(SerialBase):
-    """Serial port implementation that simulates a loop back connection in plain software."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        self.logger = None
-        self.buffer_lock = threading.Lock()
-        self.loop_buffer = bytearray()
-        self.cts = False
-        self.dsr = False
-
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        # not that there is anything to open, but the function applies the
-        # options found in the URL
-        self.fromURL(self.port)
-
-        # not that there anything to configure...
-        self._reconfigurePort()
-        # all things set up get, now a clean start
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """\
-        Set communication parameters on opened port. For the loop://
-        protocol all settings are ignored!
-        """
-        # not that's it of any real use, but it helps in the unit tests
-        if not isinstance(self._baudrate, (int, long)) or not 0 < self._baudrate < 2**32:
-            raise ValueError("invalid baudrate: %r" % (self._baudrate))
-        if self.logger:
-            self.logger.info('_reconfigurePort()')
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            self._isOpen = False
-            # in case of quick reconnects, give the server some time
-            time.sleep(0.3)
-
-    def makeDeviceName(self, port):
-        raise SerialException("there is no sensible way to turn numbers into URLs")
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("loop://"): url = url[7:]
-        try:
-            # process options now, directly altering self
-            for option in url.split('/'):
-                if '=' in option:
-                    option, value = option.split('=', 1)
-                else:
-                    value = None
-                if not option:
-                    pass
-                elif option == 'logging':
-                    logging.basicConfig()   # XXX is that good to call it here?
-                    self.logger = logging.getLogger('pySerial.loop')
-                    self.logger.setLevel(LOGGER_LEVELS[value])
-                    self.logger.debug('enabled logging')
-                else:
-                    raise ValueError('unknown option: %r' % (option,))
-        except ValueError, e:
-            raise SerialException('expected a string in the form "[loop://][option[/option...]]": %s' % e)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            # attention the logged value can differ from return value in
-            # threaded environments...
-            self.logger.debug('inWaiting() -> %d' % (len(self.loop_buffer),))
-        return len(self.loop_buffer)
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self._timeout is not None:
-            timeout = time.time() + self._timeout
-        else:
-            timeout = None
-        data = bytearray()
-        while size > 0:
-            self.buffer_lock.acquire()
-            try:
-                block = to_bytes(self.loop_buffer[:size])
-                del self.loop_buffer[:size]
-            finally:
-                self.buffer_lock.release()
-            data += block
-            size -= len(block)
-            # check for timeout now, after data has been read.
-            # useful for timeout = 0 (non blocking) read
-            if timeout and time.time() > timeout:
-                break
-        return bytes(data)
-
-    def write(self, data):
-        """\
-        Output the given string over the serial port. Can block if the
-        connection is blocked. May raise SerialException if the connection is
-        closed.
-        """
-        if not self._isOpen: raise portNotOpenError
-        # ensure we're working with bytes
-        data = to_bytes(data)
-        # calculate aprox time that would be used to send the data
-        time_used_to_send = 10.0*len(data) / self._baudrate
-        # when a write timeout is configured check if we would be successful
-        # (not sending anything, not even the part that would have time)
-        if self._writeTimeout is not None and time_used_to_send > self._writeTimeout:
-            time.sleep(self._writeTimeout) # must wait so that unit test succeeds
-            raise writeTimeoutError
-        self.buffer_lock.acquire()
-        try:
-            self.loop_buffer += data
-        finally:
-            self.buffer_lock.release()
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('flushInput()')
-        self.buffer_lock.acquire()
-        try:
-            del self.loop_buffer[:]
-        finally:
-            self.buffer_lock.release()
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('flushOutput()')
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-
-    def setBreak(self, level=True):
-        """\
-        Set break: Controls TXD. When active, to transmitting is
-        possible.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('setBreak(%r)' % (level,))
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('setRTS(%r) -> state of CTS' % (level,))
-        self.cts = level
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('setDTR(%r) -> state of DSR' % (level,))
-        self.dsr = level
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('getCTS() -> state of RTS (%r)' % (self.cts,))
-        return self.cts
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('getDSR() -> state of DTR (%r)' % (self.dsr,))
-        return self.dsr
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getRI()')
-        return False
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getCD()')
-        return True
-
-    # - - - platform specific - - -
-    # None so far
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(LoopbackSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(LoopbackSerial, io.RawIOBase):
-        pass
-
-
-# simple client test
-if __name__ == '__main__':
-    import sys
-    s = Serial('loop://')
-    sys.stdout.write('%s\n' % s)
-
-    sys.stdout.write("write...\n")
-    s.write("hello\n")
-    s.flush()
-    sys.stdout.write("read: %s\n" % s.read(5))
-
-    s.close()
diff --git a/scripts/serial/urlhandler/protocol_rfc2217.py b/scripts/serial/urlhandler/protocol_rfc2217.py
deleted file mode 100644
index 981ba45fea..0000000000
--- a/scripts/serial/urlhandler/protocol_rfc2217.py
+++ /dev/null
@@ -1,11 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see ../__init__.py
-#
-# This is a thin wrapper to load the rfc2271 implementation.
-#
-# (C) 2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-
-from serial.rfc2217 import Serial
diff --git a/scripts/serial/urlhandler/protocol_socket.py b/scripts/serial/urlhandler/protocol_socket.py
deleted file mode 100644
index dc5992342c..0000000000
--- a/scripts/serial/urlhandler/protocol_socket.py
+++ /dev/null
@@ -1,291 +0,0 @@
-#! python
-#
-# Python Serial Port Extension for Win32, Linux, BSD, Jython
-# see __init__.py
-#
-# This module implements a simple socket based client.
-# It does not support changing any port parameters and will silently ignore any
-# requests to do so.
-#
-# The purpose of this module is that applications using pySerial can connect to
-# TCP/IP to serial port converters that do not support RFC 2217.
-#
-# (C) 2001-2011 Chris Liechti <cliechti at gmx.net>
-# this is distributed under a free software license, see license.txt
-#
-# URL format:    socket://<host>:<port>[/option[/option...]]
-# options:
-# - "debug" print diagnostic messages
-
-from serial.serialutil import *
-import time
-import socket
-import select
-import logging
-
-# map log level names to constants. used in fromURL()
-LOGGER_LEVELS = {
-    'debug': logging.DEBUG,
-    'info': logging.INFO,
-    'warning': logging.WARNING,
-    'error': logging.ERROR,
-    }
-
-POLL_TIMEOUT = 2
-
-class SocketSerial(SerialBase):
-    """Serial port implementation for plain sockets."""
-
-    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-                 9600, 19200, 38400, 57600, 115200)
-
-    def open(self):
-        """\
-        Open port with current settings. This may throw a SerialException
-        if the port cannot be opened.
-        """
-        self.logger = None
-        if self._port is None:
-            raise SerialException("Port must be configured before it can be used.")
-        if self._isOpen:
-            raise SerialException("Port is already open.")
-        try:
-            # XXX in future replace with create_connection (py >=2.6)
-            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            self._socket.connect(self.fromURL(self.portstr))
-        except Exception, msg:
-            self._socket = None
-            raise SerialException("Could not open port %s: %s" % (self.portstr, msg))
-
-        self._socket.settimeout(POLL_TIMEOUT) # used for write timeout support :/
-
-        # not that there anything to configure...
-        self._reconfigurePort()
-        # all things set up get, now a clean start
-        self._isOpen = True
-        if not self._rtscts:
-            self.setRTS(True)
-            self.setDTR(True)
-        self.flushInput()
-        self.flushOutput()
-
-    def _reconfigurePort(self):
-        """\
-        Set communication parameters on opened port. For the socket://
-        protocol all settings are ignored!
-        """
-        if self._socket is None:
-            raise SerialException("Can only operate on open ports")
-        if self.logger:
-            self.logger.info('ignored port configuration change')
-
-    def close(self):
-        """Close port"""
-        if self._isOpen:
-            if self._socket:
-                try:
-                    self._socket.shutdown(socket.SHUT_RDWR)
-                    self._socket.close()
-                except:
-                    # ignore errors.
-                    pass
-                self._socket = None
-            self._isOpen = False
-            # in case of quick reconnects, give the server some time
-            time.sleep(0.3)
-
-    def makeDeviceName(self, port):
-        raise SerialException("there is no sensible way to turn numbers into URLs")
-
-    def fromURL(self, url):
-        """extract host and port from an URL string"""
-        if url.lower().startswith("socket://"): url = url[9:]
-        try:
-            # is there a "path" (our options)?
-            if '/' in url:
-                # cut away options
-                url, options = url.split('/', 1)
-                # process options now, directly altering self
-                for option in options.split('/'):
-                    if '=' in option:
-                        option, value = option.split('=', 1)
-                    else:
-                        value = None
-                    if option == 'logging':
-                        logging.basicConfig()   # XXX is that good to call it here?
-                        self.logger = logging.getLogger('pySerial.socket')
-                        self.logger.setLevel(LOGGER_LEVELS[value])
-                        self.logger.debug('enabled logging')
-                    else:
-                        raise ValueError('unknown option: %r' % (option,))
-            # get host and port
-            host, port = url.split(':', 1) # may raise ValueError because of unpacking
-            port = int(port)               # and this if it's not a number
-            if not 0 <= port < 65536: raise ValueError("port not in range 0...65535")
-        except ValueError, e:
-            raise SerialException('expected a string in the form "[rfc2217://]<host>:<port>[/option[/option...]]": %s' % e)
-        return (host, port)
-
-    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
-
-    def inWaiting(self):
-        """Return the number of characters currently in the input buffer."""
-        if not self._isOpen: raise portNotOpenError
-        # Poll the socket to see if it is ready for reading.
-        # If ready, at least one byte will be to read.
-        lr, lw, lx = select.select([self._socket], [], [], 0)
-        return len(lr)
-
-    def read(self, size=1):
-        """\
-        Read size bytes from the serial port. If a timeout is set it may
-        return less characters as requested. With no timeout it will block
-        until the requested number of bytes is read.
-        """
-        if not self._isOpen: raise portNotOpenError
-        data = bytearray()
-        if self._timeout is not None:
-            timeout = time.time() + self._timeout
-        else:
-            timeout = None
-        while len(data) < size and (timeout is None or time.time() < timeout):
-            try:
-                # an implementation with internal buffer would be better
-                # performing...
-                t = time.time()
-                block = self._socket.recv(size - len(data))
-                duration = time.time() - t
-                if block:
-                    data.extend(block)
-                else:
-                    # no data -> EOF (connection probably closed)
-                    break
-            except socket.timeout:
-                # just need to get out of recv from time to time to check if
-                # still alive
-                continue
-            except socket.error, e:
-                # connection fails -> terminate loop
-                raise SerialException('connection failed (%s)' % e)
-        return bytes(data)
-
-    def write(self, data):
-        """\
-        Output the given string over the serial port. Can block if the
-        connection is blocked. May raise SerialException if the connection is
-        closed.
-        """
-        if not self._isOpen: raise portNotOpenError
-        try:
-            self._socket.sendall(to_bytes(data))
-        except socket.error, e:
-            # XXX what exception if socket connection fails
-            raise SerialException("socket connection failed: %s" % e)
-        return len(data)
-
-    def flushInput(self):
-        """Clear input buffer, discarding all that is in the buffer."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored flushInput')
-
-    def flushOutput(self):
-        """\
-        Clear output buffer, aborting the current output and
-        discarding all that is in the buffer.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored flushOutput')
-
-    def sendBreak(self, duration=0.25):
-        """\
-        Send break condition. Timed, returns to idle state after given
-        duration.
-        """
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored sendBreak(%r)' % (duration,))
-
-    def setBreak(self, level=True):
-        """Set break: Controls TXD. When active, to transmitting is
-        possible."""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored setBreak(%r)' % (level,))
-
-    def setRTS(self, level=True):
-        """Set terminal status line: Request To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored setRTS(%r)' % (level,))
-
-    def setDTR(self, level=True):
-        """Set terminal status line: Data Terminal Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('ignored setDTR(%r)' % (level,))
-
-    def getCTS(self):
-        """Read terminal status line: Clear To Send"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getCTS()')
-        return True
-
-    def getDSR(self):
-        """Read terminal status line: Data Set Ready"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getDSR()')
-        return True
-
-    def getRI(self):
-        """Read terminal status line: Ring Indicator"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getRI()')
-        return False
-
-    def getCD(self):
-        """Read terminal status line: Carrier Detect"""
-        if not self._isOpen: raise portNotOpenError
-        if self.logger:
-            self.logger.info('returning dummy for getCD()')
-        return True
-
-    # - - - platform specific - - -
-
-    # works on Linux and probably all the other POSIX systems
-    def fileno(self):
-        """Get the file handle of the underlying socket for use with select"""
-        return self._socket.fileno()
-
-
-# assemble Serial class with the platform specific implementation and the base
-# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
-# library, derive from io.RawIOBase
-try:
-    import io
-except ImportError:
-    # classic version with our own file-like emulation
-    class Serial(SocketSerial, FileLike):
-        pass
-else:
-    # io library present
-    class Serial(SocketSerial, io.RawIOBase):
-        pass
-
-
-# simple client test
-if __name__ == '__main__':
-    import sys
-    s = Serial('socket://localhost:7000')
-    sys.stdout.write('%s\n' % s)
-
-    sys.stdout.write("write...\n")
-    s.write("hello\n")
-    s.flush()
-    sys.stdout.write("read: %s\n" % s.read(5))
-
-    s.close()
-- 
2.30.2



From s.hauer at pengutronix.de  Thu Sep  8 02:30:05 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu,  8 Sep 2022 11:30:05 +0200
Subject: [PATCH v2 5/5] bbremote: Print usage when no command is given
In-Reply-To: <20220908093005.3035259-1-s.hauer@pengutronix.de>
References: <20220908093005.3035259-1-s.hauer@pengutronix.de>
Message-ID: <20220908093005.3035259-6-s.hauer@pengutronix.de>

Instead of dumping a backtrace, print usage information when no
subcommand is given.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---

Notes:
    Changes since v1:
    - new patch

 scripts/remote/main.py | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/scripts/remote/main.py b/scripts/remote/main.py
index 2f3ce370ae..5aa176fdc4 100644
--- a/scripts/remote/main.py
+++ b/scripts/remote/main.py
@@ -206,6 +206,7 @@ parser.add_argument('--port', type=str, default=os.environ.get('BBREMOTE_PORT',
 parser.add_argument('--baudrate', type=int, default=os.environ.get('BBREMOTE_BAUDRATE', 115200))
 parser.add_argument('--export', type=str, default=os.environ.get('BBREMOTE_EXPORT', None))
 parser.add_argument('-w', '--wait', action='count', default=0)
+parser.set_defaults(func=None)
 subparsers = parser.add_subparsers(help='sub-command help')
 
 parser_run = subparsers.add_parser('run', help="run a barebox command")
@@ -277,6 +278,11 @@ parser_console.set_defaults(func=handle_console)
 args = parser.parse_args()
 logging.basicConfig(level=VERBOSITY[args.verbose],
                     format='%(levelname)-8s %(module)-8s %(funcName)-16s %(message)s')
+
+if args.func is None:
+    parser.print_help()
+    exit(1)
+
 try:
     res = args.func(args)
     exit(res)
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep  9 00:29:02 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri,  9 Sep 2022 09:29:02 +0200
Subject: [PATCH] ARM: Fix barebox header generation on arm64
Message-ID: <20220909072902.3260039-1-s.hauer@pengutronix.de>

When using multiple ENTRY_FUNCTION_WITH_STACK an entry_prologue
is emitted for each usage. The entry_proloues end up in the
same section and thus can't be discarded with the effect that the
barebox magic is at the wrong place. To fix this put the entry_prologues
in function specific sections so that the linker can discard the
unused ones.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/include/asm/barebox-arm.h | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index 16f9882b5a..a34f77f2ab 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -21,6 +21,7 @@
 #include <asm/common.h>
 #include <asm/sections.h>
 #include <asm/reloc.h>
+#include <linux/stringify.h>
 
 /*
  * We have a 4GiB address space split into 1MiB sections, with each
@@ -137,23 +138,23 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
 
 #ifdef CONFIG_CPU_64
 
-#define ____emit_entry_prologue(instr, ...) do { \
-	static __attribute__ ((unused,section(".text_head_prologue"))) \
+#define ____emit_entry_prologue(name, instr, ...) do { \
+	static __attribute__ ((unused,section(".text_head_prologue_" __stringify(name)))) \
 		const u32 __entry_prologue[] = {(instr), ##__VA_ARGS__}; \
 	barrier_data(__entry_prologue); \
 } while(0)
 
-#define __emit_entry_prologue(instr1, instr2, instr3, instr4, instr5) \
-	____emit_entry_prologue(instr1, instr2, instr3, instr4, instr5)
+#define __emit_entry_prologue(name, instr1, instr2, instr3, instr4, instr5) \
+	____emit_entry_prologue(name, instr1, instr2, instr3, instr4, instr5)
 
-#define __ARM_SETUP_STACK(stack_top) \
-	__emit_entry_prologue(0x14000002	/* b pc+0x8 */,		\
+#define __ARM_SETUP_STACK(name, stack_top) \
+	__emit_entry_prologue(name, 0x14000002	/* b pc+0x8 */,		\
 			      stack_top		/* 32-bit literal */,	\
 			      0x18ffffe9	/* ldr w9, top */,	\
 			      0xb4000049	/* cbz x9, pc+0x8 */,	\
 			      0x9100013f	/* mov sp, x9 */)
 #else
-#define __ARM_SETUP_STACK(stack_top) if (stack_top) arm_setup_stack(stack_top)
+#define __ARM_SETUP_STACK(name, stack_top) if (stack_top) arm_setup_stack(stack_top)
 #endif
 
 /*
@@ -174,7 +175,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
 				(ulong r0, ulong r1, ulong r2)		\
 		{							\
 			__barebox_arm_head();				\
-			__ARM_SETUP_STACK(stack_top);			\
+			__ARM_SETUP_STACK(name, stack_top);		\
 			__##name(r0, r1, r2);				\
 		}							\
 		static void noinline __##name				\
@@ -184,7 +185,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
 	static void ____##name(ulong, ulong, ulong);			\
 	ENTRY_FUNCTION(name, arg0, arg1, arg2)				\
 	{								\
-		__ARM_SETUP_STACK(stack_top);				\
+		__ARM_SETUP_STACK(name, stack_top);			\
 		____##name(arg0, arg1, arg2);				\
 	}								\
 	static void noinline ____##name					\
@@ -201,7 +202,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
 				(ulong r0, ulong r1, ulong r2)		\
 		{							\
 			__barebox_arm_head();				\
-			__ARM_SETUP_STACK(0);				\
+			__ARM_SETUP_STACK(name, 0);			\
 			__##name(r0, r1, r2);				\
 		}							\
 		static void NAKED noinline __##name			\
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep  9 00:37:49 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri,  9 Sep 2022 09:37:49 +0200
Subject: [PATCH 2/2] ARM: rpi: enable bcmgenet driver
In-Reply-To: <20220909073749.3260556-1-s.hauer@pengutronix.de>
References: <20220909073749.3260556-1-s.hauer@pengutronix.de>
Message-ID: <20220909073749.3260556-2-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/configs/rpi_v8a_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/rpi_v8a_defconfig b/arch/arm/configs/rpi_v8a_defconfig
index e218311a72..75f62ddb65 100644
--- a/arch/arm/configs/rpi_v8a_defconfig
+++ b/arch/arm/configs/rpi_v8a_defconfig
@@ -79,6 +79,7 @@ CONFIG_CMD_TIME=y
 CONFIG_NET=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_BCMGENET=y
 CONFIG_NET_USB=y
 CONFIG_NET_USB_SMSC95XX=y
 CONFIG_I2C=y
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep  9 00:37:48 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri,  9 Sep 2022 09:37:48 +0200
Subject: [PATCH 1/2] net: Add driver for bcmgenet
Message-ID: <20220909073749.3260556-1-s.hauer@pengutronix.de>

This adds a network driver for the bcmgenet core as found on the
Raspberry Pi4. The driver is derived from the U-Boot driver which
in turn is derived from the Linux driver. The driver has undergone the
usual barebox adjustments and has been tested on the Rpi4.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/Kconfig    |   6 +
 drivers/net/Makefile   |   1 +
 drivers/net/bcmgenet.c | 622 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 629 insertions(+)
 create mode 100644 drivers/net/bcmgenet.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 341d02a1da..27d0c4ec8b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -40,6 +40,12 @@ config DRIVER_NET_AT91_ETHER
 	depends on HAS_AT91_ETHER
 	select PHYLIB
 
+config DRIVER_NET_BCMGENET
+        bool "BCMGENET V5 support"
+        select PHYLIB
+        help
+          This driver supports the BCMGENET Ethernet MAC.
+
 config DRIVER_NET_CS8900
 	bool "cs8900 ethernet driver"
 	depends on HAS_CS8900 || COMPILE_TEST
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fa3d4583a0..a3eb10d1df 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_NET_USB)			+= usb/
 obj-$(CONFIG_DRIVER_NET_AR231X)		+= ar231x.o
 obj-$(CONFIG_DRIVER_NET_ARC_EMAC)	+= arc_emac.o
 obj-$(CONFIG_DRIVER_NET_AT91_ETHER)	+= at91_ether.o
+obj-$(CONFIG_DRIVER_NET_BCMGENET)	+= bcmgenet.o
 obj-$(CONFIG_DRIVER_NET_CS8900)		+= cs8900.o
 obj-$(CONFIG_DRIVER_NET_CPSW)		+= cpsw.o
 obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC)	+= davinci_emac.o
diff --git a/drivers/net/bcmgenet.c b/drivers/net/bcmgenet.c
new file mode 100644
index 0000000000..73c1590518
--- /dev/null
+++ b/drivers/net/bcmgenet.c
@@ -0,0 +1,622 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Amit Singh Tomar <amittomer25 at gmail.com>
+ *
+ * Driver for Broadcom GENETv5 Ethernet controller (as found on the RPi4)
+ * This driver is based on the Linux driver:
+ *      drivers/net/ethernet/broadcom/genet/bcmgenet.c
+ *      which is: Copyright (c) 2014-2017 Broadcom
+ *
+ * The hardware supports multiple queues (16 priority queues and one
+ * default queue), both for RX and TX. There are 256 DMA descriptors (both
+ * for TX and RX), and they live in MMIO registers. The hardware allows
+ * assigning descriptor ranges to queues, but we choose the most simple setup:
+ * All 256 descriptors are assigned to the default queue (#16).
+ * Also the Linux driver supports multiple generations of the MAC, whereas
+ * we only support v5, as used in the Raspberry Pi 4.
+ */
+
+#include <common.h>
+#include <dma.h>
+#include <malloc.h>
+#include <net.h>
+#include <init.h>
+#include <driver.h>
+#include <io.h>
+#include <clock.h>
+#include <xfuncs.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <of_net.h>
+#include <linux/iopoll.h>
+
+/* Register definitions derived from Linux source */
+#define SYS_REV_CTRL			0x00
+
+#define SYS_PORT_CTRL			0x04
+#define PORT_MODE_EXT_GPHY		3
+
+#define GENET_SYS_OFF			0x0000
+#define SYS_RBUF_FLUSH_CTRL		(GENET_SYS_OFF + 0x08)
+#define SYS_TBUF_FLUSH_CTRL		(GENET_SYS_OFF + 0x0c)
+
+#define GENET_EXT_OFF			0x0080
+#define EXT_RGMII_OOB_CTRL		(GENET_EXT_OFF + 0x0c)
+#define RGMII_LINK			BIT(4)
+#define OOB_DISABLE			BIT(5)
+#define RGMII_MODE_EN			BIT(6)
+#define ID_MODE_DIS			BIT(16)
+
+#define GENET_RBUF_OFF			0x0300
+#define RBUF_TBUF_SIZE_CTRL		(GENET_RBUF_OFF + 0xb4)
+#define RBUF_CTRL			(GENET_RBUF_OFF + 0x00)
+#define RBUF_ALIGN_2B			BIT(1)
+
+#define GENET_UMAC_OFF			0x0800
+#define UMAC_MIB_CTRL			(GENET_UMAC_OFF + 0x580)
+#define UMAC_MAX_FRAME_LEN		(GENET_UMAC_OFF + 0x014)
+#define UMAC_MAC0			(GENET_UMAC_OFF + 0x00c)
+#define UMAC_MAC1			(GENET_UMAC_OFF + 0x010)
+#define UMAC_CMD			(GENET_UMAC_OFF + 0x008)
+#define MDIO_CMD			(GENET_UMAC_OFF + 0x614)
+#define UMAC_TX_FLUSH			(GENET_UMAC_OFF + 0x334)
+#define MDIO_START_BUSY			BIT(29)
+#define MDIO_READ_FAIL			BIT(28)
+#define MDIO_RD				(2 << 26)
+#define MDIO_WR				BIT(26)
+#define MDIO_PMD_SHIFT			21
+#define MDIO_PMD_MASK			0x1f
+#define MDIO_REG_SHIFT			16
+#define MDIO_REG_MASK			0x1f
+
+#define CMD_TX_EN			BIT(0)
+#define CMD_RX_EN			BIT(1)
+#define UMAC_SPEED_10			0
+#define UMAC_SPEED_100			1
+#define UMAC_SPEED_1000			2
+#define UMAC_SPEED_2500			3
+#define CMD_SPEED_SHIFT			2
+#define CMD_SPEED_MASK			3
+#define CMD_SW_RESET			BIT(13)
+#define CMD_LCL_LOOP_EN			BIT(15)
+#define CMD_TX_EN			BIT(0)
+#define CMD_RX_EN			BIT(1)
+
+#define MIB_RESET_RX			BIT(0)
+#define MIB_RESET_RUNT			BIT(1)
+#define MIB_RESET_TX			BIT(2)
+
+/* total number of Buffer Descriptors, same for Rx/Tx */
+#define TOTAL_DESCS			256
+#define RX_DESCS			TOTAL_DESCS
+#define TX_DESCS			TOTAL_DESCS
+
+#define DEFAULT_Q			0x10
+
+#define ENET_MAX_MTU_SIZE		1536
+
+/* Tx/Rx Dma Descriptor common bits */
+#define DMA_EN				BIT(0)
+#define DMA_RING_BUF_EN_SHIFT		0x01
+#define DMA_RING_BUF_EN_MASK		0xffff
+#define DMA_BUFLENGTH_MASK		0x0fff
+#define DMA_BUFLENGTH_SHIFT		16
+#define DMA_RING_SIZE_SHIFT		16
+#define DMA_OWN				0x8000
+#define DMA_EOP				0x4000
+#define DMA_SOP				0x2000
+#define DMA_WRAP			0x1000
+#define DMA_MAX_BURST_LENGTH		0x8
+/* Tx specific DMA descriptor bits */
+#define DMA_TX_UNDERRUN			0x0200
+#define DMA_TX_APPEND_CRC		0x0040
+#define DMA_TX_OW_CRC			0x0020
+#define DMA_TX_DO_CSUM			0x0010
+#define DMA_TX_QTAG_SHIFT		7
+
+/* DMA rings size */
+#define DMA_RING_SIZE			0x40
+#define DMA_RINGS_SIZE			(DMA_RING_SIZE * (DEFAULT_Q + 1))
+
+/* DMA descriptor */
+#define DMA_DESC_LENGTH_STATUS		0x00
+#define DMA_DESC_ADDRESS_LO		0x04
+#define DMA_DESC_ADDRESS_HI		0x08
+#define DMA_DESC_SIZE			12
+
+#define GENET_RX_OFF			0x2000
+#define GENET_RDMA_REG_OFF		0x2c00
+#define GENET_TX_OFF			0x4000
+#define GENET_TDMA_REG_OFF		0x4c00
+
+#define DMA_FC_THRESH_HI		(RX_DESCS >> 4)
+#define DMA_FC_THRESH_LO		5
+#define DMA_FC_THRESH_VALUE		((DMA_FC_THRESH_LO << 16) |	\
+					  DMA_FC_THRESH_HI)
+
+#define DMA_XOFF_THRESHOLD_SHIFT	16
+
+#define TDMA_RING_REG_BASE		0x5000
+#define TDMA_READ_PTR			(TDMA_RING_REG_BASE + 0x00)
+#define TDMA_CONS_INDEX			(TDMA_RING_REG_BASE + 0x08)
+#define TDMA_PROD_INDEX			(TDMA_RING_REG_BASE + 0x0c)
+#define DMA_RING_BUF_SIZE		0x10
+#define DMA_START_ADDR			0x14
+#define DMA_END_ADDR			0x1c
+#define DMA_MBUF_DONE_THRESH		0x24
+#define TDMA_FLOW_PERIOD		(TDMA_RING_REG_BASE + 0x28)
+#define TDMA_WRITE_PTR			(TDMA_RING_REG_BASE + 0x2c)
+
+#define RDMA_RING_REG_BASE		0x3000
+#define RDMA_WRITE_PTR			(RDMA_RING_REG_BASE + 0x00)
+#define RDMA_PROD_INDEX			(RDMA_RING_REG_BASE + 0x08)
+#define RDMA_CONS_INDEX			(RDMA_RING_REG_BASE + 0x0c)
+#define RDMA_XON_XOFF_THRESH		(RDMA_RING_REG_BASE + 0x28)
+#define RDMA_READ_PTR			(RDMA_RING_REG_BASE + 0x2c)
+
+#define TDMA_REG_BASE			0x5040
+#define RDMA_REG_BASE			0x3040
+#define DMA_RING_CFG			0x00
+#define DMA_CTRL			0x04
+#define DMA_SCB_BURST_SIZE		0x0c
+
+#define RX_BUF_LENGTH			2048
+#define RX_TOTAL_BUFSIZE		(RX_BUF_LENGTH * RX_DESCS)
+#define RX_BUF_OFFSET			2
+
+struct bcmgenet_eth_priv {
+	char *rxbuffer;
+	void *mac_reg;
+	int tx_index;
+	int rx_index;
+	int c_index;
+	u32 interface;
+	struct mii_bus miibus;
+	struct eth_device edev;
+	struct device_d *dev;
+	unsigned char addr[6];
+};
+
+static void bcmgenet_umac_reset(struct bcmgenet_eth_priv *priv)
+{
+	u32 reg;
+
+	reg = readl(priv->mac_reg + SYS_RBUF_FLUSH_CTRL);
+	reg |= BIT(1);
+	writel(reg, (priv->mac_reg + SYS_RBUF_FLUSH_CTRL));
+	udelay(10);
+
+	reg &= ~BIT(1);
+	writel(reg, (priv->mac_reg + SYS_RBUF_FLUSH_CTRL));
+	udelay(10);
+
+	writel(0, (priv->mac_reg + SYS_RBUF_FLUSH_CTRL));
+	udelay(10);
+
+	writel(0, priv->mac_reg + UMAC_CMD);
+
+	writel(CMD_SW_RESET | CMD_LCL_LOOP_EN, priv->mac_reg + UMAC_CMD);
+	udelay(2);
+	writel(0, priv->mac_reg + UMAC_CMD);
+
+	/* clear tx/rx counter */
+	writel(MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT,
+	       priv->mac_reg + UMAC_MIB_CTRL);
+	writel(0, priv->mac_reg + UMAC_MIB_CTRL);
+
+	writel(ENET_MAX_MTU_SIZE, priv->mac_reg + UMAC_MAX_FRAME_LEN);
+
+	/* init rx registers, enable ip header optimization */
+	reg = readl(priv->mac_reg + RBUF_CTRL);
+	reg |= RBUF_ALIGN_2B;
+	writel(reg, (priv->mac_reg + RBUF_CTRL));
+
+	writel(1, (priv->mac_reg + RBUF_TBUF_SIZE_CTRL));
+}
+
+static int bcmgenet_set_hwaddr(struct eth_device *dev, const unsigned char *addr)
+{
+	struct bcmgenet_eth_priv *priv = dev->priv;
+
+	memcpy(priv->addr, addr, 6);
+
+	return 0;
+}
+
+static int __bcmgenet_set_hwaddr(struct bcmgenet_eth_priv *priv)
+{
+	const unsigned char *addr = priv->addr;
+	u32 reg;
+
+	reg = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
+	writel_relaxed(reg, priv->mac_reg + UMAC_MAC0);
+
+	reg = addr[4] << 8 | addr[5];
+	writel_relaxed(reg, priv->mac_reg + UMAC_MAC1);
+
+	return 0;
+}
+
+static int bcmgenet_get_hwaddr(struct eth_device *edev, unsigned char *mac)
+{
+	return -1;
+}
+
+static void bcmgenet_disable_dma(struct bcmgenet_eth_priv *priv)
+{
+	clrbits_le32(priv->mac_reg + TDMA_REG_BASE + DMA_CTRL, DMA_EN);
+	clrbits_le32(priv->mac_reg + RDMA_REG_BASE + DMA_CTRL, DMA_EN);
+
+	writel(1, priv->mac_reg + UMAC_TX_FLUSH);
+	udelay(10);
+	writel(0, priv->mac_reg + UMAC_TX_FLUSH);
+}
+
+static void bcmgenet_enable_dma(struct bcmgenet_eth_priv *priv)
+{
+	u32 dma_ctrl = (1 << (DEFAULT_Q + DMA_RING_BUF_EN_SHIFT)) | DMA_EN;
+
+	writel(dma_ctrl, priv->mac_reg + TDMA_REG_BASE + DMA_CTRL);
+	setbits_le32(priv->mac_reg + RDMA_REG_BASE + DMA_CTRL, dma_ctrl);
+}
+
+static int bcmgenet_gmac_eth_send(struct eth_device *edev, void *packet, int length)
+{
+	struct bcmgenet_eth_priv *priv = edev->priv;
+	void *desc_base = priv->mac_reg + GENET_TX_OFF + priv->tx_index * DMA_DESC_SIZE;
+	u32 len_stat = length << DMA_BUFLENGTH_SHIFT;
+	u32 prod_index, cons;
+	u32 tries = 100;
+	dma_addr_t dma;
+
+	prod_index = readl(priv->mac_reg + TDMA_PROD_INDEX);
+
+	dma = dma_map_single(priv->dev, packet, length, DMA_TO_DEVICE);
+	if (dma_mapping_error(priv->dev, dma))
+		return -EFAULT;
+
+	len_stat |= 0x3f << DMA_TX_QTAG_SHIFT;
+	len_stat |= DMA_TX_APPEND_CRC | DMA_SOP | DMA_EOP;
+
+	/* Set-up packet for transmission */
+	writel(lower_32_bits(dma), (desc_base + DMA_DESC_ADDRESS_LO));
+	writel(upper_32_bits(dma), (desc_base + DMA_DESC_ADDRESS_HI));
+	writel(len_stat, (desc_base + DMA_DESC_LENGTH_STATUS));
+
+	/* Increment index and start transmission */
+	if (++priv->tx_index >= TX_DESCS)
+		priv->tx_index = 0;
+
+	prod_index++;
+
+	/* Start Transmisson */
+	writel(prod_index, priv->mac_reg + TDMA_PROD_INDEX);
+
+	do {
+		cons = readl(priv->mac_reg + TDMA_CONS_INDEX);
+	} while ((cons & 0xffff) < prod_index && --tries);
+
+	dma_unmap_single(priv->dev, dma, length, DMA_TO_DEVICE);
+
+	if (!tries) {
+		dev_err(priv->dev, "sending timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int bcmgenet_gmac_eth_recv(struct eth_device *edev)
+{
+	struct bcmgenet_eth_priv *priv = edev->priv;
+	void *desc_base = priv->mac_reg + GENET_RX_OFF + priv->rx_index * DMA_DESC_SIZE;
+	u32 prod_index = readl(priv->mac_reg + RDMA_PROD_INDEX);
+	u32 length;
+	unsigned long addr_lo, addr_hi, addr;
+
+	if (prod_index == priv->c_index)
+		return -EAGAIN;
+
+	length = readl(desc_base + DMA_DESC_LENGTH_STATUS);
+	length = (length >> DMA_BUFLENGTH_SHIFT) & DMA_BUFLENGTH_MASK;
+	addr_lo = readl(desc_base + DMA_DESC_ADDRESS_LO);
+	addr_hi = readl(desc_base + DMA_DESC_ADDRESS_HI);
+	addr = addr_hi << 32 | addr_lo;
+
+	dma_sync_single_for_cpu(addr, length, DMA_FROM_DEVICE);
+
+	/* To cater for the IP header alignment the hardware does.
+	 * This would actually not be needed if we don't program
+	 * RBUF_ALIGN_2B
+	 */
+	net_receive(edev, (void *)addr + RX_BUF_OFFSET, length - RX_BUF_OFFSET);
+
+	dma_sync_single_for_device(addr, length, DMA_FROM_DEVICE);
+
+	/* Tell the MAC we have consumed that last receive buffer. */
+	priv->c_index = (priv->c_index + 1) & 0xffff;
+	writel(priv->c_index, priv->mac_reg + RDMA_CONS_INDEX);
+
+	/* Forward our descriptor pointer, wrapping around if needed. */
+	if (++priv->rx_index >= RX_DESCS)
+		priv->rx_index = 0;
+
+	return 0;
+}
+
+static void rx_descs_init(struct bcmgenet_eth_priv *priv)
+{
+	char *rxbuffs = priv->rxbuffer;
+	u32 len_stat, i;
+	void *desc_base = priv->mac_reg + GENET_RX_OFF;
+
+	len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
+
+	for (i = 0; i < RX_DESCS; i++) {
+		writel(lower_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]),
+		       desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_LO);
+		writel(upper_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]),
+		       desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_HI);
+		writel(len_stat,
+		       desc_base + i * DMA_DESC_SIZE + DMA_DESC_LENGTH_STATUS);
+	}
+}
+
+static void rx_ring_init(struct bcmgenet_eth_priv *priv)
+{
+	writel(DMA_MAX_BURST_LENGTH,
+	       priv->mac_reg + RDMA_REG_BASE + DMA_SCB_BURST_SIZE);
+
+	writel(0x0, priv->mac_reg + RDMA_RING_REG_BASE + DMA_START_ADDR);
+	writel(0x0, priv->mac_reg + RDMA_READ_PTR);
+	writel(0x0, priv->mac_reg + RDMA_WRITE_PTR);
+	writel(RX_DESCS * DMA_DESC_SIZE / 4 - 1,
+	       priv->mac_reg + RDMA_RING_REG_BASE + DMA_END_ADDR);
+
+	/* cannot init RDMA_PROD_INDEX to 0, so align RDMA_CONS_INDEX on it instead */
+	priv->c_index = readl(priv->mac_reg + RDMA_PROD_INDEX);
+	writel(priv->c_index, priv->mac_reg + RDMA_CONS_INDEX);
+	priv->rx_index = priv->c_index;
+	priv->rx_index &= 0xff;
+	writel((RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH,
+	       priv->mac_reg + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE);
+	writel(DMA_FC_THRESH_VALUE, priv->mac_reg + RDMA_XON_XOFF_THRESH);
+	writel(1 << DEFAULT_Q, priv->mac_reg + RDMA_REG_BASE + DMA_RING_CFG);
+}
+
+static void tx_ring_init(struct bcmgenet_eth_priv *priv)
+{
+	writel(DMA_MAX_BURST_LENGTH,
+	       priv->mac_reg + TDMA_REG_BASE + DMA_SCB_BURST_SIZE);
+
+	writel(0x0, priv->mac_reg + TDMA_RING_REG_BASE + DMA_START_ADDR);
+	writel(0x0, priv->mac_reg + TDMA_READ_PTR);
+	writel(0x0, priv->mac_reg + TDMA_WRITE_PTR);
+	writel(TX_DESCS * DMA_DESC_SIZE / 4 - 1,
+	       priv->mac_reg + TDMA_RING_REG_BASE + DMA_END_ADDR);
+	/* cannot init TDMA_CONS_INDEX to 0, so align TDMA_PROD_INDEX on it instead */
+	priv->tx_index = readl(priv->mac_reg + TDMA_CONS_INDEX);
+	writel(priv->tx_index, priv->mac_reg + TDMA_PROD_INDEX);
+	priv->tx_index &= 0xFF;
+	writel(0x1, priv->mac_reg + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH);
+	writel(0x0, priv->mac_reg + TDMA_FLOW_PERIOD);
+	writel((TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH,
+	       priv->mac_reg + TDMA_RING_REG_BASE + DMA_RING_BUF_SIZE);
+
+	writel(1 << DEFAULT_Q, priv->mac_reg + TDMA_REG_BASE + DMA_RING_CFG);
+}
+
+static void bcmgenet_adjust_link(struct eth_device *edev)
+{
+	struct bcmgenet_eth_priv *priv = edev->priv;
+	struct phy_device *phy_dev = edev->phydev;
+	u32 speed;
+
+	switch (phy_dev->speed) {
+	case SPEED_1000:
+		speed = UMAC_SPEED_1000;
+		break;
+	case SPEED_100:
+		speed = UMAC_SPEED_100;
+		break;
+	case SPEED_10:
+		speed = UMAC_SPEED_10;
+		break;
+	default:
+		dev_err(priv->dev, "bcmgenet: Unsupported PHY speed: %d\n", phy_dev->speed);
+		return;
+	}
+
+	clrsetbits_le32(priv->mac_reg + EXT_RGMII_OOB_CTRL, OOB_DISABLE,
+			RGMII_LINK | RGMII_MODE_EN);
+
+	if (phy_dev->interface == PHY_INTERFACE_MODE_RGMII ||
+	    phy_dev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
+		setbits_le32(priv->mac_reg + EXT_RGMII_OOB_CTRL, ID_MODE_DIS);
+		writel(PORT_MODE_EXT_GPHY, priv->mac_reg + SYS_PORT_CTRL);
+	}
+
+	clrsetbits_le32(priv->mac_reg + UMAC_CMD, CMD_SPEED_MASK << CMD_SPEED_SHIFT,
+			speed << CMD_SPEED_SHIFT);
+}
+
+static int bcmgenet_gmac_eth_start(struct eth_device *edev)
+{
+	struct bcmgenet_eth_priv *priv = edev->priv;
+	int ret;
+
+	bcmgenet_umac_reset(priv);
+
+	__bcmgenet_set_hwaddr(priv);
+
+	/* Disable RX/TX DMA and flush TX queues */
+	bcmgenet_disable_dma(priv);
+
+	rx_ring_init(priv);
+	rx_descs_init(priv);
+	tx_ring_init(priv);
+	bcmgenet_enable_dma(priv);
+
+	ret = phy_device_connect(edev, &priv->miibus, -1,
+				 bcmgenet_adjust_link, 0,
+				 priv->interface);
+	if (ret)
+                return ret;
+
+	/* Enable Rx/Tx */
+	setbits_le32(priv->mac_reg + UMAC_CMD, CMD_TX_EN | CMD_RX_EN);
+
+	return 0;
+}
+
+static void bcmgenet_mdio_start(struct bcmgenet_eth_priv *priv)
+{
+	setbits_le32(priv->mac_reg + MDIO_CMD, MDIO_START_BUSY);
+}
+
+static int bcmgenet_mdio_write(struct mii_bus *bus, int addr,
+			       int reg, u16 value)
+{
+	struct bcmgenet_eth_priv *priv = bus->priv;
+	u32 val;
+
+	/* Prepare the read operation */
+	val = MDIO_WR | (addr << MDIO_PMD_SHIFT) |
+		(reg << MDIO_REG_SHIFT) | (0xffff & value);
+	writel_relaxed(val,  priv->mac_reg + MDIO_CMD);
+
+	/* Start MDIO transaction */
+	bcmgenet_mdio_start(priv);
+
+	return readl_poll_timeout(priv->mac_reg + MDIO_CMD, reg,
+				  !(reg & MDIO_START_BUSY), 20);
+}
+
+static int bcmgenet_mdio_read(struct mii_bus *bus, int addr, int reg)
+{
+	struct bcmgenet_eth_priv *priv = bus->priv;
+	u32 val;
+	int ret;
+
+	/* Prepare the read operation */
+	val = MDIO_RD | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT);
+	writel_relaxed(val, priv->mac_reg + MDIO_CMD);
+
+	/* Start MDIO transaction */
+	bcmgenet_mdio_start(priv);
+
+	ret = readl_poll_timeout(priv->mac_reg + MDIO_CMD, reg,
+				 !(reg & MDIO_START_BUSY), 20);
+	if (ret)
+		return ret;
+
+	val = readl_relaxed(priv->mac_reg + MDIO_CMD);
+
+	return val & 0xffff;
+}
+
+static int bcmgenet_probe(struct device_d *dev)
+{
+	struct resource *iores;
+	struct bcmgenet_eth_priv *priv;
+	u32 reg;
+	int ret;
+	u8 major;
+	struct eth_device *edev;
+
+	priv = xzalloc(sizeof(*priv));
+	edev = &priv->edev;
+
+	iores = dev_request_mem_resource(dev, 0);
+	if (IS_ERR(iores)) {
+		ret = PTR_ERR(iores);
+		return ret;
+	}
+	priv->mac_reg = IOMEM(iores->start);
+	priv->dev = dev;
+	priv->rxbuffer = dma_alloc(RX_TOTAL_BUFSIZE);
+
+	edev->open = bcmgenet_gmac_eth_start;
+	edev->send = bcmgenet_gmac_eth_send;
+	edev->recv = bcmgenet_gmac_eth_recv;
+	edev->get_ethaddr = bcmgenet_get_hwaddr;
+	edev->set_ethaddr = bcmgenet_set_hwaddr;
+	edev->parent = dev;
+	edev->priv = priv;
+	dev->priv = priv;
+
+	/* Read GENET HW version */
+	reg = readl_relaxed(priv->mac_reg + SYS_REV_CTRL);
+	major = (reg >> 24) & 0x0f;
+	if (major != 6) {
+		if (major == 5)
+			major = 4;
+		else if (major == 0)
+			major = 1;
+
+		dev_err(priv->dev, "Unsupported GENETv%d.%d\n", major, (reg >> 16) & 0x0f);
+		return -ENODEV;
+	}
+
+	ret = of_get_phy_mode(dev->device_node);
+	if (ret < 0)
+		priv->interface = PHY_INTERFACE_MODE_MII;
+	else
+		priv->interface = ret;
+
+	writel(0, priv->mac_reg + SYS_RBUF_FLUSH_CTRL);
+	udelay(10);
+	/* disable MAC while updating its registers */
+	writel(0, priv->mac_reg + UMAC_CMD);
+	/* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
+	writel(CMD_SW_RESET | CMD_LCL_LOOP_EN, priv->mac_reg + UMAC_CMD);
+
+	priv->miibus.read = bcmgenet_mdio_read;
+	priv->miibus.write = bcmgenet_mdio_write;
+
+	priv->miibus.priv = priv;
+	priv->miibus.parent = dev;
+
+	ret = mdiobus_register(&priv->miibus);
+	if (ret)
+		return ret;
+
+	ret = eth_register(edev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void bcmgenet_gmac_eth_stop(struct bcmgenet_eth_priv *priv)
+{
+	clrbits_le32(priv->mac_reg + UMAC_CMD, CMD_TX_EN | CMD_RX_EN);
+
+	bcmgenet_disable_dma(priv);
+}
+
+static void bcmgenet_remove(struct device_d *dev)
+{
+	struct bcmgenet_eth_priv *priv = dev->priv;
+
+	bcmgenet_gmac_eth_stop(priv);
+}
+
+static struct of_device_id bcmgenet_ids[] = {
+        {
+                .compatible = "brcm,genet-v5",
+        }, {
+                .compatible = "brcm,bcm2711-genet-v5",
+        }, {
+                /* sentinel */
+        },
+};
+
+static struct driver_d bcmgenet_driver = {
+        .name   = "brcm-genet",
+        .probe  = bcmgenet_probe,
+        .remove = bcmgenet_remove,
+        .of_compatible = DRV_OF_COMPAT(bcmgenet_ids),
+};
+device_platform_driver(bcmgenet_driver);
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep  9 00:40:50 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri,  9 Sep 2022 09:40:50 +0200
Subject: [PATCH] of: implement of_prepend_property
Message-ID: <20220909074050.3875659-1-a.fatoum@pengutronix.de>

Like of_append_property for adding at the end of properties, implement
of_prepend_property for placing data into the front.

This is especially useful to fixup most-specific compatibles into
existing nodes.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/of/base.c           | 35 +++++++++++++++++++++++++++++++++++
 include/of.h                |  8 ++++++++
 test/self/of_manipulation.c |  2 +-
 3 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 212b226eb55c..e208949b08bd 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2378,6 +2378,41 @@ int of_append_property(struct device_node *np, const char *name, const void *val
 	return 0;
 }
 
+int of_prepend_property(struct device_node *np, const char *name, const void *val, int len)
+{
+	struct property *pp;
+	int orig_len;
+	const void *orig_buf;
+	void *buf;
+
+	if (!np)
+		return -ENOENT;
+
+	pp = of_find_property(np, name, NULL);
+	if (!pp) {
+		of_new_property(np, name, val, len);
+		return 0;
+	}
+
+	orig_len = pp->length;
+	buf = realloc(pp->value, orig_len + len);
+	if (!buf)
+		return -ENOMEM;
+
+	orig_buf = pp->value_const ?: buf;
+	if (orig_buf) {
+		memmove(buf + len, orig_buf, orig_len);
+		pp->value_const = NULL;
+	}
+
+	memcpy(buf, val, len);
+
+	pp->value = buf;
+	pp->length += len;
+
+	return 0;
+}
+
 int of_property_sprintf(struct device_node *np,
 			const char *propname, const char *fmt, ...)
 {
diff --git a/include/of.h b/include/of.h
index 153e75d3e51d..052d5fcad84c 100644
--- a/include/of.h
+++ b/include/of.h
@@ -135,6 +135,8 @@ extern int of_set_property(struct device_node *node, const char *p,
 			const void *val, int len, int create);
 extern int of_append_property(struct device_node *np, const char *p,
 			      const void *val, int len);
+extern int of_prepend_property(struct device_node *np, const char *name,
+			       const void *val, int len);
 extern struct property *of_new_property(struct device_node *node,
 				const char *name, const void *data, int len);
 extern struct property *of_new_property_const(struct device_node *node,
@@ -536,6 +538,12 @@ static inline int of_append_property(struct device_node *np, const char *p,
 	return -ENOSYS;
 }
 
+static inline int of_prepend_property(struct device_node *np, const char *name,
+				      const void *val, int len)
+{
+	return -ENOSYS;
+}
+
 static inline struct property *of_new_property(struct device_node *node,
 				const char *name, const void *data, int len)
 {
diff --git a/test/self/of_manipulation.c b/test/self/of_manipulation.c
index 7e30a60ca687..f7f95fa269af 100644
--- a/test/self/of_manipulation.c
+++ b/test/self/of_manipulation.c
@@ -103,9 +103,9 @@ static void test_of_property_strings(struct device_node *root)
 
 	of_append_property(np4, "property-single", "ayy", 4);
 
-	of_append_property(np4, "property-multi", "ayy", 4);
 	of_append_property(np4, "property-multi", "bee", 4);
 	of_append_property(np4, "property-multi", "sea", 4);
+	of_prepend_property(np4, "property-multi", "ayy", 4);
 
 	assert_equal(np3, np4);
 }
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep  9 00:43:19 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 9 Sep 2022 09:43:19 +0200
Subject: [PATCH] ARM: Fix barebox header generation on arm64
In-Reply-To: <20220909072902.3260039-1-s.hauer@pengutronix.de>
References: <20220909072902.3260039-1-s.hauer@pengutronix.de>
Message-ID: <a1f6684a-06b8-43c5-cc66-e8e8b447e249@pengutronix.de>

On 09.09.22 09:29, Sascha Hauer wrote:
> When using multiple ENTRY_FUNCTION_WITH_STACK an entry_prologue
> is emitted for each usage. The entry_proloues end up in the

                                     ^ prologues

> same section and thus can't be discarded with the effect that the
> barebox magic is at the wrong place. To fix this put the entry_prologues
> in function specific sections so that the linker can discard the
> unused ones.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>


Thanks for fixing,
Ahmad

> ---
>  arch/arm/include/asm/barebox-arm.h | 21 +++++++++++----------
>  1 file changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
> index 16f9882b5a..a34f77f2ab 100644
> --- a/arch/arm/include/asm/barebox-arm.h
> +++ b/arch/arm/include/asm/barebox-arm.h
> @@ -21,6 +21,7 @@
>  #include <asm/common.h>
>  #include <asm/sections.h>
>  #include <asm/reloc.h>
> +#include <linux/stringify.h>
>  
>  /*
>   * We have a 4GiB address space split into 1MiB sections, with each
> @@ -137,23 +138,23 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
>  
>  #ifdef CONFIG_CPU_64
>  
> -#define ____emit_entry_prologue(instr, ...) do { \
> -	static __attribute__ ((unused,section(".text_head_prologue"))) \
> +#define ____emit_entry_prologue(name, instr, ...) do { \
> +	static __attribute__ ((unused,section(".text_head_prologue_" __stringify(name)))) \
>  		const u32 __entry_prologue[] = {(instr), ##__VA_ARGS__}; \
>  	barrier_data(__entry_prologue); \
>  } while(0)
>  
> -#define __emit_entry_prologue(instr1, instr2, instr3, instr4, instr5) \
> -	____emit_entry_prologue(instr1, instr2, instr3, instr4, instr5)
> +#define __emit_entry_prologue(name, instr1, instr2, instr3, instr4, instr5) \
> +	____emit_entry_prologue(name, instr1, instr2, instr3, instr4, instr5)
>  
> -#define __ARM_SETUP_STACK(stack_top) \
> -	__emit_entry_prologue(0x14000002	/* b pc+0x8 */,		\
> +#define __ARM_SETUP_STACK(name, stack_top) \
> +	__emit_entry_prologue(name, 0x14000002	/* b pc+0x8 */,		\
>  			      stack_top		/* 32-bit literal */,	\
>  			      0x18ffffe9	/* ldr w9, top */,	\
>  			      0xb4000049	/* cbz x9, pc+0x8 */,	\
>  			      0x9100013f	/* mov sp, x9 */)
>  #else
> -#define __ARM_SETUP_STACK(stack_top) if (stack_top) arm_setup_stack(stack_top)
> +#define __ARM_SETUP_STACK(name, stack_top) if (stack_top) arm_setup_stack(stack_top)
>  #endif
>  
>  /*
> @@ -174,7 +175,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
>  				(ulong r0, ulong r1, ulong r2)		\
>  		{							\
>  			__barebox_arm_head();				\
> -			__ARM_SETUP_STACK(stack_top);			\
> +			__ARM_SETUP_STACK(name, stack_top);		\
>  			__##name(r0, r1, r2);				\
>  		}							\
>  		static void noinline __##name				\
> @@ -184,7 +185,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
>  	static void ____##name(ulong, ulong, ulong);			\
>  	ENTRY_FUNCTION(name, arg0, arg1, arg2)				\
>  	{								\
> -		__ARM_SETUP_STACK(stack_top);				\
> +		__ARM_SETUP_STACK(name, stack_top);			\
>  		____##name(arg0, arg1, arg2);				\
>  	}								\
>  	static void noinline ____##name					\
> @@ -201,7 +202,7 @@ static inline unsigned long arm_mem_barebox_image(unsigned long membase,
>  				(ulong r0, ulong r1, ulong r2)		\
>  		{							\
>  			__barebox_arm_head();				\
> -			__ARM_SETUP_STACK(0);				\
> +			__ARM_SETUP_STACK(name, 0);			\
>  			__##name(r0, r1, r2);				\
>  		}							\
>  		static void NAKED noinline __##name			\


-- 
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-5555 |


From bst at pengutronix.de  Fri Sep  9 07:39:15 2022
From: bst at pengutronix.de (Bastian Krause)
Date: Fri,  9 Sep 2022 16:39:15 +0200
Subject: [PATCH] ARM: i.MX23: fix memory size calulcation
Message-ID: <20220909143915.4081275-1-bst@pengutronix.de>

According to the i.MX233 Reference Manual (i.MX233RM, Rev. 4, 03 April
2009) section "14.1.1 AHB Address Ranges", the formula to calculate the
DRAM memory size is:

  dram_memory_available = 2 * 2^col * 2^row * (# dram_devices) * (# banks_per_device)

The calulcation in barebox misses the first factor, so the result is
only half as big as it should be.

On an iMX233 OLinuXino board the following errors can be observed:

  mmu: Critical Error: Can't request SDRAM region for ttb at 43fe4000
  Error: Cannot request SDRAM region for stack

The faulty calulcation leads to 32 MB being detected (as seen in the
output of `iomem`), although 64 MB should be available (as passed to
barebox_arm_entry() in lowlevel code).

Fix the memory calculation by adding the missing factor 2.

Fixes: 7158c5987e6 ("ARM: i.MX23: Add memory size detection")
Signed-off-by: Bastian Krause <bst at pengutronix.de>
Signed-off-by: J?rgen Borleis <jbe at pengutronix.de>
---
 arch/arm/mach-mxs/include/mach/imx23.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-mxs/include/mach/imx23.h b/arch/arm/mach-mxs/include/mach/imx23.h
index bdd3ae4407a..03eddabed0a 100644
--- a/arch/arm/mach-mxs/include/mach/imx23.h
+++ b/arch/arm/mach-mxs/include/mach/imx23.h
@@ -25,7 +25,7 @@ static inline u32 imx23_get_memsize(void)
 	cs0 = FIELD_GET(DRAM_CTL14_CS0_EN, ctl14);
 	cs1 = FIELD_GET(DRAM_CTL14_CS1_EN, ctl14);
 
-	return (1 << columns) * (1 << rows) * banks * (cs0 + cs1);
+	return 2 * (1 << columns) * (1 << rows) * banks * (cs0 + cs1);
 }
 
 #endif /* __MACH_IMX23_H */
-- 
2.30.2



From sha at pengutronix.de  Sun Sep 11 23:21:02 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 08:21:02 +0200
Subject: [PATCH] ARM: i.MX23: fix memory size calulcation
In-Reply-To: <20220909143915.4081275-1-bst@pengutronix.de>
References: <20220909143915.4081275-1-bst@pengutronix.de>
Message-ID: <20220912062102.GC24324@pengutronix.de>

On Fri, Sep 09, 2022 at 04:39:15PM +0200, Bastian Krause wrote:
> According to the i.MX233 Reference Manual (i.MX233RM, Rev. 4, 03 April
> 2009) section "14.1.1 AHB Address Ranges", the formula to calculate the
> DRAM memory size is:
> 
>   dram_memory_available = 2 * 2^col * 2^row * (# dram_devices) * (# banks_per_device)
> 
> The calulcation in barebox misses the first factor, so the result is
> only half as big as it should be.
> 
> On an iMX233 OLinuXino board the following errors can be observed:
> 
>   mmu: Critical Error: Can't request SDRAM region for ttb at 43fe4000
>   Error: Cannot request SDRAM region for stack
> 
> The faulty calulcation leads to 32 MB being detected (as seen in the
> output of `iomem`), although 64 MB should be available (as passed to
> barebox_arm_entry() in lowlevel code).
> 
> Fix the memory calculation by adding the missing factor 2.
> 
> Fixes: 7158c5987e6 ("ARM: i.MX23: Add memory size detection")
> Signed-off-by: Bastian Krause <bst at pengutronix.de>
> Signed-off-by: J?rgen Borleis <jbe at pengutronix.de>
> ---
>  arch/arm/mach-mxs/include/mach/imx23.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied to master, thanks

Sascha

> 
> diff --git a/arch/arm/mach-mxs/include/mach/imx23.h b/arch/arm/mach-mxs/include/mach/imx23.h
> index bdd3ae4407a..03eddabed0a 100644
> --- a/arch/arm/mach-mxs/include/mach/imx23.h
> +++ b/arch/arm/mach-mxs/include/mach/imx23.h
> @@ -25,7 +25,7 @@ static inline u32 imx23_get_memsize(void)
>  	cs0 = FIELD_GET(DRAM_CTL14_CS0_EN, ctl14);
>  	cs1 = FIELD_GET(DRAM_CTL14_CS1_EN, ctl14);
>  
> -	return (1 << columns) * (1 << rows) * banks * (cs0 + cs1);
> +	return 2 * (1 << columns) * (1 << rows) * banks * (cs0 + cs1);
>  }
>  
>  #endif /* __MACH_IMX23_H */
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 00:16:07 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 09:16:07 +0200
Subject: [PATCH] of: implement of_prepend_property
In-Reply-To: <20220909074050.3875659-1-a.fatoum@pengutronix.de>
References: <20220909074050.3875659-1-a.fatoum@pengutronix.de>
Message-ID: <20220912071607.GD24324@pengutronix.de>

On Fri, Sep 09, 2022 at 09:40:50AM +0200, Ahmad Fatoum wrote:
> Like of_append_property for adding at the end of properties, implement
> of_prepend_property for placing data into the front.
> 
> This is especially useful to fixup most-specific compatibles into
> existing nodes.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/of/base.c           | 35 +++++++++++++++++++++++++++++++++++
>  include/of.h                |  8 ++++++++
>  test/self/of_manipulation.c |  2 +-
>  3 files changed, 44 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 212b226eb55c..e208949b08bd 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2378,6 +2378,41 @@ int of_append_property(struct device_node *np, const char *name, const void *val
>  	return 0;
>  }
>  
> +int of_prepend_property(struct device_node *np, const char *name, const void *val, int len)
> +{
> +	struct property *pp;
> +	int orig_len;
> +	const void *orig_buf;
> +	void *buf;
> +
> +	if (!np)
> +		return -ENOENT;
> +
> +	pp = of_find_property(np, name, NULL);
> +	if (!pp) {
> +		of_new_property(np, name, val, len);
> +		return 0;
> +	}
> +
> +	orig_len = pp->length;
> +	buf = realloc(pp->value, orig_len + len);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	orig_buf = pp->value_const ?: buf;
> +	if (orig_buf) {

orig_buf is always non NULL here.

> +		memmove(buf + len, orig_buf, orig_len);
> +		pp->value_const = NULL;
> +	}
> +
> +	memcpy(buf, val, len);
> +
> +	pp->value = buf;
> +	pp->length += len;
> +
> +	return 0;
> +}

How about a bit more straight forward variant like this:

int of_prepend_property(struct device_node *np, const char *name, const void *val, int len)
{
	struct property *pp;
	int oldlen = 0;

	pp = of_find_property(np, name, &oldlen);
	if (!pp) {
		of_new_property(np, name, val, len);
		return 0;
	}

	oldval = of_property_get_value(pp);

	buf = malloc(len + oldlen);
	if (!buf)
		return -ENOMEM;

	memcpy(buf, val, len);
	memcpy(buf + len, oldval, oldlen);

	free(pp->value);
	pp->value = buf;
	pp->length = len + oldlen;
	pp->value_const = NULL;

	return 0;
}

Sascha

-- 
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-5555 |


From s.hauer at pengutronix.de  Mon Sep 12 01:01:52 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 10:01:52 +0200
Subject: Makefile.lib: cmd_dtc: warning: missing whitespace after the
 macro name
In-Reply-To: <20220907112118.71575e3650222736432b3086@gmail.com>
References: <20220907112118.71575e3650222736432b3086@gmail.com>
Message-ID: <20220912080152.GE24324@pengutronix.de>

On Wed, Sep 07, 2022 at 11:21:18AM +0300, Antony Pavlov wrote:
> Hi Everyone!
> 
> During MIPS ath79_defconfig build I have a 'missing whitespace after the macro name' warning:
> 
>   AS [P]  arch/mips/dts/ar9331_tl_mr3020.dtb.pbl.o
>   DTC     arch/mips/dts/ar9344-tl-wdr4300-v1.7.dtb
> <stdin>:1:9: warning: missing whitespace after the macro name
>   XZKERN  arch/mips/dts/ar9344-tl-wdr4300-v1.7.dtb.z
> 
> E.g. see https://gitlab.com/frantony/barebox/-/jobs/2969826747#L47
> 
> The reason is the scripts/Makefile.lib generates a C macro with the point symbol in the macro name because the arch/mips/dts/ar9344-tl-wdr4300-v1.7.dts file name contains the point symbol before '.dts', as a result we have:
> 
>   #define ar9344_tl_wdr4300_v1.7_dts 1
> 
> e.g.
> 
>   barebox$ grep -RHn -o "define ar9344_tl_wdr4300_v1.* 1" . 2>/dev/null
>   ./arch/mips/dts/.ar9344-tl-wdr4300-v1.7.dtb.cmd:1:define ar9344_tl_wdr4300_v1.7_dts 1
> 
> cmd_dtc in scripts/Makefile.lib substitutes the '-' symbols with the '_' symbols but do nothing with other unwanted C preprocessor macro name symbols.
> 
> It looks like the linux kernel has no problems with extra point symbols in dts file names, there are several files with extra dot in dts:
> 
>   barebox$ find dts/ -iname '*.*.dts' | wc -l
>   33
> 
> So we have to fix Makefile.lib.
> 
> This simple patch fixes the warning problem:
> 
> diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> index 16308497b84..2f79656c1e9 100644
> --- a/scripts/Makefile.lib
> +++ b/scripts/Makefile.lib
> @@ -363,7 +363,7 @@ $(obj)/%.dtb.z: $(obj)/%.dtb FORCE
>  dts-frags = $(subst $(quote),,$(CONFIG_EXTERNAL_DTS_FRAGMENTS))
>  quiet_cmd_dtc = DTC     $@
>  # For compatibility between make 4.2 and 4.3
> -cmd_dtc = /usr/bin/env echo -e '$(pound)define $(subst -,_,$(*F))_dts 1\n'$(foreach f,$< $(dts-frags),'$(pound)include "$(f)"\n') | \
> +cmd_dtc = /usr/bin/env echo -e '$(pound)define $(subst -,_,$(subst .,_,$(*F)))_dts 1\n'$(foreach f,$< $(dts-frags),'$(pound)include "$(f)"\n') | \
>  	$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) - ; \
>  	$(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
>  		-i $(srctree)/arch/$(SRCARCH)/dts $(DTC_FLAGS) \
> 
> I suppose that this simple patch may lead to some undesirable side effects.

One side effect is that this gets even less readable.

Another one would be that two dts filenames which only differ in the
usage of '.' and '_' would result in the same define, but I think that
case is negligible as this define is unused in barebox itself. It could
be used by external dts fragments passed in via CONFIG_EXTERNAL_DTS_FRAGMENTS.

Other than that, what side effects are you afraid of?

Sascha

-- 
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-5555 |


From antonynpavlov at gmail.com  Mon Sep 12 01:44:23 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:23 +0300
Subject: [PATCH 0/7] Documentation misc fixes
Message-ID: <20220912084430.84451-1-antonynpavlov@gmail.com>

Antony Pavlov (7):
  Documentation: OKUD Max9331: fix sphinx warning
  Documentation: Altera SOCFPGA FPGA Manager: fix sphinx error
  Documentation: Altera FPGAs in passive-serial mode: fix sphinx issues
  Documentation: barebox DT aliases: fix sphinx issues
  Documentation: barebox environment: fix list rendering
  Documentation: Common leds properties: fix 'panic-indicator' list
    entry rendering
  Documentation: Voltage/Current Regulators: fix sphinx error

 Documentation/boards/mips/max9331.rst                       | 2 +-
 Documentation/devicetree/bindings/barebox/aliases.rst       | 3 ++-
 .../devicetree/bindings/barebox/barebox,environment.rst     | 1 +
 .../devicetree/bindings/firmware/altr,passive-serial.rst    | 1 +
 .../devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst  | 6 ++++--
 Documentation/devicetree/bindings/leds/common.rst           | 2 +-
 Documentation/devicetree/bindings/regulator/regulator.rst   | 1 +
 7 files changed, 11 insertions(+), 5 deletions(-)

-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:44:25 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:25 +0300
Subject: [PATCH 2/7] Documentation: Altera SOCFPGA FPGA Manager: fix sphinx error
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220912084430.84451-3-antonynpavlov@gmail.com>

sphinx error:

  Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst:10:
   ERROR: Unexpected indentation.

Insert necessary whitespaces and empty lines to form correct
nested lists structure.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 .../devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst  | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
index 9f7de6b9858..478e8e6fc44 100644
--- a/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
+++ b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
@@ -5,10 +5,12 @@ This binding defines the FPGA Manager on Altera SOCFPGAs. This is used to upload
 the firmware to the FPGA part of the SoC.
 
 Required properties:
+
 - ``compatible``: shall be ``"altr,socfpga-fpga-mgr"``
 - ``reg``: Must contain 2 register ranges:
-	1. The control address space of the FPGA manager.
-	2. The configuration data address space where the firmware data is written to.
+
+  1. The control address space of the FPGA manager.
+  2. The configuration data address space where the firmware data is written to.
 
 Example:
 
-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:44:26 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:26 +0300
Subject: [PATCH 3/7] Documentation: Altera FPGAs in passive-serial mode: fix sphinx issues
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220912084430.84451-4-antonynpavlov@gmail.com>

sphinx issues:

  Documentation/devicetree/bindings/firmware/altr,passive-serial.rst:10:
    ERROR: Unexpected indentation.
  Documentation/devicetree/bindings/firmware/altr,passive-serial.rst:11:
    WARNING: Block quote ends without a blank line; unexpected unindent.

Insert necessary empty line to fix the problem.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 .../devicetree/bindings/firmware/altr,passive-serial.rst         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst b/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
index 1012137bc93..cbddd700ce9 100644
--- a/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
+++ b/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
@@ -6,6 +6,7 @@ passive serial mode. This is used to upload the firmware and
 to start the FPGA.
 
 Required properties:
+
 - ``compatible``: shall be ``"altr,fpga-passive-serial"`` or
   ``"altr,fpga-arria10-passive-serial"`` for Arria 10
 - ``reg``: SPI chip select
-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:44:27 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:27 +0300
Subject: [PATCH 4/7] Documentation: barebox DT aliases: fix sphinx issues
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220912084430.84451-5-antonynpavlov@gmail.com>

sphinx issues:

  Documentation/devicetree/bindings/barebox/aliases.rst:8:
    ERROR: Unexpected indentation.
  Documentation/devicetree/bindings/barebox/aliases.rst:12:
    WARNING: Definition list ends without a blank line; unexpected unindent.
  Documentation/devicetree/bindings/barebox/aliases.rst:13:
    WARNING: Definition list ends without a blank line; unexpected unindent.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 Documentation/devicetree/bindings/barebox/aliases.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/barebox/aliases.rst b/Documentation/devicetree/bindings/barebox/aliases.rst
index 527cc85ef69..e6face2c331 100644
--- a/Documentation/devicetree/bindings/barebox/aliases.rst
+++ b/Documentation/devicetree/bindings/barebox/aliases.rst
@@ -2,9 +2,10 @@ barebox DT aliases
 ==================
 
 barebox can use the properties in the ``/aliases`` node to arrive
-at deterministic names for devices, e.g.::
+at deterministic names for devices, e.g.:
 
 .. code-block:: none
+
    / {
    	aliases {
    		mmc0 = &sdhci;
-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:44:29 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:29 +0300
Subject: [PATCH 6/7] Documentation: Common leds properties: fix 'panic-indicator' list entry rendering
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220912084430.84451-7-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 Documentation/devicetree/bindings/leds/common.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/leds/common.rst b/Documentation/devicetree/bindings/leds/common.rst
index 911a55f4f66..09b4e401bc2 100644
--- a/Documentation/devicetree/bindings/leds/common.rst
+++ b/Documentation/devicetree/bindings/leds/common.rst
@@ -14,4 +14,4 @@ Common leds properties
   from the node name (excluding the unit address).
 
 * ``panic-indicator`` - This property specifies that the LED should be used as a
- panic indicator.
+  panic indicator.
-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:44:24 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:24 +0300
Subject: [PATCH 1/7] Documentation: OKUD Max9331: fix sphinx warning
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220912084430.84451-2-antonynpavlov@gmail.com>

sphinx warning:

  Documentation/boards/mips/max9331.rst:129: WARNING:
    Pygments lexer name 'assembly' is not known

Use pygments lexer for Gas (AT&T) assembly code, see
https://pygments.org/docs/lexers/#lexers-for-assembly-languages
for details.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 Documentation/boards/mips/max9331.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/boards/mips/max9331.rst b/Documentation/boards/mips/max9331.rst
index f09dabc2da1..f7529f9874d 100644
--- a/Documentation/boards/mips/max9331.rst
+++ b/Documentation/boards/mips/max9331.rst
@@ -126,7 +126,7 @@ it jump to 0x9f020000 where the first instruction of barebox.
 This is usefull when debug with jtag or choosing different bootloaders.
 or even boot kernel without bootloader.
 
-.. code-block:: assembly
+.. code-block:: asm
 
  lui  ra, 0x9f02
  jr   ra
-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:44:30 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:30 +0300
Subject: [PATCH 7/7] Documentation: Voltage/Current Regulators: fix sphinx error
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220912084430.84451-8-antonynpavlov@gmail.com>

sphinx error:

    Documentation/devicetree/bindings/regulator/regulator.rst:8:
      ERROR: Unexpected indentation.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 Documentation/devicetree/bindings/regulator/regulator.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/regulator/regulator.rst b/Documentation/devicetree/bindings/regulator/regulator.rst
index 9afc020acd3..754c4743286 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.rst
+++ b/Documentation/devicetree/bindings/regulator/regulator.rst
@@ -4,6 +4,7 @@ Voltage/Current Regulators
 In addition to the upstream bindings, another property is added:
 
 Optional properties:
+
 - ``barebox,allow-dummy-supply`` : A property to allow usage of dummy power
   regulator. This can be added to regulator nodes, whose drivers are not yet
   supported. It will rely on regulator reset defaults and use of dummy regulator
-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:44:28 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:44:28 +0300
Subject: [PATCH 5/7] Documentation: barebox environment: fix list rendering
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220912084430.84451-6-antonynpavlov@gmail.com>

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 .../devicetree/bindings/barebox/barebox,environment.rst          | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/barebox/barebox,environment.rst b/Documentation/devicetree/bindings/barebox/barebox,environment.rst
index 918efd15f55..8a57bf1add8 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,environment.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,environment.rst
@@ -9,6 +9,7 @@ Required properties:
 * ``device-path``: path to the device environment is on
 
 Optional properties:
+
 * ``file-path``: path to a file in the device named by device-path
 
 The device-path is a multistring property. The first string should contain
-- 
2.37.2



From antonynpavlov at gmail.com  Mon Sep 12 01:46:27 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:46:27 +0300
Subject: [RFC] Documentation/conf.py: fix copyright years
Message-ID: <20220912084627.84575-1-antonynpavlov@gmail.com>

N.B. N-dash is used!

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 Documentation/conf.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/conf.py b/Documentation/conf.py
index bcd8633c919..5fb8b07c380 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -44,7 +44,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'barebox'
-copyright = u'2014, The barebox project'
+copyright = u'2014?2022, The barebox project'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
-- 
2.37.2



From sha at pengutronix.de  Mon Sep 12 01:50:17 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 10:50:17 +0200
Subject: [PATCH] of: platform: propagate
 of_devices_ensure_probed_by(name|property) errors
In-Reply-To: <20220905115944.1911301-1-a.fatoum@pengutronix.de>
References: <20220905115944.1911301-1-a.fatoum@pengutronix.de>
Message-ID: <20220912085017.GG24324@pengutronix.de>

On Mon, Sep 05, 2022 at 01:59:44PM +0200, Ahmad Fatoum wrote:
> The of_devices_ensure_probed_by functions are expected to return an
> error code after iterating over all matching devices should any device
> have failed its of_device_ensure_probed. Doing this unearths one common
> failure: a matching node has status = "disabled". These will have
> of_device_ensure_probed return -ENODEV, which makes sense for users
> wanting to ensure a specific device is probed, but doesn't when
> iterating over multiple nodes.
> 
> We already have of_devices_ensure_probed_by_dev_id, which does an early
> of_device_is_available check, so do likewise for the other to
> ensure_probed_by_* functions.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/of/platform.c | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index dc784ea8e550..a9a5d4c2daf2 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -525,12 +525,15 @@ int of_devices_ensure_probed_by_property(const char *property_name)
>  		return 0;
>  
>  	for_each_node_with_property(node, property_name) {
> -		ret = of_device_ensure_probed(node);
> +		if (!of_device_is_available(node))
> +			continue;
> +
> +		err = of_device_ensure_probed(node);
>  		if (err)
>  			ret = err;
>  	}
>  
> -	return 0;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(of_devices_ensure_probed_by_property);
>  
> @@ -543,12 +546,15 @@ int of_devices_ensure_probed_by_name(const char *name)
>  		return 0;
>  
>  	for_each_node_by_name(node, name) {
> -		ret = of_device_ensure_probed(node);
> +		if (!of_device_is_available(node))
> +			continue;
> +
> +		err = of_device_ensure_probed(node);
>  		if (err)
>  			ret = err;
>  	}
>  
> -	return 0;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(of_devices_ensure_probed_by_name);
>  
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From antonynpavlov at gmail.com  Mon Sep 12 01:50:47 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 11:50:47 +0300
Subject: [PATCH next] Documentation: filesystems: tftp: fix code blocks
Message-ID: <20220912085047.84819-1-antonynpavlov@gmail.com>

The patch fixes these sphinx errors:

  Documentation/filesystems/tftp.rst:44: ERROR: Error in "code-block" directive:
    maximum 1 argument(s) allowed, 3 supplied.
  Documentation/filesystems/tftp.rst:53: ERROR: Error in "code-block" directive:
    maximum 1 argument(s) allowed, 4 supplied.

Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
---
 Documentation/filesystems/tftp.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/filesystems/tftp.rst b/Documentation/filesystems/tftp.rst
index 8929213d3c4..e88ad3dd4c8 100644
--- a/Documentation/filesystems/tftp.rst
+++ b/Documentation/filesystems/tftp.rst
@@ -42,6 +42,7 @@ the opposite effect.  Performance depends on:
    100 Mb/s) it had to be reduced to
 
    .. code-block:: console
+
      global tftp.windowsize=26
 
    for example.
@@ -51,6 +52,7 @@ the opposite effect.  Performance depends on:
    example, the `fec-imx` driver reserves place for
 
    .. code-block:: c
+
      #define FEC_RBD_NUM		64
 
    packets before they are dropped
-- 
2.37.2



From sha at pengutronix.de  Mon Sep 12 01:54:54 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 10:54:54 +0200
Subject: [PATCH] of: implement of_rename_property()
In-Reply-To: <20220905103639.1750714-1-a.fatoum@pengutronix.de>
References: <20220905103639.1750714-1-a.fatoum@pengutronix.de>
Message-ID: <20220912085454.GH24324@pengutronix.de>

On Mon, Sep 05, 2022 at 12:36:39PM +0200, Ahmad Fatoum wrote:
> It's often desirable to have the same barebox binary for multiple
> variants. DT-level differences between the variants are often handled
> by having extra device tree nodes that are disabled by default and
> patched as appropriate by board code. It can be useful to have a finer
> granularity for patching though, that covers only a select property, e.g.:
> 
>    usbotg1 {
> 	vbus-supply = <&reg_vbus_common>;
> 	vendor,specialvariant-vbus-supply = <&reg_vbus_specialvariant>;
>    };
> 
> The new of_rename_property allows board code to easily activate the
> alternative vbus supply on the specialvariant:
> 
>   of_rename_property(np, "vendor,specialvariant-vbus-supply",
> 			 "vbus-supply");
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/of/base.c             | 16 ++++++++++++++++
>  include/of.h                  |  8 ++++++++
>  test/self/of_manipulation.c   | 10 ++++++++++
>  test/self/of_manipulation.dts |  6 ++++--
>  4 files changed, 38 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 6a51dd71793d..212b226eb55c 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2301,6 +2301,22 @@ void of_delete_property(struct property *pp)
>  	free(pp);
>  }
>  
> +struct property *of_rename_property(struct device_node *np,
> +				    const char *old_name, const char *new_name)
> +{
> +	struct property *pp;
> +
> +	pp = of_find_property(np, old_name, NULL);
> +	if (!pp)
> +		return NULL;
> +
> +	of_property_write_bool(np, new_name, false);
> +
> +	free(pp->name);
> +	pp->name = xstrdup(new_name);
> +	return pp;
> +}
> +
>  /**
>   * of_set_property - create a property for a given node
>   * @node - the node
> diff --git a/include/of.h b/include/of.h
> index 29df7d912b33..153e75d3e51d 100644
> --- a/include/of.h
> +++ b/include/of.h
> @@ -143,6 +143,8 @@ extern struct property *of_new_property_const(struct device_node *node,
>  extern struct property *__of_new_property(struct device_node *node,
>  					  const char *name, void *data, int len);
>  extern void of_delete_property(struct property *pp);
> +extern struct property *of_rename_property(struct device_node *np,
> +					   const char *old_name, const char *new_name);
>  
>  extern struct device_node *of_find_node_by_name(struct device_node *from,
>  	const char *name);
> @@ -550,6 +552,12 @@ static inline void of_delete_property(struct property *pp)
>  {
>  }
>  
> +static inline struct property *of_rename_property(struct device_node *np,
> +						  const char *old_name, const char *new_name)
> +{
> +	return NULL;
> +}
> +
>  static inline int of_property_read_u32_index(const struct device_node *np,
>  				const char *propname, u32 index, u32 *out_value)
>  {
> diff --git a/test/self/of_manipulation.c b/test/self/of_manipulation.c
> index 6eb6062e126b..7e30a60ca687 100644
> --- a/test/self/of_manipulation.c
> +++ b/test/self/of_manipulation.c
> @@ -57,6 +57,16 @@ static void test_of_basics(struct device_node *root)
>  	of_property_write_bool(node1, "property1", true);
>  
>  	assert_equal(node1, node2);
> +
> +	of_property_write_bool(node2, "property1", false);
> +	of_property_write_u32(node2, "property1", 1);
> +	of_property_write_u32(node2, "property2", 2);
> +
> +	of_property_write_u32(node1, "property3", 1);
> +	of_property_write_u32(node1, "property2", 2);
> +	of_rename_property(node1, "property3", "property1");
> +
> +	assert_equal(node1, node2);
>  }
>  
>  static void test_of_property_strings(struct device_node *root)
> diff --git a/test/self/of_manipulation.dts b/test/self/of_manipulation.dts
> index a69d944c1eb5..2cc6773fa98e 100644
> --- a/test/self/of_manipulation.dts
> +++ b/test/self/of_manipulation.dts
> @@ -4,12 +4,14 @@
>  
>  / {
>  	node1 {
> -		property1;
> +		property1 = <1>;
> +		property2 = <2>;
>  		node21 { };
>  	};
>  
>  	node2 {
> -		property1;
> +		property1 = <1>;
> +		property2 = <2>;
>  		node21 { };
>  	};
>  
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 02:04:09 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 11:04:09 +0200
Subject: [PATCH 1/2] i2c: implement of_i2c_register_devices_by_node()
In-Reply-To: <20220905103613.1750340-1-a.fatoum@pengutronix.de>
References: <20220905103613.1750340-1-a.fatoum@pengutronix.de>
Message-ID: <20220912090409.GI24324@pengutronix.de>

On Mon, Sep 05, 2022 at 12:36:12PM +0200, Ahmad Fatoum wrote:
> i2c controllers probe the devices on their bus themselves, so in the
> case the i2c controller was already probed, we currently have no way to
> have it reread the device tree after fixing it up or applying an
> overlay. Add a new helper that retriggers the device creation.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/i2c/i2c.c | 20 ++++++++++++++++++++
>  include/i2c/i2c.h |  1 +
>  2 files changed, 21 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
> index b24fd88f5b39..e70e51618850 100644
> --- a/drivers/i2c/i2c.c
> +++ b/drivers/i2c/i2c.c
> @@ -427,6 +427,12 @@ static void of_i2c_register_devices(struct i2c_adapter *adap)
>  		const __be32 *addr;
>  		int len;
>  
> +		if (n->dev) {
> +			dev_dbg(&adap->dev, "of_i2c: skipping already registered %s\n",
> +				dev_name(n->dev));
> +			continue;
> +		}
> +
>  		of_modalias_node(n, info.type, I2C_NAME_SIZE);
>  
>  		info.of_node = n;
> @@ -452,6 +458,20 @@ static void of_i2c_register_devices(struct i2c_adapter *adap)
>  	}
>  }
>  
> +int of_i2c_register_devices_by_node(struct device_node *node)
> +{
> +	struct i2c_adapter *adap;
> +
> +	adap = of_find_i2c_adapter_by_node(node);
> +	if (!adap)
> +		return -ENODEV;
> +	if (IS_ERR(adap))
> +		return PTR_ERR(adap);
> +
> +	of_i2c_register_devices(adap);
> +	return 0;
> +}
> +
>  /**
>   * i2c_new_dummy - return a new i2c device bound to a dummy driver
>   * @adapter: the adapter managing the device
> diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
> index 7207b1180e1d..f5e2dc511ed1 100644
> --- a/include/i2c/i2c.h
> +++ b/include/i2c/i2c.h
> @@ -295,6 +295,7 @@ static inline int i2c_register_board_info(int busnum,
>  extern int i2c_add_numbered_adapter(struct i2c_adapter *adapter);
>  struct i2c_adapter *i2c_get_adapter(int busnum);
>  struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
> +int of_i2c_register_devices_by_node(struct device_node *node);
>  struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
>  
>  void i2c_parse_fw_timings(struct device_d *dev, struct i2c_timings *t, bool use_defaults);
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From antonynpavlov at gmail.com  Mon Sep 12 02:07:34 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Mon, 12 Sep 2022 12:07:34 +0300
Subject: Makefile.lib: cmd_dtc: warning: missing whitespace after the
 macro name
In-Reply-To: <20220912080152.GE24324@pengutronix.de>
References: <20220907112118.71575e3650222736432b3086@gmail.com>
	<20220912080152.GE24324@pengutronix.de>
Message-ID: <20220912120734.3fa82231ca6d16ba604ee262@gmail.com>

On Mon, 12 Sep 2022 10:01:52 +0200
Sascha Hauer <s.hauer at pengutronix.de> wrote:

Hi Sascha!

> On Wed, Sep 07, 2022 at 11:21:18AM +0300, Antony Pavlov wrote:
> > Hi Everyone!
> > 
> > During MIPS ath79_defconfig build I have a 'missing whitespace after the macro name' warning:
> > 
> >   AS [P]  arch/mips/dts/ar9331_tl_mr3020.dtb.pbl.o
> >   DTC     arch/mips/dts/ar9344-tl-wdr4300-v1.7.dtb
> > <stdin>:1:9: warning: missing whitespace after the macro name
> >   XZKERN  arch/mips/dts/ar9344-tl-wdr4300-v1.7.dtb.z
> > 
> > E.g. see https://gitlab.com/frantony/barebox/-/jobs/2969826747#L47
> > 
> > The reason is the scripts/Makefile.lib generates a C macro with the point symbol in the macro name because the arch/mips/dts/ar9344-tl-wdr4300-v1.7.dts file name contains the point symbol before '.dts', as a result we have:
> > 
> >   #define ar9344_tl_wdr4300_v1.7_dts 1
> > 
> > e.g.
> > 
> >   barebox$ grep -RHn -o "define ar9344_tl_wdr4300_v1.* 1" . 2>/dev/null
> >   ./arch/mips/dts/.ar9344-tl-wdr4300-v1.7.dtb.cmd:1:define ar9344_tl_wdr4300_v1.7_dts 1
> > 
> > cmd_dtc in scripts/Makefile.lib substitutes the '-' symbols with the '_' symbols but do nothing with other unwanted C preprocessor macro name symbols.
> > 
> > It looks like the linux kernel has no problems with extra point symbols in dts file names, there are several files with extra dot in dts:
> > 
> >   barebox$ find dts/ -iname '*.*.dts' | wc -l
> >   33
> > 
> > So we have to fix Makefile.lib.
> > 
> > This simple patch fixes the warning problem:
> > 
> > diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> > index 16308497b84..2f79656c1e9 100644
> > --- a/scripts/Makefile.lib
> > +++ b/scripts/Makefile.lib
> > @@ -363,7 +363,7 @@ $(obj)/%.dtb.z: $(obj)/%.dtb FORCE
> >  dts-frags = $(subst $(quote),,$(CONFIG_EXTERNAL_DTS_FRAGMENTS))
> >  quiet_cmd_dtc = DTC     $@
> >  # For compatibility between make 4.2 and 4.3
> > -cmd_dtc = /usr/bin/env echo -e '$(pound)define $(subst -,_,$(*F))_dts 1\n'$(foreach f,$< $(dts-frags),'$(pound)include "$(f)"\n') | \
> > +cmd_dtc = /usr/bin/env echo -e '$(pound)define $(subst -,_,$(subst .,_,$(*F)))_dts 1\n'$(foreach f,$< $(dts-frags),'$(pound)include "$(f)"\n') | \
> >  	$(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) - ; \
> >  	$(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \
> >  		-i $(srctree)/arch/$(SRCARCH)/dts $(DTC_FLAGS) \
> > 
> > I suppose that this simple patch may lead to some undesirable side effects.
> 
> One side effect is that this gets even less readable.

Yes, you are right :)

> Another one would be that two dts filenames which only differ in the
> usage of '.' and '_' would result in the same define, but I think that
> case is negligible as this define is unused in barebox itself. It could
                                       ^^^^^^^^^^^^^^^^^^^^^^^^
> be used by external dts fragments passed in via CONFIG_EXTERNAL_DTS_FRAGMENTS.
> 
> Other than that, what side effects are you afraid of?

I have an idea that someone relies on these *_dts macros.

Now I see (as you have noted above) that there is no macro users in mainline source tree:

  $ git grep -w .*_dts
  common/Kconfig:   #ifdef foo_board_dts
  scripts/Makefile.lib:cmd_dtc = /usr/bin/env echo -e '$(pound)define $(subst -,_,$(*F))_dts 1\n'$(foreach f,$< $(dts-frags),'$(pound)include "$(f)"\n') | \

-- 
Best regards,
? Antony Pavlov


From sha at pengutronix.de  Mon Sep 12 02:13:22 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 11:13:22 +0200
Subject: [PATCH 0/5] commands: gpio: add controller as optional argument
In-Reply-To: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
Message-ID: <20220912091322.GJ24324@pengutronix.de>

On Mon, Sep 05, 2022 at 12:35:41PM +0200, Ahmad Fatoum wrote:
> gpioinfo currently displays all GPIOs and the rest of the GPIO commands
> like gpio_direction_output expects either a GPIO label or a global GPIO
> number to act upon.
> 
> With this series, the gpio commands now accept an optional argument,
> e.g.:
> 
>   gpioinfo gpio4
>   gpio_direction_output -d gpio4 20 1
> 
> Controllers are identified by either device name, full path to the
> device tree node backing it or an alias pointing at it.
> 
> Ahmad Fatoum (5):
>   gpiolib: implement gpio_get_chip_by_dev()
>   of: platform: optimize of_find_device_by_node when deep probing
>   driver: implement find_device() helper
>   commands: gpio: add -d argument to set/get commands
>   gpiolib: gpioinfo: add optional CONTROLLER command line argument

Applied, thanks

Sascha

> 
>  commands/gpio.c        | 51 +++++++++++++++++++++++++++++-------
>  drivers/base/driver.c  | 16 ++++++++++++
>  drivers/gpio/gpiolib.c | 59 ++++++++++++++++++++++++++++++++----------
>  drivers/of/platform.c  |  3 +++
>  include/driver.h       |  5 ++++
>  include/gpio.h         |  1 +
>  6 files changed, 111 insertions(+), 24 deletions(-)
> 
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 02:16:08 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 11:16:08 +0200
Subject: [PATCH 0/2] of: overlay: avoid potential null pointer exception
In-Reply-To: <20220905100717.150557-1-michael.riesch@wolfvision.net>
References: <20220905100717.150557-1-michael.riesch@wolfvision.net>
Message-ID: <20220912091608.GK24324@pengutronix.de>

On Mon, Sep 05, 2022 at 12:07:15PM +0200, Michael Riesch wrote:
> Hi all,
> 
> The function of_overlay_fix_path returns NULL in certain error cases but
> of_overlay_apply_symbols (which is the only caller) does not check the
> return value. For broken overlays this may result in a null pointer
> exception. Fix this by checking the return value and inform the user
> what exactly went wrong. To this end, improve the error handling in
> of_overlay_apply_tree.
> 
> The thread [0] gives a bit more context.
> 
> Best regards,
> Michael
> 
> [0] https://lore.barebox.org/barebox/95ff064f-aa11-c1ce-9d41-e38f2040c565 at wolfvision.net/T/#u
> 
> Michael Riesch (2):
>   of: overlay: improve error handling in of_overlay_apply_tree
>   of: overlay: avoid potential null pointer exception

Applied, thanks

Sascha

> 
>  drivers/of/overlay.c | 18 +++++++++++++-----
>  1 file changed, 13 insertions(+), 5 deletions(-)
> 
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 02:23:33 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 11:23:33 +0200
Subject: [PATCH 01/32] clk: define stub implementation for clk_get_parent
In-Reply-To: <20220905095557.596891-2-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
 <20220905095557.596891-2-a.fatoum@pengutronix.de>
Message-ID: <20220912092333.GL24324@pengutronix.de>

On Mon, Sep 05, 2022 at 11:55:26AM +0200, Ahmad Fatoum wrote:
> To make it easier to build drivers utilizing clk_get_parent on sandbox
> for static analysis, provide a stub implementation of the function.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  include/linux/clk.h | 20 ++++++++++++--------
>  1 file changed, 12 insertions(+), 8 deletions(-)

This will break architectures which do not use the common clk framework
and implement clk_get_parent themselves.

Fortunately there's only one architecture left doing this: AT91

Sascha

> 
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 42c64d650d1f..b18fc733843d 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -128,14 +128,6 @@ int clk_hw_set_rate(struct clk_hw *hw, unsigned long rate);
>  int clk_set_parent(struct clk *clk, struct clk *parent);
>  int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *hwp);
>  
> -/**
> - * clk_get_parent - get the parent clock source for this clock
> - * @clk: clock source
> - *
> - * Returns struct clk corresponding to parent clock source, or
> - * valid IS_ERR() condition containing errno.
> - */
> -struct clk *clk_get_parent(struct clk *clk);
>  struct clk_hw *clk_hw_get_parent(struct clk_hw *hw);
>  
>  int clk_set_phase(struct clk *clk, int degrees);
> @@ -658,6 +650,14 @@ struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
>  struct clk *of_clk_get(struct device_node *np, int index);
>  struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
>  struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
> +/**
> + * clk_get_parent - get the parent clock source for this clock
> + * @clk: clock source
> + *
> + * Returns struct clk corresponding to parent clock source, or
> + * valid IS_ERR() condition containing errno.
> + */
> +struct clk *clk_get_parent(struct clk *clk);
>  unsigned int of_clk_get_parent_count(struct device_node *np);
>  int of_clk_parent_fill(struct device_node *np, const char **parents,
>  		       unsigned int size);
> @@ -717,6 +717,10 @@ static inline unsigned int of_clk_get_parent_count(struct device_node *np)
>  {
>  	return 0;
>  }
> +static inline struct clk *clk_get_parent(struct clk *clk)
> +{
> +	return ERR_PTR(-ENOENT);
> +}
>  static inline int of_clk_init(struct device_node *root,
>  			      const struct of_device_id *matches)
>  {
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 02:41:18 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 11:41:18 +0200
Subject: [PATCH 11/32] of: silence warning about never-read error
 assignment
In-Reply-To: <20220905095557.596891-12-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
 <20220905095557.596891-12-a.fatoum@pengutronix.de>
Message-ID: <20220912094118.GM24324@pengutronix.de>

On Mon, Sep 05, 2022 at 11:55:36AM +0200, Ahmad Fatoum wrote:
> err is assigned specific error codes, but they are not propagated and
> instead NULL is returned for error. Make it explicit that we handle all
> errors the same by typecasting to (void).

This warning likely goes back to assigning the variable 'err' right
before jumping to the label 'err':

	err = -EINVAL;
	goto err;

The assignment is indeed unused. We should remove this assignment
rather than suppressing the resulting warning.

Sascha

> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/of/resolver.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
> index 2457ae96a412..510d36f95192 100644
> --- a/drivers/of/resolver.c
> +++ b/drivers/of/resolver.c
> @@ -272,6 +272,7 @@ out:
>  err:
>  	of_delete_node(result);
>  
> +	(void)err;
>  	return NULL;
>  
>  }
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 02:44:11 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 11:44:11 +0200
Subject: [PATCH 13/32] commands: tutorial: fix memory leak
In-Reply-To: <20220905095557.596891-14-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
 <20220905095557.596891-14-a.fatoum@pengutronix.de>
Message-ID: <20220912094411.GN24324@pengutronix.de>

On Mon, Sep 05, 2022 at 11:55:38AM +0200, Ahmad Fatoum wrote:
> We don't need to duplicate argv[i], because it persists for the lieftime

s/lieftime/lifetime/

> of print_tutorial_step. We can thus drop the strdup and while at it,
> just drop the redundant step variable altogether.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  commands/tutorial.c | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)
> 
> diff --git a/commands/tutorial.c b/commands/tutorial.c
> index 444177764311..afe5b66f0b0a 100644
> --- a/commands/tutorial.c
> +++ b/commands/tutorial.c
> @@ -84,7 +84,6 @@ out:
>  static int do_tutorial_next(int argc, char *argv[])
>  {
>  	int opt, i;
> -	char *step = NULL;
>  	char *oldcwd;
>  	ssize_t ret = 0;
>  	bool is_prev = *argv[0] == 'p';
> @@ -121,14 +120,12 @@ static int do_tutorial_next(int argc, char *argv[])
>  		next_step = next_step > 0 ? next_step - 1 : 0;
>  
>  	if (optind == argc) {
> -		step = steps.gl_pathv[next_step];
> -		ret = print_tutorial_step(step);
> +		ret = print_tutorial_step(steps.gl_pathv[next_step]);
>  		if (ret == 0 && !is_prev)
>  			next_step = (next_step + 1) % steps.gl_pathc;
>  	} else {
>  		for (i = optind; i < argc; i++) {
> -			step = strdup(argv[i]);
> -			ret = print_tutorial_step(step);
> +			ret = print_tutorial_step(argv[i]);
>  			if (ret)
>  				break;
>  		}
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 03:06:00 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 12:06:00 +0200
Subject: [PATCH 00/32] treewide: fix some clang-analyze static analyzer
 warnings
In-Reply-To: <20220905095557.596891-1-a.fatoum@pengutronix.de>
References: <20220905095557.596891-1-a.fatoum@pengutronix.de>
Message-ID: <20220912100600.GA6477@pengutronix.de>

On Mon, Sep 05, 2022 at 11:55:25AM +0200, Ahmad Fatoum wrote:
> I ran scan-build while building barebox for sandbox with clang and
> patched some of the reported issues.
> 
> Ahmad Fatoum (32):
>   clk: define stub implementation for clk_get_parent
>   clk: have SCMI and SiFive clock controllers depend on COMMON_CLK
>   meminfo: support SANDBOX build with DEBUG log level
>   net: phy: micrel: drop useless assignment of dummy read
>   mci: core: drop useless assignment
>   nvmem: core: propagate read failure
>   fs: remove never-read initializer in mount_all()
>   usb: otg: always propagate failure to register parameters
>   usb: dwc2: gracefully handle unknown hs_phy_type
>   state: propagate failure to fixup enum32 into DT
>   of: silence warning about never-read error assignment
>   commands: trigger: drop unused variable
>   commands: tutorial: fix memory leak
>   bthread: fix null pointer dereference in error path
>   common: env: drop never-read initialization
>   of: refactor for of_fixup_reserved_memory() for clarity
>   password: avoid static analyzer false positive
>   regmap-mmio: regmap_mmio_get_min_stride: unify branches for
>     readability
>   crypto: caam - delete unused variable
>   misc: ubootvar: always initialize struct ubootvar_data::flag
>   nvmem: core: drop always true condition
>   of: fdt: gracefully handle out-of-place properties
>   of: overlay: drop unused variable of_overlay_apply_dir()
>   of: partition: drop unused variable
>   serial: ns16550_pci: drop useless assignment
>   phy: core: drop useless else clause
>   fs: ext4: ext_barebox: handle ext_get_inode() errors
>   fs: fat: propagate f_lseek failure
>   fs: drop duplicate follow_managed() call
>   lib: parse_area_spec: guard against NULL pointer dereference
>   net: ping: propagate failure
>   net: fastboot: keep error message initialized at all times

Applied 2-10 and 12-32, thanks

Sascha

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 03:11:29 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 12:11:29 +0200
Subject: [PATCH 0/3] tftp fixups
In-Reply-To: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
References: <20220905085658.3854939-1-enrico.scholz@sigma-chemnitz.de>
Message-ID: <20220912101129.GB6477@pengutronix.de>

On Mon, Sep 05, 2022 at 10:56:55AM +0200, Enrico Scholz wrote:
> Fixups for the "tftp" branch in next.
> 
> Enrico Scholz (3):
>   fixup! tftp: implement 'windowsize' (RFC 7440) support
>   fixup! tftp: detect out-of-memory situations
>   tftp: make read() fail in error case
> 
>  fs/tftp.c | 29 ++++++++++++++++++++++-------
>  1 file changed, 22 insertions(+), 7 deletions(-)

Applied, thanks

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 03:12:49 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 12:12:49 +0200
Subject: [PATCH] commands: add pm_domain for listing power domains
In-Reply-To: <20220905070448.539531-1-a.fatoum@pengutronix.de>
References: <20220905070448.539531-1-a.fatoum@pengutronix.de>
Message-ID: <20220912101249.GC6477@pengutronix.de>

On Mon, Sep 05, 2022 at 09:04:48AM +0200, Ahmad Fatoum wrote:
> Like the regulator command, this new pm_domain command gives an easy
> way for listing registered power domains and whether barebox had them
> activated.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  commands/Kconfig     |  8 ++++++++
>  commands/Makefile    |  1 +
>  commands/pm_domain.c | 18 ++++++++++++++++++
>  drivers/base/power.c | 10 ++++++++++
>  include/pm_domain.h  |  2 ++
>  5 files changed, 39 insertions(+)
>  create mode 100644 commands/pm_domain.c

Applied, thanks

Sascha

> 
> diff --git a/commands/Kconfig b/commands/Kconfig
> index 3e21dc4c0500..9894ecb9aa31 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -240,6 +240,14 @@ config CMD_REGULATOR
>  	  the regulator command lists the currently registered regulators and
>  	  their current state.
>  
> +config CMD_PM_DOMAIN
> +	bool
> +	depends on PM_GENERIC_DOMAINS
> +	prompt "pm_domain command"
> +	help
> +	  The pm_domain command lists the currently registered power domains and
> +	  their current state.
> +
>  config CMD_NVMEM
>  	bool
>  	depends on NVMEM
> diff --git a/commands/Makefile b/commands/Makefile
> index 0aae8893d696..068fbb32dad7 100644
> --- a/commands/Makefile
> +++ b/commands/Makefile
> @@ -116,6 +116,7 @@ obj-$(CONFIG_CMD_READF)		+= readf.o
>  obj-$(CONFIG_CMD_MENUTREE)	+= menutree.o
>  obj-$(CONFIG_CMD_2048)		+= 2048.o
>  obj-$(CONFIG_CMD_REGULATOR)	+= regulator.o
> +obj-$(CONFIG_CMD_PM_DOMAIN)	+= pm_domain.o
>  obj-$(CONFIG_CMD_LSPCI)		+= lspci.o
>  obj-$(CONFIG_CMD_IMD)		+= imd.o
>  obj-$(CONFIG_CMD_HWCLOCK)	+= hwclock.o
> diff --git a/commands/pm_domain.c b/commands/pm_domain.c
> new file mode 100644
> index 000000000000..ec8b769df193
> --- /dev/null
> +++ b/commands/pm_domain.c
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +#include <common.h>
> +#include <command.h>
> +#include <pm_domain.h>
> +
> +static int do_pm_domain(int argc, char *argv[])
> +{
> +	pm_genpd_print();
> +
> +	return 0;
> +}
> +
> +BAREBOX_CMD_START(pm_domain)
> +	.cmd		= do_pm_domain,
> +	BAREBOX_CMD_DESC("list power domains")
> +	BAREBOX_CMD_GROUP(CMD_GRP_INFO)
> +BAREBOX_CMD_END
> diff --git a/drivers/base/power.c b/drivers/base/power.c
> index 4a206051b137..3eabf3c897b2 100644
> --- a/drivers/base/power.c
> +++ b/drivers/base/power.c
> @@ -266,3 +266,13 @@ int genpd_dev_pm_attach(struct device_d *dev)
>  	return __genpd_dev_pm_attach(dev, dev->device_node, 0, true);
>  }
>  EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
> +
> +void pm_genpd_print(void)
> +{
> +	struct generic_pm_domain *genpd;
> +
> +	printf("%-20s %6s\n", "name", "active");
> +	list_for_each_entry(genpd, &gpd_list, gpd_list_node)
> +		printf("%-20s %6s\n", genpd->name,
> +		       genpd->status == GPD_STATE_ACTIVE ? "on" : "off");
> +}
> diff --git a/include/pm_domain.h b/include/pm_domain.h
> index 48fd170007fd..ff1aa3751165 100644
> --- a/include/pm_domain.h
> +++ b/include/pm_domain.h
> @@ -54,6 +54,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd, void *gov, bool is_off);
>  int of_genpd_add_provider_simple(struct device_node *np,
>  				 struct generic_pm_domain *genpd);
>  
> +void pm_genpd_print(void);
> +
>  #else
>  
>  static inline int pm_genpd_init(struct generic_pm_domain *genpd,
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 03:14:46 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 12:14:46 +0200
Subject: [PATCH] commands: mm: don't ignore pread() errors for larger
 access sizes
In-Reply-To: <20220902100458.2597350-1-a.fatoum@pengutronix.de>
References: <20220902100458.2597350-1-a.fatoum@pengutronix.de>
Message-ID: <20220912101446.GD6477@pengutronix.de>

On Fri, Sep 02, 2022 at 12:04:58PM +0200, Ahmad Fatoum wrote:
> Error check was before pread was called and because ret was initialized,
> compiler didn't warn about it. Fix this.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  commands/mm.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/commands/mm.c b/commands/mm.c
> index 9ce883964485..8fe87a80a18e 100644
> --- a/commands/mm.c
> +++ b/commands/mm.c
> @@ -16,7 +16,7 @@
>  
>  static int do_mem_mm(int argc, char *argv[])
>  {
> -	int ret = 0;
> +	int ret;
>  	int fd;
>  	char *filename = "/dev/mem";
>  	int mode = O_RWSIZE_4;
> @@ -65,9 +65,9 @@ static int do_mem_mm(int argc, char *argv[])
>  			goto out_write;
>  		break;
>  	case O_RWSIZE_4:
> +		ret = pread(fd, &val32, 4, adr);
>  		if (ret < 0)
>  			goto out_read;
> -		ret = pread(fd, &val32, 4, adr);
>  		val32 &= ~mask;
>  		val32 |= (value & mask);
>  		ret = pwrite(fd, &val32, 4, adr);
> @@ -75,9 +75,9 @@ static int do_mem_mm(int argc, char *argv[])
>  			goto out_write;
>  		break;
>  	case O_RWSIZE_8:
> +		ret = pread(fd, &val64, 8, adr);
>  		if (ret < 0)
>  			goto out_read;
> -		ret = pread(fd, &val64, 8, adr);
>  		val64 &= ~mask;
>  		val64 |= (value & mask);
>  		ret = pwrite(fd, &val64, 8, adr);
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 12 05:01:30 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 14:01:30 +0200
Subject: [PATCH v2 08/10] ARM: mmu: use reserve mem entries to modify maps
In-Reply-To: <20220817114244.1810531-9-a.fatoum@pengutronix.de>
References: <20220817114244.1810531-1-a.fatoum@pengutronix.de>
 <20220817114244.1810531-9-a.fatoum@pengutronix.de>
Message-ID: <20220912120130.GD12909@pengutronix.de>

This patch breaks NAND support on my Phytec i.MX6 board. There are some
problems with this patch, so I ended up reverting it for now.

On Wed, Aug 17, 2022 at 01:42:42PM +0200, Ahmad Fatoum wrote:
> @@ -468,11 +469,28 @@ void __mmu_init(bool mmu_on)
>  	vectors_init();
>  
>  	for_each_memory_bank(bank) {
> +		struct resource *rsv;
> +
>  		create_sections(ttb, bank->start, bank->start + bank->size - 1,
>  				PMD_SECT_DEF_CACHED);
> -		__mmu_cache_flush();
> +
> +		for_each_reserved_region(bank, rsv) {
> +			create_sections(ttb, resource_first_page(rsv),
> +					resource_count_pages(rsv),
> +					attrs_uncached_mem());
> +		}

This operates on 1MiB sections, so everything requiring a finer
granularity will fail here. Not sure if we currently need that, but not
even issuing a warning is not good.

>  	}
>  
> +	/*
> +	 * We could set_ttbr(ttb) here instead and save on the copy, but
> +	 * for now we play it safe, so we don't mess with the older ARMs.
> +	 */
> +	if (oldttb) {
> +		memcpy(oldttb, ttb, ARM_TTB_SIZE);
> +		free(ttb);
> +	}

in the early MMU case the MMU still uses 'oldttb' as ttb whereas 'ttb'
now points to invalid memory. Still functions like arm_create_pte()
still operate on 'ttb'. It looks like a ttb = oldttb is missing here.

Also I wonder when we have to map the reserved regions as execute never,
then the early MMU setup seems broken as well, as that creates a flat
mapping without honoring the reserved regions. Shouldn't that be fixed?

Sascha

-- 
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-5555 |


From a.fatoum at pengutronix.de  Mon Sep 12 08:15:45 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 12 Sep 2022 17:15:45 +0200
Subject: [PATCH v2 08/10] ARM: mmu: use reserve mem entries to modify maps
In-Reply-To: <20220912120130.GD12909@pengutronix.de>
References: <20220817114244.1810531-1-a.fatoum@pengutronix.de>
 <20220817114244.1810531-9-a.fatoum@pengutronix.de>
 <20220912120130.GD12909@pengutronix.de>
Message-ID: <7ef687f0-903c-e194-d3dc-a4c83e9a6efe@pengutronix.de>

Hi,

On 12.09.22 14:01, Sascha Hauer wrote:
> This patch breaks NAND support on my Phytec i.MX6 board. There are some
> problems with this patch, so I ended up reverting it for now.

I wonder why. I see no memory reserves in imx6q-phytec-phycore-som-nand.dts
and the files it includes.

> 
> On Wed, Aug 17, 2022 at 01:42:42PM +0200, Ahmad Fatoum wrote:
>> @@ -468,11 +469,28 @@ void __mmu_init(bool mmu_on)
>>  	vectors_init();
>>  
>>  	for_each_memory_bank(bank) {
>> +		struct resource *rsv;
>> +
>>  		create_sections(ttb, bank->start, bank->start + bank->size - 1,
>>  				PMD_SECT_DEF_CACHED);
>> -		__mmu_cache_flush();
>> +
>> +		for_each_reserved_region(bank, rsv) {
>> +			create_sections(ttb, resource_first_page(rsv),
>> +					resource_count_pages(rsv),
>> +					attrs_uncached_mem());
>> +		}
> 
> This operates on 1MiB sections, so everything requiring a finer
> granularity will fail here. Not sure if we currently need that, but not
> even issuing a warning is not good.

At worst it'd needlessly mark some memory uncached/XN. If users are
affected, they will notice and we can revisit this. I could add a debug
print here.

I need to rework this though, because I see now create_sections differs
between ARM64 and ARM32. On ARM64, it accepts the last address as argument,
while on ARM64, it's the size.. resource_count_pages() is not a nice
name either, because it returns bytes (aligned up to PAGE_SIZE).

> 
>>  	}
>>  
>> +	/*
>> +	 * We could set_ttbr(ttb) here instead and save on the copy, but
>> +	 * for now we play it safe, so we don't mess with the older ARMs.
>> +	 */
>> +	if (oldttb) {
>> +		memcpy(oldttb, ttb, ARM_TTB_SIZE);
>> +		free(ttb);
>> +	}
> 
> in the early MMU case the MMU still uses 'oldttb' as ttb whereas 'ttb'
> now points to invalid memory. Still functions like arm_create_pte()
> still operate on 'ttb'. It looks like a ttb = oldttb is missing here.

Why would ttb point at invalid memory? It's allocated unconditionally
with xmemalign and freed here.

> Also I wonder when we have to map the reserved regions as execute never,
> then the early MMU setup seems broken as well, as that creates a flat
> mapping without honoring the reserved regions. Shouldn't that be fixed?

Yes, see excerpt from cover letter:

"Note that this doesn't yet solve all problems. For example, PPA secure
 monitor installation on Layerscape may happen with CONFIG_MMU_EARLY=y,
 in which case barebox in EL2 may speculate into the secure memory
 before any device tree reserved-memory settings are considered. For this
 reason, both early MMU and normal MMU setup must be aware of the
 reserved memory regions. The original patch set by Rouven used FDT
 parsing in PBL to achieve this, but this is omitted here to limit
 scope of the patch series. Instead we only handle the CONFIG_OPTEE_SIZE
 case out-of-the-box."

My use case is the CONFIG_OPTEE_SIZE one and at least for ARM64, that looks
resolved now IMO.

Cheers,
Ahmad

> 
> Sascha
> 


-- 
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-5555 |


From a.fatoum at pengutronix.de  Mon Sep 12 08:54:36 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 12 Sep 2022 17:54:36 +0200
Subject: [PATCH v2] of: implement of_prepend_property
Message-ID: <20220912155436.1565755-1-a.fatoum@pengutronix.de>

Like of_append_property for adding at the end of properties, implement
of_prepend_property for placing data into the front.

This is especially useful to fixup most-specific compatibles into
existing nodes.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - simplify with malloc/memcpy instead of realloc/memmove (Sascha)
---
 drivers/of/base.c           | 30 ++++++++++++++++++++++++++++++
 include/of.h                |  8 ++++++++
 test/self/of_manipulation.c |  2 +-
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 212b226eb55c..ea2a88764bb2 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2378,6 +2378,36 @@ int of_append_property(struct device_node *np, const char *name, const void *val
 	return 0;
 }
 
+int of_prepend_property(struct device_node *np, const char *name, const void *val, int len)
+{
+	struct property *pp;
+	const void *oldval;
+	void *buf;
+	int oldlen;
+
+	pp = of_find_property(np, name, &oldlen);
+	if (!pp) {
+		of_new_property(np, name, val, len);
+		return 0;
+	}
+
+	oldval = of_property_get_value(pp);
+
+	buf = malloc(len + oldlen);
+	if (!buf)
+		return -ENOMEM;
+
+	memcpy(buf, val, len);
+	memcpy(buf + len, oldval, oldlen);
+
+	free(pp->value);
+	pp->value = buf;
+	pp->length = len + oldlen;
+	pp->value_const = NULL;
+
+	return 0;
+}
+
 int of_property_sprintf(struct device_node *np,
 			const char *propname, const char *fmt, ...)
 {
diff --git a/include/of.h b/include/of.h
index 153e75d3e51d..052d5fcad84c 100644
--- a/include/of.h
+++ b/include/of.h
@@ -135,6 +135,8 @@ extern int of_set_property(struct device_node *node, const char *p,
 			const void *val, int len, int create);
 extern int of_append_property(struct device_node *np, const char *p,
 			      const void *val, int len);
+extern int of_prepend_property(struct device_node *np, const char *name,
+			       const void *val, int len);
 extern struct property *of_new_property(struct device_node *node,
 				const char *name, const void *data, int len);
 extern struct property *of_new_property_const(struct device_node *node,
@@ -536,6 +538,12 @@ static inline int of_append_property(struct device_node *np, const char *p,
 	return -ENOSYS;
 }
 
+static inline int of_prepend_property(struct device_node *np, const char *name,
+				      const void *val, int len)
+{
+	return -ENOSYS;
+}
+
 static inline struct property *of_new_property(struct device_node *node,
 				const char *name, const void *data, int len)
 {
diff --git a/test/self/of_manipulation.c b/test/self/of_manipulation.c
index 7e30a60ca687..f7f95fa269af 100644
--- a/test/self/of_manipulation.c
+++ b/test/self/of_manipulation.c
@@ -103,9 +103,9 @@ static void test_of_property_strings(struct device_node *root)
 
 	of_append_property(np4, "property-single", "ayy", 4);
 
-	of_append_property(np4, "property-multi", "ayy", 4);
 	of_append_property(np4, "property-multi", "bee", 4);
 	of_append_property(np4, "property-multi", "sea", 4);
+	of_prepend_property(np4, "property-multi", "ayy", 4);
 
 	assert_equal(np3, np4);
 }
-- 
2.30.2



From sha at pengutronix.de  Mon Sep 12 09:36:41 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 12 Sep 2022 18:36:41 +0200
Subject: [PATCH v2 08/10] ARM: mmu: use reserve mem entries to modify maps
In-Reply-To: <7ef687f0-903c-e194-d3dc-a4c83e9a6efe@pengutronix.de>
References: <20220817114244.1810531-1-a.fatoum@pengutronix.de>
 <20220817114244.1810531-9-a.fatoum@pengutronix.de>
 <20220912120130.GD12909@pengutronix.de>
 <7ef687f0-903c-e194-d3dc-a4c83e9a6efe@pengutronix.de>
Message-ID: <20220912163641.GE6477@pengutronix.de>

On Mon, Sep 12, 2022 at 05:15:45PM +0200, Ahmad Fatoum wrote:
> Hi,
> 
> On 12.09.22 14:01, Sascha Hauer wrote:
> > This patch breaks NAND support on my Phytec i.MX6 board. There are some
> > problems with this patch, so I ended up reverting it for now.
> 
> I wonder why. I see no memory reserves in imx6q-phytec-phycore-som-nand.dts
> and the files it includes.
> 
> > 
> > On Wed, Aug 17, 2022 at 01:42:42PM +0200, Ahmad Fatoum wrote:
> >> @@ -468,11 +469,28 @@ void __mmu_init(bool mmu_on)
> >>  	vectors_init();
> >>  
> >>  	for_each_memory_bank(bank) {
> >> +		struct resource *rsv;
> >> +
> >>  		create_sections(ttb, bank->start, bank->start + bank->size - 1,
> >>  				PMD_SECT_DEF_CACHED);
> >> -		__mmu_cache_flush();
> >> +
> >> +		for_each_reserved_region(bank, rsv) {
> >> +			create_sections(ttb, resource_first_page(rsv),
> >> +					resource_count_pages(rsv),
> >> +					attrs_uncached_mem());
> >> +		}
> > 
> > This operates on 1MiB sections, so everything requiring a finer
> > granularity will fail here. Not sure if we currently need that, but not
> > even issuing a warning is not good.
> 
> At worst it'd needlessly mark some memory uncached/XN. If users are
> affected, they will notice and we can revisit this. I could add a debug
> print here.
> 
> I need to rework this though, because I see now create_sections differs
> between ARM64 and ARM32. On ARM64, it accepts the last address as argument,
> while on ARM64, it's the size.. resource_count_pages() is not a nice
> name either, because it returns bytes (aligned up to PAGE_SIZE).
> 
> > 
> >>  	}
> >>  
> >> +	/*
> >> +	 * We could set_ttbr(ttb) here instead and save on the copy, but
> >> +	 * for now we play it safe, so we don't mess with the older ARMs.
> >> +	 */
> >> +	if (oldttb) {
> >> +		memcpy(oldttb, ttb, ARM_TTB_SIZE);
> >> +		free(ttb);
> >> +	}
> > 
> > in the early MMU case the MMU still uses 'oldttb' as ttb whereas 'ttb'
> > now points to invalid memory. Still functions like arm_create_pte()
> > still operate on 'ttb'. It looks like a ttb = oldttb is missing here.
> 
> Why would ttb point at invalid memory? It's allocated unconditionally
> with xmemalign and freed here.

It becomes clearer when you look at the scope of the variable.

> 
> > Also I wonder when we have to map the reserved regions as execute never,
> > then the early MMU setup seems broken as well, as that creates a flat
> > mapping without honoring the reserved regions. Shouldn't that be fixed?
> 
> Yes, see excerpt from cover letter:
> 
> "Note that this doesn't yet solve all problems. For example, PPA secure
>  monitor installation on Layerscape may happen with CONFIG_MMU_EARLY=y,
>  in which case barebox in EL2 may speculate into the secure memory
>  before any device tree reserved-memory settings are considered. For this
>  reason, both early MMU and normal MMU setup must be aware of the
>  reserved memory regions. The original patch set by Rouven used FDT
>  parsing in PBL to achieve this, but this is omitted here to limit
>  scope of the patch series. Instead we only handle the CONFIG_OPTEE_SIZE
>  case out-of-the-box."

Ok.

Sascha

-- 
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-5555 |


From sha at pengutronix.de  Tue Sep 13 01:06:21 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:06:21 +0200
Subject: [PATCH v2] of: implement of_prepend_property
In-Reply-To: <20220912155436.1565755-1-a.fatoum@pengutronix.de>
References: <20220912155436.1565755-1-a.fatoum@pengutronix.de>
Message-ID: <20220913080621.GF6477@pengutronix.de>

On Mon, Sep 12, 2022 at 05:54:36PM +0200, Ahmad Fatoum wrote:
> Like of_append_property for adding at the end of properties, implement
> of_prepend_property for placing data into the front.
> 
> This is especially useful to fixup most-specific compatibles into
> existing nodes.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
> v1 -> v2:
>   - simplify with malloc/memcpy instead of realloc/memmove (Sascha)
> ---
>  drivers/of/base.c           | 30 ++++++++++++++++++++++++++++++
>  include/of.h                |  8 ++++++++
>  test/self/of_manipulation.c |  2 +-
>  3 files changed, 39 insertions(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 212b226eb55c..ea2a88764bb2 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2378,6 +2378,36 @@ int of_append_property(struct device_node *np, const char *name, const void *val
>  	return 0;
>  }
>  
> +int of_prepend_property(struct device_node *np, const char *name, const void *val, int len)
> +{
> +	struct property *pp;
> +	const void *oldval;
> +	void *buf;
> +	int oldlen;
> +
> +	pp = of_find_property(np, name, &oldlen);
> +	if (!pp) {
> +		of_new_property(np, name, val, len);
> +		return 0;
> +	}
> +
> +	oldval = of_property_get_value(pp);
> +
> +	buf = malloc(len + oldlen);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	memcpy(buf, val, len);
> +	memcpy(buf + len, oldval, oldlen);
> +
> +	free(pp->value);
> +	pp->value = buf;
> +	pp->length = len + oldlen;
> +	pp->value_const = NULL;
> +
> +	return 0;
> +}
> +
>  int of_property_sprintf(struct device_node *np,
>  			const char *propname, const char *fmt, ...)
>  {
> diff --git a/include/of.h b/include/of.h
> index 153e75d3e51d..052d5fcad84c 100644
> --- a/include/of.h
> +++ b/include/of.h
> @@ -135,6 +135,8 @@ extern int of_set_property(struct device_node *node, const char *p,
>  			const void *val, int len, int create);
>  extern int of_append_property(struct device_node *np, const char *p,
>  			      const void *val, int len);
> +extern int of_prepend_property(struct device_node *np, const char *name,
> +			       const void *val, int len);
>  extern struct property *of_new_property(struct device_node *node,
>  				const char *name, const void *data, int len);
>  extern struct property *of_new_property_const(struct device_node *node,
> @@ -536,6 +538,12 @@ static inline int of_append_property(struct device_node *np, const char *p,
>  	return -ENOSYS;
>  }
>  
> +static inline int of_prepend_property(struct device_node *np, const char *name,
> +				      const void *val, int len)
> +{
> +	return -ENOSYS;
> +}
> +
>  static inline struct property *of_new_property(struct device_node *node,
>  				const char *name, const void *data, int len)
>  {
> diff --git a/test/self/of_manipulation.c b/test/self/of_manipulation.c
> index 7e30a60ca687..f7f95fa269af 100644
> --- a/test/self/of_manipulation.c
> +++ b/test/self/of_manipulation.c
> @@ -103,9 +103,9 @@ static void test_of_property_strings(struct device_node *root)
>  
>  	of_append_property(np4, "property-single", "ayy", 4);
>  
> -	of_append_property(np4, "property-multi", "ayy", 4);
>  	of_append_property(np4, "property-multi", "bee", 4);
>  	of_append_property(np4, "property-multi", "sea", 4);
> +	of_prepend_property(np4, "property-multi", "ayy", 4);
>  
>  	assert_equal(np3, np4);
>  }
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From s.hauer at pengutronix.de  Tue Sep 13 01:08:37 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:08:37 +0200
Subject: [PATCH next] Documentation: filesystems: tftp: fix code blocks
In-Reply-To: <20220912085047.84819-1-antonynpavlov@gmail.com>
References: <20220912085047.84819-1-antonynpavlov@gmail.com>
Message-ID: <20220913080837.GG6477@pengutronix.de>

On Mon, Sep 12, 2022 at 11:50:47AM +0300, Antony Pavlov wrote:
> The patch fixes these sphinx errors:
> 
>   Documentation/filesystems/tftp.rst:44: ERROR: Error in "code-block" directive:
>     maximum 1 argument(s) allowed, 3 supplied.
>   Documentation/filesystems/tftp.rst:53: ERROR: Error in "code-block" directive:
>     maximum 1 argument(s) allowed, 4 supplied.
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  Documentation/filesystems/tftp.rst | 2 ++
>  1 file changed, 2 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/Documentation/filesystems/tftp.rst b/Documentation/filesystems/tftp.rst
> index 8929213d3c4..e88ad3dd4c8 100644
> --- a/Documentation/filesystems/tftp.rst
> +++ b/Documentation/filesystems/tftp.rst
> @@ -42,6 +42,7 @@ the opposite effect.  Performance depends on:
>     100 Mb/s) it had to be reduced to
>  
>     .. code-block:: console
> +
>       global tftp.windowsize=26
>  
>     for example.
> @@ -51,6 +52,7 @@ the opposite effect.  Performance depends on:
>     example, the `fec-imx` driver reserves place for
>  
>     .. code-block:: c
> +
>       #define FEC_RBD_NUM		64
>  
>     packets before they are dropped
> -- 
> 2.37.2
> 
> 

-- 
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-5555 |


From s.hauer at pengutronix.de  Tue Sep 13 01:10:23 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:10:23 +0200
Subject: [PATCH 0/7] Documentation misc fixes
In-Reply-To: <20220912084430.84451-1-antonynpavlov@gmail.com>
References: <20220912084430.84451-1-antonynpavlov@gmail.com>
Message-ID: <20220913081023.GH6477@pengutronix.de>

On Mon, Sep 12, 2022 at 11:44:23AM +0300, Antony Pavlov wrote:
> Antony Pavlov (7):
>   Documentation: OKUD Max9331: fix sphinx warning
>   Documentation: Altera SOCFPGA FPGA Manager: fix sphinx error
>   Documentation: Altera FPGAs in passive-serial mode: fix sphinx issues
>   Documentation: barebox DT aliases: fix sphinx issues
>   Documentation: barebox environment: fix list rendering
>   Documentation: Common leds properties: fix 'panic-indicator' list
>     entry rendering
>   Documentation: Voltage/Current Regulators: fix sphinx error
> 
>  Documentation/boards/mips/max9331.rst                       | 2 +-
>  Documentation/devicetree/bindings/barebox/aliases.rst       | 3 ++-
>  .../devicetree/bindings/barebox/barebox,environment.rst     | 1 +
>  .../devicetree/bindings/firmware/altr,passive-serial.rst    | 1 +
>  .../devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst  | 6 ++++--
>  Documentation/devicetree/bindings/leds/common.rst           | 2 +-
>  Documentation/devicetree/bindings/regulator/regulator.rst   | 1 +
>  7 files changed, 11 insertions(+), 5 deletions(-)

Applied, thanks

Sascha


-- 
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-5555 |


From sha at pengutronix.de  Tue Sep 13 01:14:02 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:14:02 +0200
Subject: [PATCH] test: self: provide selftest_is_running()
In-Reply-To: <20220905070125.537483-1-a.fatoum@pengutronix.de>
References: <20220905070125.537483-1-a.fatoum@pengutronix.de>
Message-ID: <20220913081402.GI6477@pengutronix.de>

On Mon, Sep 05, 2022 at 09:01:25AM +0200, Ahmad Fatoum wrote:
> For debugging during self-test run, it can be useful to enable select
> logging only when the selftest is running. Provide a selftest_is_running()
> function that can be used to determine whether a test is running.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  commands/selftest.c |  2 +-
>  include/bselftest.h |  5 +++++
>  test/self/core.c    | 26 +++++++++++++++++++++++++-
>  3 files changed, 31 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/commands/selftest.c b/commands/selftest.c
> index a10f1467fece..bb62575aa7bb 100644
> --- a/commands/selftest.c
> +++ b/commands/selftest.c
> @@ -24,7 +24,7 @@ static int run_selftest(const char *match, bool list)
>  		if (match && strcmp(test->name, match))
>  			continue;
>  
> -		err |= test->func();
> +		err |= selftest_run(test);
>  		matches++;
>  	}
>  
> diff --git a/include/bselftest.h b/include/bselftest.h
> index 21eeba0526ef..f03c803b6553 100644
> --- a/include/bselftest.h
> +++ b/include/bselftest.h
> @@ -15,6 +15,7 @@ struct selftest {
>  	const char *name;
>  	int (*func)(void);
>  	struct list_head list;
> +	bool running;
>  };
>  
>  static inline int selftest_report(unsigned int total_tests, unsigned int failed_tests,
> @@ -71,4 +72,8 @@ static inline void selftests_run(void)
>  	}							\
>  	__bselftest_initcall(_func##_bselftest_register);
>  
> +
> +int selftest_run(struct selftest *test);
> +bool selftest_is_running(struct selftest *test);
> +
>  #endif
> diff --git a/test/self/core.c b/test/self/core.c
> index caa4c27f6def..40f5ee842d16 100644
> --- a/test/self/core.c
> +++ b/test/self/core.c
> @@ -7,6 +7,30 @@
>  
>  LIST_HEAD(selftests);
>  
> +int selftest_run(struct selftest *test)
> +{
> +	int err;
> +
> +	test->running = true;
> +	err = test->func();
> +	test->running = false;
> +
> +	return err;
> +}
> +
> +bool selftest_is_running(struct selftest *test)
> +{
> +	if (test)
> +		return test->running;
> +
> +	list_for_each_entry(test, &selftests, list) {
> +		if (selftest_is_running(test))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>  void selftests_run(void)
>  {
>  	struct selftest *test;
> @@ -15,7 +39,7 @@ void selftests_run(void)
>  	pr_notice("Configured tests will run now\n");
>  
>  	list_for_each_entry(test, &selftests, list)
> -		err |= test->func();
> +		err |= selftest_run(test);
>  
>  	if (err)
>  		pr_err("Some selftests failed\n");
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Tue Sep 13 01:16:17 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:16:17 +0200
Subject: [PATCH] blspec: fix memory leak handling NFS URLs
In-Reply-To: <20220905070247.538308-1-a.fatoum@pengutronix.de>
References: <20220905070247.538308-1-a.fatoum@pengutronix.de>
Message-ID: <20220913081617.GJ6477@pengutronix.de>

On Mon, Sep 05, 2022 at 09:02:47AM +0200, Ahmad Fatoum wrote:
> parse_nfs_url() returns either an allocated string on success or an
> error pointer otherwise. blspec_bootentry_provider() will early
> exit if the path couldn't be resolved and thus not free() the string.
> 
> Fix this memory leak. While at it, change parse_nfs_url() to return NULL
> on error. The error code is unused and just returning NULL, simplifies
> the code.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  common/blspec.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/common/blspec.c b/common/blspec.c
> index 9bb25ee72123..d391f690ad0c 100644
> --- a/common/blspec.c
> +++ b/common/blspec.c
> @@ -341,10 +341,10 @@ static char *parse_nfs_url(const char *url)
>  	int ret;
>  
>  	if (!IS_ENABLED(CONFIG_FS_NFS))
> -		return ERR_PTR(-ENOSYS);
> +		return NULL;
>  
>  	if (strncmp(url, "nfs://", 6))
> -		return ERR_PTR(-EINVAL);
> +		return NULL;
>  
>  	url += 6;
>  
> @@ -413,7 +413,7 @@ out:
>  	if (ret)
>  		free(mountpath);
>  
> -	return ret ? ERR_PTR(ret) : mountpath;
> +	return ret ? NULL : mountpath;
>  }
>  
>  /*
> @@ -824,12 +824,12 @@ static int blspec_bootentry_provider(struct bootentries *bootentries,
>  	if (*name == '/' || !strncmp(name, "nfs://", 6)) {
>  		char *nfspath = parse_nfs_url(name);
>  
> -		if (!IS_ERR(nfspath))
> +		if (nfspath)
>  			name = nfspath;
>  
>  		ret = stat(name, &s);
>  		if (ret)
> -			return found;
> +			goto out;
>  
>  		if (S_ISDIR(s.st_mode))
>  			ret = blspec_scan_directory(bootentries, name);
> @@ -838,8 +838,8 @@ static int blspec_bootentry_provider(struct bootentries *bootentries,
>  		if (ret > 0)
>  			found += ret;
>  
> -		if (!IS_ERR(nfspath))
> -			free(nfspath);
> +out:
> +		free(nfspath);
>  	}
>  
>  	return found;
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Tue Sep 13 01:19:20 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:19:20 +0200
Subject: [PATCH] soc: imx: gpcv2: make available to all i.MX8M
In-Reply-To: <20220905070406.539244-1-a.fatoum@pengutronix.de>
References: <20220905070406.539244-1-a.fatoum@pengutronix.de>
Message-ID: <20220913081920.GK6477@pengutronix.de>

On Mon, Sep 05, 2022 at 09:04:06AM +0200, Ahmad Fatoum wrote:
> Now that the driver supports i.MX8M Mini, Nano and Plus, we should no
> longer restrict it to just i.MX7 and i.MX8MQ.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/soc/imx/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
> index eabe4a06d22c..624aff2ecae3 100644
> --- a/drivers/soc/imx/Kconfig
> +++ b/drivers/soc/imx/Kconfig
> @@ -3,9 +3,9 @@ menu "i.MX SoC drivers"
>  
>  config IMX_GPCV2_PM_DOMAINS
>          bool "i.MX GPCv2 PM domains"
> -	depends on ARCH_IMX7 || ARCH_IMX8MQ
> +	depends on ARCH_IMX7 || ARCH_IMX8M
>  	select PM_GENERIC_DOMAINS
> -	default y if ARCH_IMX7 || ARCH_IMX8MQ
> +	default y if ARCH_IMX7 || ARCH_IMX8M
>  
>  config IMX8M_FEATCTRL
>          bool "i.MX8M feature controller"
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Tue Sep 13 01:27:55 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:27:55 +0200
Subject: [PATCH] of: of_probe: create board's machine device at the
 earliest
In-Reply-To: <20220905070208.538012-1-a.fatoum@pengutronix.de>
References: <20220905070208.538012-1-a.fatoum@pengutronix.de>
Message-ID: <20220913082755.GL6477@pengutronix.de>

On Mon, Sep 05, 2022 at 09:02:08AM +0200, Ahmad Fatoum wrote:
> We currently create devices for matching reserved memory entries and
> firmware before creating the machine device. In a deep probe system, the
> machine driver would be probed directly at registration and as such
> needs to be probed before other devices are created, so it can disable
> other devices if needed. Move the machine device registration to the
> top, so board drivers can disabled reserved memory entries and firmware
> if they need to.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/of/base.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 52e6a9294e11..6a51dd71793d 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -2503,6 +2503,12 @@ int of_probe(void)
>  	if(!root_node)
>  		return -ENODEV;
>  
> +	/*
> +	 * We do this first thing, so board drivers can patch the device
> +	 * tree prior to device creation if needed.
> +	 */
> +	of_platform_device_create_root(root_node);
> +
>  	/*
>  	 * Handle certain compatibles explicitly, since we don't want to create
>  	 * platform_devices for every node in /reserved-memory with a
> @@ -2515,8 +2521,6 @@ int of_probe(void)
>  	if (node)
>  		of_platform_populate(node, NULL, NULL);
>  
> -	of_platform_device_create_root(root_node);
> -
>  	of_platform_populate(root_node, of_default_bus_match_table, NULL);
>  
>  	return 0;
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Tue Sep 13 01:37:51 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:37:51 +0200
Subject: [PATCH] fs: ubifs: remove always-false check
In-Reply-To: <20220811135804.271071-1-a.fatoum@pengutronix.de>
References: <20220811135804.271071-1-a.fatoum@pengutronix.de>
Message-ID: <20220913083751.GE12909@pengutronix.de>

On Thu, Aug 11, 2022 at 03:58:04PM +0200, Ahmad Fatoum wrote:
> GCC correctly warns that two bit wide compr_type can't
> exceed or be equal to UBIFS_COMPR_TYPES_CNT (== 4).
> 
> Remove the check. The check is there in the kernel as well,
> but the warning is disabled there.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  fs/ubifs/super.c | 5 -----
>  1 file changed, 5 deletions(-)
> 
> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
> index b48e21fae636..6a0074bd1a5c 100644
> --- a/fs/ubifs/super.c
> +++ b/fs/ubifs/super.c
> @@ -86,11 +86,6 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
>  		return 1;
>  	}
>  
> -	if (ui->compr_type >= UBIFS_COMPR_TYPES_CNT) {
> -		ubifs_err(c, "unknown compression type %d", ui->compr_type);
> -		return 2;
> -	}
> -

Although Richard decided for the Kernel to keep the check I decided to
take this patch for barebox. The warning is annoying and doesn't tell us
anything. Once this is solved in the Kernel we'll get the solution with
the next UBIFS sync.

Sascha

-- 
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-5555 |


From sha at pengutronix.de  Tue Sep 13 01:39:28 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 10:39:28 +0200
Subject: [PATCH master] ARM: sync_caches_for_execution: don't flush
 disabled data cache
In-Reply-To: <20220901104136.171051-1-a.fatoum@pengutronix.de>
References: <20220901104136.171051-1-a.fatoum@pengutronix.de>
Message-ID: <20220913083928.GM6477@pengutronix.de>

On Thu, Sep 01, 2022 at 12:41:36PM +0200, Ahmad Fatoum wrote:
> We unconditionally clean and then invalidate D-cache entries in
> sync_caches_for_execution by calling arm_early_mmu_cache_flush().
> 
> The function afterwards takes care to invalidate the I-cache.
> 
> This misbehaves though when the D-Cache contains stale dirty
> entries for currently executing code. Most boards avoid this
> pitfall, because barebox_arm_entry calls
> arm_early_mmu_cache_invalidate() and sync_caches_for_execution()
> is only called afterwards. But for some boards,
> relocate_to_current_adr() is called before barebox_arm_entry and
> various board code works around this by calling
> arm_early_mmu_cache_invalidate() first.
> 
> Make this unnecessary by not flushing the data cache when it's disabled
> and instead only invalidate the I-Cache.
> 
> This fixes a hang observed on a serial-booted i.MX6Q rev 1.5
> executing relocate_to_current_adr() -> sync_caches_for_execution()
> from On-Chip SRAM.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  arch/arm/cpu/common.c | 6 ++++++
>  1 file changed, 6 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/cpu/common.c b/arch/arm/cpu/common.c
> index 8cfcc8f6ce7a..5ccacf204751 100644
> --- a/arch/arm/cpu/common.c
> +++ b/arch/arm/cpu/common.c
> @@ -23,6 +23,12 @@
>   */
>  void sync_caches_for_execution(void)
>  {
> +	/* if caches are disabled, don't do data cache maintenance */
> +	if (!(get_cr() & CR_C)) {
> +		icache_invalidate();
> +		return;
> +	}
> +
>  	/*
>  	 * Despite the name arm_early_mmu_cache_flush not only flushes the
>  	 * data cache, but also invalidates the instruction cache.
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From a.fatoum at pengutronix.de  Tue Sep 13 01:47:33 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 13 Sep 2022 10:47:33 +0200
Subject: [PATCH] fs: ubifs: remove always-false check
In-Reply-To: <20220913083751.GE12909@pengutronix.de>
References: <20220811135804.271071-1-a.fatoum@pengutronix.de>
 <20220913083751.GE12909@pengutronix.de>
Message-ID: <ce1c1bd7-40de-51f4-fa37-632fa319b9af@pengutronix.de>

On 13.09.22 10:37, Sascha Hauer wrote:
> On Thu, Aug 11, 2022 at 03:58:04PM +0200, Ahmad Fatoum wrote:
>> GCC correctly warns that two bit wide compr_type can't
>> exceed or be equal to UBIFS_COMPR_TYPES_CNT (== 4).
>>
>> Remove the check. The check is there in the kernel as well,
>> but the warning is disabled there.
>>
>> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
>> ---
>>  fs/ubifs/super.c | 5 -----
>>  1 file changed, 5 deletions(-)
>>
>> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
>> index b48e21fae636..6a0074bd1a5c 100644
>> --- a/fs/ubifs/super.c
>> +++ b/fs/ubifs/super.c
>> @@ -86,11 +86,6 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
>>  		return 1;
>>  	}
>>  
>> -	if (ui->compr_type >= UBIFS_COMPR_TYPES_CNT) {
>> -		ubifs_err(c, "unknown compression type %d", ui->compr_type);
>> -		return 2;
>> -	}
>> -
> 
> Although Richard decided for the Kernel to keep the check I decided to
> take this patch for barebox. The warning is annoying and doesn't tell us
> anything. Once this is solved in the Kernel we'll get the solution with
> the next UBIFS sync.

My thoughts exactly.

Cheers,
Ahmad

> 
> Sascha
> 


-- 
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-5555 |


From s.hauer at pengutronix.de  Tue Sep 13 02:05:43 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 11:05:43 +0200
Subject: [PATCH] ARM: imx_v7_defconfig: Limit TFTP window size
Message-ID: <20220913090543.2980771-1-s.hauer@pengutronix.de>

The FEC ethernet controller is too slow to catch up with a gigabit
link. This hasn't been a problem until now, because the protocols
we use in barebox only have a single packet in flight. With TFTP
window size support and a gigabit link though we get receive
buffer overruns resulting in messages like:

WARNING: eth0: error frame: 0x2feca098 0x00000806

The resulting speed is slower than without TFTP windowsize support due
to the necessary retransmits. Limit the window size to a value that
seems to be working on i.MX6 boards.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/configs/imx_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index df2304eae9..d07abe28ae 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -210,6 +210,7 @@ CONFIG_GENERIC_PHY=y
 CONFIG_USB_NOP_XCEIV=y
 CONFIG_FS_EXT4=y
 CONFIG_FS_TFTP=y
+CONFIG_FS_TFTP_MAX_WINDOW_SIZE=8
 CONFIG_FS_NFS=y
 CONFIG_FS_FAT=y
 CONFIG_FS_FAT_WRITE=y
-- 
2.30.2



From sha at pengutronix.de  Tue Sep 13 02:25:16 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 11:25:16 +0200
Subject: TFTP RFC7440 windowsize support
Message-ID: <20220913092516.GF12909@pengutronix.de>

Hi All,

As you might have noticed Enrico added RFC7440 support to our TFTP
support. This greatly improves the speed for TFTP transfers when the
server also has RFC7440 support.

RFC7440 support has just appeared in the latest atftpd release
(version 0.8.0), so you can give this a try without locally patched
TFTP demons. This release is also available in debian backports.

Unfortunately there's no light without shadow. On i.MX6 the FEC ethernet
controller is too slow to catch up with a gigabit link. Up to now this
hasn't been a problem on barebox, as we only ever had a single packet
in flight. Now with windowsize support the controller can get
overwhelmed with so many TFTP packets that RX overruns occur. I changed
the imx_v7_defconfig to limit the windowsize to a smaller value that
seems to work here. Similar problems might exist on other ethernet
controllers, so we might have to generally switch to more conservative
default window sizes.

Sascha

-- 
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-5555 |


From s.hauer at pengutronix.de  Tue Sep 13 02:49:42 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 11:49:42 +0200
Subject: [PATCH 1/2] ARM: rdu2: Drop redundant of graph link
Message-ID: <20220913094943.100107-1-s.hauer@pengutronix.de>

The link is also present in the upstream dtsi file in the same way, so
remove it from the barebox overlay.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/dts/imx6qdl-zii-rdu2.dtsi | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
index b593545ffe..59f7656139 100644
--- a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
+++ b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
@@ -234,16 +234,6 @@
 &i2c1 {
 	edp-bridge at 68 {
 		pinctrl-0 = <&pinctrl_tc358767>, <&pinctrl_disp0>;
-
-		ports {
-			port at 1 {
-				reg = <1>;
-
-				tc358767_in: endpoint {
-					remote-endpoint = <&disp0_out>;
-				};
-			};
-		};
 	};
 };
 
-- 
2.30.2



From s.hauer at pengutronix.de  Tue Sep 13 02:49:43 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 11:49:43 +0200
Subject: [PATCH 2/2] ARM: rdu2: fix dtc warning
In-Reply-To: <20220913094943.100107-1-s.hauer@pengutronix.de>
References: <20220913094943.100107-1-s.hauer@pengutronix.de>
Message-ID: <20220913094943.100107-2-s.hauer@pengutronix.de>

This fixes:

dts/src/arm/imx6qdl.dtsi:1332.32-1334.7: Warning (graph_endpoint): /soc/ipu at 2400000/port at 2/endpoint at 0: graph connection to node '/soc/bus at 2100000/i2c at 21a0000/edp-bridge at 68/ports/port at 1/endpoint' is not bidirectional
  also defined at dts/src/arm/imx6qdl-zii-rdu2.dtsi:647.17-649.3
  also defined at arch/arm/dts/imx6qdl-zii-rdu2.dtsi:246.17-248.3
dts/src/arm/imx6qdl-zii-rdu2.dtsi:186.25-188.6: Warning (graph_endpoint): /disp0/port at 0/endpoint: graph connection to node '/soc/ipu at 2400000/port at 2/endpoint at 0' is not bidirectional
dts/src/arm/imx6qdl.dtsi:1332.32-1334.7: Warning (graph_endpoint): /soc/ipu at 2400000/port at 2/endpoint at 0: graph connection to node '/soc/bus at 2100000/i2c at 21a0000/edp-bridge at 68/ports/port at 1/endpoint' is not bidirectional
  also defined at dts/src/arm/imx6qdl-zii-rdu2.dtsi:647.17-649.3
  also defined at arch/arm/dts/imx6qdl-zii-rdu2.dtsi:246.17-248.3
dts/src/arm/imx6qdl-zii-rdu2.dtsi:186.25-188.6: Warning (graph_endpoint): /disp0/port at 0/endpoint: graph connection to node '/soc/ipu at 2400000/port at 2/endpoint at 0' is not bidirectional

I don't know if the link is non biderectional intentionally, it might
have something to do with the runtime dts adjustments. The warning
is around for a long time now without anybody caring, so just get
rid of it and see if somebody can explain the backgrounds or provide
a proper solution for it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/dts/imx6qdl-zii-rdu2.dtsi | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
index 59f7656139..714ba8e755 100644
--- a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
+++ b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
@@ -243,10 +243,6 @@
 	};
 };
 
-&ipu1_di0_disp0 {
-	remote-endpoint = <&tc358767_in>;
-};
-
 &ldb {
 	lvds-channel at 0 {
 		fsl,data-width = <24>;
-- 
2.30.2



From antonynpavlov at gmail.com  Tue Sep 13 02:54:11 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Tue, 13 Sep 2022 12:54:11 +0300
Subject: [PATCH next] Documentation: filesystems: tftp: fix code blocks
In-Reply-To: <20220913080837.GG6477@pengutronix.de>
References: <20220912085047.84819-1-antonynpavlov@gmail.com>
	<20220913080837.GG6477@pengutronix.de>
Message-ID: <20220913125411.c326e05d739ffa6a21202eed@gmail.com>

On Tue, 13 Sep 2022 10:08:37 +0200
Sascha Hauer <s.hauer at pengutronix.de> wrote:

Hi Sascha!

> On Mon, Sep 12, 2022 at 11:50:47AM +0300, Antony Pavlov wrote:
> > The patch fixes these sphinx errors:
> > 
> >   Documentation/filesystems/tftp.rst:44: ERROR: Error in "code-block" directive:
> >     maximum 1 argument(s) allowed, 3 supplied.
> >   Documentation/filesystems/tftp.rst:53: ERROR: Error in "code-block" directive:
> >     maximum 1 argument(s) allowed, 4 supplied.
> > 
> > Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> > ---
> >  Documentation/filesystems/tftp.rst | 2 ++
> >  1 file changed, 2 insertions(+)
> 
> Applied, thanks

I thought that this patch is for ammend. My bad! I shell add "for ammend" or "fixup" tag to the message subject next time.

> > 
> > diff --git a/Documentation/filesystems/tftp.rst b/Documentation/filesystems/tftp.rst
> > index 8929213d3c4..e88ad3dd4c8 100644
> > --- a/Documentation/filesystems/tftp.rst
> > +++ b/Documentation/filesystems/tftp.rst
> > @@ -42,6 +42,7 @@ the opposite effect.  Performance depends on:
> >     100 Mb/s) it had to be reduced to
> >  
> >     .. code-block:: console
> > +
> >       global tftp.windowsize=26
> >  
> >     for example.
> > @@ -51,6 +52,7 @@ the opposite effect.  Performance depends on:
> >     example, the `fec-imx` driver reserves place for
> >  
> >     .. code-block:: c
> > +
> >       #define FEC_RBD_NUM		64
> >  
> >     packets before they are dropped
> > -- 
> > 2.37.2
> > 
> > 
> 
> -- 
> 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-5555 |


-- 
Best regards,
? Antony Pavlov


From s.hauer at pengutronix.de  Tue Sep 13 03:55:19 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 12:55:19 +0200
Subject: [PATCH] ubifs: Fix pointer type mismatch in gzip decompressor
Message-ID: <20220913105519.2952569-1-s.hauer@pengutronix.de>

deflate_decompress() takes a unsigned int * for the out_len argument
whereas ubifs passes a size_t * argument. Adjust the argument type
accordingly.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/ubifs/ubifs.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 0b4f3de773..71ccd2c0e7 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -46,7 +46,14 @@ static ZSTD_DCtx *ubifs_zstd_cctx;
 static int gzip_decompress(const unsigned char *in, size_t in_len,
 			   unsigned char *out, size_t *out_len)
 {
-	return deflate_decompress(&ubifs_zlib_stream, in, in_len, out, out_len);
+	unsigned int olen;
+	int ret;
+
+	ret = deflate_decompress(&ubifs_zlib_stream, in, in_len, out, &olen);
+
+	*out_len = olen;
+
+	return ret;
 }
 #endif
 
-- 
2.30.2



From s.hauer at pengutronix.de  Tue Sep 13 04:05:49 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 13:05:49 +0200
Subject: [PATCH next] Documentation: filesystems: tftp: fix code blocks
In-Reply-To: <20220913125411.c326e05d739ffa6a21202eed@gmail.com>
References: <20220912085047.84819-1-antonynpavlov@gmail.com>
 <20220913080837.GG6477@pengutronix.de>
 <20220913125411.c326e05d739ffa6a21202eed@gmail.com>
Message-ID: <20220913110549.GN6477@pengutronix.de>

On Tue, Sep 13, 2022 at 12:54:11PM +0300, Antony Pavlov wrote:
> On Tue, 13 Sep 2022 10:08:37 +0200
> Sascha Hauer <s.hauer at pengutronix.de> wrote:
> 
> Hi Sascha!
> 
> > On Mon, Sep 12, 2022 at 11:50:47AM +0300, Antony Pavlov wrote:
> > > The patch fixes these sphinx errors:
> > > 
> > >   Documentation/filesystems/tftp.rst:44: ERROR: Error in "code-block" directive:
> > >     maximum 1 argument(s) allowed, 3 supplied.
> > >   Documentation/filesystems/tftp.rst:53: ERROR: Error in "code-block" directive:
> > >     maximum 1 argument(s) allowed, 4 supplied.
> > > 
> > > Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> > > ---
> > >  Documentation/filesystems/tftp.rst | 2 ++
> > >  1 file changed, 2 insertions(+)
> > 
> > Applied, thanks
> 
> I thought that this patch is for ammend. My bad! I shell add "for
> ammend" or "fixup" tag to the message subject next time.

Ah, ok, I didn't realize that. When the to-be-fixed-up patch sits in
next you could just commit with --fixup=, this makes it very easy to fix
it up on my side.

Sascha

-- 
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-5555 |


From m.felsch at pengutronix.de  Tue Sep 13 05:49:50 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 13 Sep 2022 14:49:50 +0200
Subject: [PATCH 2/6] RISC-V: add riscv_vendor_id() support
In-Reply-To: <20220913124954.1346533-1-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
Message-ID: <20220913124954.1346533-3-m.felsch@pengutronix.de>

Add the support to query the vendorid which is stored within the
mvendorid register. This register is only accessible from M-Mode so we
need to use the sbi interface if we are running from S-Mode.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/riscv/include/asm/system.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/riscv/include/asm/system.h b/arch/riscv/include/asm/system.h
index adf856f9e9..3eb50f63fd 100644
--- a/arch/riscv/include/asm/system.h
+++ b/arch/riscv/include/asm/system.h
@@ -5,6 +5,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/sbi.h>
+
 #define RISCV_MODE_MASK 0x3
 enum riscv_mode {
     RISCV_U_MODE	= 0,
@@ -42,6 +44,30 @@ static inline long __riscv_hartid(u32 flags)
 	return hartid;
 }
 
+static inline long __riscv_vendor_id(u32 flags)
+{
+	struct sbiret ret = { .error = -1 };
+	long id;
+
+	switch (__riscv_mode(flags)) {
+	case RISCV_M_MODE:
+		__asm__ volatile("csrr %0, mvendorid\n" : "=r"(id));
+		return id;
+	case RISCV_S_MODE:
+		/*
+		 * We need to use the sbi_ecall() since it can be that we got
+		 * called without a working stack
+		 */
+		ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID,
+				0, 0, 0, 0, 0, 0);
+		if (!ret.error)
+			return ret.value;
+	default:
+	}
+
+	return ret.error;
+}
+
 #ifndef __PBL__
 extern unsigned barebox_riscv_pbl_flags;
 
@@ -54,6 +80,11 @@ static inline long riscv_hartid(void)
 {
 	return __riscv_hartid(barebox_riscv_pbl_flags);
 }
+
+static inline long riscv_vendor_id(void)
+{
+	return __riscv_vendor_id(barebox_riscv_pbl_flags);
+}
 #endif
 
 #endif
-- 
2.30.2



From m.felsch at pengutronix.de  Tue Sep 13 05:49:54 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 13 Sep 2022 14:49:54 +0200
Subject: [PATCH 6/6] RISC-V: add Allwinner Sun20i D1 Nezha support
In-Reply-To: <20220913124954.1346533-1-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
Message-ID: <20220913124954.1346533-7-m.felsch@pengutronix.de>

Add Allwinner sun20i SoC and D1-Nezha board support.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 Documentation/boards/riscv.rst            | 102 +++++++++++++++++
 arch/riscv/Kconfig.socs                   |  16 +++
 arch/riscv/boards/Makefile                |   1 +
 arch/riscv/boards/allwinner-d1/Makefile   |   3 +
 arch/riscv/boards/allwinner-d1/lowlevel.c |  12 ++
 arch/riscv/configs/sun20i_defconfig       | 130 ++++++++++++++++++++++
 arch/riscv/include/asm/debug_ll.h         |   5 +
 common/Kconfig                            |   5 +
 images/Makefile.riscv                     |   4 +
 9 files changed, 278 insertions(+)
 create mode 100644 arch/riscv/boards/allwinner-d1/Makefile
 create mode 100644 arch/riscv/boards/allwinner-d1/lowlevel.c
 create mode 100644 arch/riscv/configs/sun20i_defconfig

diff --git a/Documentation/boards/riscv.rst b/Documentation/boards/riscv.rst
index b7a3a95f0f..4c31c4316b 100644
--- a/Documentation/boards/riscv.rst
+++ b/Documentation/boards/riscv.rst
@@ -188,3 +188,105 @@ Next, start barebox from DRAM::
   running /env/bin/init...
   /env/bin/init not found
   barebox:/
+
+Allwinner D1 Nezha
+------------------
+
+Barebox has limited second-stage support for the Allwinner D1 Nezha (sun20i)::
+
+  ARCH=riscv make sun20i_defconfig
+  ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- make
+
+The resulting ``./images/barebox-allwinner-d1.img`` can be used as 2nd stage
+image which gets called by opensbi::
+
+  git clone https://github.com/tekkamanninja/opensbi -b allwinner_d1
+  cd opensbi
+  CROSS_COMPILE=riscv64-linux-gnu- PLATFORM=generic FW_PIC=y make
+
+The resulting ``./build/platform/generic/firmware/fw_dynamic.bin`` is loaded
+by the 1st stage (spl) loader, which is basically a u-boot spl::
+
+  git clone https://github.com/smaeul/sun20i_d1_spl -b mainline
+  cd sun20i_d1_spl
+  CROSS_COMPILE=riscv64-linux-gnu- make p=sun20iw1p1 mmc
+
+The resulting ``./nboot/boot0_sdcard_sun20iw1p1.bin`` image used as 1st stage
+bootloader which loads all necessary binaries: dtb, opensbi and barebox to the
+dedicated places in DRAM. After loading it jumps to the opensbi image.  The
+initial dtb can be taken from u-boot::
+
+  git clone https://github.com/smaeul/u-boot.git -b d1-wip
+  cd u-boot
+  ARCH=riscv make nezha_defconfig
+  ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- make
+
+Make will print two warnings at the end of this command but those can be ignored
+since we only want the devicetree blob which can be found under ``./u-boot.dtb``.
+
+The final image is build by mkimage. It is some sort of a self-defined toc1
+format. So we need to compile the mkimage with the toc1 format support as
+first::
+
+  cd u-boot
+  make tools-only
+
+The resulting ``tools/mkimage`` is used to build the toc1 image which is loaded
+by the 1st stage bootloader from the mmc interface. To build the final toc1 image
+we need to specify a toc1.cfg like::
+
+  [opensbi]
+  file = <ABSOLUT_PATH_TO>/opensbi/build/platform/generic/firmware/fw_dynamic.bin
+  addr = 0x40000000
+  [dtb]
+  file = <ABSOLUT_PATH_TO>/u-boot/u-boot.dtb
+  addr = 0x44000000
+  [u-boot]
+  file = <ABSOLUT_PATH_TO>/barebox/images/barebox-allwinner-d1.img
+  addr = 0x4a000000
+
+Then we need to call::
+
+  mkimage -T sunxi_toc1 -d toc1.cfg boot.toc1
+
+The last part is to place the 1st stage bootloader and the ``boot.toc1`` image
+onto the correct places. So the ROM loader can find the 1st stage bootloader
+and the 1st bootloader can find the ``boot.toc1`` image. This is done by::
+
+  dd if=boot0_sdcard_sun20iw1p1.bin of=/dev/sd<X> bs=512 seek=16
+  dd if=boot.toc1 of=/dev/sd<X> bs=512 seek=32800
+
+Now plug in the sdcard and power device and you will see::
+
+  [309]HELLO! BOOT0 is starting!
+  [312]BOOT0 commit : 882671f-dirty
+  [315]set pll start
+  [317]periph0 has been enabled
+  [320]set pll end
+  [322]board init ok
+
+  ...
+
+  OpenSBI v0.9-204-gc9024b5
+     ____                    _____ ____ _____
+    / __ \                  / ____|  _ \_   _|
+   | |  | |_ __   ___ _ __ | (___ | |_) || |
+   | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
+   | |__| | |_) |  __/ | | |____) | |_) || |_
+    \____/| .__/ \___|_| |_|_____/|____/_____|
+          | |
+          |_|
+
+  Platform Name             : Allwinner D1 Nezha
+  Platform Features         : medeleg
+
+  ...
+
+  barebox 2022.08.0-00262-g38678340903b #1 Tue Sep 13 12:54:29 CEST 2022
+
+
+  Board: Allwinner D1 Nezha
+
+  ...
+
+  barebox at Allwinner D1 Nezha:/
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 828b65a0c1..0f03637a66 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -110,6 +110,22 @@ config BOARD_BEAGLEV_BETA
 
 endif
 
+config SOC_ALLWINNER_SUN20I
+	bool "Allwinner Sun20i SoCs"
+	depends on ARCH_RV64I
+	select HAS_ASM_DEBUG_LL
+	select HAS_CACHE
+
+if SOC_ALLWINNER_SUN20I
+
+config BOARD_ALLWINNER_D1
+	bool "Allwinner D1 Nezha"
+	select RISCV_S_MODE
+	select RISCV_M_MODE
+	def_bool y
+
+endif
+
 comment "CPU features"
 
 config SIFIVE_L2
diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile
index 3b763ff308..df16d38496 100644
--- a/arch/riscv/boards/Makefile
+++ b/arch/riscv/boards/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_BOARD_ALLWINNER_D1)	+= allwinner-d1/
 obj-$(CONFIG_BOARD_ERIZO_GENERIC)	+= erizo/
 obj-$(CONFIG_BOARD_HIFIVE)		+= hifive/
 obj-$(CONFIG_BOARD_BEAGLEV)		+= beaglev/
diff --git a/arch/riscv/boards/allwinner-d1/Makefile b/arch/riscv/boards/allwinner-d1/Makefile
new file mode 100644
index 0000000000..3d217ffe0b
--- /dev/null
+++ b/arch/riscv/boards/allwinner-d1/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+pbl-y += lowlevel.o
diff --git a/arch/riscv/boards/allwinner-d1/lowlevel.c b/arch/riscv/boards/allwinner-d1/lowlevel.c
new file mode 100644
index 0000000000..2b07a81edb
--- /dev/null
+++ b/arch/riscv/boards/allwinner-d1/lowlevel.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <debug_ll.h>
+#include <asm/barebox-riscv.h>
+
+#define DRAM_BASE	0x40000000
+
+ENTRY_FUNCTION(start_allwinner_d1, a0, a1, a2)
+{
+	barebox_riscv_supervisor_entry(DRAM_BASE, SZ_1G, a0, (void *)a1);
+}
diff --git a/arch/riscv/configs/sun20i_defconfig b/arch/riscv/configs/sun20i_defconfig
new file mode 100644
index 0000000000..157c430723
--- /dev/null
+++ b/arch/riscv/configs/sun20i_defconfig
@@ -0,0 +1,130 @@
+CONFIG_ARCH_RV64I=y
+CONFIG_SOC_ALLWINNER_SUN20I=y
+CONFIG_BOARD_ALLWINNER_D1=y
+CONFIG_RISCV_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_STACK_SIZE=0x20000
+CONFIG_MALLOC_SIZE=0x0
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
+CONFIG_RELOCATABLE=y
+CONFIG_PANIC_HANG=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+CONFIG_BOOTM_INITRD=y
+CONFIG_SYSTEM_PARTITIONS=y
+CONFIG_IMD_TARGET=y
+CONFIG_CONSOLE_ALLOW_COLOR=y
+CONFIG_PBL_CONSOLE=y
+CONFIG_PARTITION_DISK_EFI=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_BAREBOXENV_TARGET=y
+CONFIG_BAREBOXCRC32_TARGET=y
+CONFIG_STATE=y
+CONFIG_STATE_CRYPTO=y
+CONFIG_BOOTCHOOSER=y
+CONFIG_RESET_SOURCE=y
+CONFIG_MACHINE_ID=y
+CONFIG_CMD_DMESG=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_POLLER=y
+CONFIG_CMD_SLICE=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_BOOTCHOOSER=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_CMP=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_SHA256SUM=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_POWEROFF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_WD=y
+CONFIG_CMD_2048=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_OF_DIFF=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OF_DISPLAY_TIMINGS=y
+CONFIG_CMD_OF_FIXUP_STATUS=y
+CONFIG_CMD_OF_OVERLAY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_NET=y
+CONFIG_NET_NFS=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_SERIAL_SBI=y
+CONFIG_DRIVER_NET_DESIGNWARE=y
+CONFIG_DRIVER_NET_DESIGNWARE_GENERIC=y
+CONFIG_DRIVER_NET_DESIGNWARE_STARFIVE=y
+CONFIG_MICREL_PHY=y
+CONFIG_SPI_MEM=y
+CONFIG_DRIVER_SPI_GPIO=y
+CONFIG_MCI=y
+CONFIG_MCI_DW=y
+CONFIG_CLOCKSOURCE_DUMMY_RATE=60000
+CONFIG_SRAM=y
+CONFIG_STARFIVE_PWRSEQ=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_LED_TRIGGERS=y
+CONFIG_WATCHDOG=y
+CONFIG_STARFIVE_WDT=y
+CONFIG_HWRNG=y
+CONFIG_HW_RANDOM_STARFIVE=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_STARFIVE=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_RMEM=y
+CONFIG_STARFIVE_OTP=y
+CONFIG_SYSCON_REBOOT_MODE=y
+CONFIG_NVMEM_REBOOT_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+# CONFIG_VIRTIO_MENU is not set
+CONFIG_FS_EXT4=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_FS_UIMAGEFS=y
+CONFIG_FS_PSTORE=y
+CONFIG_FS_SQUASHFS=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_ZSTD_DECOMPRESS=y
+CONFIG_XZ_DECOMPRESS=y
+CONFIG_BASE64=y
+CONFIG_DIGEST_CRC32_GENERIC=y
diff --git a/arch/riscv/include/asm/debug_ll.h b/arch/riscv/include/asm/debug_ll.h
index de9bc5f5fd..34294b09dd 100644
--- a/arch/riscv/include/asm/debug_ll.h
+++ b/arch/riscv/include/asm/debug_ll.h
@@ -29,6 +29,11 @@
 #define DEBUG_LL_UART_CLK       (58982400  / 16)
 #define DEBUG_LL_UART_SHIFT	0
 #define DEBUG_LL_UART_IOSIZE8
+#elif defined CONFIG_DEBUG_SUN20I
+#define DEBUG_LL_UART_ADDR	0x2500000
+#define DEBUG_LL_UART_CLK       (24000000 / 16)
+#define DEBUG_LL_UART_SHIFT	2
+#define DEBUG_LL_UART_IOSIZE32
 #endif
 
 #define DEBUG_LL_UART_BPS       CONFIG_BAUDRATE
diff --git a/common/Kconfig b/common/Kconfig
index 43dd92b08a..624d36a978 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1469,6 +1469,11 @@ config DEBUG_LITEX
 	bool "LiteX serial port"
 	depends on SOC_LITEX
 
+config DEBUG_SUN20I
+	bool "Allwinner Sun20i ns16550 serial0 port"
+	depends on SOC_ALLWINNER_SUN20I
+	select DEBUG_LL_NS16550
+
 endchoice
 
 config DEBUG_LL_NS16550
diff --git a/images/Makefile.riscv b/images/Makefile.riscv
index 0645238c43..df0e5a9146 100644
--- a/images/Makefile.riscv
+++ b/images/Makefile.riscv
@@ -23,3 +23,7 @@ image-$(CONFIG_BOARD_BEAGLEV) += barebox-beaglev-starlight.img
 pblb-$(CONFIG_BOARD_LITEX_LINUX) += start_litex_linux
 FILE_barebox-litex-linux.img = start_litex_linux.pblb
 image-$(CONFIG_BOARD_LITEX_LINUX) += barebox-litex-linux.img
+
+pblb-$(CONFIG_BOARD_ALLWINNER_D1) += start_allwinner_d1
+FILE_barebox-allwinner-d1.img = start_allwinner_d1.pblb
+image-$(CONFIG_BOARD_ALLWINNER_D1) += barebox-allwinner-d1.img
-- 
2.30.2



From m.felsch at pengutronix.de  Tue Sep 13 05:49:53 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 13 Sep 2022 14:49:53 +0200
Subject: [PATCH 5/6] RISC-V: implement cache-management errata for T-Head SoCs
In-Reply-To: <20220913124954.1346533-1-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
Message-ID: <20220913124954.1346533-6-m.felsch@pengutronix.de>

Since riscv_vendor_id() can be used from pbl and non-pbl context as well
as from relocated and non-relocated code, we are able to query the
vendor id and add special vendor handlings. This is required since the
T-Head C906 and C910 implement a scheme for handling cache operations
different from the generic Zicbom extension.

While on it replace the 'asm' statement by '__asm__' so we are not
relying on GNU extension.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
Hi,

please note that I'm aware of the fact that not all RISC-V cores
implementing the vendorid register, which is quirky according the
"privileged architecture" documentation. For such cores I would propose
to extend the pbl-flags by adding a quirks field. Platforms not
supporting the vendorid register can set the quirk within th
lowlevel/pbl code e.g.:

  barebox_riscv_supervisor_entry(DRAM_BASE, SZ_1G, hartid, fdt, RISCV_QUIRK_NO_VENDORID);

This can be parsed by riscv_vendor_id() so in such case the vendorid 0
which is:

3.1.2 Machine Vendor ID Register mvendorid

The mvendorid CSR is a 32-bit read-only register providing the JEDEC
manufacturer ID of the provider of the core. This register must be
readable in any implementation, but a value of 0 can be returned to
indicate the field is not implemented or that this is a non-commercial
implementation.

Regards,
  Marco

 arch/riscv/include/asm/cache.h | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/cache.h b/arch/riscv/include/asm/cache.h
index 6d69ed49bd..c787f89001 100644
--- a/arch/riscv/include/asm/cache.h
+++ b/arch/riscv/include/asm/cache.h
@@ -6,10 +6,29 @@
 #ifndef _ASM_RISCV_CACHE_H
 #define _ASM_RISCV_CACHE_H
 
+#include <asm/vendorid_list.h>
+
+static inline void thead_local_flush_icache_all(void)
+{
+	/*
+	 * According [1] "13.3 Example of cache settings"
+	 * [1]: https://github.com/T-head-Semi/openc906/blob/main/ \
+	 *	doc/openc906%20datasheet.pd
+	 */
+	__asm__ volatile (".long 0x0100000b" ::: "memory"); /* th.icache.iall */
+	__asm__ volatile (".long 0x01b0000b" ::: "memory"); /* th.sync.is */
+}
+
 static inline void local_flush_icache_all(void)
 {
 #ifdef CONFIG_HAS_CACHE
-	asm volatile ("fence.i" ::: "memory");
+	switch(riscv_vendor_id()) {
+	case THEAD_VENDOR_ID:
+		thead_local_flush_icache_all();
+		break;
+	default:
+		__asm__ volatile ("fence.i" ::: "memory");
+	}
 #endif
 }
 
-- 
2.30.2



From m.felsch at pengutronix.de  Tue Sep 13 05:49:48 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 13 Sep 2022 14:49:48 +0200
Subject: [PATCH 0/6] RISC-V Allwinner D1 Support 2nd Stage Support
Message-ID: <20220913124954.1346533-1-m.felsch@pengutronix.de>

Hi,

this small series adds the basic support for the Allwinner sun20i D1
Nezsha board. It is very limited only serial is supported right now.

Patches 1-4 can be applied independently.

Patch 5 may need some more attention since Ahmad told me in person that
not all softcores implementing the vendorid register. Please see the
patch notes on this patch.

Patch 6 adds the support for the D1 board and a detailed description how
to build and flash a bootable image.

Marco Felsch (6):
  RISC-V: cache: fix local_flush_icache_all enabling
  RISC-V: add riscv_vendor_id() support
  RISC-V: import vendorid list from linux
  RISC-V: use m/sscratch registers for barebox_riscv_pbl_flags
  RISC-V: implement cache-management errata for T-Head SoCs
  RISC-V: add Allwinner Sun20i D1 Nezha support

 Documentation/boards/riscv.rst            | 102 +++++++++++++++++
 arch/riscv/Kconfig.socs                   |  16 +++
 arch/riscv/boards/Makefile                |   1 +
 arch/riscv/boards/allwinner-d1/Makefile   |   3 +
 arch/riscv/boards/allwinner-d1/lowlevel.c |  12 ++
 arch/riscv/boot/entry.c                   |   3 +-
 arch/riscv/boot/entry.h                   |   6 +-
 arch/riscv/boot/start.c                   |  13 +--
 arch/riscv/boot/uncompress.c              |   8 +-
 arch/riscv/configs/sun20i_defconfig       | 130 ++++++++++++++++++++++
 arch/riscv/include/asm/cache.h            |  23 +++-
 arch/riscv/include/asm/debug_ll.h         |   5 +
 arch/riscv/include/asm/system.h           |  71 +++++++++---
 arch/riscv/include/asm/vendorid_list.h    |  11 ++
 common/Kconfig                            |   5 +
 images/Makefile.riscv                     |   4 +
 16 files changed, 380 insertions(+), 33 deletions(-)
 create mode 100644 arch/riscv/boards/allwinner-d1/Makefile
 create mode 100644 arch/riscv/boards/allwinner-d1/lowlevel.c
 create mode 100644 arch/riscv/configs/sun20i_defconfig
 create mode 100644 arch/riscv/include/asm/vendorid_list.h

-- 
2.30.2



From m.felsch at pengutronix.de  Tue Sep 13 05:49:51 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 13 Sep 2022 14:49:51 +0200
Subject: [PATCH 3/6] RISC-V: import vendorid list from linux
In-Reply-To: <20220913124954.1346533-1-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
Message-ID: <20220913124954.1346533-4-m.felsch@pengutronix.de>

Import the vendor id list from upstream linux.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/riscv/include/asm/vendorid_list.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 arch/riscv/include/asm/vendorid_list.h

diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
new file mode 100644
index 0000000000..cb89af3f07
--- /dev/null
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2021 SiFive
+ */
+#ifndef ASM_VENDOR_LIST_H
+#define ASM_VENDOR_LIST_H
+
+#define SIFIVE_VENDOR_ID	0x489
+#define THEAD_VENDOR_ID		0x5b7
+
+#endif
-- 
2.30.2



From m.felsch at pengutronix.de  Tue Sep 13 05:49:49 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 13 Sep 2022 14:49:49 +0200
Subject: [PATCH 1/6] RISC-V: cache: fix local_flush_icache_all enabling
In-Reply-To: <20220913124954.1346533-1-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
Message-ID: <20220913124954.1346533-2-m.felsch@pengutronix.de>

Commit fe181ffda9 ("RISC-V: support incoherent I-Cache") added the
support to handle non-coherent caches and introduced the HAS_CACHE
Kconfig symbol. The symbol must be used with CONFIG_ prefixed since this
is the final Kconfig symbol which can be used within the code.

Fixes: fe181ffda9 ("RISC-V: support incoherent I-Cache")
Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/riscv/include/asm/cache.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/cache.h b/arch/riscv/include/asm/cache.h
index 9a0b9326b2..6d69ed49bd 100644
--- a/arch/riscv/include/asm/cache.h
+++ b/arch/riscv/include/asm/cache.h
@@ -8,7 +8,7 @@
 
 static inline void local_flush_icache_all(void)
 {
-#ifdef HAS_CACHE
+#ifdef CONFIG_HAS_CACHE
 	asm volatile ("fence.i" ::: "memory");
 #endif
 }
-- 
2.30.2



From m.felsch at pengutronix.de  Tue Sep 13 05:49:52 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 13 Sep 2022 14:49:52 +0200
Subject: [PATCH 4/6] RISC-V: use m/sscratch registers for barebox_riscv_pbl_flags
In-Reply-To: <20220913124954.1346533-1-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
Message-ID: <20220913124954.1346533-5-m.felsch@pengutronix.de>

Use the dedicated scratch register for setting the pbl flags. Each mode
has it's own scratch register so we are not conflicting with M-mode
running firmware e.g. OpenSBI. Using the scratch register has two main
advantages:
 1st) It can be used in PBL and non-PBL use-case.
 2nd) It is not affected by the relocation code.

This commit prepares barebox to add support for the special cache ops
used by several T-Head CPUs.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/riscv/boot/entry.c         |  3 +-
 arch/riscv/boot/entry.h         |  6 ++--
 arch/riscv/boot/start.c         | 13 +++----
 arch/riscv/boot/uncompress.c    |  8 ++---
 arch/riscv/include/asm/system.h | 62 ++++++++++++++++++++-------------
 5 files changed, 50 insertions(+), 42 deletions(-)

diff --git a/arch/riscv/boot/entry.c b/arch/riscv/boot/entry.c
index e4a5c2208d..f5a536fc78 100644
--- a/arch/riscv/boot/entry.c
+++ b/arch/riscv/boot/entry.c
@@ -25,6 +25,7 @@ void __noreturn __naked barebox_riscv_entry(unsigned long membase,
 {
 	unsigned long stack_top = riscv_mem_stack_top(membase, membase + memsize);
 	asm volatile ("move sp, %0" : : "r"(stack_top));
-	barebox_pbl_start(membase, memsize, boarddata, flags);
+	riscv_set_flags(flags);
+	barebox_pbl_start(membase, memsize, boarddata);
 }
 
diff --git a/arch/riscv/boot/entry.h b/arch/riscv/boot/entry.h
index fb4af5eae5..b3a24d2783 100644
--- a/arch/riscv/boot/entry.h
+++ b/arch/riscv/boot/entry.h
@@ -6,12 +6,10 @@
 
 void __noreturn barebox_non_pbl_start(unsigned long membase,
 				      unsigned long memsize,
-				      void *boarddata,
-				      unsigned flags);
+				      void *boarddata);
 
 void __noreturn barebox_pbl_start(unsigned long membase,
 				  unsigned long memsize,
-				  void *boarddata,
-				  unsigned flags);
+				  void *boarddata);
 
 #endif
diff --git a/arch/riscv/boot/start.c b/arch/riscv/boot/start.c
index 8b4c8bb2f0..27d9066243 100644
--- a/arch/riscv/boot/start.c
+++ b/arch/riscv/boot/start.c
@@ -27,7 +27,6 @@ static unsigned long riscv_barebox_size;
 static unsigned long riscv_endmem;
 static void *barebox_boarddata;
 static unsigned long barebox_boarddata_size;
-unsigned barebox_riscv_pbl_flags;
 
 void *barebox_riscv_boot_dtb(void)
 {
@@ -108,7 +107,7 @@ device_initcall(barebox_memory_areas_init);
  */
 __noreturn __no_sanitize_address __section(.text_entry)
 void barebox_non_pbl_start(unsigned long membase, unsigned long memsize,
-			   void *boarddata, unsigned flags)
+			   void *boarddata)
 {
 	unsigned long endmem = membase + memsize;
 	unsigned long malloc_start, malloc_end;
@@ -121,7 +120,7 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize,
 
 	barrier();
 
-	irq_init_vector(__riscv_mode(flags));
+	irq_init_vector(riscv_mode());
 
 	pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
 
@@ -171,20 +170,18 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize,
 
 	mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1);
 
-	barebox_riscv_pbl_flags = flags;
-
 	pr_debug("starting barebox...\n");
 
 	start_barebox();
 }
 
-void start(unsigned long membase, unsigned long memsize, void *boarddata, unsigned flags);
+void start(unsigned long membase, unsigned long memsize, void *boarddata);
 /*
  * First function in the uncompressed image. We get here from
  * the pbl. The stack already has been set up by the pbl.
  */
 void __no_sanitize_address __section(.text_entry) start(unsigned long membase,
-		unsigned long memsize, void *boarddata, unsigned flags)
+		unsigned long memsize, void *boarddata)
 {
-	barebox_non_pbl_start(membase, memsize, boarddata, flags);
+	barebox_non_pbl_start(membase, memsize, boarddata);
 }
diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c
index 4ed9b4d371..ee24f81e01 100644
--- a/arch/riscv/boot/uncompress.c
+++ b/arch/riscv/boot/uncompress.c
@@ -24,16 +24,16 @@ unsigned long free_mem_ptr;
 unsigned long free_mem_end_ptr;
 
 void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
-				  void *fdt, unsigned flags)
+				  void *fdt)
 {
 	uint32_t pg_len, uncompressed_len;
-	void __noreturn (*barebox)(unsigned long, unsigned long, void *, unsigned);
+	void __noreturn (*barebox)(unsigned long, unsigned long, void *);
 	unsigned long endmem = membase + memsize;
 	unsigned long barebox_base;
 	void *pg_start, *pg_end;
 	unsigned long pc = get_pc();
 
-	irq_init_vector(__riscv_mode(flags));
+	irq_init_vector(riscv_mode());
 
 	/* piggy data is not relocated, so determine the bounds now */
 	pg_start = input_data + get_runtime_offset();
@@ -72,5 +72,5 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize,
 
 	pr_debug("jumping to uncompressed image at 0x%p. dtb=0x%p\n", barebox, fdt);
 
-	barebox(membase, memsize, fdt, flags);
+	barebox(membase, memsize, fdt);
 }
diff --git a/arch/riscv/include/asm/system.h b/arch/riscv/include/asm/system.h
index 3eb50f63fd..82a8d8e77f 100644
--- a/arch/riscv/include/asm/system.h
+++ b/arch/riscv/include/asm/system.h
@@ -15,7 +15,38 @@ enum riscv_mode {
     RISCV_M_MODE	= 3,
 };
 
-static inline enum riscv_mode __riscv_mode(u32 flags)
+static inline void riscv_set_flags(unsigned flags)
+{
+	switch (flags & RISCV_MODE_MASK) {
+	case RISCV_S_MODE:
+		__asm__ volatile("csrw sscratch, %0" : : "r"(flags));
+		break;
+	case RISCV_M_MODE:
+		__asm__ volatile("csrw mscratch, %0" : : "r"(flags));
+		break;
+	default:
+		/* Other modes are not implemented yet */
+	}
+}
+
+static inline u32 riscv_get_flags(void)
+{
+	u32 flags = 0;
+
+	if (IS_ENABLED(CONFIG_RISCV_S_MODE))
+		__asm__ volatile("csrr %0, sscratch" : "=r"(flags));
+
+	/*
+	 * Since we always set the scratch register on the very beginning, a
+	 * empty flags indicates that we are running in M-mode.
+	 */
+	if (!flags)
+		__asm__ volatile("csrr %0, mscratch" : "=r"(flags));
+
+	return flags;
+}
+
+static inline enum riscv_mode riscv_mode(void)
 {
 	/* allow non-LTO builds to discard code for unused modes */
 	if (!IS_ENABLED(CONFIG_RISCV_MULTI_MODE)) {
@@ -25,14 +56,14 @@ static inline enum riscv_mode __riscv_mode(u32 flags)
 			return RISCV_S_MODE;
 	}
 
-	return flags & RISCV_MODE_MASK;
+	return riscv_get_flags() & RISCV_MODE_MASK;
 }
 
-static inline long __riscv_hartid(u32 flags)
+static inline long riscv_hartid(void)
 {
 	long hartid = -1;
 
-	switch (__riscv_mode(flags)) {
+	switch (riscv_mode()) {
 	case RISCV_S_MODE:
 		__asm__ volatile("mv %0, tp\n" : "=r"(hartid) :);
 		break;
@@ -44,12 +75,12 @@ static inline long __riscv_hartid(u32 flags)
 	return hartid;
 }
 
-static inline long __riscv_vendor_id(u32 flags)
+static inline long riscv_vendor_id(void)
 {
 	struct sbiret ret = { .error = -1 };
 	long id;
 
-	switch (__riscv_mode(flags)) {
+	switch (riscv_mode()) {
 	case RISCV_M_MODE:
 		__asm__ volatile("csrr %0, mvendorid\n" : "=r"(id));
 		return id;
@@ -68,25 +99,6 @@ static inline long __riscv_vendor_id(u32 flags)
 	return ret.error;
 }
 
-#ifndef __PBL__
-extern unsigned barebox_riscv_pbl_flags;
-
-static inline enum riscv_mode riscv_mode(void)
-{
-	return __riscv_mode(barebox_riscv_pbl_flags);
-}
-
-static inline long riscv_hartid(void)
-{
-	return __riscv_hartid(barebox_riscv_pbl_flags);
-}
-
-static inline long riscv_vendor_id(void)
-{
-	return __riscv_vendor_id(barebox_riscv_pbl_flags);
-}
-#endif
-
 #endif
 
 #endif
-- 
2.30.2



From sha at pengutronix.de  Tue Sep 13 06:56:09 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 13 Sep 2022 15:56:09 +0200
Subject: v2022.09.0
Message-ID: <20220913135609.GO6477@pengutronix.de>

Hi All,

I am happy to announce barebox-2022.09.0.

This time we have a few new board supports: Support for the 96Boards Meerkat96
board is added as well as support for the Enclustra AA1 (SoCFPGA).  Also worth
noting is that we now have ROMAPI support for the i.MX8MP and i.MX8MN.  This
allows us to bootstrap barebox via USB on these SoCs. Another nice detail has
been added by Ahmad. The of_dump command now has an option to limit the data
size for each property to be printed. This makes it particularly useful for
showing FIT images.

A lot of other small fixes and improvements went into this release, see
below.

Have Fun!
 Sascha

-------------------------8<--------------------------

Ahmad Fatoum (75):
      ARM: i.MX8M: select ARM_USE_COMPRESSED_DTB for all boards
      ARM: i.MX8M: use compressed DTBs
      partitions: efi: register guid device parameter for disk GUID
      commands: implement devlookup to find device behind device file
      block: efi: allow disabling /dev/usbdiskX renaming
      ARM: i.MX8MN: pass along correct DT depending on variant
      regulator: fixed: remove duplicate always-on handling
      aiodev: add ST L3GD20 Gyroscope and temperature sensor support
      pinctrl: stm32: keep GPIO bank clocks enabled throughout
      spi: stm32: fix reads for sizes bigger than SZ_64K-1
      common: don't allow compressing in-barebox binaries again
      pbl: make USE_COMPRESSED_DTB a PBL-only feature
      pbl: remove redundant select UNCOMRPESS
      kbuild: gen-dtb-s: use Makefile.lib instead of duplicating cmd_lzo
      pbl: compressed-dtb: use flexible array member to access data
      kbuild: pbl: use same compression algo for both barebox and DTB
      lib: zstd: sync with Linux
      decompressor: define macros for non-PBL case as well
      of: base: factor out duplication for property formatting
      commands: of_dump: support limiting size of printed properties
      string: implement str_has_prefix
      booti: add debug prints for kernel header parsing
      reset: Fix of_reset_control_get() for consistent return values
      reset: implement reset_control_get_optional()
      reset: implement reset_control_get_count()
      ARM: i.MX8M: move TF-A chainload functions in <mach/xload.h>
      ARM: i.MX8M: imx8mn-evk: use generic imx8mn_load_and_start_image_via_tfa
      ARM: i.MX8MN: add SDPS barebox-side support
      ARM: i.MX8MN: evk: simplify DDR4/LPDDR4 selection code
      ddr: imx8m: rename type to more fitting ddrc|dram_type
      ARM: i.MX8M: remove struct dram_timing_info::dram_type again
      pbl: generalize fsl i2c_early API into pbl_i2c
      i2c: add <pbl/pmic.h> for PBL use
      ARM: i.MX8M: use new pbl/pmic.h API
      mci: imx-esdhc-pbl: fix warning about unused static function
      gitignore: add device tree blobs to top-level .gitignore
      defaultenv: ikconfig: add generated directory to .gitignore
      pbl: factor out pbl_bio API into pbl/bio.h
      scripts: imx-usb-loader: add i.MX8MN support
      RISC-V: asm: factor relocation related functions into asm/reloc.h
      ARM: asm: factor relocation related functions in asm/reloc.h
      MIPS: asm: add get_runtime_offset stub
      ARM: i.MX8MP: remove select for unused ARC PBL USB gadget driver
      driver: probe: report power domain attach failure
      commands: boot: support preselecting boot entry in menu
      mfd: implement mfd_add_devices
      regmap: implement regmap_init_i2c_smbus
      regulator: consult min_uv, max_uv for regulator_get_voltage
      blspec: refactor to prepare for booting by file path
      blspec: iterate over entries in lexical order
      boot: allow booting by bootspec absolute path
      mci: add hint on how to resolve warning about vmmc-supply
      test: self: add simple environment variable test
      test: self: include new tests in CONFIG_SELFTEST_ENABLE_ALL
      bootsource: rename existing bootsource_set to bootsource_set_raw
      bootsource: allow DT aliases and bootrom numbering to differ
      ARM: dts: rk356x: align bootsource_instance numbering and MMC DT aliases
      net: designware: rework Kconfig text and menu structure
      net: designware: eqos: stm32: remove duplicate error message
      net: designware: eqos: replace double accounting of interface up status
      net: designware: eqos: remove undefined eqos_reset prototype
      FIT: add first support for compressed images
      of: implement of_append_property
      test: self: add tests for of_append_property
      power: reset: reboot-mode: refactor to allow other mode- prefixes
      power: reset: reboot-mode: parse barebox,mode-* properties
      ARM: dts: stm32mp: reuse now upstream tamp node
      ARM: dts: stm32mp: add bootrom serial (DFU) reboot mode
      regulator: recursively enable/disable regulator dependency tree
      regulator: fixed: request vin-supply as needed
      regulator: add Rockchip rk808 support
      ARM: dts: imx6: marsboard: fix flash node after upstream rename
      ARM: i.MX8M: HABv4: make barebox SHA256 embedding POSIX-shell compatible
      fs: ubootvarfs: fix double-free unlinking U-Boot variables
      ARM: sync_caches_for_execution: don't flush disabled data cache

Alexander Shiyan (15):
      ARM: vexpress: Simplify sysctl initialization
      of: Use appropriate header for of_clk_init()
      usb: gadget: Fix Kconfig dependencies
      logo: Fix Kconfig dependencies
      ARM: mxs: Fix Kconfig dependencies
      ARM: boards: ccmx51: Remove unused KConfig option
      serial: ns16550: Reuse 48MHz default clock definition for non-DT OMAP boards
      drivers: rtc: pcf8536: Remove redundant variable
      drivers: rtc: abracon: Remove redundant variable
      drivers: regulator: fixed: Fix error path in probe
      drivers: pwm: imx: Remove redundant assignment
      drivers: gpio: pcf857x: Remove redundant assignment
      drivers: led: pca955x: Remove redundant assignment
      drivers: firmware: arm-scmi: Use core_platform_driver() macro
      ARM: dts: am335x-myirtech: Update to use upstream DT partition scheme

Antony Pavlov (1):
      asm-generic: provide phys_to_virt() and virt_to_phys()

An?e Le?nik (1):
      drivers: net: fec_imx: Fix system halt after FEC reinit

Bastian Krause (1):
      ARM: i.MX23: fix memory size calulcation

Daniel Br?t (1):
      i2c: bcm283x: fix ending of transfer in case of NACK

Denis Orlov (7):
      net: e1000: remove superfluous allocation check
      net: e1000: properly read/write MDI registers on 8254x cards
      net: e1000: do not actually acquire/put swfw_sync on 8254x cards
      net: e1000: configure tx/rx and rctl in open() instead of init()
      net: rtl8169: properly map rx/tx buffers for dma
      net: rtl8169: enable pci device bus mastering on ifup
      net: rtl8169: free allocated memory on halt()

Johannes Zink (3):
      ARM: i.MX: configs: add recent boards to imx_v7_defconfig
      ARM: i.MX7: add 96Boards Meerkat96 support
      base: driver: print dev_err_probe message on permanent probe deferral

Jules Maselbas (1):
      gpiolib: Add of_xlate support

Marco Felsch (8):
      common: bootm: print error in case of appendroot failed
      ARM: i.MX8MN: fix phy-reset gpio
      phy: fix deep probe support
      phy: propagate error in of_phy_get_by_phandle
      usb: chipidea: imx: call enable_clk after all resources are requested
      ARM: i.MX8MP: adapt atf bl31 base address
      clk: imx8mm: remove SYS PLL 1/2 clock gates
      clk: imx8mn: remove SYS PLL 1/2 clock gates

Sam Ravnborg (8):
      pwm: atmel: Fix build and update
      ARM: at91: Make sdramc.h useable in multi image builds
      ARM: at91: Add initialize function to sdramc
      ARM: at91: Provide at91_mux_pio_pin for use in lowlevel
      mci: atmel_mci: Add PBL helper to configure highcapacity
      ARM: at91: Add at91sam9 xload_mmc for PBL use
      ARM: at91: Add extra register definitions
      ARM: at91: Add lowlevel helpers for at91sam9263

Sascha Hauer (29):
      dts: update to v5.19-rc4
      dts: update to v5.19-rc6
      ARM: i.MX8M: include only necessary ddrphy firmwares in image
      fs: Check if automount actually mounts something
      arm: rockchip: radxa-rock3: Add bbu handler for sd card
      ARM: i.MX8M: Add romapi support
      ARM: i.MX8MP: Add common code to load image and jump to it via TF-A
      ARM: i.MX8MP-EVK: Use imx8mp_load_and_start_image_via_tfa()
      imx-usb-loader: Factor out common code to function
      imx-usb-loader: rename mxs functions
      imx-usb-loader: Add i.MX8MP support
      imx-usb-loader: drop some casting
      imx-usb-loader: Fix first stage length
      imx-usb-loader: simplify read_memory()
      imx-usb-loader: verify correct image length
      imx-usb-loader: drop some unnecessary casting
      Merge branch 'for-next/at91'
      Merge branch 'for-next/bootsource'
      Merge branch 'for-next/compression'
      Merge branch 'for-next/dts'
      Merge branch 'for-next/e1000'
      Merge branch 'for-next/efi'
      Merge branch 'for-next/imx'
      Merge branch 'for-next/misc'
      Merge branch 'for-next/net-designware'
      Merge branch 'for-next/rk808'
      Merge branch 'for-next/socfpga'
      ARM: Fix barebox header generation on arm64
      Release v2022.09.0

Stefano Manni (1):
      kbuild: make FIT public key overwritable

Steffen Trumtrar (8):
      scripts: socfgpa_xml_to_config: document pincfg
      ARM: socfpga: achilles: remove cargo-cult
      ARM: socfpga: achilles: use dtbz instead of dtb
      ARM: socfpga: achilles: use ENTRY_FUNCTION_WITHSTACK
      ARM: socfpga: achilles: replace use of magicvalue
      ARM: socfpga: achilles: guard macros with braces
      ARM: socfpga: add support for Enclustra AA1
      ARM: socfpga: defconfig: add aa1

Uwe Kleine-K?nig (4):
      watchdog: imxwd: Convert error messages in .probe to dev_err_probe()
      watchdog: imxwd: Add error messages for some failure points in .probe()
      ARM: i.MX8MM: Consolidate common code to load image and jump to it via TF-A
      ARM: i.MX8MM: Prepare loading only piggydata in imx-usb-loader

Yannick FERTRE (1):
      video: stm32: stm32_ltdc: fix data enable polarity

Yegor Yefremov (4):
      ARM: dts: am335x: update cpsw nodes
      ARM: baltos: use GPIO names for TCA6416 chip
      ARM: baltos: use GPIO names for DIP switches
      ARM: baltos: use GPIO name for mPCIe power enable pin

-- 
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-5555 |


From sha at pengutronix.de  Wed Sep 14 00:43:32 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 14 Sep 2022 09:43:32 +0200
Subject: [PATCH 6/6] RISC-V: add Allwinner Sun20i D1 Nezha support
In-Reply-To: <20220913124954.1346533-7-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
 <20220913124954.1346533-7-m.felsch@pengutronix.de>
Message-ID: <20220914074332.GU6477@pengutronix.de>

On Tue, Sep 13, 2022 at 02:49:54PM +0200, Marco Felsch wrote:
> Add Allwinner sun20i SoC and D1-Nezha board support.
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  Documentation/boards/riscv.rst            | 102 +++++++++++++++++
>  arch/riscv/Kconfig.socs                   |  16 +++
>  arch/riscv/boards/Makefile                |   1 +
>  arch/riscv/boards/allwinner-d1/Makefile   |   3 +
>  arch/riscv/boards/allwinner-d1/lowlevel.c |  12 ++
>  arch/riscv/configs/sun20i_defconfig       | 130 ++++++++++++++++++++++
>  arch/riscv/include/asm/debug_ll.h         |   5 +
>  common/Kconfig                            |   5 +
>  images/Makefile.riscv                     |   4 +
>  9 files changed, 278 insertions(+)
>  create mode 100644 arch/riscv/boards/allwinner-d1/Makefile
>  create mode 100644 arch/riscv/boards/allwinner-d1/lowlevel.c
>  create mode 100644 arch/riscv/configs/sun20i_defconfig
> 

[...]

> diff --git a/arch/riscv/configs/sun20i_defconfig b/arch/riscv/configs/sun20i_defconfig
> new file mode 100644
> index 0000000000..157c430723
> --- /dev/null
> +++ b/arch/riscv/configs/sun20i_defconfig

I can select all machines built with sifive_defconfig, starfive_defconfig,
sun20i_defconfig and virt64_defconfig in a single config and
successfully build barebox with all these machines.

Instead of adding another defconfig we should go into the opposite
direction and consolidate the defconfigs.

Maybe a rv32i_defconfig and a rv64i_defconfig would be it.

Sascha

-- 
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-5555 |


From m.felsch at pengutronix.de  Wed Sep 14 00:52:37 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 14 Sep 2022 09:52:37 +0200
Subject: [PATCH 6/6] RISC-V: add Allwinner Sun20i D1 Nezha support
In-Reply-To: <20220914074332.GU6477@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
 <20220913124954.1346533-7-m.felsch@pengutronix.de>
 <20220914074332.GU6477@pengutronix.de>
Message-ID: <20220914075237.5agd6glzozagxyda@pengutronix.de>

On 22-09-14, Sascha Hauer wrote:
> On Tue, Sep 13, 2022 at 02:49:54PM +0200, Marco Felsch wrote:
> > Add Allwinner sun20i SoC and D1-Nezha board support.
> > 
> > Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> > ---
> >  Documentation/boards/riscv.rst            | 102 +++++++++++++++++
> >  arch/riscv/Kconfig.socs                   |  16 +++
> >  arch/riscv/boards/Makefile                |   1 +
> >  arch/riscv/boards/allwinner-d1/Makefile   |   3 +
> >  arch/riscv/boards/allwinner-d1/lowlevel.c |  12 ++
> >  arch/riscv/configs/sun20i_defconfig       | 130 ++++++++++++++++++++++
> >  arch/riscv/include/asm/debug_ll.h         |   5 +
> >  common/Kconfig                            |   5 +
> >  images/Makefile.riscv                     |   4 +
> >  9 files changed, 278 insertions(+)
> >  create mode 100644 arch/riscv/boards/allwinner-d1/Makefile
> >  create mode 100644 arch/riscv/boards/allwinner-d1/lowlevel.c
> >  create mode 100644 arch/riscv/configs/sun20i_defconfig
> > 
> 
> [...]
> 
> > diff --git a/arch/riscv/configs/sun20i_defconfig b/arch/riscv/configs/sun20i_defconfig
> > new file mode 100644
> > index 0000000000..157c430723
> > --- /dev/null
> > +++ b/arch/riscv/configs/sun20i_defconfig
> 
> I can select all machines built with sifive_defconfig, starfive_defconfig,
> sun20i_defconfig and virt64_defconfig in a single config and
> successfully build barebox with all these machines.
> 
> Instead of adding another defconfig we should go into the opposite
> direction and consolidate the defconfigs.
> 
> Maybe a rv32i_defconfig and a rv64i_defconfig would be it.

Good point. One question, do we even have support for rv32i?

Regards,
  Marco

> 
> Sascha
> 
> -- 
> 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-5555 |
> 


From sha at pengutronix.de  Wed Sep 14 00:55:40 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 14 Sep 2022 09:55:40 +0200
Subject: [PATCH 6/6] RISC-V: add Allwinner Sun20i D1 Nezha support
In-Reply-To: <20220914075237.5agd6glzozagxyda@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
 <20220913124954.1346533-7-m.felsch@pengutronix.de>
 <20220914074332.GU6477@pengutronix.de>
 <20220914075237.5agd6glzozagxyda@pengutronix.de>
Message-ID: <20220914075540.GV6477@pengutronix.de>

On Wed, Sep 14, 2022 at 09:52:37AM +0200, Marco Felsch wrote:
> On 22-09-14, Sascha Hauer wrote:
> > On Tue, Sep 13, 2022 at 02:49:54PM +0200, Marco Felsch wrote:
> > > Add Allwinner sun20i SoC and D1-Nezha board support.
> > > 
> > > Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> > > ---
> > >  Documentation/boards/riscv.rst            | 102 +++++++++++++++++
> > >  arch/riscv/Kconfig.socs                   |  16 +++
> > >  arch/riscv/boards/Makefile                |   1 +
> > >  arch/riscv/boards/allwinner-d1/Makefile   |   3 +
> > >  arch/riscv/boards/allwinner-d1/lowlevel.c |  12 ++
> > >  arch/riscv/configs/sun20i_defconfig       | 130 ++++++++++++++++++++++
> > >  arch/riscv/include/asm/debug_ll.h         |   5 +
> > >  common/Kconfig                            |   5 +
> > >  images/Makefile.riscv                     |   4 +
> > >  9 files changed, 278 insertions(+)
> > >  create mode 100644 arch/riscv/boards/allwinner-d1/Makefile
> > >  create mode 100644 arch/riscv/boards/allwinner-d1/lowlevel.c
> > >  create mode 100644 arch/riscv/configs/sun20i_defconfig
> > > 
> > 
> > [...]
> > 
> > > diff --git a/arch/riscv/configs/sun20i_defconfig b/arch/riscv/configs/sun20i_defconfig
> > > new file mode 100644
> > > index 0000000000..157c430723
> > > --- /dev/null
> > > +++ b/arch/riscv/configs/sun20i_defconfig
> > 
> > I can select all machines built with sifive_defconfig, starfive_defconfig,
> > sun20i_defconfig and virt64_defconfig in a single config and
> > successfully build barebox with all these machines.
> > 
> > Instead of adding another defconfig we should go into the opposite
> > direction and consolidate the defconfigs.
> > 
> > Maybe a rv32i_defconfig and a rv64i_defconfig would be it.
> 
> Good point. One question, do we even have support for rv32i?

It can be selected in Kconfig and we have defconfigs built with it, so I
would assume yes.

Sascha


-- 
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-5555 |


From m.felsch at pengutronix.de  Wed Sep 14 01:19:28 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 14 Sep 2022 10:19:28 +0200
Subject: [PATCH 6/6] RISC-V: add Allwinner Sun20i D1 Nezha support
In-Reply-To: <20220914075540.GV6477@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
 <20220913124954.1346533-7-m.felsch@pengutronix.de>
 <20220914074332.GU6477@pengutronix.de>
 <20220914075237.5agd6glzozagxyda@pengutronix.de>
 <20220914075540.GV6477@pengutronix.de>
Message-ID: <20220914081928.ty7a4viz2qb7geqt@pengutronix.de>

On 22-09-14, Sascha Hauer wrote:
> On Wed, Sep 14, 2022 at 09:52:37AM +0200, Marco Felsch wrote:
> > On 22-09-14, Sascha Hauer wrote:
> > > On Tue, Sep 13, 2022 at 02:49:54PM +0200, Marco Felsch wrote:
> > > > Add Allwinner sun20i SoC and D1-Nezha board support.
> > > > 
> > > > Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> > > > ---
> > > >  Documentation/boards/riscv.rst            | 102 +++++++++++++++++
> > > >  arch/riscv/Kconfig.socs                   |  16 +++
> > > >  arch/riscv/boards/Makefile                |   1 +
> > > >  arch/riscv/boards/allwinner-d1/Makefile   |   3 +
> > > >  arch/riscv/boards/allwinner-d1/lowlevel.c |  12 ++
> > > >  arch/riscv/configs/sun20i_defconfig       | 130 ++++++++++++++++++++++
> > > >  arch/riscv/include/asm/debug_ll.h         |   5 +
> > > >  common/Kconfig                            |   5 +
> > > >  images/Makefile.riscv                     |   4 +
> > > >  9 files changed, 278 insertions(+)
> > > >  create mode 100644 arch/riscv/boards/allwinner-d1/Makefile
> > > >  create mode 100644 arch/riscv/boards/allwinner-d1/lowlevel.c
> > > >  create mode 100644 arch/riscv/configs/sun20i_defconfig
> > > > 
> > > 
> > > [...]
> > > 
> > > > diff --git a/arch/riscv/configs/sun20i_defconfig b/arch/riscv/configs/sun20i_defconfig
> > > > new file mode 100644
> > > > index 0000000000..157c430723
> > > > --- /dev/null
> > > > +++ b/arch/riscv/configs/sun20i_defconfig
> > > 
> > > I can select all machines built with sifive_defconfig, starfive_defconfig,
> > > sun20i_defconfig and virt64_defconfig in a single config and
> > > successfully build barebox with all these machines.
> > > 
> > > Instead of adding another defconfig we should go into the opposite
> > > direction and consolidate the defconfigs.
> > > 
> > > Maybe a rv32i_defconfig and a rv64i_defconfig would be it.
> > 
> > Good point. One question, do we even have support for rv32i?
> 
> It can be selected in Kconfig and we have defconfigs built with it, so I
> would assume yes.

Yes, you're right. The LiteX and the Erizo are RV32I. So yes, I'm
completely with you to have two defconfigs, one for 32bit and one for
64bit. Should I do that or do you want to merge them?

Regards,
  Marco

> Sascha
> 
> 
> -- 
> 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-5555 |
> 


From sha at pengutronix.de  Wed Sep 14 01:33:25 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 14 Sep 2022 10:33:25 +0200
Subject: [PATCH 4/6] RISC-V: use m/sscratch registers for
 barebox_riscv_pbl_flags
In-Reply-To: <20220913124954.1346533-5-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
 <20220913124954.1346533-5-m.felsch@pengutronix.de>
Message-ID: <20220914083325.GJ12909@pengutronix.de>

On Tue, Sep 13, 2022 at 02:49:52PM +0200, Marco Felsch wrote:
> Use the dedicated scratch register for setting the pbl flags. Each mode
> has it's own scratch register so we are not conflicting with M-mode
> running firmware e.g. OpenSBI. Using the scratch register has two main
> advantages:
>  1st) It can be used in PBL and non-PBL use-case.
>  2nd) It is not affected by the relocation code.
> 
> This commit prepares barebox to add support for the special cache ops
> used by several T-Head CPUs.
> 
> +static inline void riscv_set_flags(unsigned flags)
> +{
> +	switch (flags & RISCV_MODE_MASK) {
> +	case RISCV_S_MODE:
> +		__asm__ volatile("csrw sscratch, %0" : : "r"(flags));
> +		break;
> +	case RISCV_M_MODE:
> +		__asm__ volatile("csrw mscratch, %0" : : "r"(flags));
> +		break;
> +	default:
> +		/* Other modes are not implemented yet */
> +	}

Compilation ends in an error here:

arch/riscv/include/asm/system.h:27:2: error: label at end of compound statement

Sascha

-- 
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-5555 |


From sha at pengutronix.de  Wed Sep 14 01:33:58 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 14 Sep 2022 10:33:58 +0200
Subject: [PATCH 2/6] RISC-V: add riscv_vendor_id() support
In-Reply-To: <20220913124954.1346533-3-m.felsch@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
 <20220913124954.1346533-3-m.felsch@pengutronix.de>
Message-ID: <20220914083358.GK12909@pengutronix.de>

On Tue, Sep 13, 2022 at 02:49:50PM +0200, Marco Felsch wrote:
> +static inline long __riscv_vendor_id(u32 flags)
> +{
> +	struct sbiret ret = { .error = -1 };
> +	long id;
> +
> +	switch (__riscv_mode(flags)) {
> +	case RISCV_M_MODE:
> +		__asm__ volatile("csrr %0, mvendorid\n" : "=r"(id));
> +		return id;
> +	case RISCV_S_MODE:
> +		/*
> +		 * We need to use the sbi_ecall() since it can be that we got
> +		 * called without a working stack
> +		 */
> +		ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID,
> +				0, 0, 0, 0, 0, 0);
> +		if (!ret.error)
> +			return ret.value;
> +	default:
> +	}

arch/riscv/include/asm/system.h:27:2: error: label at end of compound statement

Sascha

-- 
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-5555 |


From m.felsch at pengutronix.de  Wed Sep 14 02:35:01 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 14 Sep 2022 11:35:01 +0200
Subject: [PATCH 4/6] RISC-V: use m/sscratch registers for
 barebox_riscv_pbl_flags
In-Reply-To: <20220914083325.GJ12909@pengutronix.de>
References: <20220913124954.1346533-1-m.felsch@pengutronix.de>
 <20220913124954.1346533-5-m.felsch@pengutronix.de>
 <20220914083325.GJ12909@pengutronix.de>
Message-ID: <20220914093501.bd6j6sbvdfp4xoak@pengutronix.de>

On 22-09-14, Sascha Hauer wrote:
> On Tue, Sep 13, 2022 at 02:49:52PM +0200, Marco Felsch wrote:
> > Use the dedicated scratch register for setting the pbl flags. Each mode
> > has it's own scratch register so we are not conflicting with M-mode
> > running firmware e.g. OpenSBI. Using the scratch register has two main
> > advantages:
> >  1st) It can be used in PBL and non-PBL use-case.
> >  2nd) It is not affected by the relocation code.
> > 
> > This commit prepares barebox to add support for the special cache ops
> > used by several T-Head CPUs.
> > 
> > +static inline void riscv_set_flags(unsigned flags)
> > +{
> > +	switch (flags & RISCV_MODE_MASK) {
> > +	case RISCV_S_MODE:
> > +		__asm__ volatile("csrw sscratch, %0" : : "r"(flags));
> > +		break;
> > +	case RISCV_M_MODE:
> > +		__asm__ volatile("csrw mscratch, %0" : : "r"(flags));
> > +		break;
> > +	default:
> > +		/* Other modes are not implemented yet */
> > +	}
> 
> Compilation ends in an error here:
> 
> arch/riscv/include/asm/system.h:27:2: error: label at end of compound statement

Arg.. I used GCC11 they introduced the support for by commit 8b7a9a249a6
("C Parser: Implement mixing of labels and code."). Do we need to add
warning like: -Wc11-c2x-compat? So at least the developer gets informed?

Regards,
  Marco


From antonynpavlov at gmail.com  Wed Sep 14 23:18:20 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Thu, 15 Sep 2022 09:18:20 +0300
Subject: [RFC] Documentation/conf.py: fix copyright years
In-Reply-To: <20220912084627.84575-1-antonynpavlov@gmail.com>
References: <20220912084627.84575-1-antonynpavlov@gmail.com>
Message-ID: <20220915091820.aa57cf6dd4cabd1878e6d849@gmail.com>

On Mon, 12 Sep 2022 11:46:27 +0300
Antony Pavlov <antonynpavlov at gmail.com> wrote:

Hi Sascha!

Here is the barebox documentation generated in my gitlab CI/CD system with 'make docs':
  https://frantony.gitlab.io/-/barebox/-/jobs/3029093142/artifacts/Documentation/html/index.html

and this is the barebox documentation from barebox.org:
  https://www.barebox.org/doc/latest/index.html

The index.html pages look different (different color scheme is used, no barebox logo in the left top
conner after 'make docs' etc).

Could you please publish an instruction how to reproduce barebox html documentation from barebox.org?


> N.B. N-dash is used!
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  Documentation/conf.py | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/conf.py b/Documentation/conf.py
> index bcd8633c919..5fb8b07c380 100644
> --- a/Documentation/conf.py
> +++ b/Documentation/conf.py
> @@ -44,7 +44,7 @@ master_doc = 'index'
>  
>  # General information about the project.
>  project = u'barebox'
> -copyright = u'2014, The barebox project'
> +copyright = u'2014?2022, The barebox project'
>  
>  # The version info for the project you're documenting, acts as replacement for
>  # |version| and |release|, also used in various other places throughout the
> -- 
> 2.37.2
> 


-- 
Best regards,
? Antony Pavlov


From s.hauer at pengutronix.de  Thu Sep 15 23:28:43 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 08:28:43 +0200
Subject: [RFC] Documentation/conf.py: fix copyright years
In-Reply-To: <20220915091820.aa57cf6dd4cabd1878e6d849@gmail.com>
References: <20220912084627.84575-1-antonynpavlov@gmail.com>
 <20220915091820.aa57cf6dd4cabd1878e6d849@gmail.com>
Message-ID: <20220916062843.GX6477@pengutronix.de>

Hi Antony,

On Thu, Sep 15, 2022 at 09:18:20AM +0300, Antony Pavlov wrote:
> On Mon, 12 Sep 2022 11:46:27 +0300
> Antony Pavlov <antonynpavlov at gmail.com> wrote:
> 
> Hi Sascha!
> 
> Here is the barebox documentation generated in my gitlab CI/CD system with 'make docs':
>   https://frantony.gitlab.io/-/barebox/-/jobs/3029093142/artifacts/Documentation/html/index.html
> 
> and this is the barebox documentation from barebox.org:
>   https://www.barebox.org/doc/latest/index.html
> 
> The index.html pages look different (different color scheme is used, no barebox logo in the left top
> conner after 'make docs' etc).
> 
> Could you please publish an instruction how to reproduce barebox html documentation from barebox.org?

We have the theme here internally. Sorry, I can't give you any
instructions on how to reproduce the docs as found on the website.
What do you need them for?

Sascha

-- 
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-5555 |


From s.hauer at pengutronix.de  Thu Sep 15 23:29:00 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 08:29:00 +0200
Subject: [RFC] Documentation/conf.py: fix copyright years
In-Reply-To: <20220912084627.84575-1-antonynpavlov@gmail.com>
References: <20220912084627.84575-1-antonynpavlov@gmail.com>
Message-ID: <20220916062900.GY6477@pengutronix.de>

On Mon, Sep 12, 2022 at 11:46:27AM +0300, Antony Pavlov wrote:
> N.B. N-dash is used!
> 
> Signed-off-by: Antony Pavlov <antonynpavlov at gmail.com>
> ---
>  Documentation/conf.py | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/Documentation/conf.py b/Documentation/conf.py
> index bcd8633c919..5fb8b07c380 100644
> --- a/Documentation/conf.py
> +++ b/Documentation/conf.py
> @@ -44,7 +44,7 @@ master_doc = 'index'
>  
>  # General information about the project.
>  project = u'barebox'
> -copyright = u'2014, The barebox project'
> +copyright = u'2014?2022, The barebox project'
>  
>  # The version info for the project you're documenting, acts as replacement for
>  # |version| and |release|, also used in various other places throughout the
> -- 
> 2.37.2
> 
> 

-- 
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-5555 |


From antonynpavlov at gmail.com  Fri Sep 16 04:41:00 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Fri, 16 Sep 2022 14:41:00 +0300
Subject: [RFC] Documentation/conf.py: fix copyright years
In-Reply-To: <20220916062843.GX6477@pengutronix.de>
References: <20220912084627.84575-1-antonynpavlov@gmail.com>
	<20220915091820.aa57cf6dd4cabd1878e6d849@gmail.com>
	<20220916062843.GX6477@pengutronix.de>
Message-ID: <20220916144100.fcd08e98d9ffc77a7d4d016e@gmail.com>

On Fri, 16 Sep 2022 08:28:43 +0200
Sascha Hauer <s.hauer at pengutronix.de> wrote:

Hi Sascha!

> On Thu, Sep 15, 2022 at 09:18:20AM +0300, Antony Pavlov wrote:
> > On Mon, 12 Sep 2022 11:46:27 +0300
> > Antony Pavlov <antonynpavlov at gmail.com> wrote:
> > 
> > Hi Sascha!
> > 
> > Here is the barebox documentation generated in my gitlab CI/CD system with 'make docs':
> >   https://frantony.gitlab.io/-/barebox/-/jobs/3029093142/artifacts/Documentation/html/index.html
> > 
> > and this is the barebox documentation from barebox.org:
> >   https://www.barebox.org/doc/latest/index.html
> > 
> > The index.html pages look different (different color scheme is used, no barebox logo in the left top
> > conner after 'make docs' etc).
> > 
> > Could you please publish an instruction how to reproduce barebox html documentation from barebox.org?
> 
> We have the theme here internally. Sorry, I can't give you any
> instructions on how to reproduce the docs as found on the website.
> What do you need them for?

I want to extend my gitlab.com CI-CD scripts.

-- 
Best regards,
? Antony Pavlov


From s.hauer at pengutronix.de  Fri Sep 16 05:06:20 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 14:06:20 +0200
Subject: [PATCH] net: Use dma_alloc to allocate net packet
Message-ID: <20220916120620.2708538-1-s.hauer@pengutronix.de>

network packets are often DMAed by the network drivers, so allocate
them with dma_alloc() rather than assuming that an arbitrarily chosen
alignment is sufficient

This fixes network transfers on a Rockchip RK3568 board which
occasionally sent out packets with corrupt data.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 include/net.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/net.h b/include/net.h
index b50b6e76c8..310bf5169d 100644
--- a/include/net.h
+++ b/include/net.h
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <clock.h>
 #include <led.h>
+#include <dma.h>
 #include <slice.h>
 #include <xfuncs.h>
 #include <linux/phy.h>
@@ -470,7 +471,7 @@ struct net_connection {
 
 static inline char *net_alloc_packet(void)
 {
-	return xmemalign(32, PKTSIZE);
+	return dma_alloc(PKTSIZE);
 }
 
 struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport,
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 16 05:49:42 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 14:49:42 +0200
Subject: [PATCH] net: Bring up all interfaces before going interactive
Message-ID: <20220916124942.3751131-1-s.hauer@pengutronix.de>

So far we only bring up network interfaces when we actually need them.
This means we could be idling in the shell for long and once the user
decides to do networking he has to wait for the link to be established.
We can do better: Before going interactive bring up all known network
interfaces which makes the links established when the user needs them.

To implement this we have to rework carrier checking a bit, because
otherwise barebox would wait for the links to be established before
dropping to the shell.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/startup.c |  3 +++
 include/net.h    |  3 +++
 net/eth.c        | 34 +++++++++++++++++++++-------------
 3 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/common/startup.c b/common/startup.c
index f53b73f81a..f63a0ae7d5 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -37,6 +37,7 @@
 #include <linux/ctype.h>
 #include <watchdog.h>
 #include <glob.h>
+#include <net.h>
 #include <bselftest.h>
 
 extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
@@ -208,6 +209,8 @@ enum autoboot_state do_autoboot_countdown(void)
 				&outkey);
 	command_slice_acquire();
 
+	eth_open_all();
+
 	if (ret == 0)
 		autoboot_state = AUTOBOOT_BOOT;
 	else if (menu_exists && outkey == 'm')
diff --git a/include/net.h b/include/net.h
index 310bf5169d..338033d698 100644
--- a/include/net.h
+++ b/include/net.h
@@ -79,6 +79,8 @@ struct eth_device {
 #define ETH_MODE_STATIC 1
 #define ETH_MODE_DISABLED 2
 	unsigned int global_mode;
+
+	uint64_t last_link_check;
 };
 
 #define dev_to_edev(d) container_of(d, struct eth_device, dev)
@@ -109,6 +111,7 @@ int eth_open(struct eth_device *edev);
 void eth_close(struct eth_device *edev);
 int eth_send(struct eth_device *edev, void *packet, int length);	   /* Send a packet		*/
 int eth_rx(void);			/* Check for received packets	*/
+void eth_open_all(void);
 struct eth_device *of_find_eth_device_by_node(struct device_node *np);
 
 /* associate a MAC address to a ethernet device. Should be called by
diff --git a/net/eth.c b/net/eth.c
index bc641dc8e4..8f6ff7db3a 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -20,8 +20,6 @@
 #include <linux/ctype.h>
 #include <linux/stat.h>
 
-static uint64_t last_link_check;
-
 LIST_HEAD(netdev_list);
 
 struct eth_ethaddr {
@@ -173,7 +171,7 @@ int eth_complete(struct string_list *sl, char *instr)
 /*
  * Check for link if we haven't done so for longer.
  */
-static int eth_carrier_check(struct eth_device *edev, int force)
+static int eth_carrier_check(struct eth_device *edev, bool may_wait)
 {
 	int ret;
 
@@ -183,15 +181,17 @@ static int eth_carrier_check(struct eth_device *edev, int force)
 	if (!edev->phydev)
 		return 0;
 
-	if (force)
-		phy_wait_aneg_done(edev->phydev);
-
-	if (force || is_timeout(last_link_check, 5 * SECOND) ||
-			!edev->phydev->link) {
+	if (!edev->last_link_check ||
+	    is_timeout(edev->last_link_check, 5 * SECOND)) {
 		ret = phy_update_status(edev->phydev);
 		if (ret)
 			return ret;
-		last_link_check = get_time_ns();
+		edev->last_link_check = get_time_ns();
+	}
+
+	if (may_wait && !edev->phydev->link) {
+		phy_wait_aneg_done(edev->phydev);
+		edev->last_link_check = get_time_ns();
 	}
 
 	return edev->phydev->link ? 0 : -ENETDOWN;
@@ -237,7 +237,7 @@ int eth_send(struct eth_device *edev, void *packet, int length)
 	if (slice_acquired(eth_device_slice(edev)))
 		return eth_queue(edev, packet, length);
 
-	ret = eth_carrier_check(edev, 0);
+	ret = eth_carrier_check(edev, true);
 	if (ret)
 		return ret;
 
@@ -258,7 +258,7 @@ static void eth_do_work(struct eth_device *edev)
 	int ret;
 
 	if (!phy_acquired(edev->phydev)) {
-		ret = eth_carrier_check(edev, 0);
+		ret = eth_carrier_check(edev, false);
 		if (ret)
 			return;
 	}
@@ -455,12 +455,12 @@ int eth_open(struct eth_device *edev)
 	if (edev->active)
 		return 0;
 
+	edev->last_link_check = 0;
+
 	ret = edev->open(edev);
 	if (!ret)
 		edev->active = 1;
 
-	eth_carrier_check(edev, 1);
-
 	return ret;
 }
 
@@ -522,6 +522,14 @@ struct eth_device *of_find_eth_device_by_node(struct device_node *np)
 }
 EXPORT_SYMBOL(of_find_eth_device_by_node);
 
+void eth_open_all(void)
+{
+	struct eth_device *edev;
+
+	list_for_each_entry(edev, &netdev_list, list)
+		eth_open(edev);
+}
+
 static int of_populate_ethaddr(void)
 {
 	char str[sizeof("xx:xx:xx:xx:xx:xx")];
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 16 05:52:29 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 14:52:29 +0200
Subject: [PATCH 0/3] tftp updates
Message-ID: <20220916125232.3775559-1-s.hauer@pengutronix.de>

This series has some updates for the recently introduced RFC7440
support.

Also I found it useful to increase the number of receive packets in the
network driver I am currently using. Other drivers might be adjusted as
well accordingly.

Sascha

Sascha Hauer (3):
  tftp: remove selftest
  tftp: implement UDP reorder cache using lists
  net: designware_eqos: Allocate more receive buffers

 drivers/net/designware_eqos.c |   2 +-
 fs/Kconfig                    |  22 ---
 fs/tftp.c                     | 344 ++++------------------------------
 test/self/Kconfig             |   7 -
 4 files changed, 37 insertions(+), 338 deletions(-)

-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 16 05:52:31 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 14:52:31 +0200
Subject: [PATCH 2/3] tftp: implement UDP reorder cache using lists
In-Reply-To: <20220916125232.3775559-1-s.hauer@pengutronix.de>
References: <20220916125232.3775559-1-s.hauer@pengutronix.de>
Message-ID: <20220916125232.3775559-3-s.hauer@pengutronix.de>

The UDP reorder cache can be much easier implemented using lists.
As a bonus the cache grows and shrinks on demand and no fixed size
has to be configured at compile time.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/Kconfig |  22 -----
 fs/tftp.c  | 242 ++++++++---------------------------------------------
 2 files changed, 36 insertions(+), 228 deletions(-)

diff --git a/fs/Kconfig b/fs/Kconfig
index cf884e0646..0c49342859 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -57,28 +57,6 @@ config FS_TFTP_MAX_WINDOW_SIZE
 	  Requires tftp "windowsize" (RFC 7440) support on server side
 	  to have an effect.
 
-config FS_TFTP_REORDER_CACHE_SIZE
-	int
-	prompt "number of out-of-order tftp packets to be cached"
-	depends on FS_TFTP
-	default 16 if FS_TFTP_MAX_WINDOW_SIZE > 16
-	default  0 if FS_TFTP_MAX_WINDOW_SIZE = 1
-        ## TODO: it should be 'FS_TFTP_MAX_WINDOW_SIZE - 1' but this
-        ## is not supported by Kconfig
-	default FS_TFTP_MAX_WINDOW_SIZE
-	range 0 FS_TFTP_MAX_WINDOW_SIZE
-	help
-	  UDP allows reordering of datagrams; with this option,
-	  unexpected tftp packets will be cached and later
-	  reassembled.  This increases stability of the tftp download
-	  with the cost of memory (around 1440 bytes per cache
-	  element) and barebox binary size (around 700 bytes).
-
-	  A value of 0 disables caching.
-
-	  Requires tftp "windowsize" (RFC 7440) support on server side
-	  to have an effect.
-
 config FS_OMAP4_USBBOOT
 	bool
 	prompt "Filesystem over usb boot"
diff --git a/fs/tftp.c b/fs/tftp.c
index f089e2f693..0094825217 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -78,9 +78,6 @@
 /* allocate this number of blocks more than needed in the fifo */
 #define TFTP_EXTRA_BLOCKS	2
 
-/* size of cache which deals with udp reordering */
-#define TFTP_WINDOW_CACHE_NUM	CONFIG_FS_TFTP_REORDER_CACHE_SIZE
-
 /* marker for an emtpy 'tftp_cache' */
 #define TFTP_CACHE_NO_ID	(-1)
 
@@ -101,24 +98,12 @@ struct tftp_block {
 	uint16_t id;
 	uint16_t len;
 
-	struct list_head head;
+	struct list_head list;
 	uint8_t data[];
 };
 
 struct tftp_cache {
-	/* The id located at @pos or TFTP_CACHE_NO_ID when cache is empty.  It
-	   is possible that the corresponding bit in @used is NOT set. */
-	unsigned int		id;
-	unsigned int		pos;
-
-	/* bitmask */
-	unsigned long		used[BITS_TO_LONGS(TFTP_WINDOW_CACHE_NUM)];
-
-	/* size of the cache; is limited by TFTP_WINDOW_CACHE_NUM and the
-	   actual window size */
-	unsigned int		size;
-	unsigned int		block_len;
-	struct tftp_block	*blocks[TFTP_WINDOW_CACHE_NUM];
+	struct list_head	blocks;
 };
 
 struct file_priv {
@@ -145,18 +130,6 @@ struct tftp_priv {
 	IPaddr_t server;
 };
 
-static inline bool is_block_before(uint16_t a, uint16_t b)
-{
-	return (int16_t)(b - a) > 0;
-}
-
-static inline uint16_t get_block_delta(uint16_t a, uint16_t b)
-{
-	debug_assert(!is_block_before(b, a));
-
-	return b - a;
-}
-
 static bool in_window(uint16_t block, uint16_t start, uint16_t end)
 {
 	/* handle the three cases:
@@ -169,191 +142,37 @@ static bool in_window(uint16_t block, uint16_t start, uint16_t end)
 		(end   <= start && start <= block));
 }
 
-static inline size_t tftp_window_cache_size(struct tftp_cache const *cache)
-{
-	/* allows to optimize away the cache code when TFTP_WINDOW_CACHE_SIZE
-	   is 0 */
-	return TFTP_WINDOW_CACHE_NUM == 0 ? 0 : cache->size;
-}
-
-static void tftp_window_cache_init(struct tftp_cache *cache,
-				   uint16_t block_len, uint16_t window_size)
-{
-	debug_assert(window_size > 0);
-
-	*cache = (struct tftp_cache) {
-		.id		= TFTP_CACHE_NO_ID,
-		.block_len	= block_len,
-		.size		= min_t(uint16_t, window_size - 1,
-					ARRAY_SIZE(cache->blocks)),
-	};
-}
-
 static void tftp_window_cache_free(struct tftp_cache *cache)
 {
-	size_t	cache_size = tftp_window_cache_size(cache);
-	size_t	i;
+	struct tftp_block *block, *tmp;
 
-	for (i = 0; i < cache_size; ++i) {
-		free(cache->blocks[i]);
-		cache->blocks[i] = NULL;
-	}
-}
-
-static void tftp_window_cache_reset(struct tftp_cache *cache)
-{
-	cache->id = TFTP_CACHE_NO_ID;
-	memset(cache->used, 0, sizeof cache->used);
-}
-
-static int tftp_window_cache_get_pos(struct tftp_cache const *cache, uint16_t id)
-{
-	size_t		cache_size = tftp_window_cache_size(cache);
-	unsigned int	pos;
-
-	if (cache_size == 0)
-		return -1;
-
-	if (cache->id == TFTP_CACHE_NO_ID)
-		return -1;
-
-	if (!in_window(id, cache->id, cache->id + cache_size - 1))
-		return -1;
-
-	pos  = cache->pos + get_block_delta(cache->id, id);
-	pos %= cache_size;
-
-	return pos;
-}
-
-/* returns whether the first cached element has the given @id */
-static bool tftp_window_cache_starts_with(struct tftp_cache const *cache,
-					  uint16_t id)
-{
-	return (TFTP_WINDOW_CACHE_NUM > 0 &&
-		cache->id != TFTP_CACHE_NO_ID &&
-		cache->id == id &&
-		test_bit(cache->pos, cache->used));
-}
-
-static bool tftp_window_cache_is_empty(struct tftp_cache const *cache)
-{
-	/* use this indirection to avoid warnings about a '0 < 0' comparison
-	   in the loop condition when TFTP_WINDOW_CACHE_NUM is zero */
-	size_t	cache_size = ARRAY_SIZE(cache->used);
-	size_t	i;
-
-	for (i = 0; i < cache_size; ++i) {
-		if (cache->used[i] != 0)
-			return false;
-	}
-
-	return true;
+	list_for_each_entry_safe(block, tmp, &cache->blocks, list)
+		free(block);
 }
 
 static int tftp_window_cache_insert(struct tftp_cache *cache, uint16_t id,
 				    void const *data, size_t len)
 {
-	size_t const		cache_size = tftp_window_cache_size(cache);
-	int			pos;
-	struct tftp_block	*block;
-
-	if (cache_size == 0)
-		return -ENOSPC;
-
-	if (cache->id == TFTP_CACHE_NO_ID) {
-		/* initialize cache when it does not contain elements yet */
-		cache->id = id;
-		cache->pos = 0;
-
-		/* sanity check; cache is expected to be empty */
-		debug_assert(tftp_window_cache_is_empty(cache));
-	}
-
-	pos = tftp_window_cache_get_pos(cache, id);
-	if (pos < 0)
-		return -ENOSPC;
-
-	debug_assert(pos < cache_size);
-
-	if (test_bit(pos, cache->used))
-		/* block already cached */
-		return 0;
+	struct tftp_block *block, *new;
 
-	block = cache->blocks[pos];
-	if (!block) {
-		/* allocate space for the block; after being released, this
-		   memory can be reused for other blocks during the same tftp
-		   transfer */
-		block = malloc(sizeof *block + cache->block_len);
-		if (!block)
-			return -ENOMEM;
+	list_for_each_entry(block, &cache->blocks, list) {
+		if (block->id == id)
+			return 0;
+		if (block->id < id)
+			continue;
 
-		cache->blocks[pos] = block;
+		break;
 	}
 
-	__set_bit(pos, cache->used);
-	memcpy(block->data, data, len);
-	block->id = id;
-	block->len = len;
+	new = xzalloc(sizeof(*new) + len);
+	memcpy(new->data, data, len);
+	new->id = id;
+	new->len = len;
+	list_add_tail(&new->list, &block->list);
 
 	return 0;
 }
 
-/* Marks the element at 'pos' as unused and updates internal cache information.
-   Returns true iff element at pos was valid. */
-static bool tftp_window_cache_remove(struct tftp_cache *cache, unsigned int pos)
-{
-	size_t const	cache_size = tftp_window_cache_size(cache);
-	bool		res;
-
-	if (cache_size == 0)
-		return 0;
-
-	res = __test_and_clear_bit(pos, cache->used);
-
-	if (tftp_window_cache_is_empty(cache)) {
-		/* cache has been cleared; reset pointers */
-		cache->id = TFTP_CACHE_NO_ID;
-	} else if (pos != cache->pos) {
-		/* noop; elements has been removed from the middle of cache */
-	} else {
-		/* first element of cache has been removed; proceed to the
-		   next one */
-		cache->id  += 1;
-		cache->pos += 1;
-		cache->pos %= cache_size;
-	}
-
-	return res;
-}
-
-/* Releases the first element from the cache and returns its content.
- *
- * Function can return NULL when the element is not cached
- */
-static struct tftp_block *tftp_window_cache_pop(struct tftp_cache *cache)
-{
-	unsigned int	pos = cache->pos;
-
-	debug_assert(cache->id != TFTP_CACHE_NO_ID);
-
-	if (!tftp_window_cache_remove(cache, pos))
-		return NULL;
-
-	return cache->blocks[pos];
-}
-
-static bool tftp_window_cache_remove_id(struct tftp_cache *cache, uint16_t id)
-{
-	int		pos = tftp_window_cache_get_pos(cache, id);
-
-	if (pos < 0)
-		return false;
-
-	return tftp_window_cache_remove(cache, pos);
-}
-
 static int tftp_truncate(struct device_d *dev, FILE *f, loff_t size)
 {
 	return 0;
@@ -444,7 +263,6 @@ static int tftp_send(struct file_priv *priv)
 		priv->ack_block += priv->windowsize;
 		pkt = (unsigned char *)s;
 		len = pkt - xp;
-		tftp_window_cache_reset(&priv->cache);
 		break;
 	}
 
@@ -562,8 +380,7 @@ static int tftp_allocate_transfer(struct file_priv *priv)
 			goto err;
 		}
 	} else {
-		tftp_window_cache_init(&priv->cache,
-				       priv->blocksize, priv->windowsize);
+		INIT_LIST_HEAD(&priv->cache.blocks);
 	}
 
 	return 0;
@@ -606,7 +423,7 @@ static void tftp_apply_window_cache(struct file_priv *priv)
 {
 	struct tftp_cache *cache = &priv->cache;
 
-	while (tftp_window_cache_starts_with(cache, priv->last_block + 1)) {
+	while (1) {
 		struct tftp_block *block;
 
 		/* can be changed by tftp_put_data() below and must be
@@ -614,12 +431,26 @@ static void tftp_apply_window_cache(struct file_priv *priv)
 		if (priv->state != STATE_RDATA)
 			return;
 
-		block = tftp_window_cache_pop(cache);
+		if (list_empty(&cache->blocks))
+			return;
 
-		debug_assert(block);
-		debug_assert(block->id == (uint16_t)(priv->last_block + 1));
+		block = list_first_entry(&cache->blocks, struct tftp_block, list);
+
+		if (block->id < priv->last_block + 1) {
+			/* shouldn't happen, but be sure */
+			list_del(&block->list);
+			free(block);
+			continue;
+		}
+
+		if (block->id != priv->last_block + 1)
+			return;
 
 		tftp_put_data(priv, block->id, block->data, block->len);
+
+		list_del(&block->list);
+
+		free(block);
 	}
 }
 
@@ -636,7 +467,6 @@ static void tftp_handle_data(struct file_priv *priv, uint16_t block,
 		   fifo directly and try to apply cached items then */
 		tftp_timer_reset(priv);
 		tftp_put_data(priv, block, data, len);
-		tftp_window_cache_remove_id(&priv->cache, block);
 		tftp_apply_window_cache(priv);
 	} else if (!in_window(block, exp_block, priv->ack_block)) {
 		/* completely unexpected and unrelated to actual window;
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 16 05:52:32 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 14:52:32 +0200
Subject: [PATCH 3/3] net: designware_eqos: Allocate more receive buffers
In-Reply-To: <20220916125232.3775559-1-s.hauer@pengutronix.de>
References: <20220916125232.3775559-1-s.hauer@pengutronix.de>
Message-ID: <20220916125232.3775559-4-s.hauer@pengutronix.de>

With RFC7440 support in TFTP we can make good use of more receive
buffers. Increase the number.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/designware_eqos.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c
index 79b9979697..7ff0b8489c 100644
--- a/drivers/net/designware_eqos.c
+++ b/drivers/net/designware_eqos.c
@@ -169,7 +169,7 @@ struct eqos_dma_regs {
 /* We assume ARCH_DMA_MINALIGN >= 16; 16 is the EQOS HW minimum */
 #define EQOS_DESCRIPTOR_ALIGN	64
 #define EQOS_DESCRIPTORS_TX	4
-#define EQOS_DESCRIPTORS_RX	4
+#define EQOS_DESCRIPTORS_RX	64
 #define EQOS_DESCRIPTORS_NUM	(EQOS_DESCRIPTORS_TX + EQOS_DESCRIPTORS_RX)
 #define EQOS_DESCRIPTORS_SIZE	ALIGN(EQOS_DESCRIPTORS_NUM * \
 				      EQOS_DESCRIPTOR_SIZE, EQOS_DESCRIPTOR_ALIGN)
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 16 05:52:30 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 14:52:30 +0200
Subject: [PATCH 1/3] tftp: remove selftest
In-Reply-To: <20220916125232.3775559-1-s.hauer@pengutronix.de>
References: <20220916125232.3775559-1-s.hauer@pengutronix.de>
Message-ID: <20220916125232.3775559-2-s.hauer@pengutronix.de>

The out-of-order packet caching will be reworked in the next commit and
most of the functions the self test tests will vanish, so nothing to
test anymore.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 fs/tftp.c         | 102 ----------------------------------------------
 test/self/Kconfig |   7 ----
 2 files changed, 109 deletions(-)

diff --git a/fs/tftp.c b/fs/tftp.c
index e0886c49d2..f089e2f693 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -1237,105 +1237,3 @@ static int tftp_init(void)
 	return register_fs_driver(&tftp_driver);
 }
 coredevice_initcall(tftp_init);
-
-
-BSELFTEST_GLOBALS();
-
-static int __maybe_unused tftp_window_cache_selftest(void)
-{
-	struct tftp_cache	*cache = malloc(sizeof *cache);
-
-	if (!cache)
-		return -ENOMEM;
-
-	(void)skipped_tests;
-
-	expect_it( is_block_before(0, 1));
-	expect_it(!is_block_before(1, 0));
-	expect_it( is_block_before(65535, 0));
-	expect_it(!is_block_before(0, 65535));
-
-	expect_eq(get_block_delta(0, 1),     1);
-	expect_eq(get_block_delta(65535, 0), 1);
-	expect_eq(get_block_delta(65535, 1), 2);
-
-	expect_it(!in_window(0, 1, 3));
-	expect_it( in_window(1, 1, 3));
-	expect_it( in_window(2, 1, 3));
-	expect_it( in_window(3, 1, 3));
-	expect_it(!in_window(4, 1, 3));
-
-	expect_it(!in_window(65534, 65535, 1));
-	expect_it( in_window(65535, 65535, 1));
-	expect_it( in_window(    0, 65535, 1));
-	expect_it( in_window(    1, 65535, 1));
-	expect_it(!in_window(    2, 65535, 1));
-
-
-	tftp_window_cache_init(cache, 512, 5);
-
-	if (tftp_window_cache_size(cache) < 4)
-		goto out;
-
-	expect_eq(tftp_window_cache_size(cache), 4);
-
-	/* sequence 1 */
-	expect_ok (tftp_window_cache_insert(cache, 20, "20", 2));
-	expect_ok (tftp_window_cache_insert(cache, 22, "22", 2));
-	expect_ok (tftp_window_cache_insert(cache, 21, "21", 2));
-	expect_ok (tftp_window_cache_insert(cache, 23, "23", 2));
-	expect_err(tftp_window_cache_insert(cache, 24, "24", 2));
-	expect_err(tftp_window_cache_insert(cache, 19, "19", 2));
-	expect_ok (tftp_window_cache_insert(cache, 22, "22", 2));
-	expect_ok (tftp_window_cache_insert(cache, 20, "20", 2));
-
-	expect_eq(tftp_window_cache_pop(cache)->id, 20);
-	expect_eq(tftp_window_cache_pop(cache)->id, 21);
-	expect_eq(tftp_window_cache_pop(cache)->id, 22);
-	expect_eq(tftp_window_cache_pop(cache)->id, 23);
-	expect_eq(cache->id, TFTP_CACHE_NO_ID);
-
-	/* sequence 2 */
-	expect_ok (tftp_window_cache_insert(cache, 30, "30", 2));
-	expect_ok (tftp_window_cache_insert(cache, 32, "32", 2));
-	expect_err(tftp_window_cache_insert(cache, 34, "34", 2));
-
-	expect_it(tftp_window_cache_starts_with(cache, 30));
-	expect_eq(tftp_window_cache_pop(cache)->id, 30);
-
-	expect_ok (tftp_window_cache_insert(cache, 34, "34", 2));
-	expect_err(tftp_window_cache_insert(cache, 35, "35", 2));
-
-	expect_it(!tftp_window_cache_starts_with(cache, 30));
-	expect_it(!tftp_window_cache_starts_with(cache, 31));
-	expect_it(!tftp_window_cache_starts_with(cache, 32));
-	expect_NULL(tftp_window_cache_pop(cache));
-
-	expect_it(tftp_window_cache_starts_with(cache, 32));
-	expect_eq(tftp_window_cache_pop(cache)->id, 32);
-
-	expect_NULL(tftp_window_cache_pop(cache));
-	expect_eq(tftp_window_cache_pop(cache)->id, 34);
-
-	expect_eq(cache->id, TFTP_CACHE_NO_ID);
-
-	/* sequence 3 */
-	expect_ok(tftp_window_cache_insert(cache, 40, "40", 2));
-	expect_ok(tftp_window_cache_insert(cache, 42, "42", 2));
-	expect_ok(tftp_window_cache_insert(cache, 43, "43", 2));
-
-	expect_it(!tftp_window_cache_remove_id(cache, 30));
-	expect_it(!tftp_window_cache_remove_id(cache, 41));
-	expect_it(!tftp_window_cache_remove_id(cache, 44));
-
-	expect_it( tftp_window_cache_remove_id(cache, 42));
-	expect_it(!tftp_window_cache_remove_id(cache, 42));
-
-out:
-	tftp_window_cache_free(cache);
-
-	return 0;
-}
-#ifdef CONFIG_SELFTEST_TFTP
-bselftest(core, tftp_window_cache_selftest);
-#endif
diff --git a/test/self/Kconfig b/test/self/Kconfig
index 03cfa89987..680196a4fe 100644
--- a/test/self/Kconfig
+++ b/test/self/Kconfig
@@ -32,7 +32,6 @@ config SELFTEST_ENABLE_ALL
 	select SELFTEST_PROGRESS_NOTIFIER
 	select SELFTEST_OF_MANIPULATION
 	select SELFTEST_ENVIRONMENT_VARIABLES if ENVIRONMENT_VARIABLES
-	imply SELFTEST_TFTP
 	help
 	  Selects all self-tests compatible with current configuration
 
@@ -58,10 +57,4 @@ config SELFTEST_PROGRESS_NOTIFIER
 config SELFTEST_ENVIRONMENT_VARIABLES
 	bool "environment variable selftest"
 
-config SELFTEST_TFTP
-	bool "tftp selftest"
-	depends on FS_TFTP
-	help
-	  Tests tftp functionality
-
 endif
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 16 06:16:06 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 16 Sep 2022 15:16:06 +0200
Subject: [PATCH] net: Bring up all interfaces before going interactive
In-Reply-To: <20220916124942.3751131-1-s.hauer@pengutronix.de>
References: <20220916124942.3751131-1-s.hauer@pengutronix.de>
Message-ID: <20220916131606.GZ6477@pengutronix.de>

On Fri, Sep 16, 2022 at 02:49:42PM +0200, Sascha Hauer wrote:
> So far we only bring up network interfaces when we actually need them.
> This means we could be idling in the shell for long and once the user
> decides to do networking he has to wait for the link to be established.
> We can do better: Before going interactive bring up all known network
> interfaces which makes the links established when the user needs them.
> 
> To implement this we have to rework carrier checking a bit, because
> otherwise barebox would wait for the links to be established before
> dropping to the shell.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  common/startup.c |  3 +++
>  include/net.h    |  3 +++
>  net/eth.c        | 34 +++++++++++++++++++++-------------
>  3 files changed, 27 insertions(+), 13 deletions(-)
> 
> diff --git a/common/startup.c b/common/startup.c
> index f53b73f81a..f63a0ae7d5 100644
> --- a/common/startup.c
> +++ b/common/startup.c
> @@ -37,6 +37,7 @@
>  #include <linux/ctype.h>
>  #include <watchdog.h>
>  #include <glob.h>
> +#include <net.h>
>  #include <bselftest.h>
>  
>  extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
> @@ -208,6 +209,8 @@ enum autoboot_state do_autoboot_countdown(void)
>  				&outkey);
>  	command_slice_acquire();
>  
> +	eth_open_all();
> +

We could make the user experience even a bit better by doing this call
before waiting for the autoboot timeout which then speeds up netboot a
bit.

Sascha

-- 
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-5555 |


From enrico.scholz at sigma-chemnitz.de  Fri Sep 16 07:12:07 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Fri, 16 Sep 2022 16:12:07 +0200
Subject: [PATCH 2/3] tftp: implement UDP reorder cache using lists
In-Reply-To: <20220916125232.3775559-3-s.hauer@pengutronix.de> (Sascha Hauer's
	message of "Fri, 16 Sep 2022 14:52:31 +0200")
References: <20220916125232.3775559-1-s.hauer@pengutronix.de>
	<20220916125232.3775559-3-s.hauer@pengutronix.de>
Message-ID: <lypmfv8l3c.fsf@ensc-pc.intern.sigma-chemnitz.de>

Sascha Hauer <s.hauer at pengutronix.de> writes:

> The UDP reorder cache can be much easier implemented using lists.
> As a bonus the cache grows and shrinks on demand and no fixed size
> has to be configured at compile time.

There are three variants of the cache

- small, fixed sized array with linear search (very first
  implementation)  -->  O(n)
- list --> O(n) on insert, O(1) on lookup
- bitmap --> O(1)


Performance wise, I think the list implementation is the slowest one
(although the fixed sized array is O(n) on every operation, this should
be still faster for small n than the list operations and the related
memory management).

>From code size, the list implementation is in the middle.

I am not sure whether dynamic shrinking/growing of the cache is so
important or whether a small, fixed sized cache suffices.  In my
experience, only the first couple of packets really matter regarding
reordering.

Of course, the 'kfifo' could be replaced completely by a custom buffer
implementation where packets are inserted at the correct position.  O(1)
for every operation + zero additional memory.


> -static inline bool is_block_before(uint16_t a, uint16_t b)
> -{
> -	return (int16_t)(b - a) > 0;
> -}
> -
> ....
>  static int tftp_window_cache_insert(struct tftp_cache *cache, uint16_t id,
>  				    void const *data, size_t len)
>  {
> ...
> +	list_for_each_entry(block, &cache->blocks, list) {

fwiw, iterating in the reverse direction will find the position probably
faster


> +		if (block->id == id)
> +			return 0;
> +		if (block->id < id)

This will break when wrapping at 65535; the removed 'is_block_before()'
function was written for this case.


> @@ -614,12 +431,26 @@ static void tftp_apply_window_cache(struct file_priv *priv)
>  		if (priv->state != STATE_RDATA)
>  			return;
>  
> -		block = tftp_window_cache_pop(cache);
> +		if (list_empty(&cache->blocks))
> +			return;
>  
> -		debug_assert(block);
> -		debug_assert(block->id == (uint16_t)(priv->last_block + 1));
> +		block = list_first_entry(&cache->blocks, struct tftp_block, list);
> +
> +		if (block->id < priv->last_block + 1) {

ditto; wrapping at 65535


> +			/* shouldn't happen, but be sure */
> +			list_del(&block->list);
> +			free(block);
> +			continue;
> +		}
> +
> +		if (block->id != priv->last_block + 1)

ditto; wrapping at 65535.  Resp. should be written as

|		if (block->id != (uint16_t)(priv->last_block + 1))



Enrico


From hcl at datarespons.no  Fri Sep 16 07:36:50 2022
From: hcl at datarespons.no (=?iso-8859-1?Q?Hans_Christian_L=F8nstad?=)
Date: Fri, 16 Sep 2022 14:36:50 +0000
Subject: fitimage: Allow match against config node name
Message-ID: <EC219BAA-D034-4B47-8377-286110B1329C@datarespons.no>

Support fitimage configuration nodes without populated compatible fields

Yocto fit image recipe does not populate the compatible field
in the generated ITS file configuration nodes.
Barebox is thus only able to load the default configuration
preventing the use of variant based bootloader update bundles.

If the compatible match fails, fall through using a global
variable boot.fitnode allowing a match against the configuration
node name.

This allows variant boards to pick the correct configuration.

---
common/image-fit.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/common/image-fit.c b/common/image-fit.c
index a410632d70..f92e813a8b 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -7,6 +7,7 @@

#define pr_fmt(fmt) "FIT: " fmt
#include <common.h>
+#include <environment.h>
#include <init.h>
#include <bootm.h>
#include <libfile.h>
@@ -663,6 +664,7 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
struct device_node *barebox_root;
const char *machine;
int ret;
+ const char *config_node;

barebox_root = of_get_root_node();
if (!barebox_root)
@@ -680,6 +682,22 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
}
}

+ /*
+ * If the match against compatible in config node does not match
+ * (or is missing as in Yocto fitimage recipe)
+ * check for matching node name using global.boot.fitnode
+ */
+ config_node = getenv("global.boot.fitnode");
+ if (config_node) {
+ for_each_child_of_node (conf_node, child) {
+ if (strcmp(child->name, config_node) == 0) {
+ *unit = child->name;
+ pr_info("matching node name unit '%s' found\n", *unit);
+ return 0;
+ }
+ }
+ }
+
default_unit:
pr_info("No match found. Trying default.\n");
if (of_property_read_string(conf_node, "default", unit) == 0)
-- 
2.34.1

From a.fatoum at pengutronix.de  Fri Sep 16 10:26:04 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 16 Sep 2022 18:26:04 +0100
Subject: fitimage: Allow match against config node name
In-Reply-To: <EC219BAA-D034-4B47-8377-286110B1329C@datarespons.no>
References: <EC219BAA-D034-4B47-8377-286110B1329C@datarespons.no>
Message-ID: <89dbfa91-7d49-bd56-4728-42ad4d33dd6a@pengutronix.de>

Hello Hans,

On 16.09.22 15:36, Hans Christian L?nstad wrote:
> Support fitimage configuration nodes without populated compatible fields
> 
> Yocto fit image recipe does not populate the compatible field
> in the generated ITS file configuration nodes.
> Barebox is thus only able to load the default configuration
> preventing the use of variant based bootloader update bundles.
> 
> If the compatible match fails, fall through using a global
> variable boot.fitnode allowing a match against the configuration
> node name.
> 
> This allows variant boards to pick the correct configuration.

Thanks for your patch.

> 
> ---
> common/image-fit.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
> 
> diff --git a/common/image-fit.c b/common/image-fit.c
> index a410632d70..f92e813a8b 100644
> --- a/common/image-fit.c
> +++ b/common/image-fit.c
> @@ -7,6 +7,7 @@
> 
> #define pr_fmt(fmt) "FIT: " fmt
> #include <common.h>
> +#include <environment.h>
> #include <init.h>
> #include <bootm.h>
> #include <libfile.h>
> @@ -663,6 +664,7 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
> struct device_node *barebox_root;
> const char *machine;
> int ret;
> + const char *config_node;
> 
> barebox_root = of_get_root_node();
> if (!barebox_root)
> @@ -680,6 +682,22 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
> }
> }
> 
> + /*
> + * If the match against compatible in config node does not match
> + * (or is missing as in Yocto fitimage recipe)
> + * check for matching node name using global.boot.fitnode
> + */
> + config_node = getenv("global.boot.fitnode");
> + if (config_node) {
> + for_each_child_of_node (conf_node, child) {
> + if (strcmp(child->name, config_node) == 0) {
> + *unit = child->name;
> + pr_info("matching node name unit '%s' found\n", *unit);
> + return 0;
> + }
> + }
> + }

Whitespace is broken (git send-email normally does the correct thing).

But are you aware that you can have your boot-target like:

bootm /dev/mmc0.fit at configuration1

and that configuration1 will be chosen? Does this already cover
your use case? If it does, a documentation patch adding this
information at the place where you didn't find it is surely
a welcome alternate contribution. ;)

(also generally speaking magicvars need to be documented with
 BAREBOX_MAGICVAR).

Cheers,
Ahmad


> +
> default_unit:
> pr_info("No match found. Trying default.\n");
> if (of_property_read_string(conf_node, "default", unit) == 0)


-- 
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-5555 |


From hcl at datarespons.no  Fri Sep 16 23:51:29 2022
From: hcl at datarespons.no (=?utf-8?B?SGFucyBDaHJpc3RpYW4gTMO4bnN0YWQ=?=)
Date: Sat, 17 Sep 2022 06:51:29 +0000
Subject: fitimage: Allow match against config node name
In-Reply-To: <89dbfa91-7d49-bd56-4728-42ad4d33dd6a@pengutronix.de>
References: <EC219BAA-D034-4B47-8377-286110B1329C@datarespons.no>
 <89dbfa91-7d49-bd56-4728-42ad4d33dd6a@pengutronix.de>
Message-ID: <F1338C87-37DC-4F61-8E4B-9E1E4B7E8CC0@datarespons.no>

Thank you for pointing out the existing option, it resolves the issue.
Regarding patch submissions:
Are GitHub pull requests an option? Actually have one pending that is needed on USB for IMX8MP.

Hans Christian

> 16. sep. 2022 kl. 19:26 skrev Ahmad Fatoum <a.fatoum at pengutronix.de>:
> 
> Hello Hans,
> 
> On 16.09.22 15:36, Hans Christian L?nstad wrote:
>> Support fitimage configuration nodes without populated compatible fields
>> 
>> Yocto fit image recipe does not populate the compatible field
>> in the generated ITS file configuration nodes.
>> Barebox is thus only able to load the default configuration
>> preventing the use of variant based bootloader update bundles.
>> 
>> If the compatible match fails, fall through using a global
>> variable boot.fitnode allowing a match against the configuration
>> node name.
>> 
>> This allows variant boards to pick the correct configuration.
> 
> Thanks for your patch.
> 
>> 
>> ---
>> common/image-fit.c | 18 ++++++++++++++++++
>> 1 file changed, 18 insertions(+)
>> 
>> diff --git a/common/image-fit.c b/common/image-fit.c
>> index a410632d70..f92e813a8b 100644
>> --- a/common/image-fit.c
>> +++ b/common/image-fit.c
>> @@ -7,6 +7,7 @@
>> 
>> #define pr_fmt(fmt) "FIT: " fmt
>> #include <common.h>
>> +#include <environment.h>
>> #include <init.h>
>> #include <bootm.h>
>> #include <libfile.h>
>> @@ -663,6 +664,7 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
>> struct device_node *barebox_root;
>> const char *machine;
>> int ret;
>> + const char *config_node;
>> 
>> barebox_root = of_get_root_node();
>> if (!barebox_root)
>> @@ -680,6 +682,22 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
>> }
>> }
>> 
>> + /*
>> + * If the match against compatible in config node does not match
>> + * (or is missing as in Yocto fitimage recipe)
>> + * check for matching node name using global.boot.fitnode
>> + */
>> + config_node = getenv("global.boot.fitnode");
>> + if (config_node) {
>> + for_each_child_of_node (conf_node, child) {
>> + if (strcmp(child->name, config_node) == 0) {
>> + *unit = child->name;
>> + pr_info("matching node name unit '%s' found\n", *unit);
>> + return 0;
>> + }
>> + }
>> + }
> 
> Whitespace is broken (git send-email normally does the correct thing).
> 
> But are you aware that you can have your boot-target like:
> 
> bootm /dev/mmc0.fit at configuration1
> 
> and that configuration1 will be chosen? Does this already cover
> your use case? If it does, a documentation patch adding this
> information at the place where you didn't find it is surely
> a welcome alternate contribution. ;)
> 
> (also generally speaking magicvars need to be documented with
> BAREBOX_MAGICVAR).
> 
> Cheers,
> Ahmad
> 
> 
>> +
>> default_unit:
>> pr_info("No match found. Trying default.\n");
>> if (of_property_read_string(conf_node, "default", unit) == 0)
> 
> 
> -- 
> 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-5555 |


From a.fatoum at pengutronix.de  Sat Sep 17 03:13:00 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Sat, 17 Sep 2022 11:13:00 +0100
Subject: fitimage: Allow match against config node name
In-Reply-To: <F1338C87-37DC-4F61-8E4B-9E1E4B7E8CC0@datarespons.no>
References: <EC219BAA-D034-4B47-8377-286110B1329C@datarespons.no>
 <89dbfa91-7d49-bd56-4728-42ad4d33dd6a@pengutronix.de>
 <F1338C87-37DC-4F61-8E4B-9E1E4B7E8CC0@datarespons.no>
Message-ID: <4bb50cb7-d7a0-9562-b990-24231358aa1c@pengutronix.de>

Hi Hans,

On 17.09.22 07:51, Hans Christian L?nstad wrote:
> Thank you for pointing out the existing option, it resolves the issue.

:)

> Regarding patch submissions:
> Are GitHub pull requests an option? Actually have one pending that is needed on USB for IMX8MP.

Mailing list is the usual contribution method, but Sascha has accepted
Github PRs in the past.

Regarding your existing DWC3 PR, you will need to reword the commit message
to make this acceptable for barebox inclusion:

1) All contributions must have a Signed-off-by certifying origin, see
   https://developercertificate.org/

2) Commit message needs to be useful on its own. The Github issue can
   be referenced, but should not be the only documentation

3) Commit title needs to be adapted to convention for the driver.


Here's my suggestion:

  usb: dwc3: support snps,dis-u2-freeclk-exists-quirk for i.MX8MP

  The driver currently configures the Synopsis USB 2.0 PHY to
  unconditionally provide a free-running PHY clock. This must
  be disabled on the i.MX8MP as well as RK3328 and RK3399 SoC,
  because the clock control input is inactive.

  The upstream Linux binding specifies a boolean DT property
  snps,dis-u2-freeclk-exists-quirk to disable the free-running
  PHY clock and the property is already used in the i.MX8MP
  DT, that barebox imports from upstream. Thus implement the
  binding for barebox. This fixes barebox USB host support on the
  i.MX8MP, which previously triggered a BUG() when enumerating[1].

  Link: https://github.com/saschahauer/barebox/issues/13 [1]
  Fixes: e213627bbe1d ("usb: dwc3: of-simple: add i.MX8MP compatible")
  Signed-off-by: Author Name <author.email at example.com> 


If you squash this commit message into your PR, feel free to
append my

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

Also Cc'ing Lucas, as I am wondering why you ran into the issue, but Lucas
apparently didn't.

Cheers,
Ahmad

> Hans Christian
> 
>> 16. sep. 2022 kl. 19:26 skrev Ahmad Fatoum <a.fatoum at pengutronix.de>:
>>
>> Hello Hans,
>>
>> On 16.09.22 15:36, Hans Christian L?nstad wrote:
>>> Support fitimage configuration nodes without populated compatible fields
>>>
>>> Yocto fit image recipe does not populate the compatible field
>>> in the generated ITS file configuration nodes.
>>> Barebox is thus only able to load the default configuration
>>> preventing the use of variant based bootloader update bundles.
>>>
>>> If the compatible match fails, fall through using a global
>>> variable boot.fitnode allowing a match against the configuration
>>> node name.
>>>
>>> This allows variant boards to pick the correct configuration.
>>
>> Thanks for your patch.
>>
>>>
>>> ---
>>> common/image-fit.c | 18 ++++++++++++++++++
>>> 1 file changed, 18 insertions(+)
>>>
>>> diff --git a/common/image-fit.c b/common/image-fit.c
>>> index a410632d70..f92e813a8b 100644
>>> --- a/common/image-fit.c
>>> +++ b/common/image-fit.c
>>> @@ -7,6 +7,7 @@
>>>
>>> #define pr_fmt(fmt) "FIT: " fmt
>>> #include <common.h>
>>> +#include <environment.h>
>>> #include <init.h>
>>> #include <bootm.h>
>>> #include <libfile.h>
>>> @@ -663,6 +664,7 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
>>> struct device_node *barebox_root;
>>> const char *machine;
>>> int ret;
>>> + const char *config_node;
>>>
>>> barebox_root = of_get_root_node();
>>> if (!barebox_root)
>>> @@ -680,6 +682,22 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
>>> }
>>> }
>>>
>>> + /*
>>> + * If the match against compatible in config node does not match
>>> + * (or is missing as in Yocto fitimage recipe)
>>> + * check for matching node name using global.boot.fitnode
>>> + */
>>> + config_node = getenv("global.boot.fitnode");
>>> + if (config_node) {
>>> + for_each_child_of_node (conf_node, child) {
>>> + if (strcmp(child->name, config_node) == 0) {
>>> + *unit = child->name;
>>> + pr_info("matching node name unit '%s' found\n", *unit);
>>> + return 0;
>>> + }
>>> + }
>>> + }
>>
>> Whitespace is broken (git send-email normally does the correct thing).
>>
>> But are you aware that you can have your boot-target like:
>>
>> bootm /dev/mmc0.fit at configuration1
>>
>> and that configuration1 will be chosen? Does this already cover
>> your use case? If it does, a documentation patch adding this
>> information at the place where you didn't find it is surely
>> a welcome alternate contribution. ;)
>>
>> (also generally speaking magicvars need to be documented with
>> BAREBOX_MAGICVAR).
>>
>> Cheers,
>> Ahmad
>>
>>
>>> +
>>> default_unit:
>>> pr_info("No match found. Trying default.\n");
>>> if (of_property_read_string(conf_node, "default", unit) == 0)
>>
>>
>> -- 
>> 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-5555 |
> 


-- 
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-5555 |


From hcl at datarespons.no  Sat Sep 17 03:59:31 2022
From: hcl at datarespons.no (=?utf-8?B?SGFucyBDaHJpc3RpYW4gTMO4bnN0YWQ=?=)
Date: Sat, 17 Sep 2022 10:59:31 +0000
Subject: fitimage: Allow match against config node name
In-Reply-To: <4bb50cb7-d7a0-9562-b990-24231358aa1c@pengutronix.de>
References: <EC219BAA-D034-4B47-8377-286110B1329C@datarespons.no>
 <89dbfa91-7d49-bd56-4728-42ad4d33dd6a@pengutronix.de>
 <F1338C87-37DC-4F61-8E4B-9E1E4B7E8CC0@datarespons.no>
 <4bb50cb7-d7a0-9562-b990-24231358aa1c@pengutronix.de>
Message-ID: <BDDE3FBD-A6F2-46C2-9551-6A8626B192FA@datarespons.no>

Great, re-issued PR with the proper wording ?

Hans Christian

> 17. sep. 2022 kl. 12:13 skrev Ahmad Fatoum <a.fatoum at pengutronix.de>:
> 
> Hi Hans,
> 
> On 17.09.22 07:51, Hans Christian L?nstad wrote:
>> Thank you for pointing out the existing option, it resolves the issue.
> 
> :)
> 
>> Regarding patch submissions:
>> Are GitHub pull requests an option? Actually have one pending that is needed on USB for IMX8MP.
> 
> Mailing list is the usual contribution method, but Sascha has accepted
> Github PRs in the past.
> 
> Regarding your existing DWC3 PR, you will need to reword the commit message
> to make this acceptable for barebox inclusion:
> 
> 1) All contributions must have a Signed-off-by certifying origin, see
>   https://developercertificate.org/
> 
> 2) Commit message needs to be useful on its own. The Github issue can
>   be referenced, but should not be the only documentation
> 
> 3) Commit title needs to be adapted to convention for the driver.
> 
> 
> Here's my suggestion:
> 
>  usb: dwc3: support snps,dis-u2-freeclk-exists-quirk for i.MX8MP
> 
>  The driver currently configures the Synopsis USB 2.0 PHY to
>  unconditionally provide a free-running PHY clock. This must
>  be disabled on the i.MX8MP as well as RK3328 and RK3399 SoC,
>  because the clock control input is inactive.
> 
>  The upstream Linux binding specifies a boolean DT property
>  snps,dis-u2-freeclk-exists-quirk to disable the free-running
>  PHY clock and the property is already used in the i.MX8MP
>  DT, that barebox imports from upstream. Thus implement the
>  binding for barebox. This fixes barebox USB host support on the
>  i.MX8MP, which previously triggered a BUG() when enumerating[1].
> 
>  Link: https://github.com/saschahauer/barebox/issues/13 [1]
>  Fixes: e213627bbe1d ("usb: dwc3: of-simple: add i.MX8MP compatible")
>  Signed-off-by: Author Name <author.email at example.com> 
> 
> 
> If you squash this commit message into your PR, feel free to
> append my
> 
> Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> 
> Also Cc'ing Lucas, as I am wondering why you ran into the issue, but Lucas
> apparently didn't.
> 
> Cheers,
> Ahmad
> 
>> Hans Christian
>> 
>>> 16. sep. 2022 kl. 19:26 skrev Ahmad Fatoum <a.fatoum at pengutronix.de>:
>>> 
>>> Hello Hans,
>>> 
>>> On 16.09.22 15:36, Hans Christian L?nstad wrote:
>>>> Support fitimage configuration nodes without populated compatible fields
>>>> 
>>>> Yocto fit image recipe does not populate the compatible field
>>>> in the generated ITS file configuration nodes.
>>>> Barebox is thus only able to load the default configuration
>>>> preventing the use of variant based bootloader update bundles.
>>>> 
>>>> If the compatible match fails, fall through using a global
>>>> variable boot.fitnode allowing a match against the configuration
>>>> node name.
>>>> 
>>>> This allows variant boards to pick the correct configuration.
>>> 
>>> Thanks for your patch.
>>> 
>>>> 
>>>> ---
>>>> common/image-fit.c | 18 ++++++++++++++++++
>>>> 1 file changed, 18 insertions(+)
>>>> 
>>>> diff --git a/common/image-fit.c b/common/image-fit.c
>>>> index a410632d70..f92e813a8b 100644
>>>> --- a/common/image-fit.c
>>>> +++ b/common/image-fit.c
>>>> @@ -7,6 +7,7 @@
>>>> 
>>>> #define pr_fmt(fmt) "FIT: " fmt
>>>> #include <common.h>
>>>> +#include <environment.h>
>>>> #include <init.h>
>>>> #include <bootm.h>
>>>> #include <libfile.h>
>>>> @@ -663,6 +664,7 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
>>>> struct device_node *barebox_root;
>>>> const char *machine;
>>>> int ret;
>>>> + const char *config_node;
>>>> 
>>>> barebox_root = of_get_root_node();
>>>> if (!barebox_root)
>>>> @@ -680,6 +682,22 @@ static int fit_find_compatible_unit(struct device_node *conf_node,
>>>> }
>>>> }
>>>> 
>>>> + /*
>>>> + * If the match against compatible in config node does not match
>>>> + * (or is missing as in Yocto fitimage recipe)
>>>> + * check for matching node name using global.boot.fitnode
>>>> + */
>>>> + config_node = getenv("global.boot.fitnode");
>>>> + if (config_node) {
>>>> + for_each_child_of_node (conf_node, child) {
>>>> + if (strcmp(child->name, config_node) == 0) {
>>>> + *unit = child->name;
>>>> + pr_info("matching node name unit '%s' found\n", *unit);
>>>> + return 0;
>>>> + }
>>>> + }
>>>> + }
>>> 
>>> Whitespace is broken (git send-email normally does the correct thing).
>>> 
>>> But are you aware that you can have your boot-target like:
>>> 
>>> bootm /dev/mmc0.fit at configuration1
>>> 
>>> and that configuration1 will be chosen? Does this already cover
>>> your use case? If it does, a documentation patch adding this
>>> information at the place where you didn't find it is surely
>>> a welcome alternate contribution. ;)
>>> 
>>> (also generally speaking magicvars need to be documented with
>>> BAREBOX_MAGICVAR).
>>> 
>>> Cheers,
>>> Ahmad
>>> 
>>> 
>>>> +
>>>> default_unit:
>>>> pr_info("No match found. Trying default.\n");
>>>> if (of_property_read_string(conf_node, "default", unit) == 0)
>>> 
>>> 
>>> -- 
>>> 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-5555 |
>> 
> 
> 
> -- 
> 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-5555 |


From hcl at datarespons.no  Sat Sep 17 05:04:51 2022
From: hcl at datarespons.no (=?utf-8?B?SGFucyBDaHJpc3RpYW4gTMO4bnN0YWQ=?=)
Date: Sat, 17 Sep 2022 12:04:51 +0000
Subject: Imx-usb-loader broken on IMX8MP/v2022.09.0
Message-ID: <8CA6ADB4-FD4B-4CC8-9BD2-21DA02C08C85@datarespons.no>

This is observed using straight out of the box v2022.09.0 on NXP IMX8MP Eval kit:

---------

$ sudo ../drimx8/scripts/imx/imx-usb-loader ../drimx8/images/barebox-nxp-imx8mp-evk.img 
[sudo] password for hcl: 
found i.MX8MP USB device [1fc9:0146]
4 in err=-9, last_trans=0  00 00 00 00
status failed

????

Stripping off the header gap (32K) allows the binary to load using the standard NXP uuu (Ubuntu 22.04) utility,.

This further raises the question: Why have a header gap at all?

The makes sense for SD card loading, but not for eMMC boot partitions where ROM expects code to start at 0.
Maybe better just use a seek to put the code at the relevant position on the SD card?

For instance, I am using the Rauc boot loader slot update mechanism expecting no gap thus  requiring me to shave of 32k
prior to shipping.

Comments??

Hans Christian


From s.hauer at pengutronix.de  Mon Sep 19 00:33:45 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 09:33:45 +0200
Subject: [PATCH 2/3] tftp: implement UDP reorder cache using lists
In-Reply-To: <lypmfv8l3c.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <20220916125232.3775559-1-s.hauer@pengutronix.de>
 <20220916125232.3775559-3-s.hauer@pengutronix.de>
 <lypmfv8l3c.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <20220919073345.GA6477@pengutronix.de>

Hi Enrico,

On Fri, Sep 16, 2022 at 04:12:07PM +0200, Enrico Scholz wrote:
> Sascha Hauer <s.hauer at pengutronix.de> writes:
> 
> > The UDP reorder cache can be much easier implemented using lists.
> > As a bonus the cache grows and shrinks on demand and no fixed size
> > has to be configured at compile time.
> 
> There are three variants of the cache
> 
> - small, fixed sized array with linear search (very first
>   implementation)  -->  O(n)
> - list --> O(n) on insert, O(1) on lookup
> - bitmap --> O(1)
> 
> 
> Performance wise, I think the list implementation is the slowest one
> (although the fixed sized array is O(n) on every operation, this should
> be still faster for small n than the list operations and the related
> memory management).
> 
> From code size, the list implementation is in the middle.
> 
> I am not sure whether dynamic shrinking/growing of the cache is so
> important or whether a small, fixed sized cache suffices.  In my
> experience, only the first couple of packets really matter regarding
> reordering.

I don't think that the performance of the cache limits the tftp
performance, given the low number of entries in the cache. You may prove
me wrong here, I don't have any setup here where I could test packet
reordering. What happens here instead is that packets get dropped
because of the RX queue of the network interface get overwhelmed by
packets, see my patch reducing the windowsize setting for i.MX. Packets
get cached then, but the missing packets come in later when retransmits
are triggered. Performance is very bad then anyway.

What counts for me here is the simplicity of the implementation and
the ability to check it for correctness. Here the list implementation
has clear advantages.

The dynamic shrinking/growing of the cache hasn't been a goal for me,
it's just easier to implement then having to maintain a fixed size
pool.

> 
> Of course, the 'kfifo' could be replaced completely by a custom buffer
> implementation where packets are inserted at the correct position.  O(1)
> for every operation + zero additional memory.

Yes, that could be a next step, although the kfifo makes it easy to
decouple the fixed sized blocks coming in from the read() call with
varying sizes.

> 
> 
> > -static inline bool is_block_before(uint16_t a, uint16_t b)
> > -{
> > -	return (int16_t)(b - a) > 0;
> > -}
> > -
> > ....
> >  static int tftp_window_cache_insert(struct tftp_cache *cache, uint16_t id,
> >  				    void const *data, size_t len)
> >  {
> > ...
> > +	list_for_each_entry(block, &cache->blocks, list) {
> 
> fwiw, iterating in the reverse direction will find the position probably
> faster
> 
> 
> > +		if (block->id == id)
> > +			return 0;
> > +		if (block->id < id)
> 
> This will break when wrapping at 65535; the removed 'is_block_before()'
> function was written for this case.

Oh, yes, I missed this. I'll fix it here and elsewhere. Thanks for
noting.

Sascha

-- 
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-5555 |


From s.hauer at pengutronix.de  Mon Sep 19 01:01:32 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:32 +0200
Subject: [PATCH 8/9] net: ks8851_mll: Allocate own receive buffer
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-9-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/ks8851_mll.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index b037e19633..7609623ad1 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -366,6 +366,7 @@ struct ks_net {
 	void __iomem		*hw_addr_cmd;
 	struct platform_device	*pdev;
 	int			bus_width;
+	void			*rx_buf;
 };
 
 #define BE3             0x8000      /* Byte Enable 3 */
@@ -659,7 +660,6 @@ static void ks_setup(struct ks_net *ks)
 static int ks8851_rx_frame(struct ks_net *ks)
 {
 	struct device_d *dev = &ks->edev.dev;
-	u16 *rdptr = (u16 *) NetRxPackets[0];
 	u16 RxStatus, RxLen = 0;
 	u16 tmp_rxqcr;
 
@@ -679,14 +679,14 @@ static int ks8851_rx_frame(struct ks_net *ks)
 	tmp_rxqcr = ks_rdreg16(ks, KS_RXQCR);
 	ks_wrreg16(ks, KS_RXQCR, tmp_rxqcr | RXQCR_SDA);
 	/* read 2 bytes for dummy, 2 for status, 2 for len*/
-	ks_inblk(ks, rdptr, 2 + 2 + 2);
-	ks_inblk(ks, rdptr, ALIGN(RxLen, 4));
+	ks_inblk(ks, ks->rx_buf, 2 + 2 + 2);
+	ks_inblk(ks, ks->rx_buf, ALIGN(RxLen, 4));
 	ks_wrreg16(ks, KS_RXQCR, tmp_rxqcr);
 
 	if (RxStatus & RXFSHR_RXFV) {
 		/* Pass to upper layer */
 		dev_dbg(dev, "passing packet to upper layer\n\n");
-		net_receive(&ks->edev, NetRxPackets[0], RxLen);
+		net_receive(&ks->edev, ks->rx_buf, RxLen);
 		return RxLen;
 	} else if (RxStatus & RXFSHR_ERR) {
 		dev_err(dev, "RxStatus error 0x%04x\n", RxStatus & RXFSHR_ERR);
@@ -827,6 +827,7 @@ static int ks8851_probe(struct device_d *dev)
 	ks->hw_addr_cmd = IOMEM(iores->start);
 
 	ks->bus_width = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
+	ks->rx_buf = xmalloc(PKTSIZE);
 
 	edev->init = ks8851_init_dev;
 	edev->open = ks8851_eth_open;
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:25 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:25 +0200
Subject: [PATCH 1/9] net: tap: Allocate own receive buffer
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-2-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/tap.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 1fbfa085b1..8a659c125e 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -15,6 +15,7 @@
 struct tap_priv {
 	int fd;
 	char *name;
+	char *rx_buf;
 };
 
 static int tap_eth_send(struct eth_device *edev, void *packet, int length)
@@ -30,10 +31,10 @@ static int tap_eth_rx(struct eth_device *edev)
 	struct tap_priv *priv = edev->priv;
 	int length;
 
-	length = linux_read_nonblock(priv->fd, NetRxPackets[0], PKTSIZE);
+	length = linux_read_nonblock(priv->fd, priv->rx_buf, PKTSIZE);
 
 	if (length > 0)
-		net_receive(edev, NetRxPackets[0], length);
+		net_receive(edev, priv->rx_buf, length);
 
 	return 0;
 }
@@ -73,6 +74,8 @@ static int tap_probe(struct device_d *dev)
 		goto out;
 	}
 
+	priv->rx_buf = xmalloc(PKTSIZE);
+
 	edev = xzalloc(sizeof(struct eth_device));
 	edev->priv = priv;
 	edev->parent = dev;
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:28 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:28 +0200
Subject: [PATCH 4/9] net: liteeth: Do not use NetRxPackets
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-5-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/liteeth.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/liteeth.c b/drivers/net/liteeth.c
index 771f57eead..547f5486ae 100644
--- a/drivers/net/liteeth.c
+++ b/drivers/net/liteeth.c
@@ -73,6 +73,8 @@ struct liteeth {
 	int rx_slot;
 	int num_rx_slots;
 	void __iomem *rx_base;
+
+	void *rx_buf;
 };
 
 static inline void litex_write8(void __iomem *addr, u8 val)
@@ -230,9 +232,9 @@ static int liteeth_eth_rx(struct eth_device *edev)
 
 	rx_slot = litex_read8(priv->base + LITEETH_WRITER_SLOT);
 
-	memcpy(NetRxPackets[0], priv->rx_base + rx_slot * LITEETH_BUFFER_SIZE, len);
+	memcpy(priv->rx_buf, priv->rx_base + rx_slot * LITEETH_BUFFER_SIZE, len);
 
-	net_receive(edev, NetRxPackets[0], len);
+	net_receive(edev, priv->rx_buf, len);
 
 	litex_write8(priv->base + LITEETH_WRITER_EV_PENDING, reg);
 
@@ -323,6 +325,8 @@ static int liteeth_probe(struct device_d *dev)
 	priv->tx_base = buf_base + priv->num_rx_slots * LITEETH_BUFFER_SIZE;
 	priv->tx_slot = 0;
 
+	priv->rx_buf = xmalloc(PKTSIZE);
+
 	edev->init = liteeth_init_dev;
 	edev->open = liteeth_eth_open;
 	edev->send = liteeth_eth_send;
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:29 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:29 +0200
Subject: [PATCH 5/9] net: efi-snp: Allocate own receive buffer
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-6-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/efi-snp.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/efi-snp.c b/drivers/net/efi-snp.c
index 9cb7144187..d30da820a0 100644
--- a/drivers/net/efi-snp.c
+++ b/drivers/net/efi-snp.c
@@ -120,6 +120,7 @@ struct efi_snp_priv {
 	struct device_d *dev;
 	struct eth_device edev;
 	struct efi_simple_network *snp;
+	void *rx_buf;
 };
 
 static inline struct efi_snp_priv *to_priv(struct eth_device *edev)
@@ -163,7 +164,7 @@ static int efi_snp_eth_rx(struct eth_device *edev)
 	long bufsize = PKTSIZE;
 	efi_status_t efiret;
 
-	efiret = priv->snp->receive(priv->snp, NULL, &bufsize, NetRxPackets[0], NULL, NULL, NULL);
+	efiret = priv->snp->receive(priv->snp, NULL, &bufsize, priv->rx_buf, NULL, NULL, NULL);
 	if (efiret == EFI_NOT_READY)
 		return 0;
 
@@ -172,7 +173,7 @@ static int efi_snp_eth_rx(struct eth_device *edev)
 		return -efi_errno(efiret);
 	}
 
-	net_receive(edev, NetRxPackets[0], bufsize);
+	net_receive(edev, priv->rx_buf, bufsize);
 
 	return 0;
 }
@@ -285,6 +286,7 @@ static int efi_snp_probe(struct efi_device *efidev)
 	priv = xzalloc(sizeof(struct efi_snp_priv));
 	priv->snp = efidev->protocol;
 	priv->dev = &efidev->dev;
+	priv->rx_buf = xmalloc(PKTSIZE);
 
 	dev_dbg(&efidev->dev, "perm: %02x:%02x:%02x:%02x:%02x:%02x\n",
 			priv->snp->Mode->PermanentAddress.Addr[0],
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:24 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:24 +0200
Subject: [PATCH 0/9] Reduce usage of NetRxPackets[]
Message-ID: <20220919080133.877651-1-s.hauer@pengutronix.de>

Usage of the globally allocted network receive buffers NetRxPackets[] is
inherently broken. Some drivers queue these buffers in the hardware.
When multiple of these drivers are active at the same time then they
stamp over each others packets and bad things happen.

The goal is to remove NetRxPackets[] entirely in favor of per device
packet buffers. This series is a first step into that direction. It
removes the simple cases where only NetRxPackets[0] is used to store the
single packet that is pulled out of the hardware before net_receive() is
called.

Sascha

Sascha Hauer (9):
  net: tap: Allocate own receive buffer
  net: macb: Allocate own receive buffer
  net: cs8900: Allocate own receive buffer
  net: liteeth: Do not use NetRxPackets
  net: efi-snp: Allocate own receive buffer
  net: smc91111: Allocate own receive buffer
  net: smc911x: Allocate own receive buffer
  net: ks8851_mll: Allocate own receive buffer
  net: remove altera_tse driver

 drivers/net/Kconfig      |  16 --
 drivers/net/Makefile     |   1 -
 drivers/net/altera_tse.c | 563 ---------------------------------------
 drivers/net/altera_tse.h | 296 --------------------
 drivers/net/cs8900.c     |   7 +-
 drivers/net/efi-snp.c    |   6 +-
 drivers/net/ks8851_mll.c |   9 +-
 drivers/net/liteeth.c    |   8 +-
 drivers/net/macb.c       |  12 +-
 drivers/net/smc91111.c   |  10 +-
 drivers/net/smc911x.c    |   8 +-
 drivers/net/tap.c        |   7 +-
 12 files changed, 45 insertions(+), 898 deletions(-)
 delete mode 100644 drivers/net/altera_tse.c
 delete mode 100644 drivers/net/altera_tse.h

-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:26 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:26 +0200
Subject: [PATCH 2/9] net: macb: Allocate own receive buffer
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-3-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/macb.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 511846122a..5dbca1553e 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -64,6 +64,7 @@ struct macb_device {
 
 	void			*rx_buffer;
 	void			*tx_buffer;
+	void			*rx_packet_buf;
 	struct macb_dma_desc	*rx_ring;
 	struct macb_dma_desc	*tx_ring;
 	struct macb_dma_desc	*gem_q1_descs;
@@ -230,16 +231,15 @@ static int macb_recv(struct eth_device *edev)
 				taillen = length - headlen;
 				dma_sync_single_for_cpu((unsigned long)buffer,
 							headlen, DMA_FROM_DEVICE);
-				memcpy((void *)NetRxPackets[0], buffer, headlen);
+				memcpy(macb->rx_packet_buf, buffer, headlen);
 				dma_sync_single_for_cpu((unsigned long)macb->rx_buffer,
 							taillen, DMA_FROM_DEVICE);
-				memcpy((void *)NetRxPackets[0] + headlen,
-					macb->rx_buffer, taillen);
+				memcpy(macb->rx_packet_buf + headlen, macb->rx_buffer, taillen);
 				dma_sync_single_for_device((unsigned long)buffer,
 							headlen, DMA_FROM_DEVICE);
 				dma_sync_single_for_device((unsigned long)macb->rx_buffer,
 							taillen, DMA_FROM_DEVICE);
-				net_receive(edev, NetRxPackets[0], length);
+				net_receive(edev, macb->rx_packet_buf, length);
 			} else {
 				dma_sync_single_for_cpu((unsigned long)buffer, length,
 							DMA_FROM_DEVICE);
@@ -898,6 +898,8 @@ static int macb_probe(struct device_d *dev)
 		macb->gem_q1_descs = dma_alloc_coherent(GEM_Q1_DESC_BYTES,
 				DMA_ADDRESS_BROKEN);
 
+	macb->rx_packet_buf = xmalloc(PKTSIZE);
+
 	macb_reset_hw(macb);
 	ncfgr = macb_mdc_clk_div(macb);
 	ncfgr |= MACB_BIT(PAE);		/* PAuse Enable */
@@ -921,6 +923,8 @@ static void macb_remove(struct device_d *dev)
 	struct macb_device *macb = dev->priv;
 
 	macb_halt(&macb->netdev);
+
+	free(macb->rx_packet_buf);
 }
 
 static const struct macb_config fu540_c000_config = {
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:30 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:30 +0200
Subject: [PATCH 6/9] net: smc91111: Allocate own receive buffer
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-7-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/smc91111.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index d503535c25..3b23bfedfd 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -446,6 +446,7 @@ struct smc91c111_priv {
 	int revision;
 	unsigned int control_setup;
 	unsigned int config_setup;
+	void *rx_buf;
 };
 
 #if (SMC_DEBUG > 2 )
@@ -1302,14 +1303,14 @@ static int smc91c111_eth_rx(struct eth_device *edev)
 		   to send the DWORDs or the bytes first, or some
 		   mixture.  A mixture might improve already slow PIO
 		   performance	*/
-		SMC_insl(priv, SMC91111_DATA_REG , NetRxPackets[0],
+		SMC_insl(priv, SMC91111_DATA_REG , priv->rx_buf,
 				packet_length >> 2);
 		/* read the left over bytes */
 		if (packet_length & 3) {
 			int i;
 
 			unsigned char *tail =
-					(unsigned char *)(NetRxPackets[0] +
+					(unsigned char *)(priv->rx_buf +
 					(packet_length & ~3));
 			unsigned long leftover = SMC_inl(priv,
 					SMC91111_DATA_REG);
@@ -1320,7 +1321,7 @@ static int smc91c111_eth_rx(struct eth_device *edev)
 
 #if	SMC_DEBUG > 2
 		printf("Receiving Packet\n");
-		print_packet( NetRxPackets[0], packet_length );
+		print_packet(priv->rx_buf, packet_length );
 #endif
 	} else {
 		/* error ... */
@@ -1343,7 +1344,7 @@ static int smc91c111_eth_rx(struct eth_device *edev)
 
 	if (!is_error) {
 		/* Pass the packet up to the protocol layers. */
-		net_receive(edev, NetRxPackets[0], packet_length);
+		net_receive(edev, priv->rx_buf, packet_length);
 		return 0;
 	}
 
@@ -1445,6 +1446,7 @@ static int smc91c111_probe(struct device_d *dev)
 
 	priv = edev->priv;
 	priv->a = access_via_32bit;
+	priv->rx_buf = xmalloc(PKTSIZE);
 
 	if (dev->platform_data) {
 		struct smc91c111_pdata *pdata = dev->platform_data;
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:27 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:27 +0200
Subject: [PATCH 3/9] net: cs8900: Allocate own receive buffer
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-4-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/cs8900.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c
index 75bbbd79e1..16e1d498c7 100644
--- a/drivers/net/cs8900.c
+++ b/drivers/net/cs8900.c
@@ -180,6 +180,7 @@ struct cs8900_priv {
 	void *regs;
 	struct cs89x0_product *product;
 	struct cs89x0_chip *chip;
+	void *rx_buf;
 };
 
 /* Read a 16-bit value from PacketPage Memory using I/O Space operation */
@@ -294,13 +295,13 @@ static int cs8900_recv(struct eth_device *dev)
 	status = readw(priv->regs + CS8900_RTDATA0);
 	len = readw(priv->regs + CS8900_RTDATA0);
 
-	for (addr = (u16 *) NetRxPackets[0], i = len >> 1; i > 0; i--) {
+	for (addr = (u16 *)priv->rx_buf, i = len >> 1; i > 0; i--) {
 		*addr++ = readw(priv->regs + CS8900_RTDATA0);
 	}
 	if (len & 1) {
 		*addr++ = readw(priv->regs + CS8900_RTDATA0);
 	}
-	net_receive(dev, NetRxPackets[0], len);
+	net_receive(dev, priv->rx_buf, len);
 
 	return len;
 }
@@ -442,6 +443,8 @@ static int cs8900_probe(struct device_d *dev)
 		return -1;
 	}
 
+	priv->rx_buf = xmalloc(PKTSIZE);
+
 	edev = (struct eth_device *)xmalloc(sizeof(struct eth_device));
 	edev->priv = priv;
 
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:31 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:31 +0200
Subject: [PATCH 7/9] net: smc911x: Allocate own receive buffer
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-8-s.hauer@pengutronix.de>

Use a driver private buffer as network receive buffer rather than the
globally allocated ones which will be removed soon.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/smc911x.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 1edc16ce44..7fd5c2aadb 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -32,6 +32,8 @@ struct smc911x_priv {
 	unsigned int using_extphy;
 	unsigned int phy_mask;
 
+	void *rx_buf;
+
 	u32 (*reg_read)(struct smc911x_priv *priv, u32 reg);
 	void (*reg_write)(struct smc911x_priv *priv, u32 reg, u32 val);
 };
@@ -447,7 +449,7 @@ static void smc911x_eth_halt(struct eth_device *edev)
 static int smc911x_eth_rx(struct eth_device *edev)
 {
 	struct smc911x_priv *priv = (struct smc911x_priv *)edev->priv;
-	u32 *data = (u32 *)NetRxPackets[0];
+	u32 *data = priv->rx_buf;
 	u32 pktlen, tmplen;
 	u32 status;
 
@@ -465,7 +467,7 @@ static int smc911x_eth_rx(struct eth_device *edev)
 			dev_err(&edev->dev, "dropped bad packet. Status: 0x%08x\n",
 				status);
 		else
-			net_receive(edev, NetRxPackets[0], pktlen);
+			net_receive(edev, priv->rx_buf, pktlen);
 	}
 
 	return 0;
@@ -608,6 +610,8 @@ static int smc911x_probe(struct device_d *dev)
 	dev_info(dev, "LAN911x identified, idrev: 0x%08X, generation: %d\n",
 		   val, priv->generation);
 
+	priv->rx_buf = xmalloc(PKTSIZE);
+
 	edev = &priv->edev;
 	edev->priv = priv;
 
-- 
2.30.2



From s.hauer at pengutronix.de  Mon Sep 19 01:01:33 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 10:01:33 +0200
Subject: [PATCH 9/9] net: remove altera_tse driver
In-Reply-To: <20220919080133.877651-1-s.hauer@pengutronix.de>
References: <20220919080133.877651-1-s.hauer@pengutronix.de>
Message-ID: <20220919080133.877651-10-s.hauer@pengutronix.de>

The driver is unused throughout the tree and isn't compiled in any
defconfig. Remove it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/net/Kconfig      |  16 --
 drivers/net/Makefile     |   1 -
 drivers/net/altera_tse.c | 563 ---------------------------------------
 drivers/net/altera_tse.h | 296 --------------------
 4 files changed, 876 deletions(-)
 delete mode 100644 drivers/net/altera_tse.c
 delete mode 100644 drivers/net/altera_tse.h

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 27d0c4ec8b..84a01c5328 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -283,22 +283,6 @@ config DRIVER_NET_AG71XX
 	help
 	  This option enables support for Atheros AG71XX ethernet chip.
 
-config DRIVER_NET_TSE
-	depends on NIOS2
-	bool "Altera TSE ethernet driver"
-	select PHYLIB
-	help
-	  This option enables support for the Altera TSE MAC.
-
-config TSE_USE_DEDICATED_DESC_MEM
-	depends on DRIVER_NET_TSE
-	bool "Altera TSE uses dedicated descriptor memory"
-	help
-	  This option tells the TSE driver to use an onchip memory
-	  to store SGDMA descriptors. Descriptor memory is not
-	  reserved with a malloc but directly mapped to the memory
-	  address (defined in config.h)
-
 config DRIVER_NET_LITEETH
 	bool "LiteX ethernet driver"
 	select PHYLIB
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a3eb10d1df..47ad749943 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -39,7 +39,6 @@ obj-$(CONFIG_DRIVER_NET_SJA1105)	+= sja1105.o
 obj-$(CONFIG_DRIVER_NET_SMC911X)	+= smc911x.o
 obj-$(CONFIG_DRIVER_NET_SMC91111)	+= smc91111.o
 obj-$(CONFIG_DRIVER_NET_TAP)		+= tap.o
-obj-$(CONFIG_DRIVER_NET_TSE)		+= altera_tse.o
 obj-$(CONFIG_DRIVER_NET_EFI_SNP)	+= efi-snp.o
 obj-$(CONFIG_DRIVER_NET_VIRTIO)		+= virtio.o
 obj-$(CONFIG_DRIVER_NET_AG71XX)		+= ag71xx.o
diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c
deleted file mode 100644
index f1dfe5952c..0000000000
--- a/drivers/net/altera_tse.c
+++ /dev/null
@@ -1,563 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Altera TSE Network driver
- *
- * Copyright (C) 2008 Altera Corporation.
- * Copyright (C) 2010 Thomas Chou <thomas at wytron.com.tw>
- * Copyright (C) 2011 Franck JULLIEN, <elec4fun at gmail.com>
- */
-
-#include <common.h>
-#include <dma.h>
-#include <net.h>
-#include <init.h>
-#include <clock.h>
-#include <linux/mii.h>
-#include <linux/phy.h>
-#include <linux/err.h>
-
-#include <io.h>
-#include <asm/dma-mapping.h>
-
-#include "altera_tse.h"
-
-/* This is a generic routine that the SGDMA mode-specific routines
- * call to populate a descriptor.
- * arg1     :pointer to first SGDMA descriptor.
- * arg2     :pointer to next  SGDMA descriptor.
- * arg3     :Address to where data to be written.
- * arg4     :Address from where data to be read.
- * arg5     :no of byte to transaction.
- * arg6     :variable indicating to generate start of packet or not
- * arg7     :read fixed
- * arg8     :write fixed
- * arg9     :read burst
- * arg10    :write burst
- * arg11    :atlantic_channel number
- */
-static void alt_sgdma_construct_descriptor_burst(
-	struct alt_sgdma_descriptor *desc,
-	struct alt_sgdma_descriptor *next,
-	uint32_t *read_addr,
-	uint32_t *write_addr,
-	uint16_t length_or_eop,
-	uint8_t generate_eop,
-	uint8_t read_fixed,
-	uint8_t write_fixed_or_sop,
-	uint8_t read_burst,
-	uint8_t write_burst,
-	uint8_t atlantic_channel)
-{
-	uint32_t temp;
-
-	/*
-	 * Mark the "next" descriptor as "not" owned by hardware. This prevents
-	 * The SGDMA controller from continuing to process the chain. This is
-	 * done as a single IO write to bypass cache, without flushing
-	 * the entire descriptor, since only the 8-bit descriptor status must
-	 * be flushed.
-	 */
-	if (!next)
-		printf("Next descriptor not defined!!\n");
-
-	temp = readb(&next->descriptor_control);
-	writeb(temp & ~ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK,
-		&next->descriptor_control);
-
-	writel((uint32_t)read_addr, &desc->source);
-	writel((uint32_t)write_addr, &desc->destination);
-	writel((uint32_t)next, &desc->next);
-
-	writel(0, &desc->source_pad);
-	writel(0, &desc->destination_pad);
-	writel(0, &desc->next_pad);
-	writew(length_or_eop, &desc->bytes_to_transfer);
-	writew(0, &desc->actual_bytes_transferred);
-	writeb(0, &desc->descriptor_status);
-
-	/* SGDMA burst not currently supported */
-	writeb(0, &desc->read_burst);
-	writeb(0, &desc->write_burst);
-
-	/*
-	 * Set the descriptor control block as follows:
-	 * - Set "owned by hardware" bit
-	 * - Optionally set "generate EOP" bit
-	 * - Optionally set the "read from fixed address" bit
-	 * - Optionally set the "write to fixed address bit (which serves
-	 *   serves as a "generate SOP" control bit in memory-to-stream mode).
-	 * - Set the 4-bit atlantic channel, if specified
-	 *
-	 * Note this step is performed after all other descriptor information
-	 * has been filled out so that, if the controller already happens to be
-	 * pointing at this descriptor, it will not run (via the "owned by
-	 * hardware" bit) until all other descriptor has been set up.
-	 */
-
-	writeb((ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK) |
-		(generate_eop ? ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK : 0) |
-		(read_fixed ? ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK : 0) |
-		(write_fixed_or_sop ? ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK : 0) |
-		(atlantic_channel ? ((atlantic_channel & 0x0F) << 3) : 0),
-		&desc->descriptor_control);
-}
-
-static int alt_sgdma_do_sync_transfer(struct alt_sgdma_registers *dev,
-					struct alt_sgdma_descriptor *desc)
-{
-	uint32_t temp;
-	uint64_t start;
-	uint64_t tout;
-
-	/* Wait for any pending transfers to complete */
-	tout = ALT_TSE_SGDMA_BUSY_WATCHDOG_TOUT * MSECOND;
-
-	start = get_time_ns();
-
-	while (readl(&dev->status) & ALT_SGDMA_STATUS_BUSY_MSK) {
-		if (is_timeout(start, tout)) {
-			debug("Timeout waiting sgdma in do sync!\n");
-			break;
-		}
-	}
-
-	/*
-	 * Clear any (previous) status register information
-	 * that might occlude our error checking later.
-	 */
-	writel(0xFF, &dev->status);
-
-	/* Point the controller at the descriptor */
-	writel((uint32_t)desc, &dev->next_descriptor_pointer);
-	debug("next desc in sgdma 0x%x\n", (uint32_t)dev->next_descriptor_pointer);
-
-	/*
-	 * Set up SGDMA controller to:
-	 * - Disable interrupt generation
-	 * - Run once a valid descriptor is written to controller
-	 * - Stop on an error with any particular descriptor
-	 */
-	writel(ALT_SGDMA_CONTROL_RUN_MSK | ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK,
-		&dev->control);
-
-	/* Wait for the descriptor (chain) to complete */
-	debug("wait for sgdma....");
-	start = get_time_ns();
-
-	while (readl(&dev->status) & ALT_SGDMA_STATUS_BUSY_MSK) {
-		if (is_timeout(start, tout)) {
-			debug("Timeout waiting sgdma in do sync!\n");
-			break;
-		}
-	}
-
-	debug("done\n");
-
-	/* Clear Run */
-	temp = readl(&dev->control);
-	writel(temp & ~ALT_SGDMA_CONTROL_RUN_MSK, &dev->control);
-
-	/* Get & clear status register contents */
-	debug("tx sgdma status = 0x%x", readl(&dev->status));
-	writel(0xFF, &dev->status);
-
-	return 0;
-}
-
-static int alt_sgdma_do_async_transfer(struct alt_sgdma_registers *dev,
-					struct alt_sgdma_descriptor *desc)
-{
-	uint64_t start;
-	uint64_t tout;
-
-	/* Wait for any pending transfers to complete */
-	tout = ALT_TSE_SGDMA_BUSY_WATCHDOG_TOUT * MSECOND;
-
-	start = get_time_ns();
-
-	while (readl(&dev->status) & ALT_SGDMA_STATUS_BUSY_MSK) {
-		if (is_timeout(start, tout)) {
-			debug("Timeout waiting sgdma in do async!\n");
-			break;
-		}
-	}
-
-	/*
-	 * Clear any (previous) status register information
-	 * that might occlude our error checking later.
-	 */
-	writel(0xFF, &dev->status);
-
-	/* Point the controller at the descriptor */
-	writel((uint32_t)desc, &dev->next_descriptor_pointer);
-
-	/*
-	 * Set up SGDMA controller to:
-	 * - Disable interrupt generation
-	 * - Run once a valid descriptor is written to controller
-	 * - Stop on an error with any particular descriptor
-	 */
-	writel(ALT_SGDMA_CONTROL_RUN_MSK | ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK,
-		&dev->control);
-
-	return 0;
-}
-
-static int tse_get_ethaddr(struct eth_device *edev, unsigned char *m)
-{
-	struct altera_tse_priv *priv = edev->priv;
-	struct alt_tse_mac *mac_dev = priv->tse_regs;
-
-	m[5] = (readl(&mac_dev->mac_addr_1) >> 8)  && 0xFF;
-	m[4] = (readl(&mac_dev->mac_addr_1))       && 0xFF;
-	m[3] = (readl(&mac_dev->mac_addr_0) >> 24) && 0xFF;
-	m[2] = (readl(&mac_dev->mac_addr_0) >> 16) && 0xFF;
-	m[1] = (readl(&mac_dev->mac_addr_0) >>  8) && 0xFF;
-	m[0] = (readl(&mac_dev->mac_addr_0))       && 0xFF;
-
-	return 0;
-}
-
-static int tse_set_ethaddr(struct eth_device *edev, const unsigned char *m)
-{
-	struct altera_tse_priv *priv = edev->priv;
-	struct alt_tse_mac *mac_dev = priv->tse_regs;
-
-	debug("Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n",
-		m[0], m[1], m[2], m[3], m[4], m[5]);
-
-	writel(m[3] << 24 | m[2] << 16 | m[1] << 8 | m[0], &mac_dev->mac_addr_0);
-	writel((m[5] << 8 | m[4]) & 0xFFFF, &mac_dev->mac_addr_1);
-
-	return 0;
-}
-
-static int tse_phy_read(struct mii_bus *bus, int phy_addr, int reg)
-{
-	struct altera_tse_priv *priv = bus->priv;
-	struct alt_tse_mac *mac_dev = priv->tse_regs;
-	uint32_t *mdio_regs;
-
-	writel(phy_addr, &mac_dev->mdio_phy1_addr);
-
-	mdio_regs = (uint32_t *)&mac_dev->mdio_phy1;
-
-	return readl(&mdio_regs[reg]) & 0xFFFF;
-}
-
-static int tse_phy_write(struct mii_bus *bus, int phy_addr, int reg, u16 val)
-{
-	struct altera_tse_priv *priv = bus->priv;
-	struct alt_tse_mac *mac_dev = priv->tse_regs;
-	uint32_t *mdio_regs;
-
-	writel(phy_addr, &mac_dev->mdio_phy1_addr);
-
-	mdio_regs = (uint32_t *)&mac_dev->mdio_phy1;
-
-	writel((uint32_t)val, &mdio_regs[reg]);
-
-	return 0;
-}
-
-static void tse_reset(struct eth_device *edev)
-{
-	/* stop sgdmas, disable tse receive */
-	struct altera_tse_priv *priv = edev->priv;
-	struct alt_tse_mac *mac_dev = priv->tse_regs;
-	struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx_regs;
-	struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx_regs;
-	struct alt_sgdma_descriptor *rx_desc = priv->rx_desc;
-	struct alt_sgdma_descriptor *tx_desc = priv->tx_desc;
-	uint64_t start;
-	uint64_t tout;
-
-	tout = ALT_TSE_SGDMA_BUSY_WATCHDOG_TOUT * MSECOND;
-
-	/* clear rx desc & wait for sgdma to complete */
-	writeb(0, &rx_desc->descriptor_control);
-	writel(0, &rx_sgdma->control);
-
-	writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &rx_sgdma->control);
-	writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &rx_sgdma->control);
-	mdelay(100);
-
-	start = get_time_ns();
-
-	while (readl(&rx_sgdma->status) & ALT_SGDMA_STATUS_BUSY_MSK) {
-		if (is_timeout(start, tout)) {
-			printf("Timeout waiting for rx sgdma!\n");
-			writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &rx_sgdma->control);
-			writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &rx_sgdma->control);
-			break;
-		}
-	}
-
-	/* clear tx desc & wait for sgdma to complete */
-	writeb(0, &tx_desc->descriptor_control);
-	writel(0, &tx_sgdma->control);
-
-	writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &tx_sgdma->control);
-	writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &tx_sgdma->control);
-	mdelay(100);
-
-	start = get_time_ns();
-
-	while (readl(&tx_sgdma->status) & ALT_SGDMA_STATUS_BUSY_MSK) {
-		if (is_timeout(start, tout)) {
-			printf("Timeout waiting for tx sgdma!\n");
-			writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &tx_sgdma->control);
-			writel(ALT_SGDMA_CONTROL_SOFTWARERESET_MSK, &tx_sgdma->control);
-			break;
-		}
-	}
-
-	/* reset the mac */
-	writel(ALTERA_TSE_CMD_TX_ENA_MSK | ALTERA_TSE_CMD_RX_ENA_MSK |
-		ALTERA_TSE_CMD_SW_RESET_MSK, &mac_dev->command_config);
-
-	start = get_time_ns();
-	tout = ALT_TSE_SW_RESET_WATCHDOG_TOUT * MSECOND;
-
-	while (readl(&mac_dev->command_config) & ALTERA_TSE_CMD_SW_RESET_MSK) {
-		if (is_timeout(start, tout)) {
-			printf("TSEMAC SW reset bit never cleared!\n");
-			break;
-		}
-	}
-}
-
-static int tse_eth_open(struct eth_device *edev)
-{
-	struct altera_tse_priv *priv = edev->priv;
-	int ret;
-
-	ret = phy_device_connect(edev, priv->miibus, priv->phy_addr, NULL, 0,
-				 PHY_INTERFACE_MODE_NA);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int tse_eth_send(struct eth_device *edev, void *packet, int length)
-{
-
-	struct altera_tse_priv *priv = edev->priv;
-	struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx_regs;
-	struct alt_sgdma_descriptor *tx_desc = priv->tx_desc;
-	struct alt_sgdma_descriptor *tx_desc_cur = tx_desc;
-
-	flush_dcache_range((uint32_t)packet, (uint32_t)packet + length);
-	alt_sgdma_construct_descriptor_burst(
-		(struct alt_sgdma_descriptor *)&tx_desc[0],
-		(struct alt_sgdma_descriptor *)&tx_desc[1],
-		(uint32_t *)packet,	/* read addr */
-		(uint32_t *)0,		/*           */
-		length,			/* length or EOP ,will change for each tx */
-		0x1,			/* gen eop */
-		0x0,			/* read fixed */
-		0x1,			/* write fixed or sop */
-		0x0,			/* read burst */
-		0x0,			/* write burst */
-		0x0			/* channel */
-		);
-
-	alt_sgdma_do_sync_transfer(tx_sgdma, tx_desc_cur);
-
-	return 0;
-}
-
-static void tse_eth_halt(struct eth_device *edev)
-{
-	struct altera_tse_priv *priv = edev->priv;
-	struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx_regs;
-	struct alt_sgdma_registers *tx_sgdma = priv->sgdma_tx_regs;
-
-	writel(0, &rx_sgdma->control); /* Stop the controller and reset settings */
-	writel(0, &tx_sgdma->control); /* Stop the controller and reset settings */
-}
-
-static int tse_eth_rx(struct eth_device *edev)
-{
-	uint16_t packet_length = 0;
-
-	struct altera_tse_priv *priv = edev->priv;
-	struct alt_sgdma_descriptor *rx_desc = priv->rx_desc;
-	struct alt_sgdma_descriptor *rx_desc_cur = rx_desc;
-	struct alt_sgdma_registers *rx_sgdma = priv->sgdma_rx_regs;
-
-	if (rx_desc_cur->descriptor_status &
-		ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK) {
-
-		packet_length = rx_desc->actual_bytes_transferred;
-		net_receive(edev, NetRxPackets[0], packet_length);
-
-		/* Clear Run */
-		rx_sgdma->control = (rx_sgdma->control & (~ALT_SGDMA_CONTROL_RUN_MSK));
-
-		/* start descriptor again */
-		flush_dcache_range((uint32_t)(NetRxPackets[0]), (uint32_t)(NetRxPackets[0]) + PKTSIZE);
-		alt_sgdma_construct_descriptor_burst(
-			(struct alt_sgdma_descriptor *)&rx_desc[0],
-			(struct alt_sgdma_descriptor *)&rx_desc[1],
-			(uint32_t)0x0,			/* read addr */
-			(uint32_t *)NetRxPackets[0],	/*           */
-			0x0,				/* length or EOP */
-			0x0,				/* gen eop */
-			0x0,				/* read fixed */
-			0x0,				/* write fixed or sop */
-			0x0,				/* read burst */
-			0x0,				/* write burst */
-			0x0				/* channel */
-		);
-
-		/* setup the sgdma */
-		alt_sgdma_do_async_transfer(priv->sgdma_rx_regs, rx_desc);
-	}
-
-	return 0;
-}
-
-static int tse_init_dev(struct eth_device *edev)
-{
-	struct altera_tse_priv *priv = edev->priv;
-	struct alt_tse_mac *mac_dev = priv->tse_regs;
-	struct alt_sgdma_descriptor *tx_desc = priv->tx_desc;
-	struct alt_sgdma_descriptor *rx_desc = priv->rx_desc;
-	struct alt_sgdma_descriptor *rx_desc_cur;
-
-	rx_desc_cur = rx_desc;
-
-	tse_reset(edev);
-
-	/* need to create sgdma */
-	alt_sgdma_construct_descriptor_burst(
-		(struct alt_sgdma_descriptor *)&tx_desc[0],
-		(struct alt_sgdma_descriptor *)&tx_desc[1],
-		(uint32_t *)NULL,	/* read addr */
-		(uint32_t *)0,		/*           */
-		0,			/* length or EOP ,will change for each tx */
-		0x1,			/* gen eop */
-		0x0,			/* read fixed */
-		0x1,			/* write fixed or sop */
-		0x0,			/* read burst */
-		0x0,			/* write burst */
-		0x0			/* channel */
-		);
-
-	flush_dcache_range((uint32_t)(NetRxPackets[0]), (uint32_t)(NetRxPackets[0]) + PKTSIZE);
-	alt_sgdma_construct_descriptor_burst(
-		(struct alt_sgdma_descriptor *)&rx_desc[0],
-		(struct alt_sgdma_descriptor *)&rx_desc[1],
-		(uint32_t)0x0,			/* read addr */
-		(uint32_t *)NetRxPackets[0],	/*           */
-		0x0,				/* length or EOP */
-		0x0,				/* gen eop */
-		0x0,				/* read fixed */
-		0x0,				/* write fixed or sop */
-		0x0,				/* read burst */
-		0x0,				/* write burst */
-		0x0				/* channel */
-		);
-
-	/* start rx async transfer */
-	alt_sgdma_do_async_transfer(priv->sgdma_rx_regs, rx_desc_cur);
-
-	/* Initialize MAC registers */
-	writel(PKTSIZE, &mac_dev->max_frame_length);
-
-	/* NO Shift */
-	writel(0, &mac_dev->rx_cmd_stat);
-	writel(0, &mac_dev->tx_cmd_stat);
-
-	/* enable MAC */
-	writel(ALTERA_TSE_CMD_TX_ENA_MSK | ALTERA_TSE_CMD_RX_ENA_MSK, &mac_dev->command_config);
-
-	return 0;
-}
-
-static int tse_probe(struct device_d *dev)
-{
-	struct resource *iores;
-	struct altera_tse_priv *priv;
-	struct mii_bus *miibus;
-	struct eth_device *edev;
-	struct alt_sgdma_descriptor *rx_desc;
-	struct alt_sgdma_descriptor *tx_desc;
-#ifndef CONFIG_TSE_USE_DEDICATED_DESC_MEM
-	uint32_t dma_handle;
-#endif
-	edev = xzalloc(sizeof(struct eth_device));
-	priv = xzalloc(sizeof(struct altera_tse_priv));
-	miibus = xzalloc(sizeof(struct mii_bus));
-
-	edev->priv = priv;
-
-	edev->init = tse_init_dev;
-	edev->open = tse_eth_open;
-	edev->send = tse_eth_send;
-	edev->recv = tse_eth_rx;
-	edev->halt = tse_eth_halt;
-	edev->get_ethaddr = tse_get_ethaddr;
-	edev->set_ethaddr = tse_set_ethaddr;
-	edev->parent = dev;
-
-#ifdef CONFIG_TSE_USE_DEDICATED_DESC_MEM
-	iores = dev_request_mem_resource(dev, 3);
-	if (IS_ERR(iores))
-		return PTR_ERR(iores);
-	tx_desc = IOMEM(iores->start);
-	rx_desc = tx_desc + 2;
-#else
-	tx_desc = dma_alloc_coherent(sizeof(*tx_desc) * (3 + PKTBUFSRX), (dma_addr_t *)&dma_handle);
-	rx_desc = tx_desc + 2;
-
-	if (!tx_desc) {
-		free(edev);
-		free(miibus);
-		return 0;
-	}
-#endif
-
-	memset(rx_desc, 0, (sizeof *rx_desc) * (PKTBUFSRX + 1));
-	memset(tx_desc, 0, (sizeof *tx_desc) * 2);
-
-	iores = dev_request_mem_resource(dev, 0);
-	if (IS_ERR(iores))
-		return PTR_ERR(iores);
-	priv->tse_regs = IOMEM(iores->start);
-	iores = dev_request_mem_resource(dev, 1);
-	if (IS_ERR(iores))
-		return PTR_ERR(iores);
-	priv->sgdma_rx_regs = IOMEM(iores->start);
-
-	iores = dev_request_mem_resource(dev, 2);
-	if (IS_ERR(iores))
-		return PTR_ERR(iores);
-	priv->sgdma_tx_regs = IOMEM(iores->start);
-	priv->rx_desc = rx_desc;
-	priv->tx_desc = tx_desc;
-
-	priv->miibus = miibus;
-
-	miibus->read = tse_phy_read;
-	miibus->write = tse_phy_write;
-	miibus->priv = priv;
-	miibus->parent = dev;
-
-	if (dev->platform_data != NULL)
-		priv->phy_addr = *((int8_t *)(dev->platform_data));
-	else
-		priv->phy_addr = -1;
-
-	mdiobus_register(miibus);
-
-	return eth_register(edev);
-}
-
-static struct driver_d altera_tse_driver = {
-	.name = "altera_tse",
-	.probe = tse_probe,
-};
-device_platform_driver(altera_tse_driver);
diff --git a/drivers/net/altera_tse.h b/drivers/net/altera_tse.h
deleted file mode 100644
index 7bff14de81..0000000000
--- a/drivers/net/altera_tse.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Altera 10/100/1000 triple speed ethernet mac
- *
- * Copyright (C) 2008 Altera Corporation.
- * Copyright (C) 2010 Thomas Chou <thomas at wytron.com.tw>
- * Copyright (C) 2011 Franck JULLIEN <elec4fun at gmail.com>
- */
-#ifndef _ALTERA_TSE_H_
-#define _ALTERA_TSE_H_
-
-/* SGDMA Stuff */
-#define ALT_SGDMA_STATUS_ERROR_MSK			(0x00000001)
-#define ALT_SGDMA_STATUS_EOP_ENCOUNTERED_MSK		(0x00000002)
-#define ALT_SGDMA_STATUS_DESC_COMPLETED_MSK		(0x00000004)
-#define ALT_SGDMA_STATUS_CHAIN_COMPLETED_MSK		(0x00000008)
-#define ALT_SGDMA_STATUS_BUSY_MSK			(0x00000010)
-
-#define ALT_SGDMA_CONTROL_IE_ERROR_MSK			(0x00000001)
-#define ALT_SGDMA_CONTROL_IE_EOP_ENCOUNTERED_MSK	(0x00000002)
-#define ALT_SGDMA_CONTROL_IE_DESC_COMPLETED_MSK		(0x00000004)
-#define ALT_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK	(0x00000008)
-#define ALT_SGDMA_CONTROL_IE_GLOBAL_MSK			(0x00000010)
-#define ALT_SGDMA_CONTROL_RUN_MSK			(0x00000020)
-#define ALT_SGDMA_CONTROL_STOP_DMA_ER_MSK		(0x00000040)
-#define ALT_SGDMA_CONTROL_IE_MAX_DESC_PROCESSED_MSK	(0x00000080)
-#define ALT_SGDMA_CONTROL_MAX_DESC_PROCESSED_MSK	(0x0000FF00)
-#define ALT_SGDMA_CONTROL_SOFTWARERESET_MSK		(0x00010000)
-#define ALT_SGDMA_CONTROL_PARK_MSK			(0x00020000)
-#define ALT_SGDMA_CONTROL_CLEAR_INTERRUPT_MSK		(0x80000000)
-
-#define ALTERA_TSE_SGDMA_INTR_MASK  (ALT_SGDMA_CONTROL_IE_CHAIN_COMPLETED_MSK \
-			| ALT_SGDMA_STATUS_DESC_COMPLETED_MSK \
-			| ALT_SGDMA_CONTROL_IE_GLOBAL_MSK)
-
-/*
- * Descriptor control bit masks & offsets
- *
- * Note: The control byte physically occupies bits [31:24] in memory.
- *	 The following bit-offsets are expressed relative to the LSB of
- *	 the control register bitfield.
- */
-#define ALT_SGDMA_DESCRIPTOR_CONTROL_GENERATE_EOP_MSK		(0x00000001)
-#define ALT_SGDMA_DESCRIPTOR_CONTROL_READ_FIXED_ADDRESS_MSK	(0x00000002)
-#define ALT_SGDMA_DESCRIPTOR_CONTROL_WRITE_FIXED_ADDRESS_MSK	(0x00000004)
-#define ALT_SGDMA_DESCRIPTOR_CONTROL_ATLANTIC_CHANNEL_MSK	(0x00000008)
-#define ALT_SGDMA_DESCRIPTOR_CONTROL_OWNED_BY_HW_MSK		(0x00000080)
-
-/*
- * Descriptor status bit masks & offsets
- *
- * Note: The status byte physically occupies bits [23:16] in memory.
- *	 The following bit-offsets are expressed relative to the LSB of
- *	 the status register bitfield.
- */
-#define ALT_SGDMA_DESCRIPTOR_STATUS_E_CRC_MSK			(0x00000001)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_E_PARITY_MSK		(0x00000002)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_E_OVERFLOW_MSK		(0x00000004)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_E_SYNC_MSK			(0x00000008)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_E_UEOP_MSK			(0x00000010)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_E_MEOP_MSK			(0x00000020)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_E_MSOP_MSK			(0x00000040)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_TERMINATED_BY_EOP_MSK	(0x00000080)
-#define ALT_SGDMA_DESCRIPTOR_STATUS_ERROR_MSK			(0x0000007F)
-
-/*
- * The SGDMA controller buffer descriptor allocates
- * 64 bits for each address. To support ANSI C, the
- * struct implementing a descriptor places 32-bits
- * of padding directly above each address; each pad must
- * be cleared when initializing a descriptor.
- */
-
-/*
- * Buffer Descriptor data structure
- *
- */
-struct alt_sgdma_descriptor {
-	unsigned int *source;           /* the address of data to be read. */
-	unsigned int source_pad;
-
-	unsigned int *destination;     /* the address to write data */
-	unsigned int destination_pad;
-
-	unsigned int *next;            /* the next descriptor in the list. */
-	unsigned int next_pad;
-
-	unsigned short bytes_to_transfer; /* the number of bytes to transfer */
-	unsigned char read_burst;
-	unsigned char write_burst;
-
-	unsigned short actual_bytes_transferred;/* bytes transferred by DMA */
-	unsigned char descriptor_status;
-	unsigned char descriptor_control;
-
-} __attribute__ ((packed, aligned(1)));
-
-/* SG-DMA Control/Status Slave registers map */
-
-struct alt_sgdma_registers {
-	unsigned int status;
-	unsigned int status_pad[3];
-	unsigned int control;
-	unsigned int control_pad[3];
-	unsigned int next_descriptor_pointer;
-	unsigned int descriptor_pad[3];
-};
-
-/* TSE Stuff */
-#define ALTERA_TSE_CMD_TX_ENA_MSK		(0x00000001)
-#define ALTERA_TSE_CMD_RX_ENA_MSK		(0x00000002)
-#define ALTERA_TSE_CMD_XON_GEN_MSK		(0x00000004)
-#define ALTERA_TSE_CMD_ETH_SPEED_MSK		(0x00000008)
-#define ALTERA_TSE_CMD_PROMIS_EN_MSK		(0x00000010)
-#define ALTERA_TSE_CMD_PAD_EN_MSK		(0x00000020)
-#define ALTERA_TSE_CMD_CRC_FWD_MSK		(0x00000040)
-#define ALTERA_TSE_CMD_PAUSE_FWD_MSK		(0x00000080)
-#define ALTERA_TSE_CMD_PAUSE_IGNORE_MSK		(0x00000100)
-#define ALTERA_TSE_CMD_TX_ADDR_INS_MSK		(0x00000200)
-#define ALTERA_TSE_CMD_HD_ENA_MSK		(0x00000400)
-#define ALTERA_TSE_CMD_EXCESS_COL_MSK		(0x00000800)
-#define ALTERA_TSE_CMD_LATE_COL_MSK		(0x00001000)
-#define ALTERA_TSE_CMD_SW_RESET_MSK		(0x00002000)
-#define ALTERA_TSE_CMD_MHASH_SEL_MSK		(0x00004000)
-#define ALTERA_TSE_CMD_LOOPBACK_MSK		(0x00008000)
-/* Bits (18:16) = address select */
-#define ALTERA_TSE_CMD_TX_ADDR_SEL_MSK		(0x00070000)
-#define ALTERA_TSE_CMD_MAGIC_ENA_MSK		(0x00080000)
-#define ALTERA_TSE_CMD_SLEEP_MSK		(0x00100000)
-#define ALTERA_TSE_CMD_WAKEUP_MSK		(0x00200000)
-#define ALTERA_TSE_CMD_XOFF_GEN_MSK		(0x00400000)
-#define ALTERA_TSE_CMD_CNTL_FRM_ENA_MSK		(0x00800000)
-#define ALTERA_TSE_CMD_NO_LENGTH_CHECK_MSK	(0x01000000)
-#define ALTERA_TSE_CMD_ENA_10_MSK		(0x02000000)
-#define ALTERA_TSE_CMD_RX_ERR_DISC_MSK		(0x04000000)
-/* Bits (30..27) reserved */
-#define ALTERA_TSE_CMD_CNT_RESET_MSK		(0x80000000)
-
-#define ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16	(0x00040000)
-#define ALTERA_TSE_TX_CMD_STAT_OMIT_CRC		(0x00020000)
-
-#define ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16	(0x02000000)
-
-#define ALT_TSE_SW_RESET_WATCHDOG_CNTR		10000
-#define ALT_TSE_SGDMA_BUSY_WATCHDOG_CNTR	90000000
-
-#define ALT_TSE_SW_RESET_WATCHDOG_TOUT		1    /* ms */
-#define ALT_TSE_SGDMA_BUSY_WATCHDOG_TOUT	5    /* ms */
-
-struct alt_tse_mdio {
-	unsigned int control; /*PHY device operation control register */
-	unsigned int status;  /*PHY device operation status register */
-	unsigned int phy_id1; /*Bits 31:16 of PHY identifier. */
-	unsigned int phy_id2; /*Bits 15:0 of PHY identifier. */
-	unsigned int auto_negotiation_advertisement;
-	unsigned int remote_partner_base_page_ability;
-
-	unsigned int reg6;
-	unsigned int reg7;
-	unsigned int reg8;
-	unsigned int reg9;
-	unsigned int rega;
-	unsigned int regb;
-	unsigned int regc;
-	unsigned int regd;
-	unsigned int rege;
-	unsigned int regf;
-	unsigned int reg10;
-	unsigned int reg11;
-	unsigned int reg12;
-	unsigned int reg13;
-	unsigned int reg14;
-	unsigned int reg15;
-	unsigned int reg16;
-	unsigned int reg17;
-	unsigned int reg18;
-	unsigned int reg19;
-	unsigned int reg1a;
-	unsigned int reg1b;
-	unsigned int reg1c;
-	unsigned int reg1d;
-	unsigned int reg1e;
-	unsigned int reg1f;
-};
-
-/* MAC register Space */
-
-struct alt_tse_mac {
-	unsigned int megacore_revision;
-	unsigned int scratch_pad;
-	unsigned int command_config;
-	unsigned int mac_addr_0;
-	unsigned int mac_addr_1;
-	unsigned int max_frame_length;
-	unsigned int pause_quanta;
-	unsigned int rx_sel_empty_threshold;
-	unsigned int rx_sel_full_threshold;
-	unsigned int tx_sel_empty_threshold;
-	unsigned int tx_sel_full_threshold;
-	unsigned int rx_almost_empty_threshold;
-	unsigned int rx_almost_full_threshold;
-	unsigned int tx_almost_empty_threshold;
-	unsigned int tx_almost_full_threshold;
-	unsigned int mdio_phy0_addr;
-	unsigned int mdio_phy1_addr;
-
-	/* only if 100/1000 BaseX PCS, reserved otherwise */
-	unsigned int reservedx44[5];
-
-	unsigned int reg_read_access_status;
-	unsigned int min_tx_ipg_length;
-
-	/* IEEE 802.3 oEntity Managed Object Support */
-	unsigned int aMACID_1;	/*The MAC addresses */
-	unsigned int aMACID_2;
-	unsigned int aFramesTransmittedOK;
-	unsigned int aFramesReceivedOK;
-	unsigned int aFramesCheckSequenceErrors;
-	unsigned int aAlignmentErrors;
-	unsigned int aOctetsTransmittedOK;
-	unsigned int aOctetsReceivedOK;
-
-	/* IEEE 802.3 oPausedEntity Managed Object Support */
-	unsigned int aTxPAUSEMACCtrlFrames;
-	unsigned int aRxPAUSEMACCtrlFrames;
-
-	/* IETF MIB (MIB-II) Object Support */
-	unsigned int ifInErrors;
-	unsigned int ifOutErrors;
-	unsigned int ifInUcastPkts;
-	unsigned int ifInMulticastPkts;
-	unsigned int ifInBroadcastPkts;
-	unsigned int ifOutDiscards;
-	unsigned int ifOutUcastPkts;
-	unsigned int ifOutMulticastPkts;
-	unsigned int ifOutBroadcastPkts;
-
-	/* IETF RMON MIB Object Support */
-	unsigned int etherStatsDropEvent;
-	unsigned int etherStatsOctets;
-	unsigned int etherStatsPkts;
-	unsigned int etherStatsUndersizePkts;
-	unsigned int etherStatsOversizePkts;
-	unsigned int etherStatsPkts64Octets;
-	unsigned int etherStatsPkts65to127Octets;
-	unsigned int etherStatsPkts128to255Octets;
-	unsigned int etherStatsPkts256to511Octets;
-	unsigned int etherStatsPkts512to1023Octets;
-	unsigned int etherStatsPkts1024to1518Octets;
-
-	unsigned int etherStatsPkts1519toXOctets;
-	unsigned int etherStatsJabbers;
-	unsigned int etherStatsFragments;
-
-	unsigned int reservedxE4;
-
-	/*FIFO control register. */
-	unsigned int tx_cmd_stat;
-	unsigned int rx_cmd_stat;
-
-	unsigned int ipaccTxConf;
-	unsigned int ipaccRxConf;
-	unsigned int ipaccRxStat;
-	unsigned int ipaccRxStatSum;
-
-	/*Multicast address resolution table */
-	unsigned int hash_table[64];
-
-	/*Registers 0 to 31 within PHY device 0/1 */
-	struct alt_tse_mdio mdio_phy0;
-	struct alt_tse_mdio mdio_phy1;
-
-	/*4 Supplemental MAC Addresses */
-	unsigned int supp_mac_addr_0_0;
-	unsigned int supp_mac_addr_0_1;
-	unsigned int supp_mac_addr_1_0;
-	unsigned int supp_mac_addr_1_1;
-	unsigned int supp_mac_addr_2_0;
-	unsigned int supp_mac_addr_2_1;
-	unsigned int supp_mac_addr_3_0;
-	unsigned int supp_mac_addr_3_1;
-
-	unsigned int reservedx320[56];
-};
-
-struct altera_tse_priv {
-	void __iomem *tse_regs;
-	void __iomem *sgdma_rx_regs;
-	void __iomem *sgdma_tx_regs;
-	void __iomem *rx_desc;
-	void __iomem *tx_desc;
-	int phy_addr;
-	struct mii_bus *miibus;
-};
-
-#endif /* _ALTERA_TSE_H_ */
-- 
2.30.2



From sha at pengutronix.de  Mon Sep 19 02:01:35 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 11:01:35 +0200
Subject: [PATCH 0/2] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <20220905145214.290551-1-michael.riesch@wolfvision.net>
References: <20220905145214.290551-1-michael.riesch@wolfvision.net>
Message-ID: <20220919090135.GB6477@pengutronix.de>

On Mon, Sep 05, 2022 at 04:52:12PM +0200, Michael Riesch wrote:
> Hi all,
> 
> The IO domains on Rockchip SoCs need to be configured to the correct
> bank voltage. In Linux this is achieved by means of a platform driver
> that reads the voltage value of the supplies and configures the bits
> in the general register file (GRF) accordingly.
> 
> This series ports this driver to barebox to provide support for the
> Rockchip RK356x SoCs. Please note that I could only test the changes
> on RK3568 boards, so I left out the parts for the other SoCs supported
> by the Linux driver. Also, it should be noted that the Linux driver
> uses notifiers to react to voltage changes. This is not supported by
> this barebox driver.
> 
> WARNING: Use those patches with care as they have the potential to
> fry up your board. That said, testers are very welcome ;-)

You are frightening me.

I would apply this series, but given you warn about its usage I'm not
sure what I should do with it. I could give it a test on the RK3568-EVB
once it returned back in our remote lab, but I neither have a Pine64 nor
a BananaPi R2 Pro.

Sascha

-- 
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-5555 |


From s.hauer at pengutronix.de  Mon Sep 19 02:14:10 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 11:14:10 +0200
Subject: Makefile.lib: cmd_dtc: warning: missing whitespace after the
 macro name
In-Reply-To: <20220912120734.3fa82231ca6d16ba604ee262@gmail.com>
References: <20220907112118.71575e3650222736432b3086@gmail.com>
 <20220912080152.GE24324@pengutronix.de>
 <20220912120734.3fa82231ca6d16ba604ee262@gmail.com>
Message-ID: <20220919091410.GC6477@pengutronix.de>

Hi Antony,

On Mon, Sep 12, 2022 at 12:07:34PM +0300, Antony Pavlov wrote:
> On Mon, 12 Sep 2022 10:01:52 +0200
> Sascha Hauer <s.hauer at pengutronix.de> wrote:
> 
> > One side effect is that this gets even less readable.
> 
> Yes, you are right :)
> 
> > Another one would be that two dts filenames which only differ in the
> > usage of '.' and '_' would result in the same define, but I think that
> > case is negligible as this define is unused in barebox itself. It could
>                                        ^^^^^^^^^^^^^^^^^^^^^^^^
> > be used by external dts fragments passed in via CONFIG_EXTERNAL_DTS_FRAGMENTS.
> > 
> > Other than that, what side effects are you afraid of?
> 
> I have an idea that someone relies on these *_dts macros.
> 
> Now I see (as you have noted above) that there is no macro users in mainline source tree:

Could you create a formal patch from this?

Sascha

-- 
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-5555 |


From michael.riesch at wolfvision.net  Mon Sep 19 02:50:41 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 11:50:41 +0200
Subject: [PATCH 0/2] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <20220919090135.GB6477@pengutronix.de>
References: <20220905145214.290551-1-michael.riesch@wolfvision.net>
 <20220919090135.GB6477@pengutronix.de>
Message-ID: <485704f1-fe73-53dd-10d4-7657e9e27b5a@wolfvision.net>

Hi Sascha,

On 9/19/22 11:01, Sascha Hauer wrote:
> On Mon, Sep 05, 2022 at 04:52:12PM +0200, Michael Riesch wrote:
>> Hi all,
>>
>> The IO domains on Rockchip SoCs need to be configured to the correct
>> bank voltage. In Linux this is achieved by means of a platform driver
>> that reads the voltage value of the supplies and configures the bits
>> in the general register file (GRF) accordingly.
>>
>> This series ports this driver to barebox to provide support for the
>> Rockchip RK356x SoCs. Please note that I could only test the changes
>> on RK3568 boards, so I left out the parts for the other SoCs supported
>> by the Linux driver. Also, it should be noted that the Linux driver
>> uses notifiers to react to voltage changes. This is not supported by
>> this barebox driver.
>>
>> WARNING: Use those patches with care as they have the potential to
>> fry up your board. That said, testers are very welcome ;-)
> 
> You are frightening me.

That was not my intention :-) In the mean time I have tested the driver
successfully on a RK3568 EVB1 and I plan to dig out my Quartz64.
However, I do not have a BananaPi R2 Pro and cannot test the patches there.

> I would apply this series, but given you warn about its usage I'm not
> sure what I should do with it. I could give it a test on the RK3568-EVB
> once it returned back in our remote lab, but I neither have a Pine64 nor
> a BananaPi R2 Pro.

I will submit a v2 of this series that features additional clean up
work. I'll try to keep the changes that affect the BananaPi R2 Pro
separate. They need Frank's approval, the rest can be applied IMHO.

Best regards,
Michael


From michael.riesch at wolfvision.net  Mon Sep 19 04:39:41 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:41 +0200
Subject: [PATCH v2 0/7] soc: rockchip: add driver for rockchip io domains
Message-ID: <20220919113948.991245-1-michael.riesch@wolfvision.net>

Hi all,

The IO domains in Rockchip SoCs need to be configured to match the
corresponding bank voltage. In Linux this is achieved by means of a
platform driver that reads the voltage value of the supplies and
configures the bits in the general register file (GRF) accordingly.

This series ports this driver to barebox to provide support for the
Rockchip RK356x SoCs. Please note that I could only test the changes
on RK3568 boards, so I left out the parts for the other SoCs supported
by the Linux driver. Also, it should be noted that the Linux driver
uses notifiers to react to voltage changes. This is not supported by
this barebox driver.

The driver has been tested on a Radxa ROCK3 Model A and a Rockchip
RK3568 EVB1. I do not have a BananaPi R2Pro and would therefore like
to ask someone with such a board a test.

The removal of the IO domain configuration in the low-level code allows
to refactor the low-level initialization to a common method rk3568_start.
This is introduced and used in patches 6 and 7.

Looking forward to your comments!

Best regards,
Michael

Changes since v1:
 - add defconfig
 - extend removal of IO domain configuration code
 - refactor initialization to rk3568_start()

Michael Riesch (7):
  soc: rockchip: add driver for rockchip io domains
  arm: rockchip_v8_defconfig: enable io domain driver
  arm: rockchip: radxa-rock3: remove io domain configuration
  arm: rockchip: rk3568-evb: remove io domain configuration
  arm: rockchip: rk3568-bpi-r2pro: remove io domain configuration
  arm: rockchip: rk3568: refactor common rk3568_start method
  arm: rockchip: rk3568-bpi-r2pro: use common method rk3568_start

 arch/arm/boards/pine64-quartz64/lowlevel.c    |  30 +--
 arch/arm/boards/radxa-rock3/lowlevel.c        |  33 ---
 .../rockchip-rk3568-bpi-r2pro/lowlevel.c      |  42 +---
 .../arm/boards/rockchip-rk3568-evb/lowlevel.c |  39 +--
 arch/arm/configs/rockchip_v8_defconfig        |   4 +
 .../arm/mach-rockchip/include/mach/rockchip.h |   1 +
 arch/arm/mach-rockchip/rk3568.c               |  24 ++
 drivers/soc/Kconfig                           |   1 +
 drivers/soc/Makefile                          |   1 +
 drivers/soc/rockchip/Kconfig                  |  17 ++
 drivers/soc/rockchip/Makefile                 |   6 +
 drivers/soc/rockchip/io-domain.c              | 223 ++++++++++++++++++
 12 files changed, 280 insertions(+), 141 deletions(-)
 create mode 100644 drivers/soc/rockchip/Kconfig
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/io-domain.c

-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep 19 04:39:43 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:43 +0200
Subject: [PATCH v2 2/7] arm: rockchip_v8_defconfig: enable io domain driver
In-Reply-To: <20220919113948.991245-1-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
Message-ID: <20220919113948.991245-3-michael.riesch@wolfvision.net>

The IO domain driver is required on RK356x boards to configure
the IO domains correctly. Enable this driver in the defconfig.
Since the corresponding voltages are usually supplied by the
RK80x companion PMIC, enable the RK808 driver as well.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm/configs/rockchip_v8_defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/configs/rockchip_v8_defconfig b/arch/arm/configs/rockchip_v8_defconfig
index 7fba31ddc3..d673f7f788 100644
--- a/arch/arm/configs/rockchip_v8_defconfig
+++ b/arch/arm/configs/rockchip_v8_defconfig
@@ -139,3 +139,7 @@ CONFIG_FS_FAT_LFN=y
 CONFIG_FS_BPKFS=y
 CONFIG_FS_UIMAGEFS=y
 CONFIG_LZO_DECOMPRESS=y
+CONFIG_I2C_RK3X=y
+CONFIG_MFD_RK808=y
+CONFIG_REGULATOR_RK808=y
+CONFIG_ROCKCHIP_IODOMAIN=y
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep 19 04:39:44 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:44 +0200
Subject: [PATCH v2 3/7] arm: rockchip: radxa-rock3: remove io domain configuration
In-Reply-To: <20220919113948.991245-1-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
Message-ID: <20220919113948.991245-4-michael.riesch@wolfvision.net>

Let the recently added Rockchip IO domain driver configure the IO
domains instead of setting the bits in rk3568_start().

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm/boards/radxa-rock3/lowlevel.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/arch/arm/boards/radxa-rock3/lowlevel.c b/arch/arm/boards/radxa-rock3/lowlevel.c
index 00a68889cd..5c2499362b 100644
--- a/arch/arm/boards/radxa-rock3/lowlevel.c
+++ b/arch/arm/boards/radxa-rock3/lowlevel.c
@@ -23,12 +23,6 @@ static noinline void rk3568_start(void *fdt)
 
 	setup_c();
 
-	/*
-	 * Enable vccio4 1.8V and vccio6 1.8V
-	 * Needed for GMAC to work.
-	 */
-	writel(RK_SETBITS(0x50), 0xfdc20140);
-
 	if (current_el() == 3) {
 		rk3568_lowlevel_init();
 		rk3568_atf_load_bl31(fdt);
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep 19 04:39:45 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:45 +0200
Subject: [PATCH v2 4/7] arm: rockchip: rk3568-evb: remove io domain configuration
In-Reply-To: <20220919113948.991245-1-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
Message-ID: <20220919113948.991245-5-michael.riesch@wolfvision.net>

Let the recently added Rockchip IO domain driver configure the IO
domains instead of setting the bits in rk3568_start().

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm/boards/rockchip-rk3568-evb/lowlevel.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
index 363639d21b..9c1c7be8a6 100644
--- a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
+++ b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
@@ -15,12 +15,6 @@ static noinline void rk3568_start(void)
 {
 	void *fdt;
 
-	/*
-	 * Enable vccio4 1.8V and vccio6 1.8V
-	 * Needed for GMAC to work.
-	 */
-	writel(RK_SETBITS(0x50), 0xfdc20140);
-
 	fdt = __dtb_rk3568_evb1_v10_start;
 
 	if (current_el() == 3) {
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep 19 04:39:42 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:42 +0200
Subject: [PATCH v2 1/7] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <20220919113948.991245-1-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
Message-ID: <20220919113948.991245-2-michael.riesch@wolfvision.net>

The IO domains in Rockchip SoCs need to be configured to match the
corresponding bank voltage. In Linux this is achieved by means of a
platform driver that reads the voltage value of the supplies and
configures the bits in the general register file (GRF) accordingly.
Port this driver to barebox to provide support for the Rockchip
RK356x SoCs.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 drivers/soc/Kconfig              |   1 +
 drivers/soc/Makefile             |   1 +
 drivers/soc/rockchip/Kconfig     |  17 +++
 drivers/soc/rockchip/Makefile    |   6 +
 drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
 5 files changed, 248 insertions(+)
 create mode 100644 drivers/soc/rockchip/Kconfig
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/io-domain.c

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 54b69cc42e..c0fe214429 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,5 +2,6 @@ menu "SoC drivers"
 
 source "drivers/soc/imx/Kconfig"
 source "drivers/soc/kvx/Kconfig"
+source "drivers/soc/rockchip/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index a23e81ffb3..9bff737b78 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,5 +2,6 @@
 
 obj-$(CONFIG_ARCH_IMX)		+= imx/
 obj-$(CONFIG_KVX)		+= kvx/
+obj-$(CONFIG_ARCH_ROCKCHIP)	+= rockchip/
 obj-$(CONFIG_CPU_SIFIVE)	+= sifive/
 obj-$(CONFIG_SOC_STARFIVE)	+= starfive/
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
new file mode 100644
index 0000000000..3484b37e22
--- /dev/null
+++ b/drivers/soc/rockchip/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_ROCKCHIP || COMPILE_TEST
+
+menu "Rockchip SoC drivers"
+
+config ROCKCHIP_IODOMAIN
+	tristate "Rockchip IO domain support"
+	depends on OFDEVICE
+	help
+	  Say y here to enable support io domains on Rockchip SoCs. It is
+	  necessary for the io domain setting of the SoC to match the
+	  voltage supplied by the regulators.
+
+endmenu
+
+endif
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 0000000000..104fad968e
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Rockchip Soc drivers
+#
+
+obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o
diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c
new file mode 100644
index 0000000000..ac5724c0e7
--- /dev/null
+++ b/drivers/soc/rockchip/io-domain.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Rockchip IO Voltage Domain driver
+ *
+ * Copyright 2014 MundoReader S.L.
+ * Copyright 2014 Google, Inc.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <linux/err.h>
+#include <mfd/syscon.h>
+#include <regmap.h>
+#include <regulator.h>
+
+#define MAX_SUPPLIES		16
+
+/*
+ * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
+ * "Recommended Operating Conditions" for "Digital GPIO".   When the typical
+ * is 3.3V the max is 3.6V.  When the typical is 1.8V the max is 1.98V.
+ *
+ * They are used like this:
+ * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
+ *   SoC we're at 3.3.
+ * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
+ *   that to be an error.
+ */
+#define MAX_VOLTAGE_1_8		1980000
+#define MAX_VOLTAGE_3_3		3600000
+
+#define RK3568_PMU_GRF_IO_VSEL0 (0x0140)
+#define RK3568_PMU_GRF_IO_VSEL1 (0x0144)
+#define RK3568_PMU_GRF_IO_VSEL2 (0x0148)
+
+struct rockchip_iodomain;
+
+struct rockchip_iodomain_supply {
+	struct rockchip_iodomain *iod;
+	struct regulator *reg;
+	int idx;
+};
+
+struct rockchip_iodomain_soc_data {
+	int grf_offset;
+	const char *supply_names[MAX_SUPPLIES];
+	void (*init)(struct rockchip_iodomain *iod);
+	int (*write)(struct rockchip_iodomain_supply *supply, int uV);
+};
+
+struct rockchip_iodomain {
+	struct device_d *dev;
+	struct regmap *grf;
+	const struct rockchip_iodomain_soc_data *soc_data;
+	struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
+	int (*write)(struct rockchip_iodomain_supply *supply, int uV);
+};
+
+static int rk3568_iodomain_write(struct rockchip_iodomain_supply *supply,
+				 int uV)
+{
+	struct rockchip_iodomain *iod = supply->iod;
+	u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
+	u32 val0, val1;
+	int b;
+
+	dev_dbg(iod->dev, "set domain %d to %d uV\n", supply->idx, uV);
+
+	switch (supply->idx) {
+	case 0: /* pmuio1 */
+		break;
+	case 1: /* pmuio2 */
+		b = supply->idx;
+		val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+		b = supply->idx + 4;
+		val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val0);
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL2, val1);
+		break;
+	case 3: /* vccio2 */
+		break;
+	case 2: /* vccio1 */
+	case 4: /* vccio3 */
+	case 5: /* vccio4 */
+	case 6: /* vccio5 */
+	case 7: /* vccio6 */
+	case 8: /* vccio7 */
+		b = supply->idx - 1;
+		val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
+		val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
+
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL0, val0);
+		regmap_write(iod->grf, RK3568_PMU_GRF_IO_VSEL1, val1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
+	.grf_offset = 0x140,
+	.supply_names = {
+		"pmuio1",
+		"pmuio2",
+		"vccio1",
+		"vccio2",
+		"vccio3",
+		"vccio4",
+		"vccio5",
+		"vccio6",
+		"vccio7",
+	},
+	.write = rk3568_iodomain_write,
+};
+
+static const struct of_device_id rockchip_iodomain_match[] = {
+	{ .compatible = "rockchip,rk3568-pmu-io-voltage-domain",
+	  .data = &soc_data_rk3568_pmu },
+	{ /* sentinel */ },
+};
+
+static int rockchip_iodomain_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node, *parent;
+	struct rockchip_iodomain *iod;
+	int i, ret = 0;
+
+	if (!np)
+		return -ENODEV;
+
+	iod = xzalloc(sizeof(*iod));
+	iod->dev = dev;
+	iod->soc_data = device_get_match_data(dev);
+
+	if (iod->soc_data->write)
+		iod->write = iod->soc_data->write;
+
+	parent = of_get_parent(np);
+	if (parent) {
+		iod->grf = syscon_node_to_regmap(parent);
+	} else {
+		dev_dbg(dev, "falling back to old binding\n");
+		iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	}
+
+	if (IS_ERR(iod->grf)) {
+		dev_err(dev, "couldn't find grf regmap\n");
+		return PTR_ERR(iod->grf);
+	}
+
+	for (i = 0; i < MAX_SUPPLIES; i++) {
+		const char *supply_name = iod->soc_data->supply_names[i];
+		struct rockchip_iodomain_supply *supply = &iod->supplies[i];
+		struct regulator *reg;
+		int uV;
+
+		if (!supply_name)
+			continue;
+
+		reg = regulator_get(dev, supply_name);
+		if (IS_ERR(reg)) {
+			ret = PTR_ERR(reg);
+
+			/* If a supply wasn't specified, that's OK */
+			if (ret == -ENODEV)
+				continue;
+			else if (ret != -EPROBE_DEFER)
+				dev_err(dev, "couldn't get regulator %s\n",
+					supply_name);
+			goto out;
+		}
+
+		/* set initial correct value */
+		uV = regulator_get_voltage(reg);
+
+		/* must be a regulator we can get the voltage of */
+		if (uV < 0) {
+			dev_err(dev, "Can't determine voltage: %s\n",
+				supply_name);
+			ret = uV;
+			goto out;
+		}
+
+		if (uV > MAX_VOLTAGE_3_3) {
+			dev_crit(dev, "%d uV is too high. May damage SoC!\n",
+				 uV);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* setup our supply */
+		supply->idx = i;
+		supply->iod = iod;
+		supply->reg = reg;
+
+		ret = iod->write(supply, uV);
+		if (ret) {
+			supply->reg = NULL;
+			goto out;
+		}
+	}
+
+	if (iod->soc_data->init)
+		iod->soc_data->init(iod);
+
+	ret = 0;
+out:
+	return ret;
+}
+
+static struct driver_d rockchip_iodomain_driver = {
+	.name = "rockchip-iodomain",
+	.probe = rockchip_iodomain_probe,
+	.of_compatible = rockchip_iodomain_match,
+};
+coredevice_platform_driver(rockchip_iodomain_driver);
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep 19 04:39:46 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:46 +0200
Subject: [PATCH v2 5/7] arm: rockchip: rk3568-bpi-r2pro: remove io domain configuration
In-Reply-To: <20220919113948.991245-1-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
Message-ID: <20220919113948.991245-6-michael.riesch@wolfvision.net>

Let the recently added Rockchip IO domain driver configure the IO
domains instead of setting the bits in rk3568_start().

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
index f79f975080..36f7acd7d0 100644
--- a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
+++ b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
@@ -15,15 +15,6 @@ static noinline void rk3568_start(void)
 {
 	void *fdt;
 
-	/*
-	 * set iodomain vccio6 to 1.8V needed for GMAC1 to work.
-	 * vccio4 (gmac0/switch) needs to stay at 3v3 (default)
-	 */
-	//set bit 6 in PMU_GRF_IO_VSEL0 for vccio6 1v8
-	writel(RK_SETBITS(BIT(6)), PMU_GRF_IO_VSEL0);
-	//clear bit 6 for 3v3 as it was set to 1v8
-	writel(RK_CLRBITS(BIT(6)), PMU_GRF_IO_VSEL1);
-
 	fdt = __dtb_rk3568_bpi_r2_pro_start;
 
 	if (current_el() == 3) {
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep 19 04:39:47 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:47 +0200
Subject: [PATCH v2 6/7] arm: rockchip: rk3568: refactor common rk3568_start method
In-Reply-To: <20220919113948.991245-1-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
Message-ID: <20220919113948.991245-7-michael.riesch@wolfvision.net>

After the removal of the IO domain configuration code, the low-level
initialization is the same for all RK356x boards. Add a common
method rk3568_start to remove this code duplication.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 arch/arm/boards/pine64-quartz64/lowlevel.c    | 30 +----------------
 arch/arm/boards/radxa-rock3/lowlevel.c        | 27 ---------------
 .../arm/boards/rockchip-rk3568-evb/lowlevel.c | 33 +------------------
 .../arm/mach-rockchip/include/mach/rockchip.h |  1 +
 arch/arm/mach-rockchip/rk3568.c               | 24 ++++++++++++++
 5 files changed, 27 insertions(+), 88 deletions(-)

diff --git a/arch/arm/boards/pine64-quartz64/lowlevel.c b/arch/arm/boards/pine64-quartz64/lowlevel.c
index b295885522..e1beb3e624 100644
--- a/arch/arm/boards/pine64-quartz64/lowlevel.c
+++ b/arch/arm/boards/pine64-quartz64/lowlevel.c
@@ -1,39 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <common.h>
-#include <linux/sizes.h>
-#include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
-#include <mach/hardware.h>
-#include <mach/atf.h>
-#include <debug_ll.h>
 #include <mach/rockchip.h>
 
 extern char __dtb_rk3566_quartz64_a_start[];
 
-static noinline void start_quartz64(void *fdt)
-{
-	/*
-	 * Image execution starts at 0x0, but this is used for ATF and
-	 * OP-TEE later, so move away from here.
-	 */
-	if (current_el() == 3)
-		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
-	else
-		relocate_to_current_adr();
-
-	setup_c();
-
-	if (current_el() == 3) {
-		rk3568_lowlevel_init();
-		rk3568_atf_load_bl31(fdt);
-		/* not reached */
-	}
-
-	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM,
-			  fdt);
-}
-
 ENTRY_FUNCTION(start_quartz64a, r0, r1, r2)
 {
-	start_quartz64(__dtb_rk3566_quartz64_a_start);
+	rk3568_start(__dtb_rk3566_quartz64_a_start);
 }
diff --git a/arch/arm/boards/radxa-rock3/lowlevel.c b/arch/arm/boards/radxa-rock3/lowlevel.c
index 5c2499362b..9875a3966b 100644
--- a/arch/arm/boards/radxa-rock3/lowlevel.c
+++ b/arch/arm/boards/radxa-rock3/lowlevel.c
@@ -1,37 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0-only
 #include <common.h>
-#include <linux/sizes.h>
-#include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
-#include <mach/hardware.h>
-#include <mach/atf.h>
-#include <debug_ll.h>
 #include <mach/rockchip.h>
 
 extern char __dtb_rk3568_rock_3a_start[];
 
-static noinline void rk3568_start(void *fdt)
-{
-	/*
-	 * Image execution starts at 0x0, but this is used for ATF and
-	 * OP-TEE later, so move away from here.
-	 */
-	if (current_el() == 3)
-		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
-	else
-		relocate_to_current_adr();
-
-	setup_c();
-
-	if (current_el() == 3) {
-		rk3568_lowlevel_init();
-		rk3568_atf_load_bl31(fdt);
-		/* not reached */
-	}
-
-	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM, fdt);
-}
-
 ENTRY_FUNCTION(start_rock3a, r0, r1, r2)
 {
 	rk3568_start(__dtb_rk3568_rock_3a_start);
diff --git a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
index 9c1c7be8a6..4954e9a3cc 100644
--- a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
+++ b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
@@ -1,43 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
 #include <common.h>
-#include <linux/sizes.h>
-#include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
-#include <mach/hardware.h>
-#include <mach/atf.h>
-#include <debug_ll.h>
 #include <mach/rockchip.h>
 
 extern char __dtb_rk3568_evb1_v10_start[];
 
-static noinline void rk3568_start(void)
-{
-	void *fdt;
-
-	fdt = __dtb_rk3568_evb1_v10_start;
-
-	if (current_el() == 3) {
-		rk3568_lowlevel_init();
-		rk3568_atf_load_bl31(fdt);
-		/* not reached */
-	}
-
-	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM, fdt);
-}
-
 ENTRY_FUNCTION(start_rk3568_evb, r0, r1, r2)
 {
-	/*
-	 * Image execution starts at 0x0, but this is used for ATF and
-	 * OP-TEE later, so move away from here.
-	 */
-	if (current_el() == 3)
-		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
-	else
-		relocate_to_current_adr();
-
-	setup_c();
-
-	rk3568_start();
+	rk3568_start(__dtb_rk3568_evb1_v10_start);
 }
diff --git a/arch/arm/mach-rockchip/include/mach/rockchip.h b/arch/arm/mach-rockchip/include/mach/rockchip.h
index ff8b1109f8..7b681c6ce3 100644
--- a/arch/arm/mach-rockchip/include/mach/rockchip.h
+++ b/arch/arm/mach-rockchip/include/mach/rockchip.h
@@ -34,5 +34,6 @@ static inline int rk3568_init(void)
 #endif
 
 void rk3568_lowlevel_init(void);
+void rk3568_start(void *fdt);
 
 #endif /* __MACH_ROCKCHIP_H */
diff --git a/arch/arm/mach-rockchip/rk3568.c b/arch/arm/mach-rockchip/rk3568.c
index 19dfa9b871..26bc4a06eb 100644
--- a/arch/arm/mach-rockchip/rk3568.c
+++ b/arch/arm/mach-rockchip/rk3568.c
@@ -2,8 +2,10 @@
 #include <common.h>
 #include <io.h>
 #include <bootsource.h>
+#include <mach/atf.h>
 #include <mach/rk3568-regs.h>
 #include <mach/rockchip.h>
+#include <asm/barebox-arm.h>
 
 #define GRF_BASE		0xfdc60000
 #define GRF_GPIO1B_DS_2		0x218
@@ -169,3 +171,25 @@ int rk3568_init(void)
 
 	return 0;
 }
+
+void rk3568_start(void *fdt)
+{
+	/*
+	 * Image execution starts at 0x0, but this is used for ATF and
+	 * OP-TEE later, so move away from here.
+	 */
+	if (current_el() == 3)
+		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
+	else
+		relocate_to_current_adr();
+
+	setup_c();
+
+	if (current_el() == 3) {
+		rk3568_lowlevel_init();
+		rk3568_atf_load_bl31(fdt);
+		/* not reached */
+	}
+
+	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM, fdt);
+}
-- 
2.30.2



From michael.riesch at wolfvision.net  Mon Sep 19 04:39:48 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 19 Sep 2022 13:39:48 +0200
Subject: [PATCH v2 7/7] arm: rockchip: rk3568-bpi-r2pro: use common method rk3568_start
In-Reply-To: <20220919113948.991245-1-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
Message-ID: <20220919113948.991245-8-michael.riesch@wolfvision.net>

After the removal of the IO domain configuration code, the common
low-level initialization  method rk3568_start can be used to remove
code duplication.

Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 .../rockchip-rk3568-bpi-r2pro/lowlevel.c      | 33 +------------------
 1 file changed, 1 insertion(+), 32 deletions(-)

diff --git a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
index 36f7acd7d0..8b04dccc1e 100644
--- a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
+++ b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
@@ -1,43 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
 #include <common.h>
-#include <linux/sizes.h>
-#include <asm/barebox-arm-head.h>
 #include <asm/barebox-arm.h>
-#include <mach/hardware.h>
-#include <mach/atf.h>
-#include <debug_ll.h>
 #include <mach/rockchip.h>
 
 extern char __dtb_rk3568_bpi_r2_pro_start[];
 
-static noinline void rk3568_start(void)
-{
-	void *fdt;
-
-	fdt = __dtb_rk3568_bpi_r2_pro_start;
-
-	if (current_el() == 3) {
-		rk3568_lowlevel_init();
-		rk3568_atf_load_bl31(fdt);
-		/* not reached */
-	}
-
-	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM, fdt);
-}
-
 ENTRY_FUNCTION(start_rk3568_bpi_r2pro, r0, r1, r2)
 {
-	/*
-	 * Image execution starts at 0x0, but this is used for ATF and
-	 * OP-TEE later, so move away from here.
-	 */
-	if (current_el() == 3)
-		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
-	else
-		relocate_to_current_adr();
-
-	setup_c();
-
-	rk3568_start();
+	rk3568_start(__dtb_rk3568_bpi_r2_pro_start);
 }
-- 
2.30.2



From enrico.scholz at sigma-chemnitz.de  Mon Sep 19 05:37:59 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Mon, 19 Sep 2022 14:37:59 +0200
Subject: malloc() alignment on 32 bit
Message-ID: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>

Hello,

on an iMX6ull I stumpled across

| zstd_decomp_init:536 workspace=8ff1a004+161320
| ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument

which is caused by

| static int zstd_decomp_init(void)
|	void *wksp = malloc(wksp_size);
| ...
| ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */


Trivial fix would be 'memalign(8, wksp_size)', but is it really ok that
malloc() for 32 bit has only an alignment of 4?

Relevant code seems to be in common/tlsf.c

| enum tlsf_private
| {
| #if defined (TLSF_64BIT)
| 	/* All allocation sizes and addresses are aligned to 8 bytes. */
| 	ALIGN_SIZE_LOG2 = 3,
| #else
| 	/* All allocation sizes and addresses are aligned to 4 bytes. */
| 	ALIGN_SIZE_LOG2 = 2,
| #endif

'ldrd/strd' require 8 byte alignment which might break with such
alignment.


Enrico


From a.fatoum at pengutronix.de  Mon Sep 19 06:33:59 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 19 Sep 2022 14:33:59 +0100
Subject: malloc() alignment on 32 bit
In-Reply-To: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <cacddc32-3b0f-7014-393c-8c93e5971627@pengutronix.de>

On 19.09.22 13:37, Enrico Scholz wrote:
> Hello,
> 
> on an iMX6ull I stumpled across
> 
> | zstd_decomp_init:536 workspace=8ff1a004+161320
> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
> 
> which is caused by
> 
> | static int zstd_decomp_init(void)
> |	void *wksp = malloc(wksp_size);
> | ...
> | ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
> |    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */
> 
> 
> Trivial fix would be 'memalign(8, wksp_size)', but is it really ok that
> malloc() for 32 bit has only an alignment of 4?
> 
> Relevant code seems to be in common/tlsf.c
> 
> | enum tlsf_private
> | {
> | #if defined (TLSF_64BIT)
> | 	/* All allocation sizes and addresses are aligned to 8 bytes. */
> | 	ALIGN_SIZE_LOG2 = 3,
> | #else
> | 	/* All allocation sizes and addresses are aligned to 4 bytes. */
> | 	ALIGN_SIZE_LOG2 = 2,
> | #endif
> 
> 'ldrd/strd' require 8 byte alignment which might break with such
> alignment.

I recently learnt too that on 32-bit TLSF only has 4 byte alignment.
I also think that this is too low. 8 byte alignment sounds good IMO.

Cheers,
Ahmad

> 
> 
> Enrico
> 
> 


-- 
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-5555 |


From sha at pengutronix.de  Mon Sep 19 06:57:51 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 19 Sep 2022 15:57:51 +0200
Subject: malloc() alignment on 32 bit
In-Reply-To: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <20220919135751.GD6477@pengutronix.de>

Hi Enrico,

On Mon, Sep 19, 2022 at 02:37:59PM +0200, Enrico Scholz wrote:
> Hello,
> 
> on an iMX6ull I stumpled across
> 
> | zstd_decomp_init:536 workspace=8ff1a004+161320
> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
> 
> which is caused by
> 
> | static int zstd_decomp_init(void)
> |	void *wksp = malloc(wksp_size);
> | ...
> | ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
> |    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */
> 
> 
> Trivial fix would be 'memalign(8, wksp_size)', but is it really ok that
> malloc() for 32 bit has only an alignment of 4?
> 
> Relevant code seems to be in common/tlsf.c
> 
> | enum tlsf_private
> | {
> | #if defined (TLSF_64BIT)
> | 	/* All allocation sizes and addresses are aligned to 8 bytes. */
> | 	ALIGN_SIZE_LOG2 = 3,
> | #else
> | 	/* All allocation sizes and addresses are aligned to 4 bytes. */
> | 	ALIGN_SIZE_LOG2 = 2,
> | #endif
> 
> 'ldrd/strd' require 8 byte alignment which might break with such
> alignment.

If you had asked me which alignment we have then I would have said it's
bigger. OTOH I never received any reports about insufficient alignment
on ARM or any other 32bit architecture.

I suspect we could just drop the check without any harm, but that's just
a gut feeling because we never had any alignment issues.

BTW are you sure ldrd/strd need 8 byte alignment? I just tested it with
the following patch and this works without problems. I verified the
compiler indeed generates ldrd/strd for accessing the 64bit field.

Sascha

-------------------------8<----------------------------

diff --git a/common/startup.c b/common/startup.c
index f53b73f81a..f261b1bdac 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -334,10 +334,31 @@ static void do_ctors(void)
 
 int (*barebox_main)(void);
 
+struct bar {
+	uint64_t foo;
+};
+
+struct bar *myfoo(void)
+{
+	struct bar *x;
+	void *ptr;
+
+	ptr = malloc(16);
+
+	ptr = (void *)((unsigned long)ptr | 4);
+
+	x = ptr;
+
+	x->foo = get_time_ns();
+
+	return x;
+}
+
 void __noreturn start_barebox(void)
 {
 	initcall_t *initcall;
 	int result;
+	struct bar *b;
 
 	if (!IS_ENABLED(CONFIG_SHELL_NONE) && IS_ENABLED(CONFIG_COMMAND_SUPPORT))
 		barebox_main = run_init;
@@ -355,6 +376,9 @@ void __noreturn start_barebox(void)
 
 	pr_debug("initcalls done\n");
 
+	b = myfoo();
+	printf("V: %lld\n", b->foo);
+
 	if (IS_ENABLED(CONFIG_SELFTEST_AUTORUN))
 		selftests_run();
 
-- 
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-5555 |


From enrico.scholz at sigma-chemnitz.de  Mon Sep 19 07:24:19 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Mon, 19 Sep 2022 16:24:19 +0200
Subject: malloc() alignment on 32 bit
In-Reply-To: <20220919135751.GD6477@pengutronix.de> (Sascha Hauer's message of
	"Mon, 19 Sep 2022 15:57:51 +0200")
References: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>
	<20220919135751.GD6477@pengutronix.de>
Message-ID: <ly35cn1lyk.fsf@ensc-pc.intern.sigma-chemnitz.de>

Sascha Hauer <sha at pengutronix.de> writes:

>> | zstd_decomp_init:536 workspace=8ff1a004+161320
>> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
>> 
> If you had asked me which alignment we have then I would have said it's
> bigger. OTOH I never received any reports about insufficient alignment
> on ARM or any other 32bit architecture.

The code which failed for me was added 3 months ago

| commit b4a9782d4f56333e897dccc35c2c27e2605f6b93
| Author: Ahmad Fatoum <a.fatoum at pengutronix.de>
| Date:   Wed Jul 13 12:09:18 2022 +0200
| 
|     lib: zstd: sync with Linux

and the Kconfig options (FS_UBIFS_COMPRESSION_ZSTD) are set to "off"...


> I suspect we could just drop the check without any harm, but that's just
> a gut feeling because we never had any alignment issues.
>
> BTW are you sure ldrd/strd need 8 byte alignment?

Their EX variants (LDREXD + STREXD; see [1]).  Unaligned access on
plain LDRD/STRD is allowed on ARMv7-A.  But not on ARMv7-M or ARMv6 and
earlier.




Enrico

Footnotes:
[1]  https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Application-Level-Memory-Model/Alignment-support/Unaligned-data-access


From trent.piepho at igorinstitute.com  Mon Sep 19 10:20:53 2022
From: trent.piepho at igorinstitute.com (Trent Piepho)
Date: Mon, 19 Sep 2022 10:20:53 -0700
Subject: [PATCH] net: Bring up all interfaces before going interactive
In-Reply-To: <20220916131606.GZ6477@pengutronix.de>
References: <20220916124942.3751131-1-s.hauer@pengutronix.de> <20220916131606.GZ6477@pengutronix.de>
Message-ID: <CAMHeXxOuxZnVcavXvwi1Y13kfRBP+opRgqwyEvSGBjQK6dSX1A@mail.gmail.com>

On Fri, Sep 16, 2022 at 6:16 AM Sascha Hauer <s.hauer at pengutronix.de> wrote:
>
> On Fri, Sep 16, 2022 at 02:49:42PM +0200, Sascha Hauer wrote:
> > So far we only bring up network interfaces when we actually need them.
> > This means we could be idling in the shell for long and once the user
> > decides to do networking he has to wait for the link to be established.
>
> We could make the user experience even a bit better by doing this call
> before waiting for the autoboot timeout which then speeds up netboot a
> bit.

The Linux phy driver almost invariably does not bother to avoid
resetting the network phy when not necessary.  So if network
auto-negotiation is started in barebox, it will be reset and then
restarted shortly after in Linux.  The link auto-negotiation impacts
the LAN's spanning tree if that is in use.

So there is a drawback, besides the small added boot time to
initialize the network hardware, to adding an unneeded network restart
in Barebox in the case where interactive mode is not entered and
network boot is not used.


From sha at pengutronix.de  Tue Sep 20 00:36:22 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 20 Sep 2022 09:36:22 +0200
Subject: malloc() alignment on 32 bit
In-Reply-To: <ly35cn1lyk.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>
 <20220919135751.GD6477@pengutronix.de>
 <ly35cn1lyk.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <20220920073622.GE6477@pengutronix.de>

On Mon, Sep 19, 2022 at 04:24:19PM +0200, Enrico Scholz wrote:
> Sascha Hauer <sha at pengutronix.de> writes:
> 
> >> | zstd_decomp_init:536 workspace=8ff1a004+161320
> >> | ERROR: initcall ubifs_init+0x1/0xc4 failed: Invalid argument
> >> 
> > If you had asked me which alignment we have then I would have said it's
> > bigger. OTOH I never received any reports about insufficient alignment
> > on ARM or any other 32bit architecture.
> 
> The code which failed for me was added 3 months ago
> 
> | commit b4a9782d4f56333e897dccc35c2c27e2605f6b93
> | Author: Ahmad Fatoum <a.fatoum at pengutronix.de>
> | Date:   Wed Jul 13 12:09:18 2022 +0200
> | 
> |     lib: zstd: sync with Linux
> 
> and the Kconfig options (FS_UBIFS_COMPRESSION_ZSTD) are set to "off"...

When I said I received no reports about insufficient malloc alignment I
meant reports about erroneous accesses, like wrong data read/writes or data
aborts.

> 
> 
> > I suspect we could just drop the check without any harm, but that's just
> > a gut feeling because we never had any alignment issues.
> >
> > BTW are you sure ldrd/strd need 8 byte alignment?
> 
> Their EX variants (LDREXD + STREXD; see [1]).  Unaligned access on
> plain LDRD/STRD is allowed on ARMv7-A.  But not on ARMv7-M or ARMv6 and
> earlier.

Ok, I found this for the LDRD instruction:

| Prior to ARMv6, if the memory address is not 64-bit aligned, the data read from memory is
| UNPREDICTABLE. Alignment checking (taking a data abort), and support for a big-endian
| (BE-32) data format are implementation options.

So it seems it's really a good idea to increase malloc alignment
accordingly.

Sascha

-- 
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-5555 |


From s.hauer at pengutronix.de  Tue Sep 20 00:41:20 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Tue, 20 Sep 2022 09:41:20 +0200
Subject: [PATCH] net: Bring up all interfaces before going interactive
In-Reply-To: <CAMHeXxOuxZnVcavXvwi1Y13kfRBP+opRgqwyEvSGBjQK6dSX1A@mail.gmail.com>
References: <20220916124942.3751131-1-s.hauer@pengutronix.de>
 <20220916131606.GZ6477@pengutronix.de>
 <CAMHeXxOuxZnVcavXvwi1Y13kfRBP+opRgqwyEvSGBjQK6dSX1A@mail.gmail.com>
Message-ID: <20220920074120.GF6477@pengutronix.de>

On Mon, Sep 19, 2022 at 10:20:53AM -0700, Trent Piepho wrote:
> On Fri, Sep 16, 2022 at 6:16 AM Sascha Hauer <s.hauer at pengutronix.de> wrote:
> >
> > On Fri, Sep 16, 2022 at 02:49:42PM +0200, Sascha Hauer wrote:
> > > So far we only bring up network interfaces when we actually need them.
> > > This means we could be idling in the shell for long and once the user
> > > decides to do networking he has to wait for the link to be established.
> >
> > We could make the user experience even a bit better by doing this call
> > before waiting for the autoboot timeout which then speeds up netboot a
> > bit.
> 
> The Linux phy driver almost invariably does not bother to avoid
> resetting the network phy when not necessary.  So if network
> auto-negotiation is started in barebox, it will be reset and then
> restarted shortly after in Linux.  The link auto-negotiation impacts
> the LAN's spanning tree if that is in use.
> 
> So there is a drawback, besides the small added boot time to
> initialize the network hardware, to adding an unneeded network restart
> in Barebox in the case where interactive mode is not entered and
> network boot is not used.

So is this a vote to only do the autonegotiaton when going interactive
in barebox, or a vote to do autonegotiation only when the network is
being used in barebox?

Sascha

-- 
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-5555 |


From m.felsch at pengutronix.de  Tue Sep 20 01:22:01 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 20 Sep 2022 10:22:01 +0200
Subject: [PATCH] net: Bring up all interfaces before going interactive
In-Reply-To: <20220916124942.3751131-1-s.hauer@pengutronix.de>
References: <20220916124942.3751131-1-s.hauer@pengutronix.de>
Message-ID: <20220920082201.ghopbp75jw3hcfsv@pengutronix.de>

Hi Sascha,

On 22-09-16, Sascha Hauer wrote:
> So far we only bring up network interfaces when we actually need them.
> This means we could be idling in the shell for long and once the user
> decides to do networking he has to wait for the link to be established.
> We can do better: Before going interactive bring up all known network
> interfaces which makes the links established when the user needs them.

can we do that conditional e.g. by using a globalvar? Since this can
cause regression e.g. if your use-case is to boot as fast as possible.

Regards,
  Marco


From trent.piepho at igorinstitute.com  Tue Sep 20 02:47:07 2022
From: trent.piepho at igorinstitute.com (Trent Piepho)
Date: Tue, 20 Sep 2022 02:47:07 -0700
Subject: [PATCH] net: Bring up all interfaces before going interactive
In-Reply-To: <20220920074120.GF6477@pengutronix.de>
References: <20220916124942.3751131-1-s.hauer@pengutronix.de>
 <20220916131606.GZ6477@pengutronix.de> <CAMHeXxOuxZnVcavXvwi1Y13kfRBP+opRgqwyEvSGBjQK6dSX1A@mail.gmail.com>
 <20220920074120.GF6477@pengutronix.de>
Message-ID: <CAMHeXxPJoHO6_eL9sf-_Fu+oqJQv278f9D8RifBkG2YV_yYYmw@mail.gmail.com>

On Tue, Sep 20, 2022 at 12:41 AM Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Mon, Sep 19, 2022 at 10:20:53AM -0700, Trent Piepho wrote:
> > On Fri, Sep 16, 2022 at 6:16 AM Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > >
> > > We could make the user experience even a bit better by doing this call
> > > before waiting for the autoboot timeout which then speeds up netboot a
> > > bit.
> >
> > The Linux phy driver almost invariably does not bother to avoid
> > resetting the network phy when not necessary.  So if network
> > auto-negotiation is started in barebox, it will be reset and then
> > restarted shortly after in Linux.  The link auto-negotiation impacts
> > the LAN's spanning tree if that is in use.
> >
> > So there is a drawback, besides the small added boot time to
> > initialize the network hardware, to adding an unneeded network restart
> > in Barebox in the case where interactive mode is not entered and
> > network boot is not used.
>
> So is this a vote to only do the autonegotiaton when going interactive
> in barebox, or a vote to do autonegotiation only when the network is
> being used in barebox?

I would vote to only do it when going interactive.

It also seems reasonable to bring the network up quickly when network
booting, but I think determining if the system will network boot,
before actually trying to boot, is probably unreasonably difficult to
do.


From o.rempel at pengutronix.de  Tue Sep 20 05:55:31 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Tue, 20 Sep 2022 14:55:31 +0200
Subject: [PATCH v1 1/3] net: port support for microchip SMI0 MDIO bus
Message-ID: <20220920125533.2497108-1-o.rempel@pengutronix.de>

SMI0 is a mangled version of MDIO. The main low level difference is
the MDIO C22 OP code is always 0, not 0x2 or 0x1 for Read/Write. The
read/write information is instead encoded in the PHY address.

Extend the bit-bang code to allow the op code to be overridden, but
default to normal C22 values. Add an extra compatible to the mdio-gpio
driver, and when this compatible is present, set the op codes to 0.

A higher level driver, sitting on top of the basic MDIO bus driver can
then implement the rest of the microchip SMI0 odderties.

This code was ported from the kernel v6.0-rc2.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 drivers/net/phy/mdio-bitbang.c | 8 ++++++--
 drivers/net/phy/mdio-gpio.c    | 8 ++++++++
 include/linux/mdio-bitbang.h   | 3 +++
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index 839a7d1eb8..656557589d 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -158,7 +158,7 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
 		mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
 	} else
-		mdiobb_cmd(ctrl, MDIO_READ, phy, reg);
+		mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg);
 
 	ctrl->ops->set_mdio_dir(ctrl, 0);
 
@@ -188,7 +188,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
 		reg = mdiobb_cmd_addr(ctrl, phy, reg);
 		mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
 	} else
-		mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg);
+		mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg);
 
 	/* send the turnaround (10) */
 	mdiobb_send_bit(ctrl, 1);
@@ -219,6 +219,10 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
 	bus->write = mdiobb_write;
 	bus->reset = mdiobb_reset;
 	bus->priv = ctrl;
+	if (!ctrl->override_op_c22) {
+		ctrl->op_c22_read = MDIO_READ;
+		ctrl->op_c22_write = MDIO_WRITE;
+	}
 
 	return bus;
 }
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 80d2394f4b..c64f2b3925 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -193,6 +193,13 @@ static int mdio_gpio_probe(struct device_d *dev)
 		goto free_mdo;
 	}
 
+	if (np &&
+	    of_device_is_compatible(np, "microchip,mdio-smi0")) {
+		info->ctrl.op_c22_read = 0;
+		info->ctrl.op_c22_write = 0;
+		info->ctrl.override_op_c22 = 1;
+	}
+
 	bus = alloc_mdio_bitbang(&info->ctrl);
 	bus->parent = dev;
 	bus->dev.device_node = np;
@@ -217,6 +224,7 @@ free_info:
 
 static const struct of_device_id gpio_mdio_dt_ids[] = {
 	{ .compatible = "virtual,mdio-gpio", },
+	{ .compatible = "microchip,mdio-smi0" },
 	{ /* sentinel */ }
 };
 
diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h
index a6e6057886..49fe435429 100644
--- a/include/linux/mdio-bitbang.h
+++ b/include/linux/mdio-bitbang.h
@@ -36,6 +36,9 @@ struct mdiobb_ctrl {
 	const struct mdiobb_ops *ops;
 	/* reset callback */
 	int (*reset)(struct mii_bus *bus);
+	unsigned int override_op_c22;
+	u8 op_c22_read;
+	u8 op_c22_write;
 };
 
 /* The returned bus is not yet registered with the phy layer. */
-- 
2.30.2



From o.rempel at pengutronix.de  Tue Sep 20 05:55:32 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Tue, 20 Sep 2022 14:55:32 +0200
Subject: [PATCH v1 2/3] net: add support for MDIO devices
In-Reply-To: <20220920125533.2497108-1-o.rempel@pengutronix.de>
References: <20220920125533.2497108-1-o.rempel@pengutronix.de>
Message-ID: <20220920125533.2497108-2-o.rempel@pengutronix.de>

On the MDIO bus we can have PHYs and some other type of devices.
Typical not_PHY MDIO devices do not have easy detectable ID and can't be
used as-is by the PHY framework. So, add additional handler to register
MDIO devices and drivers alongside with the PHY devices/drivers.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 drivers/net/phy/mdio_bus.c | 101 ++++++++++++++++++++++++++++++-------
 drivers/net/phy/phy.c      |   2 +
 include/linux/mdio.h       |  14 +++++
 include/linux/phy.h        |   1 +
 4 files changed, 101 insertions(+), 17 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index e37ab79f3e..f06ab68f50 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -19,6 +19,7 @@
 #include <clock.h>
 #include <net.h>
 #include <errno.h>
+#include <linux/mdio.h>
 #include <linux/phy.h>
 #include <linux/err.h>
 #include <of_device.h>
@@ -29,6 +30,56 @@
 
 LIST_HEAD(mii_bus_list);
 
+static struct phy_device *mdio_device_create(struct mii_bus *bus, int addr)
+{
+	struct phy_device *phydev;
+
+	phydev = xzalloc(sizeof(*phydev));
+
+	phydev->addr = addr;
+	phydev->bus = bus;
+	phydev->dev.bus = &mdio_bus_type;
+
+	dev_set_name(&phydev->dev, "mdio%d-dev%02x", phydev->bus->dev.id,
+		     phydev->addr);
+	phydev->dev.id = DEVICE_ID_SINGLE;
+
+	return phydev;
+}
+
+static int mdio_register_device(struct phy_device *phydev)
+{
+	int ret;
+
+	if (phydev->registered)
+		return -EBUSY;
+
+	if (!phydev->dev.parent)
+		phydev->dev.parent = &phydev->bus->dev;
+
+	ret = register_device(&phydev->dev);
+	if (ret)
+		return ret;
+
+	if (phydev->bus)
+		phydev->bus->phy_map[phydev->addr] = phydev;
+
+	phydev->registered = 1;
+
+	if (phydev->dev.driver)
+		return 0;
+
+	return ret;
+}
+
+int mdio_driver_register(struct phy_driver *phydrv)
+{
+	phydrv->drv.bus = &mdio_bus_type;
+	phydrv->is_phy = false;
+
+	return register_driver(&phydrv->drv);
+}
+
 int mdiobus_detect(struct device_d *dev)
 {
 	struct mii_bus *mii = to_mii_bus(dev);
@@ -84,6 +135,28 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
 	return 0;
 }
 
+static int of_mdiobus_register_device(struct mii_bus *mdio,
+				      struct device_node *child, u32 addr)
+{
+	struct phy_device *mdiodev;
+	int ret;
+
+	mdiodev = mdio_device_create(mdio, addr);
+	if (IS_ERR(mdiodev))
+		return PTR_ERR(mdiodev);
+
+	mdiodev->dev.device_node = child;
+
+	ret = mdio_register_device(mdiodev);
+	if (ret)
+		return ret;
+
+	dev_dbg(&mdio->dev, "registered mdio device %s at address %i\n",
+		child->name, addr);
+
+	return 0;
+}
+
 /*
  * Node is considered a PHY node if:
  * o Compatible string of "ethernet-phy-idX.X"
@@ -176,20 +249,6 @@ static int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 
 	/* Loop over the child nodes and register a phy_device for each one */
 	for_each_available_child_of_node(np, child) {
-		if (!of_mdiobus_child_is_phy(child)) {
-			if (of_get_property(child, "compatible", NULL)) {
-				if (!of_platform_device_create(child,
-							       &mdio->dev)) {
-					dev_err(&mdio->dev,
-						"Failed to create device "
-						"for %s\n",
-						child->full_name);
-				}
-			}
-
-			continue;
-		}
-
 		ret = of_property_read_u32(child, "reg", &addr);
 		if (ret) {
 			dev_dbg(&mdio->dev, "%s has invalid PHY address\n",
@@ -205,7 +264,11 @@ static int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 
 		of_pinctrl_select_state_default(child);
 		of_mdiobus_reset_phy(mdio, child);
-		of_mdiobus_register_phy(mdio, child, addr);
+
+		if (of_mdiobus_child_is_phy(child))
+			of_mdiobus_register_phy(mdio, child, addr);
+		else
+			of_mdiobus_register_device(mdio, child, addr);
 	}
 
 	return 0;
@@ -356,9 +419,13 @@ static int mdio_bus_match(struct device_d *dev, struct driver_d *drv)
 	struct phy_device *phydev = to_phy_device(dev);
 	struct phy_driver *phydrv = to_phy_driver(drv);
 
-	if ((phydrv->phy_id & phydrv->phy_id_mask) ==
-	    (phydev->phy_id & phydrv->phy_id_mask))
+	if (phydrv->is_phy) {
+		if ((phydrv->phy_id & phydrv->phy_id_mask) ==
+		    (phydev->phy_id & phydrv->phy_id_mask))
 		return 0;
+	} else {
+		return device_match(dev, drv);
+	}
 
 	return 1;
 }
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 60b5839b40..56ec8a28df 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -933,6 +933,8 @@ int phy_driver_register(struct phy_driver *phydrv)
 {
 	phydrv->drv.bus = &mdio_bus_type;
 
+	phydrv->is_phy = true;
+
 	if (!phydrv->config_init)
 		phydrv->config_init = genphy_config_init;
 
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index b910b05cec..a4aee49d8d 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -326,4 +326,18 @@ static inline __u16 mdio_phy_id_c45(int prtad, int devad)
 
 #define MDIO_DEVAD_NONE			(-1)
 
+struct phy_driver;
+
+int mdio_driver_register(struct phy_driver *drv);
+
+#define mdio_register_driver_macro(level, drv)		\
+        static int __init drv##_register(void)		\
+        {						\
+                return mdio_driver_register(&drv);	\
+        }						\
+        level##_initcall(drv##_register)
+
+#define device_mdio_driver(drv)	\
+        mdio_register_driver_macro(device, drv)
+
 #endif /* _UAPI__LINUX_MDIO_H__ */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index a4c3f43c06..ba1740ff55 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -223,6 +223,7 @@ struct phy_driver {
 	unsigned int phy_id_mask;
 	u32 features;
 	const void *driver_data;
+	bool is_phy;
 
 	/*
 	 * Called to initialize the PHY,
-- 
2.30.2



From o.rempel at pengutronix.de  Tue Sep 20 05:55:33 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Tue, 20 Sep 2022 14:55:33 +0200
Subject: [PATCH v1 3/3] net: add ksz8873 switch support
In-Reply-To: <20220920125533.2497108-1-o.rempel@pengutronix.de>
References: <20220920125533.2497108-1-o.rempel@pengutronix.de>
Message-ID: <20220920125533.2497108-3-o.rempel@pengutronix.de>

Add minimal DSA driver for the KSZ8873 switches

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 drivers/net/Kconfig   |   6 +
 drivers/net/Makefile  |   1 +
 drivers/net/ksz8873.c | 424 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 431 insertions(+)
 create mode 100644 drivers/net/ksz8873.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 84a01c5328..2dafd9c7a8 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -300,6 +300,12 @@ menuconfig DSA
 
 if DSA
 
+config DRIVER_NET_KSZ8873
+	bool "KSZ8873 switch driver"
+	help
+	  This option enables support for the Microchip KSZ8873
+	  switch chip.
+
 config DRIVER_NET_KSZ9477
 	bool "KSZ9477 switch driver"
 	depends on SPI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 47ad749943..7ff330a2bf 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_DRIVER_NET_FEC_IMX)	+= fec_imx.o
 obj-$(CONFIG_DRIVER_NET_FSL_FMAN)	+= fsl-fman.o
 obj-$(CONFIG_DRIVER_NET_GIANFAR)	+= gianfar.o
 obj-$(CONFIG_DRIVER_NET_KS8851_MLL)	+= ks8851_mll.o
+obj-$(CONFIG_DRIVER_NET_KSZ8873)	+= ksz8873.o
 obj-$(CONFIG_DRIVER_NET_KSZ9477)	+= ksz9477.o
 obj-$(CONFIG_DRIVER_NET_MACB)		+= macb.o
 obj-$(CONFIG_DRIVER_NET_MICREL)		+= ksz8864rmn.o
diff --git a/drivers/net/ksz8873.c b/drivers/net/ksz8873.c
new file mode 100644
index 0000000000..bd8071b872
--- /dev/null
+++ b/drivers/net/ksz8873.c
@@ -0,0 +1,424 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <common.h>
+#include <complete.h>
+#include <dsa.h>
+#include <gpiod.h>
+#include <linux/mii.h>
+#include <linux/mdio.h>
+#include <net.h>
+#include <of_device.h>
+#include <regmap.h>
+
+#define KSZ8873_GLOBAL_CTRL_1		0x03
+#define KSZ8873_PASS_ALL_FRAMES		BIT(7)
+#define KSZ8873_P3_TAIL_TAG_EN		BIT(6)
+
+/*
+ * port specific registers. Should be used with ksz_pwrite/ksz_pread functions
+ */
+#define KSZ8873_PORTx_CTRL_1		0x01
+#define KSZ8873_PORTx_CTRL_12		0x0c
+
+#define PORT_AUTO_NEG_ENABLE		BIT(7)
+#define PORT_FORCE_100_MBIT		BIT(6)
+#define PORT_FORCE_FULL_DUPLEX		BIT(5)
+#define PORT_AUTO_NEG_100BTX_FD		BIT(3)
+#define PORT_AUTO_NEG_100BTX		BIT(2)
+#define PORT_AUTO_NEG_10BT_FD		BIT(1)
+#define PORT_AUTO_NEG_10BT		BIT(0)
+
+#define KSZ8873_PORTx_CTRL_13		0x0d
+
+#define PORT_AUTO_NEG_RESTART		BIT(5)
+#define PORT_POWER_DOWN			BIT(3)
+
+#define KSZ8873_PORTx_STATUS_0		0x0e
+
+#define PORT_AUTO_NEG_COMPLETE		BIT(6)
+#define PORT_STAT_LINK_GOOD		BIT(5)
+#define PORT_REMOTE_100BTX_FD		BIT(3)
+#define PORT_REMOTE_100BTX		BIT(2)
+#define PORT_REMOTE_10BT_FD		BIT(1)
+#define PORT_REMOTE_10BT		BIT(0)
+
+#define KSZ8873_PORTx_STATUS_1		0x0f
+
+#define KSZ8795_ID_HI			0x0022
+#define KSZ8863_ID_LO			0x1430
+
+#define PORT_CTRL_ADDR(port, addr)	((addr) + 0x10 + (port) * 0x10)
+
+struct ksz8873_dcfg {
+	unsigned int num_ports;
+	unsigned int phy_port_cnt;
+};
+
+struct ksz8873_switch {
+	struct phy_device *mdiodev;
+	struct dsa_switch ds;
+	struct device_d *dev;
+	const struct ksz8873_dcfg *dcfg;
+	struct regmap *regmap;
+};
+
+/* Serial Management Interface (SMI) uses the following frame format:
+ *
+ *       preamble|start|Read/Write|  PHY   |  REG  |TA|   Data bits      | Idle
+ *               |frame| OP code  |address |address|  |                  |
+ * read | 32x1?s | 01  |    00    | 1xRRR  | RRRRR |Z0| 00000000DDDDDDDD |  Z
+ * write| 32x1?s | 01  |    00    | 0xRRR  | RRRRR |10| xxxxxxxxDDDDDDDD |  Z
+ *
+ */
+
+#define SMI_KSZ88XX_READ_PHY	BIT(4)
+
+static int ksz8873_mdio_read(void *ctx, unsigned int reg, unsigned int *val)
+{
+	struct ksz8873_switch *priv = ctx;
+	struct phy_device *mdiodev = priv->mdiodev;
+	int ret;
+
+	ret = mdiobus_read(mdiodev->bus, ((reg & 0xE0) >> 5) |
+			     SMI_KSZ88XX_READ_PHY, reg);
+	if (ret < 0)
+		return ret;
+
+	*val = ret;
+
+	return 0;
+}
+
+static ssize_t ksz8873_mdio_write(void *ctx, unsigned int reg, unsigned int val)
+{
+	struct ksz8873_switch *priv = ctx;
+	struct phy_device *mdiodev = priv->mdiodev;
+
+	return mdiobus_write(mdiodev->bus, ((reg & 0xE0) >> 5), reg, val);
+}
+
+static const struct regmap_bus ksz8873_regmap_smi = {
+	.reg_read = ksz8873_mdio_read,
+	.reg_write = ksz8873_mdio_write,
+};
+
+static const struct regmap_config ksz8873_regmap_config = {
+	.name = "#8",
+	.reg_bits = 8,
+	.pad_bits = 24,
+	.val_bits = 8,
+};
+
+static int ksz_read8(struct ksz8873_switch *priv, u32 reg, u8 *val)
+{
+	unsigned int value;
+	int ret = regmap_read(priv->regmap, reg, &value);
+
+	*val = value & 0xff;
+
+	return ret;
+}
+
+static int ksz_write8(struct ksz8873_switch *priv, u32 reg, u8 value)
+{
+	return regmap_write(priv->regmap, reg, value);
+}
+
+static int ksz_pread8(struct ksz8873_switch *priv, int port, int reg, u8 *val)
+{
+	return ksz_read8(priv, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static int ksz_pwrite8(struct ksz8873_switch *priv, int port, int reg, u8 val)
+{
+	return ksz_write8(priv, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static void ksz8_r_phy(struct ksz8873_switch *priv, u16 phy, u16 reg, u16 *val)
+{
+	u8 restart, ctrl, link;
+	int processed = true;
+	u16 data = 0;
+	u8 p = phy;
+
+	switch (reg) {
+	case MII_BMCR:
+		ksz_pread8(priv, p, KSZ8873_PORTx_CTRL_13, &restart);
+		ksz_pread8(priv, p, KSZ8873_PORTx_CTRL_12, &ctrl);
+		if (ctrl & PORT_FORCE_100_MBIT)
+			data |= BMCR_SPEED100;
+		if ((ctrl & PORT_AUTO_NEG_ENABLE))
+			data |= BMCR_ANENABLE;
+		if (restart & PORT_POWER_DOWN)
+			data |= BMCR_PDOWN;
+		if (restart & PORT_AUTO_NEG_RESTART)
+			data |= BMCR_ANRESTART;
+		if (ctrl & PORT_FORCE_FULL_DUPLEX)
+			data |= BMCR_FULLDPLX;
+		break;
+	case MII_BMSR:
+		ksz_pread8(priv, p, KSZ8873_PORTx_STATUS_0, &link);
+		data = BMSR_100FULL |
+		       BMSR_100HALF |
+		       BMSR_10FULL |
+		       BMSR_10HALF |
+		       BMSR_ANEGCAPABLE;
+		if (link & PORT_AUTO_NEG_COMPLETE)
+			data |= BMSR_ANEGCOMPLETE;
+		if (link & PORT_STAT_LINK_GOOD)
+			data |= BMSR_LSTATUS;
+		break;
+	case MII_PHYSID1:
+		data = KSZ8795_ID_HI;
+		break;
+	case MII_PHYSID2:
+		data = KSZ8863_ID_LO;
+		break;
+	case MII_ADVERTISE:
+		ksz_pread8(priv, p, KSZ8873_PORTx_CTRL_12, &ctrl);
+		data = ADVERTISE_CSMA;
+		if (ctrl & PORT_AUTO_NEG_100BTX_FD)
+			data |= ADVERTISE_100FULL;
+		if (ctrl & PORT_AUTO_NEG_100BTX)
+			data |= ADVERTISE_100HALF;
+		if (ctrl & PORT_AUTO_NEG_10BT_FD)
+			data |= ADVERTISE_10FULL;
+		if (ctrl & PORT_AUTO_NEG_10BT)
+			data |= ADVERTISE_10HALF;
+		break;
+	case MII_LPA:
+		ksz_pread8(priv, p, KSZ8873_PORTx_STATUS_0, &link);
+		data = LPA_SLCT;
+		if (link & PORT_REMOTE_100BTX_FD)
+			data |= LPA_100FULL;
+		if (link & PORT_REMOTE_100BTX)
+			data |= LPA_100HALF;
+		if (link & PORT_REMOTE_10BT_FD)
+			data |= LPA_10FULL;
+		if (link & PORT_REMOTE_10BT)
+			data |= LPA_10HALF;
+		if (data & ~LPA_SLCT)
+			data |= LPA_LPACK;
+		break;
+	default:
+		processed = false;
+		break;
+	}
+	if (processed)
+		*val = data;
+}
+
+static void ksz8_w_phy(struct ksz8873_switch *priv, u16 phy, u16 reg, u16 val)
+{
+	u8 restart, ctrl, data;
+	u8 p = phy;
+
+	switch (reg) {
+	case MII_BMCR:
+		ksz_pread8(priv, p, KSZ8873_PORTx_CTRL_12, &ctrl);
+		data = ctrl;
+		if ((val & BMCR_ANENABLE))
+			data |= PORT_AUTO_NEG_ENABLE;
+		else
+			data &= ~PORT_AUTO_NEG_ENABLE;
+
+		if (val & BMCR_SPEED100)
+			data |= PORT_FORCE_100_MBIT;
+		else
+			data &= ~PORT_FORCE_100_MBIT;
+		if (val & BMCR_FULLDPLX)
+			data |= PORT_FORCE_FULL_DUPLEX;
+		else
+			data &= ~PORT_FORCE_FULL_DUPLEX;
+		if (data != ctrl)
+			ksz_pwrite8(priv, p, KSZ8873_PORTx_CTRL_12, data);
+		ksz_pread8(priv, p, KSZ8873_PORTx_CTRL_13, &restart);
+		data = restart;
+		if (val & BMCR_ANRESTART)
+			data |= PORT_AUTO_NEG_RESTART;
+		else
+			data &= ~(PORT_AUTO_NEG_RESTART);
+		if (val & BMCR_PDOWN)
+			data |= PORT_POWER_DOWN;
+		else
+			data &= ~PORT_POWER_DOWN;
+		if (data != restart)
+			ksz_pwrite8(priv, p, KSZ8873_PORTx_CTRL_13, data);
+		break;
+	case MII_ADVERTISE:
+		ksz_pread8(priv, p, KSZ8873_PORTx_CTRL_12, &ctrl);
+		data = ctrl;
+		data &= ~(PORT_AUTO_NEG_100BTX_FD |
+			  PORT_AUTO_NEG_100BTX |
+			  PORT_AUTO_NEG_10BT_FD |
+			  PORT_AUTO_NEG_10BT);
+		if (val & ADVERTISE_100FULL)
+			data |= PORT_AUTO_NEG_100BTX_FD;
+		if (val & ADVERTISE_100HALF)
+			data |= PORT_AUTO_NEG_100BTX;
+		if (val & ADVERTISE_10FULL)
+			data |= PORT_AUTO_NEG_10BT_FD;
+		if (val & ADVERTISE_10HALF)
+			data |= PORT_AUTO_NEG_10BT;
+		if (data != ctrl)
+			ksz_pwrite8(priv, p, KSZ8873_PORTx_CTRL_12, data);
+		break;
+	default:
+		break;
+	}
+}
+
+static int ksz8873_phy_read16(struct dsa_switch *ds, int addr, int reg)
+{
+	struct device_d *dev = ds->dev;
+	struct ksz8873_switch *priv = dev_get_priv(dev);
+	u16 val = 0xffff;
+
+	if (addr >= priv->dcfg->phy_port_cnt)
+		return val;
+
+	ksz8_r_phy(priv, addr, reg, &val);
+
+	return val;
+}
+
+static int ksz8873_phy_write16(struct dsa_switch *ds, int addr, int reg,
+			       u16 val)
+{
+	struct device_d *dev = ds->dev;
+	struct ksz8873_switch *priv = dev_get_priv(dev);
+
+	/* No real PHY after this. */
+	if (addr >= priv->dcfg->phy_port_cnt)
+		return 0;
+
+	ksz8_w_phy(priv, addr, reg, val);
+
+	return 0;
+}
+
+static void ksz8873_cfg_port_member(struct ksz8873_switch *priv, int port,
+				    u8 member)
+{
+	ksz_pwrite8(priv, port, KSZ8873_PORTx_CTRL_1, member);
+}
+
+static int ksz8873_port_enable(struct dsa_port *dp, int port,
+			   struct phy_device *phy)
+{
+	return 0;
+}
+
+static int ksz8873_xmit(struct dsa_port *dp, int port, void *packet, int length)
+{
+	u8 *tag = packet + length - dp->ds->needed_tx_tailroom;
+
+	*tag = BIT(dp->index);
+
+	return 0;
+}
+
+static int ksz8873_recv(struct dsa_switch *ds, int *port, void *packet,
+			int length)
+{
+	u8 *tag = packet + length - ds->needed_rx_tailroom;
+
+	*port = *tag & 7;
+
+	return 0;
+};
+
+static const struct dsa_ops ksz8873_dsa_ops = {
+	.port_enable = ksz8873_port_enable,
+	.xmit = ksz8873_xmit,
+	.rcv = ksz8873_recv,
+	.phy_read = ksz8873_phy_read16,
+	.phy_write = ksz8873_phy_write16,
+};
+
+static int ksz8873_default_setup(struct ksz8873_switch *priv)
+{
+	int i;
+
+	ksz_write8(priv, KSZ8873_GLOBAL_CTRL_1, KSZ8873_PASS_ALL_FRAMES |
+		   KSZ8873_P3_TAIL_TAG_EN);
+
+	for (i = 0; i < priv->ds.num_ports; i++) {
+		u8 member;
+		/* isolate all ports by default */
+		member = BIT(priv->ds.cpu_port);
+		ksz8873_cfg_port_member(priv, i, member);
+
+		member = dsa_user_ports(&priv->ds);
+		ksz8873_cfg_port_member(priv, priv->ds.cpu_port, member);
+	}
+
+	return 0;
+}
+
+static int ksz8873_probe_mdio(struct phy_device *mdiodev)
+{
+	struct device_d *dev = &mdiodev->dev;
+	const struct ksz8873_dcfg *dcfg;
+	struct ksz8873_switch *priv;
+	struct dsa_switch *ds;
+	int ret, gpio;
+
+	priv = xzalloc(sizeof(*priv));
+
+	dcfg = of_device_get_match_data(dev);
+	if (!dcfg)
+		return -EINVAL;
+
+	dev->priv = priv;
+	priv->dev = dev;
+	priv->dcfg = dcfg;
+	priv->mdiodev = mdiodev;
+
+	priv->regmap = regmap_init(dev, &ksz8873_regmap_smi, priv,
+				   &ksz8873_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return dev_err_probe(dev, PTR_ERR(priv->regmap),
+				     "Failed to initialize regmap.\n");
+
+	gpio = gpiod_get(dev, "reset", GPIOF_OUT_INIT_ACTIVE);
+	if (gpio_is_valid(gpio)) {
+		mdelay(1);
+		gpio_set_active(gpio, false);
+	}
+
+	ds = &priv->ds;
+	ds->dev = dev;
+	ds->num_ports = dcfg->num_ports;
+	ds->ops = &ksz8873_dsa_ops;
+	ds->needed_rx_tailroom = 1;
+	ds->needed_tx_tailroom = 1;
+	ds->phys_mii_mask = 0x3;
+
+	ret = dsa_register_switch(ds);
+	if (ret)
+		return ret;
+
+	ksz8873_default_setup(priv);
+
+	return 0;
+}
+
+static const struct ksz8873_dcfg ksz8873_dcfg = {
+	.num_ports = 3,
+	.phy_port_cnt = 2,
+};
+
+static const struct of_device_id ksz8873_dt_ids[] = {
+	{ .compatible = "microchip,ksz8873", .data = &ksz8873_dcfg },
+	{ }
+};
+
+static struct phy_driver ksz8873_driver_mdio = {
+	.drv = {
+		.name = "KSZ8873 MDIO",
+		.of_compatible = DRV_OF_COMPAT(ksz8873_dt_ids),
+	},
+	.probe = ksz8873_probe_mdio,
+};
+device_mdio_driver(ksz8873_driver_mdio);
-- 
2.30.2



From michael.riesch at wolfvision.net  Tue Sep 20 23:55:12 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Wed, 21 Sep 2022 08:55:12 +0200
Subject: [PATCH 1/2] of: overlay: improve error handling in
 of_overlay_apply_tree
In-Reply-To: <20220905100717.150557-2-michael.riesch@wolfvision.net>
References: <20220905100717.150557-1-michael.riesch@wolfvision.net>
 <20220905100717.150557-2-michael.riesch@wolfvision.net>
Message-ID: <2ab1b3d8-eff0-f012-94bb-a6ddc61b982f@wolfvision.net>

Hi all,

On 9/5/22 12:07, Michael Riesch wrote:
> Propagate any error from of_overlay_apply_symbols and let the user
> know if the provided overlay is not applicable.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
>  drivers/of/overlay.c | 14 +++++++++-----
>  1 file changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index 20a43f5170..20686db511 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -115,8 +115,8 @@ static char *of_overlay_fix_path(struct device_node *root,
>  	return basprintf("%s%s", target->full_name, path_tail);
>  }
>  
> -static void of_overlay_apply_symbols(struct device_node *root,
> -				     struct device_node *overlay)
> +static int of_overlay_apply_symbols(struct device_node *root,
> +				    struct device_node *overlay)
>  {
>  	const char *old_path;
>  	char *new_path;
> @@ -129,12 +129,12 @@ static void of_overlay_apply_symbols(struct device_node *root,
>  
>  	if (!overlay_symbols) {
>  		pr_debug("overlay doesn't have a __symbols__ node\n");
> -		return;
> +		return -EINVAL;

Come to think of it, do all overlays need to provide a __symbols__ node?
If not, this check is overly strict.

>  	}
>  
>  	if (!root_symbols) {
>  		pr_info("root doesn't have a __symbols__ node\n");
> -		return;
> +		return -EINVAL;

Ditto for the root.

>  	}
>  
>  	list_for_each_entry(prop, &overlay_symbols->properties, list) {
> @@ -148,6 +148,8 @@ static void of_overlay_apply_symbols(struct device_node *root,
>  			 prop->name, new_path);
>  		of_property_write_string(root_symbols, prop->name, new_path);
>  	}
> +
> +	return 0;
>  }
>  
>  static int of_overlay_apply_fragment(struct device_node *root,
> @@ -190,7 +192,9 @@ int of_overlay_apply_tree(struct device_node *root,
>  		goto out_err;
>  
>  	/* Copy symbols from resolved overlay to base device tree */
> -	of_overlay_apply_symbols(root, resolved);
> +	err = of_overlay_apply_symbols(root, resolved);
> +	if (err)
> +		goto out_err;

If both checks need to be relaxed, the complete patch should be reverted
I guess :-/

Thanks in advance for your comments.

Best regards,
Michael

>  
>  	/* Copy nodes and properties from resolved overlay to root */
>  	for_each_child_of_node(resolved, fragment) {


From m.tretter at pengutronix.de  Wed Sep 21 00:57:05 2022
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Wed, 21 Sep 2022 09:57:05 +0200
Subject: [PATCH 1/2] of: overlay: improve error handling in
 of_overlay_apply_tree
In-Reply-To: <2ab1b3d8-eff0-f012-94bb-a6ddc61b982f@wolfvision.net>
References: <20220905100717.150557-1-michael.riesch@wolfvision.net>
 <20220905100717.150557-2-michael.riesch@wolfvision.net>
 <2ab1b3d8-eff0-f012-94bb-a6ddc61b982f@wolfvision.net>
Message-ID: <20220921075705.GD16312@pengutronix.de>

On Wed, 21 Sep 2022 08:55:12 +0200, Michael Riesch wrote:
> On 9/5/22 12:07, Michael Riesch wrote:
> > Propagate any error from of_overlay_apply_symbols and let the user
> > know if the provided overlay is not applicable.
> > 
> > Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> > ---
> >  drivers/of/overlay.c | 14 +++++++++-----
> >  1 file changed, 9 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> > index 20a43f5170..20686db511 100644
> > --- a/drivers/of/overlay.c
> > +++ b/drivers/of/overlay.c
> > @@ -115,8 +115,8 @@ static char *of_overlay_fix_path(struct device_node *root,
> >  	return basprintf("%s%s", target->full_name, path_tail);
> >  }
> >  
> > -static void of_overlay_apply_symbols(struct device_node *root,
> > -				     struct device_node *overlay)
> > +static int of_overlay_apply_symbols(struct device_node *root,
> > +				    struct device_node *overlay)
> >  {
> >  	const char *old_path;
> >  	char *new_path;
> > @@ -129,12 +129,12 @@ static void of_overlay_apply_symbols(struct device_node *root,
> >  
> >  	if (!overlay_symbols) {
> >  		pr_debug("overlay doesn't have a __symbols__ node\n");
> > -		return;
> > +		return -EINVAL;
> 
> Come to think of it, do all overlays need to provide a __symbols__ node?
> If not, this check is overly strict.

Overlays don't need a __symbols__ node. It would be only required, if overlays
are stacked and the second overlay refers to nodes of the first overlay by
labels. Having no __symbols__ in the overlay is a success path and the message
is just a debug message.

> 
> >  	}
> >  
> >  	if (!root_symbols) {
> >  		pr_info("root doesn't have a __symbols__ node\n");
> > -		return;
> > +		return -EINVAL;
> 
> Ditto for the root.

I'm not sure what should happen, if the root does not have __symbols__.
Barebox wouldn't be able to copy the __symbols__ of the overlay, but this
still wouldn't be a problem unless overlays are stacked. In the stacking case,
only applying the second overlay should fail.

Maybe, we should add a new __symbols__ node, if the root doesn't have a
__symbols__ node?

> 
> >  	}
> >  
> >  	list_for_each_entry(prop, &overlay_symbols->properties, list) {
> > @@ -148,6 +148,8 @@ static void of_overlay_apply_symbols(struct device_node *root,
> >  			 prop->name, new_path);
> >  		of_property_write_string(root_symbols, prop->name, new_path);
> >  	}
> > +
> > +	return 0;
> >  }
> >  
> >  static int of_overlay_apply_fragment(struct device_node *root,
> > @@ -190,7 +192,9 @@ int of_overlay_apply_tree(struct device_node *root,
> >  		goto out_err;
> >  
> >  	/* Copy symbols from resolved overlay to base device tree */
> > -	of_overlay_apply_symbols(root, resolved);
> > +	err = of_overlay_apply_symbols(root, resolved);
> > +	if (err)
> > +		goto out_err;
> 
> If both checks need to be relaxed, the complete patch should be reverted
> I guess :-/

What did you do to run into this error? What was your expectation?

Michael


From s.hauer at pengutronix.de  Wed Sep 21 02:13:16 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 21 Sep 2022 11:13:16 +0200
Subject: [PATCH] arm: rk3568 boards: call setup_c() before accessing global pointers
Message-ID: <20220921091316.2879347-1-s.hauer@pengutronix.de>

Global pointers may only be accessed after setup_c() has been called.

In pine-quartz64 and the Radxa Rock3 board the device tree pointer has
been initialized earlier. As a result the pointer points to the address
the device tree would be placed when the binary would run from 0x0. For
some reason it nevertheless seemed to work though.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boards/pine64-quartz64/lowlevel.c | 26 ++++++++++++----------
 arch/arm/boards/radxa-rock3/lowlevel.c     | 26 ++++++++++++----------
 2 files changed, 28 insertions(+), 24 deletions(-)

diff --git a/arch/arm/boards/pine64-quartz64/lowlevel.c b/arch/arm/boards/pine64-quartz64/lowlevel.c
index b295885522..ae1f0cf920 100644
--- a/arch/arm/boards/pine64-quartz64/lowlevel.c
+++ b/arch/arm/boards/pine64-quartz64/lowlevel.c
@@ -10,18 +10,9 @@
 
 extern char __dtb_rk3566_quartz64_a_start[];
 
-static noinline void start_quartz64(void *fdt)
+static noinline void start_quartz64(void)
 {
-	/*
-	 * Image execution starts at 0x0, but this is used for ATF and
-	 * OP-TEE later, so move away from here.
-	 */
-	if (current_el() == 3)
-		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
-	else
-		relocate_to_current_adr();
-
-	setup_c();
+	void *fdt = __dtb_rk3566_quartz64_a_start;
 
 	if (current_el() == 3) {
 		rk3568_lowlevel_init();
@@ -35,5 +26,16 @@ static noinline void start_quartz64(void *fdt)
 
 ENTRY_FUNCTION(start_quartz64a, r0, r1, r2)
 {
-	start_quartz64(__dtb_rk3566_quartz64_a_start);
+	/*
+	 * Image execution starts at 0x0, but this is used for ATF and
+	 * OP-TEE later, so move away from here.
+	 */
+	if (current_el() == 3)
+		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
+	else
+		relocate_to_current_adr();
+
+	setup_c();
+
+	start_quartz64();
 }
diff --git a/arch/arm/boards/radxa-rock3/lowlevel.c b/arch/arm/boards/radxa-rock3/lowlevel.c
index 00a68889cd..2a449c17ae 100644
--- a/arch/arm/boards/radxa-rock3/lowlevel.c
+++ b/arch/arm/boards/radxa-rock3/lowlevel.c
@@ -10,18 +10,9 @@
 
 extern char __dtb_rk3568_rock_3a_start[];
 
-static noinline void rk3568_start(void *fdt)
+static noinline void rk3568_start(void)
 {
-	/*
-	 * Image execution starts at 0x0, but this is used for ATF and
-	 * OP-TEE later, so move away from here.
-	 */
-	if (current_el() == 3)
-		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
-	else
-		relocate_to_current_adr();
-
-	setup_c();
+	void *fdt = __dtb_rk3568_rock_3a_start;
 
 	/*
 	 * Enable vccio4 1.8V and vccio6 1.8V
@@ -40,5 +31,16 @@ static noinline void rk3568_start(void *fdt)
 
 ENTRY_FUNCTION(start_rock3a, r0, r1, r2)
 {
-	rk3568_start(__dtb_rk3568_rock_3a_start);
+	/*
+	 * Image execution starts at 0x0, but this is used for ATF and
+	 * OP-TEE later, so move away from here.
+	 */
+	if (current_el() == 3)
+		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
+	else
+		relocate_to_current_adr();
+
+	setup_c();
+
+	rk3568_start();
 }
-- 
2.30.2



From sha at pengutronix.de  Wed Sep 21 02:17:24 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 21 Sep 2022 11:17:24 +0200
Subject: [PATCH v2 6/7] arm: rockchip: rk3568: refactor common
 rk3568_start method
In-Reply-To: <20220919113948.991245-7-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-7-michael.riesch@wolfvision.net>
Message-ID: <20220921091724.GB986@pengutronix.de>

On Mon, Sep 19, 2022 at 01:39:47PM +0200, Michael Riesch wrote:
> After the removal of the IO domain configuration code, the low-level
> initialization is the same for all RK356x boards. Add a common
> method rk3568_start to remove this code duplication.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
>  arch/arm/boards/pine64-quartz64/lowlevel.c    | 30 +----------------
>  arch/arm/boards/radxa-rock3/lowlevel.c        | 27 ---------------
>  .../arm/boards/rockchip-rk3568-evb/lowlevel.c | 33 +------------------
>  .../arm/mach-rockchip/include/mach/rockchip.h |  1 +
>  arch/arm/mach-rockchip/rk3568.c               | 24 ++++++++++++++
>  5 files changed, 27 insertions(+), 88 deletions(-)
> 
> diff --git a/arch/arm/boards/pine64-quartz64/lowlevel.c b/arch/arm/boards/pine64-quartz64/lowlevel.c
> index b295885522..e1beb3e624 100644
> --- a/arch/arm/boards/pine64-quartz64/lowlevel.c
> +++ b/arch/arm/boards/pine64-quartz64/lowlevel.c
> @@ -1,39 +1,11 @@
>  // SPDX-License-Identifier: GPL-2.0-only
>  #include <common.h>
> -#include <linux/sizes.h>
> -#include <asm/barebox-arm-head.h>
>  #include <asm/barebox-arm.h>
> -#include <mach/hardware.h>
> -#include <mach/atf.h>
> -#include <debug_ll.h>
>  #include <mach/rockchip.h>
>  
>  extern char __dtb_rk3566_quartz64_a_start[];
>  
> -static noinline void start_quartz64(void *fdt)
> -{
> -	/*
> -	 * Image execution starts at 0x0, but this is used for ATF and
> -	 * OP-TEE later, so move away from here.
> -	 */
> -	if (current_el() == 3)
> -		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
> -	else
> -		relocate_to_current_adr();
> -
> -	setup_c();
> -
> -	if (current_el() == 3) {
> -		rk3568_lowlevel_init();
> -		rk3568_atf_load_bl31(fdt);
> -		/* not reached */
> -	}
> -
> -	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM,
> -			  fdt);
> -}
> -
>  ENTRY_FUNCTION(start_quartz64a, r0, r1, r2)
>  {
> -	start_quartz64(__dtb_rk3566_quartz64_a_start);
> +	rk3568_start(__dtb_rk3566_quartz64_a_start);
>  }

Here __dtb_rk3566_quartz64_a_start is accessed before setup_c() has been
called. That is not allowed, see the patch I just sent.

BTW this patch breaks compilation, which is only fixed in 7/7:

/ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c:14:22: error: conflicting types for 'rk3568_start'
   14 | static noinline void rk3568_start(void)
      |                      ^~~~~~~~~~~~
In file included from /ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c:10:
/ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/arch/arm/mach-rockchip/include/mach/rockchip.h:37:6: note: previous declaration of 'rk3568_start' was here
   37 | void rk3568_start(void *fdt);
      |      ^~~~~~~~~~~~


Sascha

-- 
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-5555 |


From sha at pengutronix.de  Wed Sep 21 02:46:49 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 21 Sep 2022 11:46:49 +0200
Subject: [PATCH v2 1/7] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <20220919113948.991245-2-michael.riesch@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-2-michael.riesch@wolfvision.net>
Message-ID: <20220921094649.GC986@pengutronix.de>

On Mon, Sep 19, 2022 at 01:39:42PM +0200, Michael Riesch wrote:
> The IO domains in Rockchip SoCs need to be configured to match the
> corresponding bank voltage. In Linux this is achieved by means of a
> platform driver that reads the voltage value of the supplies and
> configures the bits in the general register file (GRF) accordingly.
> Port this driver to barebox to provide support for the Rockchip
> RK356x SoCs.
> 
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
>  drivers/soc/Kconfig              |   1 +
>  drivers/soc/Makefile             |   1 +
>  drivers/soc/rockchip/Kconfig     |  17 +++
>  drivers/soc/rockchip/Makefile    |   6 +
>  drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
>  5 files changed, 248 insertions(+)
>  create mode 100644 drivers/soc/rockchip/Kconfig
>  create mode 100644 drivers/soc/rockchip/Makefile
>  create mode 100644 drivers/soc/rockchip/io-domain.c

There's nothing in this driver that makes sure it is probed before the
users of the io domains. What happens when the users are probed before
the io domain driver?

Normally I would expect that the consumers have some phandle to their io
domain, but there's nothing like it in the device trees.

Sascha

-- 
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-5555 |


From michael.riesch at wolfvision.net  Wed Sep 21 03:00:38 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Wed, 21 Sep 2022 12:00:38 +0200
Subject: [PATCH 1/2] of: overlay: improve error handling in
 of_overlay_apply_tree
In-Reply-To: <20220921075705.GD16312@pengutronix.de>
References: <20220905100717.150557-1-michael.riesch@wolfvision.net>
 <20220905100717.150557-2-michael.riesch@wolfvision.net>
 <2ab1b3d8-eff0-f012-94bb-a6ddc61b982f@wolfvision.net>
 <20220921075705.GD16312@pengutronix.de>
Message-ID: <521707bd-6b5a-af0b-1976-7f971d90a9e7@wolfvision.net>

Hi Michael,

On 9/21/22 09:57, Michael Tretter wrote:
> On Wed, 21 Sep 2022 08:55:12 +0200, Michael Riesch wrote:
>> On 9/5/22 12:07, Michael Riesch wrote:
>>> Propagate any error from of_overlay_apply_symbols and let the user
>>> know if the provided overlay is not applicable.
>>>
>>> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
>>> ---
>>>  drivers/of/overlay.c | 14 +++++++++-----
>>>  1 file changed, 9 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
>>> index 20a43f5170..20686db511 100644
>>> --- a/drivers/of/overlay.c
>>> +++ b/drivers/of/overlay.c
>>> @@ -115,8 +115,8 @@ static char *of_overlay_fix_path(struct device_node *root,
>>>  	return basprintf("%s%s", target->full_name, path_tail);
>>>  }
>>>  
>>> -static void of_overlay_apply_symbols(struct device_node *root,
>>> -				     struct device_node *overlay)
>>> +static int of_overlay_apply_symbols(struct device_node *root,
>>> +				    struct device_node *overlay)
>>>  {
>>>  	const char *old_path;
>>>  	char *new_path;
>>> @@ -129,12 +129,12 @@ static void of_overlay_apply_symbols(struct device_node *root,
>>>  
>>>  	if (!overlay_symbols) {
>>>  		pr_debug("overlay doesn't have a __symbols__ node\n");
>>> -		return;
>>> +		return -EINVAL;
>>
>> Come to think of it, do all overlays need to provide a __symbols__ node?
>> If not, this check is overly strict.
> 
> Overlays don't need a __symbols__ node. It would be only required, if overlays
> are stacked and the second overlay refers to nodes of the first overlay by
> labels. Having no __symbols__ in the overlay is a success path and the message
> is just a debug message.

Thanks for the clarification. We need to fix this one, then.

Seeing that the patch is in next: Am I supposed to send an incremental
"fixup! ..." patch which can be squashed? Or should I send a proper
patch with a Fixes: tag?

>>>  	}
>>>  
>>>  	if (!root_symbols) {
>>>  		pr_info("root doesn't have a __symbols__ node\n");
>>> -		return;
>>> +		return -EINVAL;
>>
>> Ditto for the root.
> 
> I'm not sure what should happen, if the root does not have __symbols__.
> Barebox wouldn't be able to copy the __symbols__ of the overlay, but this
> still wouldn't be a problem unless overlays are stacked. In the stacking case,
> only applying the second overlay should fail.

I can reestablish the behavior before this patch, i.e., __symbols__ is
optional in both root and overlay.

> Maybe, we should add a new __symbols__ node, if the root doesn't have a
> __symbols__ node?

If this is desired, I can implement the change -- but is it desired?

>>>  	}
>>>  
>>>  	list_for_each_entry(prop, &overlay_symbols->properties, list) {
>>> @@ -148,6 +148,8 @@ static void of_overlay_apply_symbols(struct device_node *root,
>>>  			 prop->name, new_path);
>>>  		of_property_write_string(root_symbols, prop->name, new_path);
>>>  	}
>>> +
>>> +	return 0;
>>>  }
>>>  
>>>  static int of_overlay_apply_fragment(struct device_node *root,
>>> @@ -190,7 +192,9 @@ int of_overlay_apply_tree(struct device_node *root,
>>>  		goto out_err;
>>>  
>>>  	/* Copy symbols from resolved overlay to base device tree */
>>> -	of_overlay_apply_symbols(root, resolved);
>>> +	err = of_overlay_apply_symbols(root, resolved);
>>> +	if (err)
>>> +		goto out_err;
>>
>> If both checks need to be relaxed, the complete patch should be reverted
>> I guess :-/
> 
> What did you do to run into this error? What was your expectation?

Well I tried to apply an overlay without __symbols__ :-) (which did work
before).

Best regards,
Michael


From michael.riesch at wolfvision.net  Wed Sep 21 04:49:49 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Wed, 21 Sep 2022 13:49:49 +0200
Subject: [PATCH v2 1/7] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <20220921094649.GC986@pengutronix.de>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-2-michael.riesch@wolfvision.net>
 <20220921094649.GC986@pengutronix.de>
Message-ID: <223f9b7c-a95a-7847-503d-e51cb2abaf64@wolfvision.net>

Hi Sascha,

On 9/21/22 11:46, Sascha Hauer wrote:
> On Mon, Sep 19, 2022 at 01:39:42PM +0200, Michael Riesch wrote:
>> The IO domains in Rockchip SoCs need to be configured to match the
>> corresponding bank voltage. In Linux this is achieved by means of a
>> platform driver that reads the voltage value of the supplies and
>> configures the bits in the general register file (GRF) accordingly.
>> Port this driver to barebox to provide support for the Rockchip
>> RK356x SoCs.
>>
>> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
>> ---
>>  drivers/soc/Kconfig              |   1 +
>>  drivers/soc/Makefile             |   1 +
>>  drivers/soc/rockchip/Kconfig     |  17 +++
>>  drivers/soc/rockchip/Makefile    |   6 +
>>  drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
>>  5 files changed, 248 insertions(+)
>>  create mode 100644 drivers/soc/rockchip/Kconfig
>>  create mode 100644 drivers/soc/rockchip/Makefile
>>  create mode 100644 drivers/soc/rockchip/io-domain.c
> 
> There's nothing in this driver that makes sure it is probed before the
> users of the io domains. What happens when the users are probed before
> the io domain driver?

Correct. Unfortunately, the situation is quite the same in the kernel.
Only recently there was a discussion as to how to resolve this issue
[0]. While the RFC in [0] was received well there is no mainline
solution to this problem. I would suggest that the mainline kernel
solution is adopted once there is one.

In the mean time we could
 - accept that it just works for some reason (TM)
 - leave the magic bits in the low-level initialization to be on the
   safe side
 - simply wait
 - ???

> Normally I would expect that the consumers have some phandle to their io
> domain, but there's nothing like it in the device trees.

The RFC in [0] suggests that the pinctrl is a consumer of the io
domains, which would be in alignment with your expectations.

Best regards,
Michael

[0]
https://lore.kernel.org/lkml/20220802095252.2486591-1-foss+kernel at 0leil.net/T/


From michael.riesch at wolfvision.net  Wed Sep 21 04:57:25 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Wed, 21 Sep 2022 13:57:25 +0200
Subject: [PATCH v2 6/7] arm: rockchip: rk3568: refactor common
 rk3568_start method
In-Reply-To: <20220921091724.GB986@pengutronix.de>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-7-michael.riesch@wolfvision.net>
 <20220921091724.GB986@pengutronix.de>
Message-ID: <f78a05c7-3142-626c-3b02-f969c729b40f@wolfvision.net>

Hi Sascha,

On 9/21/22 11:17, Sascha Hauer wrote:
> On Mon, Sep 19, 2022 at 01:39:47PM +0200, Michael Riesch wrote:
>> After the removal of the IO domain configuration code, the low-level
>> initialization is the same for all RK356x boards. Add a common
>> method rk3568_start to remove this code duplication.
>>
>> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
>> ---
>>  arch/arm/boards/pine64-quartz64/lowlevel.c    | 30 +----------------
>>  arch/arm/boards/radxa-rock3/lowlevel.c        | 27 ---------------
>>  .../arm/boards/rockchip-rk3568-evb/lowlevel.c | 33 +------------------
>>  .../arm/mach-rockchip/include/mach/rockchip.h |  1 +
>>  arch/arm/mach-rockchip/rk3568.c               | 24 ++++++++++++++
>>  5 files changed, 27 insertions(+), 88 deletions(-)
>>
>> diff --git a/arch/arm/boards/pine64-quartz64/lowlevel.c b/arch/arm/boards/pine64-quartz64/lowlevel.c
>> index b295885522..e1beb3e624 100644
>> --- a/arch/arm/boards/pine64-quartz64/lowlevel.c
>> +++ b/arch/arm/boards/pine64-quartz64/lowlevel.c
>> @@ -1,39 +1,11 @@
>>  // SPDX-License-Identifier: GPL-2.0-only
>>  #include <common.h>
>> -#include <linux/sizes.h>
>> -#include <asm/barebox-arm-head.h>
>>  #include <asm/barebox-arm.h>
>> -#include <mach/hardware.h>
>> -#include <mach/atf.h>
>> -#include <debug_ll.h>
>>  #include <mach/rockchip.h>
>>  
>>  extern char __dtb_rk3566_quartz64_a_start[];
>>  
>> -static noinline void start_quartz64(void *fdt)
>> -{
>> -	/*
>> -	 * Image execution starts at 0x0, but this is used for ATF and
>> -	 * OP-TEE later, so move away from here.
>> -	 */
>> -	if (current_el() == 3)
>> -		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
>> -	else
>> -		relocate_to_current_adr();
>> -
>> -	setup_c();
>> -
>> -	if (current_el() == 3) {
>> -		rk3568_lowlevel_init();
>> -		rk3568_atf_load_bl31(fdt);
>> -		/* not reached */
>> -	}
>> -
>> -	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM,
>> -			  fdt);
>> -}
>> -
>>  ENTRY_FUNCTION(start_quartz64a, r0, r1, r2)
>>  {
>> -	start_quartz64(__dtb_rk3566_quartz64_a_start);
>> +	rk3568_start(__dtb_rk3566_quartz64_a_start);
>>  }
> 
> Here __dtb_rk3566_quartz64_a_start is accessed before setup_c() has been
> called. That is not allowed, see the patch I just sent.

Does the refactoring make sense to you in general? Can I change it to

ENTRY_FUNCTION(start_my_fancy_board, r0, r1, r2)
{
	setup_c();
	rk3568_start(__dtb_my_fancy_board_start);
}

?

> BTW this patch breaks compilation, which is only fixed in 7/7:
> 
> /ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c:14:22: error: conflicting types for 'rk3568_start'
>    14 | static noinline void rk3568_start(void)
>       |                      ^~~~~~~~~~~~
> In file included from /ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c:10:
> /ptx/work/WORK_EIHEI/sha/projects/barebox/barebox/arch/arm/mach-rockchip/include/mach/rockchip.h:37:6: note: previous declaration of 'rk3568_start' was here
>    37 | void rk3568_start(void *fdt);
>       |      ^~~~~~~~~~~~

Oops. The goal was to separate the changes that affect the BananaPi, but
in this case 6 + 7 need to be squashed. I guess Frank needs to object to
the combined patch if it breaks something on his side.

Best regards,
Michael


From sha at pengutronix.de  Wed Sep 21 05:21:46 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 21 Sep 2022 14:21:46 +0200
Subject: [PATCH v2 6/7] arm: rockchip: rk3568: refactor common
 rk3568_start method
In-Reply-To: <f78a05c7-3142-626c-3b02-f969c729b40f@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-7-michael.riesch@wolfvision.net>
 <20220921091724.GB986@pengutronix.de>
 <f78a05c7-3142-626c-3b02-f969c729b40f@wolfvision.net>
Message-ID: <20220921122146.GD986@pengutronix.de>

On Wed, Sep 21, 2022 at 01:57:25PM +0200, Michael Riesch wrote:
> Hi Sascha,
> 
> On 9/21/22 11:17, Sascha Hauer wrote:
> > On Mon, Sep 19, 2022 at 01:39:47PM +0200, Michael Riesch wrote:
> >> After the removal of the IO domain configuration code, the low-level
> >> initialization is the same for all RK356x boards. Add a common
> >> method rk3568_start to remove this code duplication.
> >>
> >> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> >> ---
> >>  arch/arm/boards/pine64-quartz64/lowlevel.c    | 30 +----------------
> >>  arch/arm/boards/radxa-rock3/lowlevel.c        | 27 ---------------
> >>  .../arm/boards/rockchip-rk3568-evb/lowlevel.c | 33 +------------------
> >>  .../arm/mach-rockchip/include/mach/rockchip.h |  1 +
> >>  arch/arm/mach-rockchip/rk3568.c               | 24 ++++++++++++++
> >>  5 files changed, 27 insertions(+), 88 deletions(-)
> >>
> >> diff --git a/arch/arm/boards/pine64-quartz64/lowlevel.c b/arch/arm/boards/pine64-quartz64/lowlevel.c
> >> index b295885522..e1beb3e624 100644
> >> --- a/arch/arm/boards/pine64-quartz64/lowlevel.c
> >> +++ b/arch/arm/boards/pine64-quartz64/lowlevel.c
> >> @@ -1,39 +1,11 @@
> >>  // SPDX-License-Identifier: GPL-2.0-only
> >>  #include <common.h>
> >> -#include <linux/sizes.h>
> >> -#include <asm/barebox-arm-head.h>
> >>  #include <asm/barebox-arm.h>
> >> -#include <mach/hardware.h>
> >> -#include <mach/atf.h>
> >> -#include <debug_ll.h>
> >>  #include <mach/rockchip.h>
> >>  
> >>  extern char __dtb_rk3566_quartz64_a_start[];
> >>  
> >> -static noinline void start_quartz64(void *fdt)
> >> -{
> >> -	/*
> >> -	 * Image execution starts at 0x0, but this is used for ATF and
> >> -	 * OP-TEE later, so move away from here.
> >> -	 */
> >> -	if (current_el() == 3)
> >> -		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
> >> -	else
> >> -		relocate_to_current_adr();
> >> -
> >> -	setup_c();
> >> -
> >> -	if (current_el() == 3) {
> >> -		rk3568_lowlevel_init();
> >> -		rk3568_atf_load_bl31(fdt);
> >> -		/* not reached */
> >> -	}
> >> -
> >> -	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM,
> >> -			  fdt);
> >> -}
> >> -
> >>  ENTRY_FUNCTION(start_quartz64a, r0, r1, r2)
> >>  {
> >> -	start_quartz64(__dtb_rk3566_quartz64_a_start);
> >> +	rk3568_start(__dtb_rk3566_quartz64_a_start);
> >>  }
> > 
> > Here __dtb_rk3566_quartz64_a_start is accessed before setup_c() has been
> > called. That is not allowed, see the patch I just sent.
> 
> Does the refactoring make sense to you in general? Can I change it to
> 
> ENTRY_FUNCTION(start_my_fancy_board, r0, r1, r2)
> {
> 	setup_c();
> 	rk3568_start(__dtb_my_fancy_board_start);
> }

Well it's not only setup_c() but also the relocate_to_adr_full() or
relocate_to_current_adr() part that has to be called before setup_c().

At that point there is not much left to factor out to a common function.

Unless you want to turn this into preprocessor macros (and I don't
recommand doing that) my suggestion is that we just live with this bit
of code duplication.

Sascha

-- 
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-5555 |


From michael.riesch at wolfvision.net  Wed Sep 21 05:34:36 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Wed, 21 Sep 2022 14:34:36 +0200
Subject: [PATCH v2 6/7] arm: rockchip: rk3568: refactor common
 rk3568_start method
In-Reply-To: <20220921122146.GD986@pengutronix.de>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-7-michael.riesch@wolfvision.net>
 <20220921091724.GB986@pengutronix.de>
 <f78a05c7-3142-626c-3b02-f969c729b40f@wolfvision.net>
 <20220921122146.GD986@pengutronix.de>
Message-ID: <93af97cb-bf91-8931-c554-654d8bb61b07@wolfvision.net>

Hi Sascha,

On 9/21/22 14:21, Sascha Hauer wrote:
> On Wed, Sep 21, 2022 at 01:57:25PM +0200, Michael Riesch wrote:
>> Hi Sascha,
>>
>> On 9/21/22 11:17, Sascha Hauer wrote:
>>> On Mon, Sep 19, 2022 at 01:39:47PM +0200, Michael Riesch wrote:
>>>> After the removal of the IO domain configuration code, the low-level
>>>> initialization is the same for all RK356x boards. Add a common
>>>> method rk3568_start to remove this code duplication.
>>>>
>>>> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
>>>> ---
>>>>  arch/arm/boards/pine64-quartz64/lowlevel.c    | 30 +----------------
>>>>  arch/arm/boards/radxa-rock3/lowlevel.c        | 27 ---------------
>>>>  .../arm/boards/rockchip-rk3568-evb/lowlevel.c | 33 +------------------
>>>>  .../arm/mach-rockchip/include/mach/rockchip.h |  1 +
>>>>  arch/arm/mach-rockchip/rk3568.c               | 24 ++++++++++++++
>>>>  5 files changed, 27 insertions(+), 88 deletions(-)
>>>>
>>>> diff --git a/arch/arm/boards/pine64-quartz64/lowlevel.c b/arch/arm/boards/pine64-quartz64/lowlevel.c
>>>> index b295885522..e1beb3e624 100644
>>>> --- a/arch/arm/boards/pine64-quartz64/lowlevel.c
>>>> +++ b/arch/arm/boards/pine64-quartz64/lowlevel.c
>>>> @@ -1,39 +1,11 @@
>>>>  // SPDX-License-Identifier: GPL-2.0-only
>>>>  #include <common.h>
>>>> -#include <linux/sizes.h>
>>>> -#include <asm/barebox-arm-head.h>
>>>>  #include <asm/barebox-arm.h>
>>>> -#include <mach/hardware.h>
>>>> -#include <mach/atf.h>
>>>> -#include <debug_ll.h>
>>>>  #include <mach/rockchip.h>
>>>>  
>>>>  extern char __dtb_rk3566_quartz64_a_start[];
>>>>  
>>>> -static noinline void start_quartz64(void *fdt)
>>>> -{
>>>> -	/*
>>>> -	 * Image execution starts at 0x0, but this is used for ATF and
>>>> -	 * OP-TEE later, so move away from here.
>>>> -	 */
>>>> -	if (current_el() == 3)
>>>> -		relocate_to_adr_full(RK3568_BAREBOX_LOAD_ADDRESS);
>>>> -	else
>>>> -		relocate_to_current_adr();
>>>> -
>>>> -	setup_c();
>>>> -
>>>> -	if (current_el() == 3) {
>>>> -		rk3568_lowlevel_init();
>>>> -		rk3568_atf_load_bl31(fdt);
>>>> -		/* not reached */
>>>> -	}
>>>> -
>>>> -	barebox_arm_entry(RK3568_DRAM_BOTTOM, 0x80000000 - RK3568_DRAM_BOTTOM,
>>>> -			  fdt);
>>>> -}
>>>> -
>>>>  ENTRY_FUNCTION(start_quartz64a, r0, r1, r2)
>>>>  {
>>>> -	start_quartz64(__dtb_rk3566_quartz64_a_start);
>>>> +	rk3568_start(__dtb_rk3566_quartz64_a_start);
>>>>  }
>>>
>>> Here __dtb_rk3566_quartz64_a_start is accessed before setup_c() has been
>>> called. That is not allowed, see the patch I just sent.
>>
>> Does the refactoring make sense to you in general? Can I change it to
>>
>> ENTRY_FUNCTION(start_my_fancy_board, r0, r1, r2)
>> {
>> 	setup_c();
>> 	rk3568_start(__dtb_my_fancy_board_start);
>> }
> 
> Well it's not only setup_c() but also the relocate_to_adr_full() or
> relocate_to_current_adr() part that has to be called before setup_c().

Ah OK! Thanks for the clarification.

> At that point there is not much left to factor out to a common function.
> 
> Unless you want to turn this into preprocessor macros (and I don't
> recommand doing that) my suggestion is that we just live with this bit
> of code duplication.

OK, patches 6+7 can be dropped, then.

Best regards,
Michael


From m.felsch at pengutronix.de  Wed Sep 21 10:20:52 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 21 Sep 2022 19:20:52 +0200
Subject: [PATCH 2/2] ARM: i.MX8M: remove fsp_table entry
In-Reply-To: <20220921172052.2989506-1-m.felsch@pengutronix.de>
References: <20220921172052.2989506-1-m.felsch@pengutronix.de>
Message-ID: <20220921172052.2989506-2-m.felsch@pengutronix.de>

Barebox now have the support to write the fsp_table entries
automatically based on fsp_msg.drata information. Remove the fsp_table
entry and let the common code do the rest for us.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/boards/mnt-reform/lpddr4-timing.c     | 1 -
 arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c   | 1 -
 arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c | 1 -
 arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c | 1 -
 4 files changed, 4 deletions(-)

diff --git a/arch/arm/boards/mnt-reform/lpddr4-timing.c b/arch/arm/boards/mnt-reform/lpddr4-timing.c
index 0b5853000d..38fa2c50f1 100644
--- a/arch/arm/boards/mnt-reform/lpddr4-timing.c
+++ b/arch/arm/boards/mnt-reform/lpddr4-timing.c
@@ -1008,5 +1008,4 @@ struct dram_timing_info mnt_reform_dram_timing = {
 	.fsp_msg_num = ARRAY_SIZE(mnt_reform_lpddr4_dram_fsp_msg),
 	.ddrphy_pie = mnt_reform_lpddr4_phy_pie,
 	.ddrphy_pie_num = ARRAY_SIZE(mnt_reform_lpddr4_phy_pie),
-	.fsp_table = { 3200, 667, },
 };
diff --git a/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c b/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c
index 131a63156e..df10bdcc9d 100644
--- a/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c
+++ b/arch/arm/boards/nxp-imx8mn-evk/ddr4-timing.c
@@ -1050,5 +1050,4 @@ struct dram_timing_info imx8mn_evk_ddr4_timing = {
 	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
 	.ddrphy_pie = ddr_phy_pie,
 	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
-	.fsp_table = { 2400, 1066, },
 };
diff --git a/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c b/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c
index 940b21cedb..63851c87d4 100644
--- a/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c
+++ b/arch/arm/boards/nxp-imx8mn-evk/lpddr4-timing.c
@@ -1586,5 +1586,4 @@ struct dram_timing_info imx8mn_evk_lpddr4_timing = {
 	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
 	.ddrphy_pie = ddr_phy_pie,
 	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
-	.fsp_table = { 3200, 400, 100, },
 };
diff --git a/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c b/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c
index 3028bc084c..b8c6b78017 100644
--- a/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c
+++ b/arch/arm/boards/nxp-imx8mp-evk/lpddr4-timing.c
@@ -1844,5 +1844,4 @@ struct dram_timing_info imx8mp_evk_dram_timing = {
 	.ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr),
 	.ddrphy_pie = ddr_phy_pie,
 	.ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie),
-	.fsp_table = { 4000, 400, 100, },
 };
-- 
2.30.2



From m.felsch at pengutronix.de  Wed Sep 21 10:20:51 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 21 Sep 2022 19:20:51 +0200
Subject: [PATCH 1/2] ddr: imx8m: write fsp_table entry automatically
Message-ID: <20220921172052.2989506-1-m.felsch@pengutronix.de>

Currently the fsp_table must be set manually within the 'struct
dram_timing_info'. Since the 'struct fsp_msg' already has all
information needed for the fsp_table we can use it to set it
automatically. This approach is less error-prone and avoids information
duplication.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 drivers/ddr/imx8m/ddrphy_train.c |  3 +++
 drivers/ddr/imx8m/helper.c       | 19 +++++++++++++++++++
 include/soc/imx8m/ddr.h          |  2 ++
 3 files changed, 24 insertions(+)

diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx8m/ddrphy_train.c
index e9d35afdfb..09f1e77295 100644
--- a/drivers/ddr/imx8m/ddrphy_train.c
+++ b/drivers/ddr/imx8m/ddrphy_train.c
@@ -165,6 +165,9 @@ int ddr_cfg_phy(struct dram_timing_info *dram_timing, unsigned type)
 
 		dwc_ddrphy_apb_wr(0xd0000, 0x1);
 
+		/* Training done, add entry to fsp_table */
+		dram_write_fsp_table_entry(dram_timing, fsp_msg->drate);
+
 		fsp_msg++;
 	}
 
diff --git a/drivers/ddr/imx8m/helper.c b/drivers/ddr/imx8m/helper.c
index 98e4084958..e71401c1b2 100644
--- a/drivers/ddr/imx8m/helper.c
+++ b/drivers/ddr/imx8m/helper.c
@@ -18,6 +18,25 @@
 #define DMEM_OFFSET_ADDR 0x00054000
 #define DDR_TRAIN_CODE_BASE_ADDR IP2APB_DDRPHY_IPS_BASE_ADDR(0)
 
+void dram_write_fsp_table_entry(struct dram_timing_info *timing_info,
+				unsigned int data_rate)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(timing_info->fsp_table); i++) {
+		unsigned int entry = timing_info->fsp_table[i];
+
+		/* Skip already existing entries */
+		if (entry == data_rate)
+			return;
+
+		if (entry == 0) {
+			timing_info->fsp_table[i] = data_rate;
+			return;
+		}
+	}
+}
+
 void ddrphy_trained_csr_save(struct dram_cfg_param *ddrphy_csr,
 			     unsigned int num)
 {
diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
index 2149ae4325..222ab8e0f4 100644
--- a/include/soc/imx8m/ddr.h
+++ b/include/soc/imx8m/ddr.h
@@ -436,6 +436,8 @@ int ddr_cfg_phy(struct dram_timing_info *timing_info, enum ddrc_type ddrc_type);
 void load_lpddr4_phy_pie(void);
 void ddrphy_trained_csr_save(struct dram_cfg_param *param, unsigned int num);
 void dram_config_save(struct dram_timing_info *info, unsigned long base);
+void dram_write_fsp_table_entry(struct dram_timing_info *timing_info,
+				unsigned int data_rate);
 
 /* utils function for ddr phy training */
 int wait_ddrphy_training_complete(void);
-- 
2.30.2



From j.zink at pengutronix.de  Thu Sep 22 00:27:23 2022
From: j.zink at pengutronix.de (Johannes Zink)
Date: Thu, 22 Sep 2022 09:27:23 +0200
Subject: [PATCH] USB: gadget: fastboot: introduce optional flag for fastboot partitions
Message-ID: <20220922072723.1559333-1-j.zink@pengutronix.de>

On some boards, some partitions exposed to fastboot may become
unavailable under certain circumstances, e.g. if an SD-Card exposed to
fastboot is removed.

Previously, this lead to an error and the fastboot gadget did not
initialize the remaining partitions exposed via fastboot, e.g. an
eMMC which usually is permanently soldered on the board.

This patch allows to append an optional flag 'o' to the description of a
fastboot partition. If this partition is unavailable at the
initialization of the fastboot gadget, said partition is skipped, while
the remaining available partitions are still exposed.

Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
---
 Documentation/user/usb.rst | 1 +
 common/fastboot.c          | 6 +++++-
 common/file-list.c         | 3 +++
 include/file-list.h        | 1 +
 4 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
index 2479efe9d6..f2f57ead98 100644
--- a/Documentation/user/usb.rst
+++ b/Documentation/user/usb.rst
@@ -65,6 +65,7 @@ Several **flags** are supported, each denoted by a single character:
 * ``r`` Readback. The partition is allowed to be read back (DFU specific)
 * ``c`` The file shall be created if it doesn't exist. Needed when a regular file is exported.
 * ``u`` The partition is a MTD device and shall be flashed with a UBI image.
+* ``o`` The partition is optional, i.e. if it is not available at initialization time, it is skipped instead of aborting the initialization
 
 Example:
 
diff --git a/common/fastboot.c b/common/fastboot.c
index 330a06f5a3..6bd1191325 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -177,7 +177,11 @@ int fastboot_generic_init(struct fastboot *fb, bool export_bbu)
 	file_list_for_each_entry(fb->files, fentry) {
 		ret = fastboot_add_partition_variables(fb, fentry);
 		if (ret)
-			return ret;
+			if((fentry->flags & FILE_LIST_FLAG_OPTIONAL))
+				pr_info("failed to add optional partition %s to fastboot gadget\n",
+					fentry->filename);
+			else
+				return ret;
 	}
 
 	return 0;
diff --git a/common/file-list.c b/common/file-list.c
index 407b312833..68a7768696 100644
--- a/common/file-list.c
+++ b/common/file-list.c
@@ -88,6 +88,9 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
 			case 'u':
 				flags |= FILE_LIST_FLAG_UBI;
 				break;
+			case 'o':
+				flags |= FILE_LIST_FLAG_OPTIONAL;
+				break;
 			default:
 				pr_err("Unknown flag '%c'\n", *partstr);
 				return -EINVAL;
diff --git a/include/file-list.h b/include/file-list.h
index 5090313739..bcb06979c8 100644
--- a/include/file-list.h
+++ b/include/file-list.h
@@ -8,6 +8,7 @@
 #define FILE_LIST_FLAG_READBACK	(1 << 1)
 #define FILE_LIST_FLAG_CREATE	(1 << 2)
 #define FILE_LIST_FLAG_UBI	(1 << 3)
+#define FILE_LIST_FLAG_OPTIONAL (1 << 4)
 
 struct file_list_entry {
 	char *name;
-- 
2.30.2



From sha at pengutronix.de  Thu Sep 22 01:03:29 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 22 Sep 2022 10:03:29 +0200
Subject: [PATCH v2 1/7] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <223f9b7c-a95a-7847-503d-e51cb2abaf64@wolfvision.net>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-2-michael.riesch@wolfvision.net>
 <20220921094649.GC986@pengutronix.de>
 <223f9b7c-a95a-7847-503d-e51cb2abaf64@wolfvision.net>
Message-ID: <20220922080329.GG986@pengutronix.de>

On Wed, Sep 21, 2022 at 01:49:49PM +0200, Michael Riesch wrote:
> Hi Sascha,
> 
> On 9/21/22 11:46, Sascha Hauer wrote:
> > On Mon, Sep 19, 2022 at 01:39:42PM +0200, Michael Riesch wrote:
> >> The IO domains in Rockchip SoCs need to be configured to match the
> >> corresponding bank voltage. In Linux this is achieved by means of a
> >> platform driver that reads the voltage value of the supplies and
> >> configures the bits in the general register file (GRF) accordingly.
> >> Port this driver to barebox to provide support for the Rockchip
> >> RK356x SoCs.
> >>
> >> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> >> ---
> >>  drivers/soc/Kconfig              |   1 +
> >>  drivers/soc/Makefile             |   1 +
> >>  drivers/soc/rockchip/Kconfig     |  17 +++
> >>  drivers/soc/rockchip/Makefile    |   6 +
> >>  drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
> >>  5 files changed, 248 insertions(+)
> >>  create mode 100644 drivers/soc/rockchip/Kconfig
> >>  create mode 100644 drivers/soc/rockchip/Makefile
> >>  create mode 100644 drivers/soc/rockchip/io-domain.c
> > 
> > There's nothing in this driver that makes sure it is probed before the
> > users of the io domains. What happens when the users are probed before
> > the io domain driver?
> 
> Correct. Unfortunately, the situation is quite the same in the kernel.
> Only recently there was a discussion as to how to resolve this issue
> [0]. While the RFC in [0] was received well there is no mainline
> solution to this problem. I would suggest that the mainline kernel
> solution is adopted once there is one.
> 
> In the mean time we could
>  - accept that it just works for some reason (TM)
>  - leave the magic bits in the low-level initialization to be on the
>    safe side

Decided for this solution for now.

I added the following as a reminder that there's still something
to do.

Sascha

---------------------------8<---------------------------

>From 502c4e819b80a6ccaefbce4af4c55b830b7e2c73 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer at pengutronix.de>
Date: Thu, 22 Sep 2022 09:56:57 +0200
Subject: [PATCH] ARM: Rockchip: Add FIXME comment to io domain setup

We have a io-domain driver for rockchip boards which correctly
configures the io domain voltages, but currently there is no way
to make sure the io-domain driver is probed before its consumers.

To be on the safe side keep the io domain setup in the lowlevel code
for now, but add a comment that it should be removed once this issue
is resolved.

To solve this issue we need a phandle from the consumers to the io
domain node. We could add this in barebox locally, but decided to
wait until the upstream dts files have them.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/boards/radxa-rock3/lowlevel.c               | 4 ++++
 arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c | 4 ++++
 arch/arm/boards/rockchip-rk3568-evb/lowlevel.c       | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/arch/arm/boards/radxa-rock3/lowlevel.c b/arch/arm/boards/radxa-rock3/lowlevel.c
index 2a449c17ae..a62f60dff8 100644
--- a/arch/arm/boards/radxa-rock3/lowlevel.c
+++ b/arch/arm/boards/radxa-rock3/lowlevel.c
@@ -17,6 +17,10 @@ static noinline void rk3568_start(void)
 	/*
 	 * Enable vccio4 1.8V and vccio6 1.8V
 	 * Needed for GMAC to work.
+	 * FIXME: This is done by the io-domain driver as well, but there
+	 * currently is no mechanism to make sure the driver gets probed
+	 * before its consumers. Remove this setup once this issue is
+	 * resolved.
 	 */
 	writel(RK_SETBITS(0x50), 0xfdc20140);
 
diff --git a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
index f79f975080..4336d99365 100644
--- a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
+++ b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
@@ -18,6 +18,10 @@ static noinline void rk3568_start(void)
 	/*
 	 * set iodomain vccio6 to 1.8V needed for GMAC1 to work.
 	 * vccio4 (gmac0/switch) needs to stay at 3v3 (default)
+	 * FIXME: This is done by the io-domain driver as well, but there
+	 * currently is no mechanism to make sure the driver gets probed
+	 * before its consumers. Remove this setup once this issue is
+	 * resolved.
 	 */
 	//set bit 6 in PMU_GRF_IO_VSEL0 for vccio6 1v8
 	writel(RK_SETBITS(BIT(6)), PMU_GRF_IO_VSEL0);
diff --git a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
index 363639d21b..9ab436135c 100644
--- a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
+++ b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
@@ -18,6 +18,10 @@ static noinline void rk3568_start(void)
 	/*
 	 * Enable vccio4 1.8V and vccio6 1.8V
 	 * Needed for GMAC to work.
+	 * FIXME: This is done by the io-domain driver as well, but there
+	 * currently is no mechanism to make sure the driver gets probed
+	 * before its consumers. Remove this setup once this issue is
+	 * resolved.
 	 */
 	writel(RK_SETBITS(0x50), 0xfdc20140);
 
-- 
2.30.2

-- 
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-5555 |


From a.fatoum at pengutronix.de  Thu Sep 22 01:13:35 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 22 Sep 2022 09:13:35 +0100
Subject: [PATCH v2 1/7] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <20220922080329.GG986@pengutronix.de>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-2-michael.riesch@wolfvision.net>
 <20220921094649.GC986@pengutronix.de>
 <223f9b7c-a95a-7847-503d-e51cb2abaf64@wolfvision.net>
 <20220922080329.GG986@pengutronix.de>
Message-ID: <d4e9f025-4327-2370-89f1-ad79d72e62af@pengutronix.de>

Hi,

On 22.09.22 09:03, Sascha Hauer wrote:
> On Wed, Sep 21, 2022 at 01:49:49PM +0200, Michael Riesch wrote:
>> Hi Sascha,
>>
>> On 9/21/22 11:46, Sascha Hauer wrote:
>>> On Mon, Sep 19, 2022 at 01:39:42PM +0200, Michael Riesch wrote:
>>>> The IO domains in Rockchip SoCs need to be configured to match the
>>>> corresponding bank voltage. In Linux this is achieved by means of a
>>>> platform driver that reads the voltage value of the supplies and
>>>> configures the bits in the general register file (GRF) accordingly.
>>>> Port this driver to barebox to provide support for the Rockchip
>>>> RK356x SoCs.
>>>>
>>>> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
>>>> ---
>>>>  drivers/soc/Kconfig              |   1 +
>>>>  drivers/soc/Makefile             |   1 +
>>>>  drivers/soc/rockchip/Kconfig     |  17 +++
>>>>  drivers/soc/rockchip/Makefile    |   6 +
>>>>  drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
>>>>  5 files changed, 248 insertions(+)
>>>>  create mode 100644 drivers/soc/rockchip/Kconfig
>>>>  create mode 100644 drivers/soc/rockchip/Makefile
>>>>  create mode 100644 drivers/soc/rockchip/io-domain.c
>>>
>>> There's nothing in this driver that makes sure it is probed before the
>>> users of the io domains. What happens when the users are probed before
>>> the io domain driver?
>>
>> Correct. Unfortunately, the situation is quite the same in the kernel.
>> Only recently there was a discussion as to how to resolve this issue
>> [0]. While the RFC in [0] was received well there is no mainline
>> solution to this problem. I would suggest that the mainline kernel
>> solution is adopted once there is one.
>>
>> In the mean time we could
>>  - accept that it just works for some reason (TM)
>>  - leave the magic bits in the low-level initialization to be on the
>>    safe side
> 
> Decided for this solution for now.
> 
> I added the following as a reminder that there's still something
> to do.

Why not do an of_device_ensure_probed for the I/O domain driver in
rk3568_init()?

> 
> Sascha
> 
> ---------------------------8<---------------------------
> 
> From 502c4e819b80a6ccaefbce4af4c55b830b7e2c73 Mon Sep 17 00:00:00 2001
> From: Sascha Hauer <s.hauer at pengutronix.de>
> Date: Thu, 22 Sep 2022 09:56:57 +0200
> Subject: [PATCH] ARM: Rockchip: Add FIXME comment to io domain setup
> 
> We have a io-domain driver for rockchip boards which correctly
> configures the io domain voltages, but currently there is no way
> to make sure the io-domain driver is probed before its consumers.
> 
> To be on the safe side keep the io domain setup in the lowlevel code
> for now, but add a comment that it should be removed once this issue
> is resolved.
> 
> To solve this issue we need a phandle from the consumers to the io
> domain node. We could add this in barebox locally, but decided to
> wait until the upstream dts files have them.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  arch/arm/boards/radxa-rock3/lowlevel.c               | 4 ++++
>  arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c | 4 ++++
>  arch/arm/boards/rockchip-rk3568-evb/lowlevel.c       | 4 ++++
>  3 files changed, 12 insertions(+)
> 
> diff --git a/arch/arm/boards/radxa-rock3/lowlevel.c b/arch/arm/boards/radxa-rock3/lowlevel.c
> index 2a449c17ae..a62f60dff8 100644
> --- a/arch/arm/boards/radxa-rock3/lowlevel.c
> +++ b/arch/arm/boards/radxa-rock3/lowlevel.c
> @@ -17,6 +17,10 @@ static noinline void rk3568_start(void)
>  	/*
>  	 * Enable vccio4 1.8V and vccio6 1.8V
>  	 * Needed for GMAC to work.
> +	 * FIXME: This is done by the io-domain driver as well, but there
> +	 * currently is no mechanism to make sure the driver gets probed
> +	 * before its consumers. Remove this setup once this issue is
> +	 * resolved.
>  	 */
>  	writel(RK_SETBITS(0x50), 0xfdc20140);
>  
> diff --git a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
> index f79f975080..4336d99365 100644
> --- a/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
> +++ b/arch/arm/boards/rockchip-rk3568-bpi-r2pro/lowlevel.c
> @@ -18,6 +18,10 @@ static noinline void rk3568_start(void)
>  	/*
>  	 * set iodomain vccio6 to 1.8V needed for GMAC1 to work.
>  	 * vccio4 (gmac0/switch) needs to stay at 3v3 (default)
> +	 * FIXME: This is done by the io-domain driver as well, but there
> +	 * currently is no mechanism to make sure the driver gets probed
> +	 * before its consumers. Remove this setup once this issue is
> +	 * resolved.
>  	 */
>  	//set bit 6 in PMU_GRF_IO_VSEL0 for vccio6 1v8
>  	writel(RK_SETBITS(BIT(6)), PMU_GRF_IO_VSEL0);
> diff --git a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
> index 363639d21b..9ab436135c 100644
> --- a/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
> +++ b/arch/arm/boards/rockchip-rk3568-evb/lowlevel.c
> @@ -18,6 +18,10 @@ static noinline void rk3568_start(void)
>  	/*
>  	 * Enable vccio4 1.8V and vccio6 1.8V
>  	 * Needed for GMAC to work.
> +	 * FIXME: This is done by the io-domain driver as well, but there
> +	 * currently is no mechanism to make sure the driver gets probed
> +	 * before its consumers. Remove this setup once this issue is
> +	 * resolved.
>  	 */
>  	writel(RK_SETBITS(0x50), 0xfdc20140);
>  


-- 
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-5555 |


From a.fatoum at pengutronix.de  Thu Sep 22 01:13:41 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 22 Sep 2022 09:13:41 +0100
Subject: [PATCH] USB: gadget: fastboot: introduce optional flag for
 fastboot partitions
In-Reply-To: <20220922072723.1559333-1-j.zink@pengutronix.de>
References: <20220922072723.1559333-1-j.zink@pengutronix.de>
Message-ID: <5ffe5490-4c93-f183-28d5-2f127da3fd9d@pengutronix.de>

Hi,

On 22.09.22 08:27, Johannes Zink wrote:
> On some boards, some partitions exposed to fastboot may become
> unavailable under certain circumstances, e.g. if an SD-Card exposed to
> fastboot is removed.
> 
> Previously, this lead to an error and the fastboot gadget did not
> initialize the remaining partitions exposed via fastboot, e.g. an
> eMMC which usually is permanently soldered on the board.
> 
> This patch allows to append an optional flag 'o' to the description of a
> fastboot partition. If this partition is unavailable at the
> initialization of the fastboot gadget, said partition is skipped, while
> the remaining available partitions are still exposed.
> 
> Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
> ---
>  Documentation/user/usb.rst | 1 +
>  common/fastboot.c          | 6 +++++-
>  common/file-list.c         | 3 +++
>  include/file-list.h        | 1 +
>  4 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
> index 2479efe9d6..f2f57ead98 100644
> --- a/Documentation/user/usb.rst
> +++ b/Documentation/user/usb.rst
> @@ -65,6 +65,7 @@ Several **flags** are supported, each denoted by a single character:
>  * ``r`` Readback. The partition is allowed to be read back (DFU specific)
>  * ``c`` The file shall be created if it doesn't exist. Needed when a regular file is exported.
>  * ``u`` The partition is a MTD device and shall be flashed with a UBI image.
> +* ``o`` The partition is optional, i.e. if it is not available at initialization time, it is skipped instead of aborting the initialization
>  
>  Example:
>  
> diff --git a/common/fastboot.c b/common/fastboot.c
> index 330a06f5a3..6bd1191325 100644
> --- a/common/fastboot.c
> +++ b/common/fastboot.c
> @@ -177,7 +177,11 @@ int fastboot_generic_init(struct fastboot *fb, bool export_bbu)
>  	file_list_for_each_entry(fb->files, fentry) {
>  		ret = fastboot_add_partition_variables(fb, fentry);
>  		if (ret)
> -			return ret;
> +			if((fentry->flags & FILE_LIST_FLAG_OPTIONAL))
> +				pr_info("failed to add optional partition %s to fastboot gadget\n",

s/failed to add/skipping unavailable/

to make this more in line with the chosen log level.

> +					fentry->filename);
> +			else
> +				return ret;

Please avoid dangling else here, either with braces or by having an 
if (ret && fentry->flags & FILE_LIST_FLAG_OPTIONAL)) as first condition.

>  	}
>  
>  	return 0;
> diff --git a/common/file-list.c b/common/file-list.c
> index 407b312833..68a7768696 100644
> --- a/common/file-list.c
> +++ b/common/file-list.c
> @@ -88,6 +88,9 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
>  			case 'u':
>  				flags |= FILE_LIST_FLAG_UBI;
>  				break;
> +			case 'o':
> +				flags |= FILE_LIST_FLAG_OPTIONAL;
> +				break;
>  			default:
>  				pr_err("Unknown flag '%c'\n", *partstr);
>  				return -EINVAL;

When adding new flags, search for all instances of a similar flag and add
your new flag there as well. You're missing flags_to_str().

> diff --git a/include/file-list.h b/include/file-list.h
> index 5090313739..bcb06979c8 100644
> --- a/include/file-list.h
> +++ b/include/file-list.h
> @@ -8,6 +8,7 @@
>  #define FILE_LIST_FLAG_READBACK	(1 << 1)
>  #define FILE_LIST_FLAG_CREATE	(1 << 2)
>  #define FILE_LIST_FLAG_UBI	(1 << 3)
> +#define FILE_LIST_FLAG_OPTIONAL (1 << 4)
>  
>  struct file_list_entry {
>  	char *name;

Cheers,

-- 
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-5555 |


From sha at pengutronix.de  Thu Sep 22 01:23:01 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 22 Sep 2022 10:23:01 +0200
Subject: [PATCH v2 1/7] soc: rockchip: add driver for rockchip io domains
In-Reply-To: <d4e9f025-4327-2370-89f1-ad79d72e62af@pengutronix.de>
References: <20220919113948.991245-1-michael.riesch@wolfvision.net>
 <20220919113948.991245-2-michael.riesch@wolfvision.net>
 <20220921094649.GC986@pengutronix.de>
 <223f9b7c-a95a-7847-503d-e51cb2abaf64@wolfvision.net>
 <20220922080329.GG986@pengutronix.de>
 <d4e9f025-4327-2370-89f1-ad79d72e62af@pengutronix.de>
Message-ID: <20220922082301.GH986@pengutronix.de>

On Thu, Sep 22, 2022 at 09:13:35AM +0100, Ahmad Fatoum wrote:
> Hi,
> 
> On 22.09.22 09:03, Sascha Hauer wrote:
> > On Wed, Sep 21, 2022 at 01:49:49PM +0200, Michael Riesch wrote:
> >> Hi Sascha,
> >>
> >> On 9/21/22 11:46, Sascha Hauer wrote:
> >>> On Mon, Sep 19, 2022 at 01:39:42PM +0200, Michael Riesch wrote:
> >>>> The IO domains in Rockchip SoCs need to be configured to match the
> >>>> corresponding bank voltage. In Linux this is achieved by means of a
> >>>> platform driver that reads the voltage value of the supplies and
> >>>> configures the bits in the general register file (GRF) accordingly.
> >>>> Port this driver to barebox to provide support for the Rockchip
> >>>> RK356x SoCs.
> >>>>
> >>>> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> >>>> ---
> >>>>  drivers/soc/Kconfig              |   1 +
> >>>>  drivers/soc/Makefile             |   1 +
> >>>>  drivers/soc/rockchip/Kconfig     |  17 +++
> >>>>  drivers/soc/rockchip/Makefile    |   6 +
> >>>>  drivers/soc/rockchip/io-domain.c | 223 +++++++++++++++++++++++++++++++
> >>>>  5 files changed, 248 insertions(+)
> >>>>  create mode 100644 drivers/soc/rockchip/Kconfig
> >>>>  create mode 100644 drivers/soc/rockchip/Makefile
> >>>>  create mode 100644 drivers/soc/rockchip/io-domain.c
> >>>
> >>> There's nothing in this driver that makes sure it is probed before the
> >>> users of the io domains. What happens when the users are probed before
> >>> the io domain driver?
> >>
> >> Correct. Unfortunately, the situation is quite the same in the kernel.
> >> Only recently there was a discussion as to how to resolve this issue
> >> [0]. While the RFC in [0] was received well there is no mainline
> >> solution to this problem. I would suggest that the mainline kernel
> >> solution is adopted once there is one.
> >>
> >> In the mean time we could
> >>  - accept that it just works for some reason (TM)
> >>  - leave the magic bits in the low-level initialization to be on the
> >>    safe side
> > 
> > Decided for this solution for now.
> > 
> > I added the following as a reminder that there's still something
> > to do.
> 
> Why not do an of_device_ensure_probed for the I/O domain driver in
> rk3568_init()?

We can't do a of_device_ensure_probed() properly from plain initcalls.
For example rk3568_init() is called at postcore level, at that time the
io-domain driver is not yet registered.

We would have to find an initcall level where the io-domain driver and
all its dependencies (i2c bus driver, PMIC driver) is registered, but
none of its consumers are probed. While we could probably find the right
initcall level this defeats the purpose of deep probe.

Sascha

-- 
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-5555 |


From sha at pengutronix.de  Thu Sep 22 01:35:43 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 22 Sep 2022 10:35:43 +0200
Subject: [PATCH] USB: gadget: fastboot: introduce optional flag for
 fastboot partitions
In-Reply-To: <20220922072723.1559333-1-j.zink@pengutronix.de>
References: <20220922072723.1559333-1-j.zink@pengutronix.de>
Message-ID: <20220922083543.GI986@pengutronix.de>

On Thu, Sep 22, 2022 at 09:27:23AM +0200, Johannes Zink wrote:
> On some boards, some partitions exposed to fastboot may become
> unavailable under certain circumstances, e.g. if an SD-Card exposed to
> fastboot is removed.
> 
> Previously, this lead to an error and the fastboot gadget did not
> initialize the remaining partitions exposed via fastboot, e.g. an
> eMMC which usually is permanently soldered on the board.
> 
> This patch allows to append an optional flag 'o' to the description of a
> fastboot partition. If this partition is unavailable at the
> initialization of the fastboot gadget, said partition is skipped, while
> the remaining available partitions are still exposed.
> 
> Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
> ---
>  Documentation/user/usb.rst | 1 +
>  common/fastboot.c          | 6 +++++-
>  common/file-list.c         | 3 +++
>  include/file-list.h        | 1 +
>  4 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
> index 2479efe9d6..f2f57ead98 100644
> --- a/Documentation/user/usb.rst
> +++ b/Documentation/user/usb.rst
> @@ -65,6 +65,7 @@ Several **flags** are supported, each denoted by a single character:
>  * ``r`` Readback. The partition is allowed to be read back (DFU specific)
>  * ``c`` The file shall be created if it doesn't exist. Needed when a regular file is exported.
>  * ``u`` The partition is a MTD device and shall be flashed with a UBI image.
> +* ``o`` The partition is optional, i.e. if it is not available at initialization time, it is skipped instead of aborting the initialization
>  
>  Example:
>  
> diff --git a/common/fastboot.c b/common/fastboot.c
> index 330a06f5a3..6bd1191325 100644
> --- a/common/fastboot.c
> +++ b/common/fastboot.c
> @@ -177,7 +177,11 @@ int fastboot_generic_init(struct fastboot *fb, bool export_bbu)
>  	file_list_for_each_entry(fb->files, fentry) {
>  		ret = fastboot_add_partition_variables(fb, fentry);
>  		if (ret)
> -			return ret;
> +			if((fentry->flags & FILE_LIST_FLAG_OPTIONAL))
> +				pr_info("failed to add optional partition %s to fastboot gadget\n",
> +					fentry->filename);
> +			else
> +				return ret;

I would prefer to check the FILE_LIST_FLAG_OPTIONAL flag in
fastboot_add_partition_variables(). That gives us the possibility to
explicitly check for the right conditions rather than generalising
all possible errors from fastboot_add_partition_variables().

Sascha


-- 
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-5555 |


From sha at pengutronix.de  Thu Sep 22 02:29:02 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 22 Sep 2022 11:29:02 +0200
Subject: [PATCH v1 1/3] net: port support for microchip SMI0 MDIO bus
In-Reply-To: <20220920125533.2497108-1-o.rempel@pengutronix.de>
References: <20220920125533.2497108-1-o.rempel@pengutronix.de>
Message-ID: <20220922092902.GJ986@pengutronix.de>

On Tue, Sep 20, 2022 at 02:55:31PM +0200, Oleksij Rempel wrote:
> SMI0 is a mangled version of MDIO. The main low level difference is
> the MDIO C22 OP code is always 0, not 0x2 or 0x1 for Read/Write. The
> read/write information is instead encoded in the PHY address.
> 
> Extend the bit-bang code to allow the op code to be overridden, but
> default to normal C22 values. Add an extra compatible to the mdio-gpio
> driver, and when this compatible is present, set the op codes to 0.
> 
> A higher level driver, sitting on top of the basic MDIO bus driver can
> then implement the rest of the microchip SMI0 odderties.
> 
> This code was ported from the kernel v6.0-rc2.
> 
> Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
> ---
>  drivers/net/phy/mdio-bitbang.c | 8 ++++++--
>  drivers/net/phy/mdio-gpio.c    | 8 ++++++++
>  include/linux/mdio-bitbang.h   | 3 +++
>  3 files changed, 17 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
> index 839a7d1eb8..656557589d 100644
> --- a/drivers/net/phy/mdio-bitbang.c
> +++ b/drivers/net/phy/mdio-bitbang.c
> @@ -158,7 +158,7 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int reg)
>  		reg = mdiobb_cmd_addr(ctrl, phy, reg);
>  		mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
>  	} else
> -		mdiobb_cmd(ctrl, MDIO_READ, phy, reg);
> +		mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg);
>  
>  	ctrl->ops->set_mdio_dir(ctrl, 0);
>  
> @@ -188,7 +188,7 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int reg, u16 val)
>  		reg = mdiobb_cmd_addr(ctrl, phy, reg);
>  		mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
>  	} else
> -		mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg);
> +		mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg);
>  
>  	/* send the turnaround (10) */
>  	mdiobb_send_bit(ctrl, 1);
> @@ -219,6 +219,10 @@ struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
>  	bus->write = mdiobb_write;
>  	bus->reset = mdiobb_reset;
>  	bus->priv = ctrl;
> +	if (!ctrl->override_op_c22) {
> +		ctrl->op_c22_read = MDIO_READ;
> +		ctrl->op_c22_write = MDIO_WRITE;
> +	}
>  
>  	return bus;
>  }
> diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
> index 80d2394f4b..c64f2b3925 100644
> --- a/drivers/net/phy/mdio-gpio.c
> +++ b/drivers/net/phy/mdio-gpio.c
> @@ -193,6 +193,13 @@ static int mdio_gpio_probe(struct device_d *dev)
>  		goto free_mdo;
>  	}
>  
> +	if (np &&
> +	    of_device_is_compatible(np, "microchip,mdio-smi0")) {
> +		info->ctrl.op_c22_read = 0;
> +		info->ctrl.op_c22_write = 0;
> +		info->ctrl.override_op_c22 = 1;
> +	}
> +
>  	bus = alloc_mdio_bitbang(&info->ctrl);
>  	bus->parent = dev;
>  	bus->dev.device_node = np;
> @@ -217,6 +224,7 @@ free_info:
>  
>  static const struct of_device_id gpio_mdio_dt_ids[] = {
>  	{ .compatible = "virtual,mdio-gpio", },
> +	{ .compatible = "microchip,mdio-smi0" },
>  	{ /* sentinel */ }
>  };
>  
> diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h
> index a6e6057886..49fe435429 100644
> --- a/include/linux/mdio-bitbang.h
> +++ b/include/linux/mdio-bitbang.h
> @@ -36,6 +36,9 @@ struct mdiobb_ctrl {
>  	const struct mdiobb_ops *ops;
>  	/* reset callback */
>  	int (*reset)(struct mii_bus *bus);
> +	unsigned int override_op_c22;
> +	u8 op_c22_read;
> +	u8 op_c22_write;
>  };
>  
>  /* The returned bus is not yet registered with the phy layer. */
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From s.hauer at pengutronix.de  Thu Sep 22 02:41:15 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 22 Sep 2022 11:41:15 +0200
Subject: [PATCH] net: Bring up all interfaces before going interactive
In-Reply-To: <CAMHeXxPJoHO6_eL9sf-_Fu+oqJQv278f9D8RifBkG2YV_yYYmw@mail.gmail.com>
References: <20220916124942.3751131-1-s.hauer@pengutronix.de>
 <20220916131606.GZ6477@pengutronix.de>
 <CAMHeXxOuxZnVcavXvwi1Y13kfRBP+opRgqwyEvSGBjQK6dSX1A@mail.gmail.com>
 <20220920074120.GF6477@pengutronix.de>
 <CAMHeXxPJoHO6_eL9sf-_Fu+oqJQv278f9D8RifBkG2YV_yYYmw@mail.gmail.com>
Message-ID: <20220922094115.GK986@pengutronix.de>

On Tue, Sep 20, 2022 at 02:47:07AM -0700, Trent Piepho wrote:
> On Tue, Sep 20, 2022 at 12:41 AM Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > On Mon, Sep 19, 2022 at 10:20:53AM -0700, Trent Piepho wrote:
> > > On Fri, Sep 16, 2022 at 6:16 AM Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > > >
> > > > We could make the user experience even a bit better by doing this call
> > > > before waiting for the autoboot timeout which then speeds up netboot a
> > > > bit.
> > >
> > > The Linux phy driver almost invariably does not bother to avoid
> > > resetting the network phy when not necessary.  So if network
> > > auto-negotiation is started in barebox, it will be reset and then
> > > restarted shortly after in Linux.  The link auto-negotiation impacts
> > > the LAN's spanning tree if that is in use.
> > >
> > > So there is a drawback, besides the small added boot time to
> > > initialize the network hardware, to adding an unneeded network restart
> > > in Barebox in the case where interactive mode is not entered and
> > > network boot is not used.
> >
> > So is this a vote to only do the autonegotiaton when going interactive
> > in barebox, or a vote to do autonegotiation only when the network is
> > being used in barebox?
> 
> I would vote to only do it when going interactive.

I changed the behaviour accordingly.

> 
> It also seems reasonable to bring the network up quickly when network
> booting, but I think determining if the system will network boot,
> before actually trying to boot, is probably unreasonably difficult to
> do.

I don't know how we could determine if we are going to do a network
boot.
We could do the network initialisation earlier based on some globalvar
like Marco suggested, but currently I do not have enough motivation to
implement it.

Sascha

-- 
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-5555 |


From sha at pengutronix.de  Thu Sep 22 02:51:56 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 22 Sep 2022 11:51:56 +0200
Subject: [PATCH 1/2] ddr: imx8m: write fsp_table entry automatically
In-Reply-To: <20220921172052.2989506-1-m.felsch@pengutronix.de>
References: <20220921172052.2989506-1-m.felsch@pengutronix.de>
Message-ID: <20220922095156.GL986@pengutronix.de>

On Wed, Sep 21, 2022 at 07:20:51PM +0200, Marco Felsch wrote:
> Currently the fsp_table must be set manually within the 'struct
> dram_timing_info'. Since the 'struct fsp_msg' already has all
> information needed for the fsp_table we can use it to set it
> automatically. This approach is less error-prone and avoids information
> duplication.

Is this really worth it? The whole dram timing code comes directly from
the NXP DRAM tools, so the fsp_table comes back with each new board or
with a DRAM timing update.

Sascha

-- 
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-5555 |


From m.felsch at pengutronix.de  Thu Sep 22 02:54:21 2022
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Thu, 22 Sep 2022 11:54:21 +0200
Subject: [PATCH 1/2] ddr: imx8m: write fsp_table entry automatically
In-Reply-To: <20220922095156.GL986@pengutronix.de>
References: <20220921172052.2989506-1-m.felsch@pengutronix.de>
 <20220922095156.GL986@pengutronix.de>
Message-ID: <20220922095421.r4im3dbbmrz4ats2@pengutronix.de>

On 22-09-22, Sascha Hauer wrote:
> On Wed, Sep 21, 2022 at 07:20:51PM +0200, Marco Felsch wrote:
> > Currently the fsp_table must be set manually within the 'struct
> > dram_timing_info'. Since the 'struct fsp_msg' already has all
> > information needed for the fsp_table we can use it to set it
> > automatically. This approach is less error-prone and avoids information
> > duplication.
> 
> Is this really worth it? The whole dram timing code comes directly from
> the NXP DRAM tools, so the fsp_table comes back with each new board or
> with a DRAM timing update.

I had a problem with the missing fsp_table for the MX8MM-EVK and a buggy
TF-A. Therefore I would say yes, since it is not guaranteed that the
fsp_table is existing.

Regards,
  Marco


From j.zink at pengutronix.de  Thu Sep 22 06:24:10 2022
From: j.zink at pengutronix.de (Johannes Zink)
Date: Thu, 22 Sep 2022 15:24:10 +0200
Subject: [PATCH v2] USB: gadget: fastboot: introduce optional flag for fastboot partitions
Message-ID: <20220922132410.2653284-1-j.zink@pengutronix.de>

On some boards, some partitions exposed to fastboot may become
unavailable under certain circumstances, e.g. if an SD-Card exposed to
fastboot is removed.

Previously, this lead to an error and the fastboot gadget did not
initialize the remaining partitions exposed via fastboot, e.g. an
eMMC which usually is permanently soldered on the board.

This patch allows to append an optional flag 'o' to the description of a
fastboot partition. If this partition is unavailable at the
initialization of the fastboot gadget, said partition is skipped, while
the remaining available partitions are still exposed.

Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
---
Changes since v1:
 - moved check for FILE_LIST_OPTIONAL flag to fastboot_add_partition_variables().
   This allows for cleaner error checking on error conditions (Thanks Sascha)
 - reworded info message to indicate intended condition on skipping optional
   partitions rather than indicating an error condition (Thanks Ahmad)
 - added FILE_LIST_OPTIONAL flag to flags_to_str() (Thanks Ahmad

 Documentation/user/usb.rst | 1 +
 common/fastboot.c          | 8 ++++++++
 common/file-list.c         | 7 ++++++-
 include/file-list.h        | 1 +
 4 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
index 2479efe9d6..f2f57ead98 100644
--- a/Documentation/user/usb.rst
+++ b/Documentation/user/usb.rst
@@ -65,6 +65,7 @@ Several **flags** are supported, each denoted by a single character:
 * ``r`` Readback. The partition is allowed to be read back (DFU specific)
 * ``c`` The file shall be created if it doesn't exist. Needed when a regular file is exported.
 * ``u`` The partition is a MTD device and shall be flashed with a UBI image.
+* ``o`` The partition is optional, i.e. if it is not available at initialization time, it is skipped instead of aborting the initialization
 
 Example:
 
diff --git a/common/fastboot.c b/common/fastboot.c
index 330a06f5a3..249e953ad6 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -95,6 +95,14 @@ static int fastboot_add_partition_variables(struct fastboot *fb,
 	}
 
 	if (ret) {
+		if (fentry->flags & FILE_LIST_FLAG_OPTIONAL) {
+			pr_info("skipping unavailable optional partition %s for fastboot gadget\n",
+				fentry->filename);
+			ret = 0;
+			type = "unavailable";
+			goto out;
+		}
+
 		if (fentry->flags & FILE_LIST_FLAG_CREATE) {
 			ret = 0;
 			type = "file";
diff --git a/common/file-list.c b/common/file-list.c
index 407b312833..3bb3b39d05 100644
--- a/common/file-list.c
+++ b/common/file-list.c
@@ -88,6 +88,9 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
 			case 'u':
 				flags |= FILE_LIST_FLAG_UBI;
 				break;
+			case 'o':
+				flags |= FILE_LIST_FLAG_OPTIONAL;
+				break;
 			default:
 				pr_err("Unknown flag '%c'\n", *partstr);
 				return -EINVAL;
@@ -113,7 +116,7 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
 
 static const char *flags_to_str(int flags)
 {
-	static char str[sizeof "srcu"];
+	static char str[sizeof "srcuo"];
 	char *s = str;;
 
 	if (flags & FILE_LIST_FLAG_SAFE)
@@ -124,6 +127,8 @@ static const char *flags_to_str(int flags)
 		*s++ = 'c';
 	if (flags & FILE_LIST_FLAG_UBI)
 		*s++ = 'u';
+	if (flags & FILE_LIST_FLAG_OPTIONAL)
+		*s++ = 'o';
 
 	*s = '\0';
 
diff --git a/include/file-list.h b/include/file-list.h
index 5090313739..bcb06979c8 100644
--- a/include/file-list.h
+++ b/include/file-list.h
@@ -8,6 +8,7 @@
 #define FILE_LIST_FLAG_READBACK	(1 << 1)
 #define FILE_LIST_FLAG_CREATE	(1 << 2)
 #define FILE_LIST_FLAG_UBI	(1 << 3)
+#define FILE_LIST_FLAG_OPTIONAL (1 << 4)
 
 struct file_list_entry {
 	char *name;
-- 
2.30.2



From antonynpavlov at gmail.com  Thu Sep 22 09:24:21 2022
From: antonynpavlov at gmail.com (Antony Pavlov)
Date: Thu, 22 Sep 2022 19:24:21 +0300
Subject: Makefile.lib: cmd_dtc: warning: missing whitespace after the
 macro name
In-Reply-To: <20220919091410.GC6477@pengutronix.de>
References: <20220907112118.71575e3650222736432b3086@gmail.com>
	<20220912080152.GE24324@pengutronix.de>
	<20220912120734.3fa82231ca6d16ba604ee262@gmail.com>
	<20220919091410.GC6477@pengutronix.de>
Message-ID: <20220922192421.62a169b0993a454da401cc8f@gmail.com>

On Mon, 19 Sep 2022 11:14:10 +0200
Sascha Hauer <s.hauer at pengutronix.de> wrote:

Hi Sascha!

> Hi Antony,
> 
> On Mon, Sep 12, 2022 at 12:07:34PM +0300, Antony Pavlov wrote:
> > On Mon, 12 Sep 2022 10:01:52 +0200
> > Sascha Hauer <s.hauer at pengutronix.de> wrote:
> > 
> > > One side effect is that this gets even less readable.
> > 
> > Yes, you are right :)
> > 
> > > Another one would be that two dts filenames which only differ in the
> > > usage of '.' and '_' would result in the same define, but I think that
> > > case is negligible as this define is unused in barebox itself. It could
> >                                        ^^^^^^^^^^^^^^^^^^^^^^^^
> > > be used by external dts fragments passed in via CONFIG_EXTERNAL_DTS_FRAGMENTS.
> > > 
> > > Other than that, what side effects are you afraid of?
> > 
> > I have an idea that someone relies on these *_dts macros.
> > 
> > Now I see (as you have noted above) that there is no macro users in mainline source tree:
> 
> Could you create a formal patch from this?

I'll a formal patch in a few days.

-- 
Best regards,
? Antony Pavlov


From sha at pengutronix.de  Sun Sep 25 23:01:52 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 26 Sep 2022 08:01:52 +0200
Subject: [PATCH 1/2] ddr: imx8m: write fsp_table entry automatically
In-Reply-To: <20220921172052.2989506-1-m.felsch@pengutronix.de>
References: <20220921172052.2989506-1-m.felsch@pengutronix.de>
Message-ID: <20220926060152.GQ12909@pengutronix.de>

On Wed, Sep 21, 2022 at 07:20:51PM +0200, Marco Felsch wrote:
> Currently the fsp_table must be set manually within the 'struct
> dram_timing_info'. Since the 'struct fsp_msg' already has all
> information needed for the fsp_table we can use it to set it
> automatically. This approach is less error-prone and avoids information
> duplication.
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  drivers/ddr/imx8m/ddrphy_train.c |  3 +++
>  drivers/ddr/imx8m/helper.c       | 19 +++++++++++++++++++
>  include/soc/imx8m/ddr.h          |  2 ++
>  3 files changed, 24 insertions(+)
> 
> diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx8m/ddrphy_train.c
> index e9d35afdfb..09f1e77295 100644
> --- a/drivers/ddr/imx8m/ddrphy_train.c
> +++ b/drivers/ddr/imx8m/ddrphy_train.c
> @@ -165,6 +165,9 @@ int ddr_cfg_phy(struct dram_timing_info *dram_timing, unsigned type)
>  
>  		dwc_ddrphy_apb_wr(0xd0000, 0x1);
>  
> +		/* Training done, add entry to fsp_table */
> +		dram_write_fsp_table_entry(dram_timing, fsp_msg->drate);
> +
>  		fsp_msg++;
>  	}
>  
> diff --git a/drivers/ddr/imx8m/helper.c b/drivers/ddr/imx8m/helper.c
> index 98e4084958..e71401c1b2 100644
> --- a/drivers/ddr/imx8m/helper.c
> +++ b/drivers/ddr/imx8m/helper.c
> @@ -18,6 +18,25 @@
>  #define DMEM_OFFSET_ADDR 0x00054000
>  #define DDR_TRAIN_CODE_BASE_ADDR IP2APB_DDRPHY_IPS_BASE_ADDR(0)
>  
> +void dram_write_fsp_table_entry(struct dram_timing_info *timing_info,
> +				unsigned int data_rate)
> +{
> +	unsigned int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(timing_info->fsp_table); i++) {
> +		unsigned int entry = timing_info->fsp_table[i];
> +
> +		/* Skip already existing entries */
> +		if (entry == data_rate)
> +			return;
> +
> +		if (entry == 0) {
> +			timing_info->fsp_table[i] = data_rate;
> +			return;
> +		}
> +	}
> +}

The input struct dram_timing_info * comes directly from the boards and
should be treated as const. If you go that route please parse the
.fsp_msg data directly in dram_config_save().

Another way could be to just check the .fsp_msg and .fsp_table for
consistency and warn about it if necessary.
In the end the input data from the boards is redundant here. We are
not going to change the input data format as that comes from the NXP
DRAM tools. Just ignoring the .fsp_table like you do here might be
confusing as well.

Sascha

-- 
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-5555 |


From o.rempel at pengutronix.de  Mon Sep 26 01:17:34 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:34 +0200
Subject: [PATCH v1 2/8] driver: add dev_is_probed() helper function
In-Reply-To: <20220926081740.76968-1-o.rempel@pengutronix.de>
References: <20220926081740.76968-1-o.rempel@pengutronix.de>
Message-ID: <20220926081740.76968-2-o.rempel@pengutronix.de>

Add function to get device/driver probe state.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 include/driver.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/driver.h b/include/driver.h
index 543287a276..f48e906fec 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -618,4 +618,9 @@ static inline void *dev_get_priv(struct device_d *dev)
 	return dev->priv;
 }
 
+static inline bool dev_is_probed(struct device_d *dev)
+{
+	return dev->driver ? true : false;
+}
+
 #endif /* DRIVER_H */
-- 
2.30.2



From o.rempel at pengutronix.de  Mon Sep 26 01:17:38 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:38 +0200
Subject: [PATCH v1 6/8] ARM: boards: Skov-i.MX6: select KSZ8873 switch driver
In-Reply-To: <20220926081740.76968-1-o.rempel@pengutronix.de>
References: <20220926081740.76968-1-o.rempel@pengutronix.de>
Message-ID: <20220926081740.76968-6-o.rempel@pengutronix.de>

The board code depends now on the switch driver probe functionality. If
this driver is not enabled, we will make wrong decision.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/mach-imx/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index dcb70c8c1a..c78c950357 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -646,6 +646,8 @@ config MACH_SKOV_IMX6
 	select ARCH_IMX6
 	select ARM_USE_COMPRESSED_DTB
 	select MCI_IMX_ESDHC_PBL
+	select DSA
+	select DRIVER_NET_KSZ8873
 
 endif
 
-- 
2.30.2



From o.rempel at pengutronix.de  Mon Sep 26 01:17:33 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:33 +0200
Subject: [PATCH v1 1/8] mdio_bus: do reset only on PHY devices
Message-ID: <20220926081740.76968-1-o.rempel@pengutronix.de>

Do not reset MDIO devices. Device drivers should handle it.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 drivers/net/phy/mdio_bus.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index f06ab68f50..a68b0e47c0 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -263,12 +263,13 @@ static int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 		}
 
 		of_pinctrl_select_state_default(child);
-		of_mdiobus_reset_phy(mdio, child);
 
-		if (of_mdiobus_child_is_phy(child))
+		if (of_mdiobus_child_is_phy(child)) {
+			of_mdiobus_reset_phy(mdio, child);
 			of_mdiobus_register_phy(mdio, child, addr);
-		else
+		} else {
 			of_mdiobus_register_device(mdio, child, addr);
+		}
 	}
 
 	return 0;
-- 
2.30.2



From o.rempel at pengutronix.de  Mon Sep 26 01:17:35 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:35 +0200
Subject: [PATCH v1 3/8] net: ksz8873: add device validation to be able to detect missing switch
In-Reply-To: <20220926081740.76968-1-o.rempel@pengutronix.de>
References: <20220926081740.76968-1-o.rempel@pengutronix.de>
Message-ID: <20220926081740.76968-3-o.rempel@pengutronix.de>

Some board variants do not have ksz8873 chip but still need to use
same devicetree as the board with this chip. So we need to make sure if
switch chip is actually present, before completing the probe sequence.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 drivers/net/ksz8873.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/net/ksz8873.c b/drivers/net/ksz8873.c
index bd8071b872..38f61ed43e 100644
--- a/drivers/net/ksz8873.c
+++ b/drivers/net/ksz8873.c
@@ -10,6 +10,11 @@
 #include <of_device.h>
 #include <regmap.h>
 
+#define KSZ8873_CHIP_ID0		0x00
+#define KSZ8873_CHIP_ID1		0x01
+#define KSZ88_CHIP_ID_M			GENMASK(7, 4)
+#define KSZ88_REV_ID_M			GENMASK(3, 1)
+
 #define KSZ8873_GLOBAL_CTRL_1		0x03
 #define KSZ8873_PASS_ALL_FRAMES		BIT(7)
 #define KSZ8873_P3_TAIL_TAG_EN		BIT(6)
@@ -52,6 +57,8 @@
 struct ksz8873_dcfg {
 	unsigned int num_ports;
 	unsigned int phy_port_cnt;
+	u8 id0;
+	u8 id1;
 };
 
 struct ksz8873_switch {
@@ -363,6 +370,7 @@ static int ksz8873_probe_mdio(struct phy_device *mdiodev)
 	struct ksz8873_switch *priv;
 	struct dsa_switch *ds;
 	int ret, gpio;
+	u8 id0, id1;
 
 	priv = xzalloc(sizeof(*priv));
 
@@ -387,6 +395,18 @@ static int ksz8873_probe_mdio(struct phy_device *mdiodev)
 		gpio_set_active(gpio, false);
 	}
 
+	ret = ksz_read8(priv, KSZ8873_CHIP_ID0, &id0);
+	if (ret)
+		return ret;
+
+	ret = ksz_read8(priv, KSZ8873_CHIP_ID1, &id1);
+	if (ret)
+		return ret;
+
+	if (id0 != dcfg->id0 ||
+	    (id1 & (KSZ88_CHIP_ID_M | KSZ88_REV_ID_M)) != dcfg->id1)
+		return -ENODEV;
+
 	ds = &priv->ds;
 	ds->dev = dev;
 	ds->num_ports = dcfg->num_ports;
@@ -407,6 +427,8 @@ static int ksz8873_probe_mdio(struct phy_device *mdiodev)
 static const struct ksz8873_dcfg ksz8873_dcfg = {
 	.num_ports = 3,
 	.phy_port_cnt = 2,
+	.id0 = 0x88,
+	.id1 = 0x30,
 };
 
 static const struct of_device_id ksz8873_dt_ids[] = {
-- 
2.30.2



From o.rempel at pengutronix.de  Mon Sep 26 01:17:37 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:37 +0200
Subject: [PATCH v1 5/8] ARM: boards: skov-imx6: rework switch detection
In-Reply-To: <20220926081740.76968-1-o.rempel@pengutronix.de>
References: <20220926081740.76968-1-o.rempel@pengutronix.de>
Message-ID: <20220926081740.76968-5-o.rempel@pengutronix.de>

The KSZ8873 switch supports two ways of communication over MDIO bus:
1. Standard MDIO opcodes to talk with the switch PHYs only.
2. Not standard MDIO opcodes to talk with complete switch management and
   PHYs.

Previous switch detection board code was using option 1. over FEC. Now,
with the switch driver we are using option 2. with GPIO bitbang MDIO
bus, since FEC do not support special opcodes.

To avoid duplicating switch driver functionality, we will let do switch
detection and validation to the switch driver and the board code should
only test if switch driver was probed.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/skov-imx6/board.c | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/arch/arm/boards/skov-imx6/board.c b/arch/arm/boards/skov-imx6/board.c
index 140689c87b..3c51b76735 100644
--- a/arch/arm/boards/skov-imx6/board.c
+++ b/arch/arm/boards/skov-imx6/board.c
@@ -133,9 +133,6 @@ copy_mac_from_eth0:
 	return eth_of_fixup_node_from_eth_device(root, node_path, ethname);
 }
 
-#define SKOV_GPIO_MDIO_BUS	0
-#define SKOV_LAN1_PHY_ADDR	1
-
 #define MAX_V_GPIO 8
 
 struct board_description {
@@ -547,29 +544,25 @@ static void skov_init_board(const struct board_description *variant)
 
 static int skov_switch_test(void)
 {
-	struct phy_device *phydev;
+	struct device_d *sw_dev;
 	struct device_d *eth0;
-	struct mii_bus *mii;
 	int ret;
 
 	if (skov_board_no < 0)
 		return 0;
 
-	/* On this boards, we have only one MDIO bus. So, it is enough to take
-	 * the first one.
-	 */
-	mii = mdiobus_get_bus(SKOV_GPIO_MDIO_BUS);
-	/* We can't read the switch ID, but we get get ID of the first PHY,
-	 * which is enough to test if the switch is attached.
+	/* Driver should be able to detect if device do actually
+	 * exist. So, we need only to detect if driver is actually
+	 * probed.
 	 */
-	phydev = get_phy_device(mii, SKOV_LAN1_PHY_ADDR);
-	if (IS_ERR(phydev))
-		goto no_switch;
-
-	if (phydev->phy_id != PHY_ID_KSZ886X)
+	sw_dev = of_find_device_by_node_path("/mdio/switch at 0");
+	if (!sw_dev) {
+		pr_err("switch at 0 device was not created!\n");
 		goto no_switch;
+	}
 
-	return 0;
+	if (dev_is_probed(sw_dev))
+		return 0;
 
 no_switch:
 	skov_have_switch = false;
-- 
2.30.2



From o.rempel at pengutronix.de  Mon Sep 26 01:17:40 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:40 +0200
Subject: [PATCH v1 8/8] net: dsa: do not wait for aneg is actually done on the port start
In-Reply-To: <20220926081740.76968-1-o.rempel@pengutronix.de>
References: <20220926081740.76968-1-o.rempel@pengutronix.de>
Message-ID: <20220926081740.76968-8-o.rempel@pengutronix.de>

Aneg configuration should be done by the eth code, not dsa.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 drivers/net/dsa.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/net/dsa.c b/drivers/net/dsa.c
index 7a64a79412..040ba897e2 100644
--- a/drivers/net/dsa.c
+++ b/drivers/net/dsa.c
@@ -111,10 +111,6 @@ static int dsa_port_start(struct eth_device *edev)
 
 	dsa_port_set_ethaddr(edev);
 
-	ret = phy_wait_aneg_done(dp->edev.phydev);
-	if (ret)
-		return ret;
-
 	if (ops->port_enable) {
 		ret = ops->port_enable(dp, dp->index, dp->edev.phydev);
 		if (ret)
-- 
2.30.2



From o.rempel at pengutronix.de  Mon Sep 26 01:17:36 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:36 +0200
Subject: [PATCH v1 4/8] ARM: boards: skov-imx6: free used gpio devices pins
In-Reply-To: <20220926081740.76968-1-o.rempel@pengutronix.de>
References: <20220926081740.76968-1-o.rempel@pengutronix.de>
Message-ID: <20220926081740.76968-4-o.rempel@pengutronix.de>

Free used gpio pins to allow to take over them by actual device nodes

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/boards/skov-imx6/board.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/boards/skov-imx6/board.c b/arch/arm/boards/skov-imx6/board.c
index bceb215a01..140689c87b 100644
--- a/arch/arm/boards/skov-imx6/board.c
+++ b/arch/arm/boards/skov-imx6/board.c
@@ -501,11 +501,13 @@ static void skov_init_board(const struct board_description *variant)
 		 */
 		gpio_request(24, "must_be_low");
 		gpio_direction_output(24, 0);
+		gpio_free(24);
 	}
 
 	/* SD card handling */
 	gpio_request(205, "mmc io supply");
 	gpio_direction_output(205, 0); /* select 3.3 V IO voltage */
+	gpio_free(205);
 
 	if (variant->flags & SKOV_ENABLE_MMC_POWER) {
 		/*
@@ -516,6 +518,7 @@ static void skov_init_board(const struct board_description *variant)
 		gpio_direction_output(200, 0); /* switch on */
 		mdelay(1);
 		gpio_direction_output(200, 1); /* switch on */
+		gpio_free(200);
 	}
 
 	if (variant->flags & SKOV_DISPLAY_PARALLEL) {
-- 
2.30.2



From o.rempel at pengutronix.de  Mon Sep 26 01:17:39 2022
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Mon, 26 Sep 2022 10:17:39 +0200
Subject: [PATCH v1 7/8] ARM: dts: Skov i.MX6: start using mainlined kernel dts
In-Reply-To: <20220926081740.76968-1-o.rempel@pengutronix.de>
References: <20220926081740.76968-1-o.rempel@pengutronix.de>
Message-ID: <20220926081740.76968-7-o.rempel@pengutronix.de>

Skov i.MX6 device tree is mainline now, so now we can start using it in
the barebox.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/arm/dts/imx6q-skov-imx6.dts    |   4 -
 arch/arm/dts/imx6qdl-skov-imx6.dtsi | 233 +++-------------------------
 2 files changed, 25 insertions(+), 212 deletions(-)

diff --git a/arch/arm/dts/imx6q-skov-imx6.dts b/arch/arm/dts/imx6q-skov-imx6.dts
index fea84cb498..a14ddbf6db 100644
--- a/arch/arm/dts/imx6q-skov-imx6.dts
+++ b/arch/arm/dts/imx6q-skov-imx6.dts
@@ -17,10 +17,6 @@
 / {
 	model = "Skov IMX6";
 	compatible = "skov,imx6", "fsl,imx6q";
-
-	chosen {
-		stdout-path = &uart2;
-	};
 };
 
 &i2c2 {
diff --git a/arch/arm/dts/imx6qdl-skov-imx6.dtsi b/arch/arm/dts/imx6qdl-skov-imx6.dtsi
index 371a931e53..f4610ee1e7 100644
--- a/arch/arm/dts/imx6qdl-skov-imx6.dtsi
+++ b/arch/arm/dts/imx6qdl-skov-imx6.dtsi
@@ -9,7 +9,7 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <dt-bindings/gpio/gpio.h>
+#include <arm/imx6qdl-skov-cpu.dtsi>
 
 / {
 	aliases {
@@ -30,29 +30,6 @@
 		};
 	};
 
-	leds {
-		compatible = "gpio-leds";
-
-		led0: D1 {
-			label = "D1";
-			gpios = <&gpio1 2 0>;
-			default-state = "on";
-			linux,default-trigger = "heartbeat";
-		};
-
-		led1: D2 {
-			label = "D2";
-			gpios = <&gpio1 0 0>;
-			default-state = "off";
-		};
-
-		led2: D3 {
-			label = "D3";
-			gpios = <&gpio1 4 0>;
-			default-state = "on";
-		};
-	};
-
 	/* State: mutable part */
 	state: state {
 		magic = <0x34a0fc27>;
@@ -241,20 +218,6 @@
 	};
 };
 
-&pwm2 {
-	/* used for backlight brightness */
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_pwm2_2>;
-	status = "okay";
-};
-
-&pwm3 {
-	/* used for LCD contrast control */
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_pwm3_2>;
-	status = "okay";
-};
-
 &i2c2 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
@@ -278,21 +241,6 @@
 	status = "okay";
 };
 
-/* no usbh2 */
-&usbphynop1 {
-	status = "disabled";
-};
-
-/* no usbh3 */
-&usbphynop2 {
-	status = "disabled";
-};
-
-&usbotg {
-	disable-over-current;
-	status = "okay";
-};
-
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
@@ -300,10 +248,6 @@
 	pinctrl_hog: hoggrp {
 		/* we need a few pins as GPIOs */
 		fsl,pins = <
-			/* MMC IO voltage select */
-			MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x40000058
-			/* MMC Power Supply Switch (since revision C)
-			MX6QDL_PAD_SD3_RST__GPIO7_IO08 0x40000058
 			/* Backlight Power Supply Switch (since revision B)
 			MX6QDL_PAD_RGMII_TD3__GPIO6_IO23 0x40000058
 			/* Backlight Brightness */
@@ -313,70 +257,6 @@
 		>;
 	};
 
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
-			MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
-		>;
-	};
-
-	pinctrl_ecspi1: ecspi1grp {
-		fsl,pins = <
-			MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1
-			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1
-			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
-			MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x40000058 /* CS# signal */
-		>;
-	};
-
-	/* pins for eth0 */
-	pinctrl_enet: enetgrp {
-		fsl,pins = <
-			MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
-			MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
-			MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x100b0
-			MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x100b0
-			MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x100b0
-			MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x100b0
-			MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x100b0
-			MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x100b0
-			MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x400000c0
-		>;
-	};
-
-	pinctrl_usdhc3: usdhc3grp {
-		fsl,pins = <
-			MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
-			MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
-			MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
-			MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
-			MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
-			MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
-			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x1b040 /* WP */
-			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x1b040 /* CD */
-		>;
-	};
-
-	pinctrl_gpmi_nand: gpminandgrp {
-		fsl,pins = <
-			MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
-			MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
-			MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
-			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
-			MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
-			MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
-			MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
-			MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
-			MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
-			MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
-			MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
-			MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
-			MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
-			MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
-			MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
-		>;
-	};
-
 	pinctrl_i2c2_2: i2c2grp-2 {
 		fsl,pins = <
 			/* internal 22 k pull up required */
@@ -424,18 +304,6 @@
 			MX6QDL_PAD_RGMII_TD3__GPIO6_IO23	0x40000058
 		>;
 	};
-
-	pinctrl_pwm2_2: pwm2grp-2 {
-		fsl,pins = <
-			MX6QDL_PAD_GPIO_1__PWM2_OUT		0x00058
-		>;
-	};
-
-	pinctrl_pwm3_2: pwm3grp-2 {
-		fsl,pins = <
-			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x00058
-		>;
-	};
 };
 
 &clks {
@@ -445,43 +313,34 @@
 				 <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>;
 };
 
-/* console */
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	status = "okay";
-};
-
 /* spi */
 &ecspi1 {
-	fsl,spi-num-chipselects = <1>;
-	cs-gpios = <&gpio3 24 0>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi1>;
-	status = "okay";
+	flash at 0 {
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
 
-	norflash: m25p80 at 0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "jedec,spi-nor";
-		spi-max-frequency = <54000000>;
-		reg = <0>;
-	};
-};
+			partition at 0 {
+				label = "barebox";
+				reg = <0x0 0x100000>;
+			};
 
-/* eth0 */
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet>;
-	phy-mode = "rmii";
-	status = "okay";
-	phy-reset-gpios = <&gpio1 5 0>;
-	phy-reset-duration = <100>;
-	#address-cells = <0>;
-	#size-cells = <1>;
-	fixed-link {
-		speed = <100>;
-		full-duplex;
+			/* space left to let barebox grow */
+
+			/* placed near the end of the NOR memory */
+			barebox_env: partition at 780000 {
+				label = "barebox-environment";
+				reg = <0x780000 0x40000>;
+			};
+
+			/* placed at the end of the NOR memory */
+			state_storage: partition at 7C0000 {
+				label = "barebox-state";
+				/* four times mirrored */
+				reg = <0x7C0000 0x40000>;
+			};
+		};
 	};
 };
 
@@ -506,21 +365,7 @@
 	status = "okay";
 };
 
-&usdhc3 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc3>;
-	wp-gpios = <&gpio7 1 0>;
-	cd-gpios = <&gpio7 0 0>;
-	status = "okay";
-	fsl,delay-line;
-};
-
 &gpmi {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_gpmi_nand>;
-	nand-on-flash-bbt;
-	status = "okay";
-
 	partitions {
 		compatible = "fixed-partitions";
 		#address-cells = <1>;
@@ -533,34 +378,6 @@
 	};
 };
 
-/* define the SPI based 8 MiB NOR flash layout */
-&norflash {
-	partitions {
-		compatible = "fixed-partitions";
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		partition at 0 {
-			label = "barebox";
-			reg = <0x0 0x100000>;
-		};
-
-		/* space left to let barebox grow */
-
-		/* placed near the end of the NOR memory */
-		barebox_env: partition at 780000 {
-			label = "barebox-environment";
-			reg = <0x780000 0x40000>;
-		};
-
-		/* placed at the end of the NOR memory */
-		state_storage: partition at 7C0000 {
-			label = "barebox-state";
-			reg = <0x7C0000 0x40000>; /* four times mirrored */
-		};
-	};
-};
-
 &ocotp {
 	barebox,provide-mac-address = <&fec 0x620>;
 };
-- 
2.30.2



From sha at pengutronix.de  Mon Sep 26 01:22:28 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 26 Sep 2022 10:22:28 +0200
Subject: [PATCH v2] USB: gadget: fastboot: introduce optional flag for
 fastboot partitions
In-Reply-To: <20220922132410.2653284-1-j.zink@pengutronix.de>
References: <20220922132410.2653284-1-j.zink@pengutronix.de>
Message-ID: <20220926082228.GS986@pengutronix.de>

On Thu, Sep 22, 2022 at 03:24:10PM +0200, Johannes Zink wrote:
> On some boards, some partitions exposed to fastboot may become
> unavailable under certain circumstances, e.g. if an SD-Card exposed to
> fastboot is removed.
> 
> Previously, this lead to an error and the fastboot gadget did not
> initialize the remaining partitions exposed via fastboot, e.g. an
> eMMC which usually is permanently soldered on the board.
> 
> This patch allows to append an optional flag 'o' to the description of a
> fastboot partition. If this partition is unavailable at the
> initialization of the fastboot gadget, said partition is skipped, while
> the remaining available partitions are still exposed.
> 
> Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
> ---
> Changes since v1:
>  - moved check for FILE_LIST_OPTIONAL flag to fastboot_add_partition_variables().
>    This allows for cleaner error checking on error conditions (Thanks Sascha)
>  - reworded info message to indicate intended condition on skipping optional
>    partitions rather than indicating an error condition (Thanks Ahmad)
>  - added FILE_LIST_OPTIONAL flag to flags_to_str() (Thanks Ahmad

Applied, thanks

Sascha

> 
>  Documentation/user/usb.rst | 1 +
>  common/fastboot.c          | 8 ++++++++
>  common/file-list.c         | 7 ++++++-
>  include/file-list.h        | 1 +
>  4 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
> index 2479efe9d6..f2f57ead98 100644
> --- a/Documentation/user/usb.rst
> +++ b/Documentation/user/usb.rst
> @@ -65,6 +65,7 @@ Several **flags** are supported, each denoted by a single character:
>  * ``r`` Readback. The partition is allowed to be read back (DFU specific)
>  * ``c`` The file shall be created if it doesn't exist. Needed when a regular file is exported.
>  * ``u`` The partition is a MTD device and shall be flashed with a UBI image.
> +* ``o`` The partition is optional, i.e. if it is not available at initialization time, it is skipped instead of aborting the initialization
>  
>  Example:
>  
> diff --git a/common/fastboot.c b/common/fastboot.c
> index 330a06f5a3..249e953ad6 100644
> --- a/common/fastboot.c
> +++ b/common/fastboot.c
> @@ -95,6 +95,14 @@ static int fastboot_add_partition_variables(struct fastboot *fb,
>  	}
>  
>  	if (ret) {
> +		if (fentry->flags & FILE_LIST_FLAG_OPTIONAL) {
> +			pr_info("skipping unavailable optional partition %s for fastboot gadget\n",
> +				fentry->filename);
> +			ret = 0;
> +			type = "unavailable";
> +			goto out;
> +		}
> +
>  		if (fentry->flags & FILE_LIST_FLAG_CREATE) {
>  			ret = 0;
>  			type = "file";
> diff --git a/common/file-list.c b/common/file-list.c
> index 407b312833..3bb3b39d05 100644
> --- a/common/file-list.c
> +++ b/common/file-list.c
> @@ -88,6 +88,9 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
>  			case 'u':
>  				flags |= FILE_LIST_FLAG_UBI;
>  				break;
> +			case 'o':
> +				flags |= FILE_LIST_FLAG_OPTIONAL;
> +				break;
>  			default:
>  				pr_err("Unknown flag '%c'\n", *partstr);
>  				return -EINVAL;
> @@ -113,7 +116,7 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
>  
>  static const char *flags_to_str(int flags)
>  {
> -	static char str[sizeof "srcu"];
> +	static char str[sizeof "srcuo"];
>  	char *s = str;;
>  
>  	if (flags & FILE_LIST_FLAG_SAFE)
> @@ -124,6 +127,8 @@ static const char *flags_to_str(int flags)
>  		*s++ = 'c';
>  	if (flags & FILE_LIST_FLAG_UBI)
>  		*s++ = 'u';
> +	if (flags & FILE_LIST_FLAG_OPTIONAL)
> +		*s++ = 'o';
>  
>  	*s = '\0';
>  
> diff --git a/include/file-list.h b/include/file-list.h
> index 5090313739..bcb06979c8 100644
> --- a/include/file-list.h
> +++ b/include/file-list.h
> @@ -8,6 +8,7 @@
>  #define FILE_LIST_FLAG_READBACK	(1 << 1)
>  #define FILE_LIST_FLAG_CREATE	(1 << 2)
>  #define FILE_LIST_FLAG_UBI	(1 << 3)
> +#define FILE_LIST_FLAG_OPTIONAL (1 << 4)
>  
>  struct file_list_entry {
>  	char *name;
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From michael.riesch at wolfvision.net  Mon Sep 26 03:06:10 2022
From: michael.riesch at wolfvision.net (Michael Riesch)
Date: Mon, 26 Sep 2022 12:06:10 +0200
Subject: [PATCH] of: overlay: fix overly strict check for symbols
Message-ID: <20220926100610.1457821-1-michael.riesch@wolfvision.net>

The recent patch "of: overlay: improve error handling in
of_overlay_apply_tree" introduced overly strict checks for symbols
in the root device tree and the overlay. However, it is legal for
both to have no symbols. Fix the checks in order to implement the
status quo.

Fixes: bc475fd88810 ("of: overlay: improve error handling in of_overlay_apply_tree")
Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
---
 drivers/of/overlay.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 0fc440fdcf..9d112b67f1 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -131,12 +131,12 @@ static int of_overlay_apply_symbols(struct device_node *root,
 
 	if (!overlay_symbols) {
 		pr_debug("overlay doesn't have a __symbols__ node\n");
-		return -EINVAL;
+		return 0;
 	}
 
 	if (!root_symbols) {
 		pr_info("root doesn't have a __symbols__ node\n");
-		return -EINVAL;
+		return 0;
 	}
 
 	list_for_each_entry(prop, &overlay_symbols->properties, list) {
-- 
2.30.2



From a.fatoum at pengutronix.de  Mon Sep 26 03:26:55 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 26 Sep 2022 11:26:55 +0100
Subject: [PATCH] of: overlay: fix overly strict check for symbols
In-Reply-To: <20220926100610.1457821-1-michael.riesch@wolfvision.net>
References: <20220926100610.1457821-1-michael.riesch@wolfvision.net>
Message-ID: <fd93df72-c4da-0347-9c77-a9d96c2bc2e5@pengutronix.de>

On 26.09.22 11:06, Michael Riesch wrote:
> The recent patch "of: overlay: improve error handling in
> of_overlay_apply_tree" introduced overly strict checks for symbols
> in the root device tree and the overlay. However, it is legal for
> both to have no symbols. Fix the checks in order to implement the
> status quo.
> 
> Fixes: bc475fd88810 ("of: overlay: improve error handling in of_overlay_apply_tree")
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>


Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

FWIW, we do such fixups on the emulated Virt platforms. The device tree comes
from QEMU and lacks symbols, still barebox applies an overlay with state
and environment nodes on top of it.

Cheers,
Ahmad

> ---
>  drivers/of/overlay.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index 0fc440fdcf..9d112b67f1 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -131,12 +131,12 @@ static int of_overlay_apply_symbols(struct device_node *root,
>  
>  	if (!overlay_symbols) {
>  		pr_debug("overlay doesn't have a __symbols__ node\n");
> -		return -EINVAL;
> +		return 0;
>  	}
>  
>  	if (!root_symbols) {
>  		pr_info("root doesn't have a __symbols__ node\n");
> -		return -EINVAL;
> +		return 0;
>  	}
>  
>  	list_for_each_entry(prop, &overlay_symbols->properties, list) {


-- 
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-5555 |


From enrico.scholz at sigma-chemnitz.de  Tue Sep 27 10:21:33 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Tue, 27 Sep 2022 19:21:33 +0200
Subject: Broken ubifs-zstd
Message-ID: <lyr0zw68de.fsf@ensc-pc.intern.sigma-chemnitz.de>

Hello,

trying to mount a zstd compressed ubifs fails on an iMX6ULL with

| ERROR: UBIFS error (ubi0:0): 9fe6691d: cannot decompress 2612 bytes, compressor zstd, error -22
| ERROR: UBIFS error (ubi0:0): 9fe6692d: cannot decompress 2612 bytes, compressor zstd, error -22
| ERROR: UBIFS error (ubi0:0): 9fe66a65: bad data node (block 0, inode 815)
| ERROR:  magic          0x6101831

(2022.09 and master).


After reverting

| commit b4a9782d4f56333e897dccc35c2c27e2605f6b93
| Author: Ahmad Fatoum <a.fatoum at pengutronix.de>
| Date:   Wed Jul 13 12:09:18 2022 +0200
| 
|     lib: zstd: sync with Linux

it works again (both in Linux 5.15 and barebox).


ubifs was created by recent OpenEmbedded kirkstone with

| MKUBIFS_ARGS = "-F -m 2048 -e 126976 -c 2048 --compr=zstd"


Warnings are triggered (after fixing assert()) at

| WARNING: at lib/zstd/decompress/../common/bitstream.h:390/BIT_reloadDStreamFast()!


Is anybody else experiencing these problems?



Enrico


From enrico.scholz at sigma-chemnitz.de  Tue Sep 27 10:22:17 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Tue, 27 Sep 2022 19:22:17 +0200
Subject: [PATCH] zstd: fix assert() logic
Message-ID: <20220927172217.662321-1-enrico.scholz@sigma-chemnitz.de>

It should warn when condition does **not** hold

Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
---
 lib/zstd/common/zstd_deps.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/zstd/common/zstd_deps.h b/lib/zstd/common/zstd_deps.h
index 7a5bf44839c9..f06df065dec0 100644
--- a/lib/zstd/common/zstd_deps.h
+++ b/lib/zstd/common/zstd_deps.h
@@ -84,7 +84,7 @@ static uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) {
 
 #include <linux/kernel.h>
 
-#define assert(x) WARN_ON((x))
+#define assert(x) WARN_ON(!(x))
 
 #endif /* ZSTD_DEPS_ASSERT */
 #endif /* ZSTD_DEPS_NEED_ASSERT */
-- 
2.37.3



From a.fatoum at pengutronix.de  Tue Sep 27 10:31:01 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 27 Sep 2022 19:31:01 +0200
Subject: [PATCH master] imx-usb-loader: skip initial SDP_ERROR_STATUS query for SDPS
Message-ID: <20220927173101.1696673-1-a.fatoum@pengutronix.de>

We do an initial do_status() every time, which fails for i.MX8MP and
i.MX8MN:

  found i.MX8MP USB device [1fc9:0146]
  4 in err=-9, last_trans=0  00 00 00 00
  status failed

If we instead skip it for SDPS (i.e. hid_endpoint), upload works as
expected (tested on i.MX8M Nano).

Reported-by: Hans Christian L?nstad <hcl at datarespons.no>
Fixes: 23e2203150b6 ("imx-usb-loader: Add i.MX8MP support")
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 scripts/imx/imx-usb-loader.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 1242f2dedda5..a98ab0e33f8a 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -1628,10 +1628,12 @@ int main(int argc, char *argv[])
 		goto out;
 	}
 
-	err = do_status();
-	if (err) {
-		printf("status failed\n");
-		goto out;
+	if (!mach_id->hid_endpoint) {
+		err = do_status();
+		if (err) {
+			printf("status failed\n");
+			goto out;
+		}
 	}
 
 	if (initfile) {
-- 
2.30.2



From a.fatoum at pengutronix.de  Tue Sep 27 10:42:47 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 27 Sep 2022 18:42:47 +0100
Subject: Imx-usb-loader broken on IMX8MP/v2022.09.0
In-Reply-To: <8CA6ADB4-FD4B-4CC8-9BD2-21DA02C08C85@datarespons.no>
References: <8CA6ADB4-FD4B-4CC8-9BD2-21DA02C08C85@datarespons.no>
Message-ID: <e0778785-7de6-f91c-d4b1-3f828f6effe1@pengutronix.de>

Hello Hans,

On 17.09.22 13:04, Hans Christian L?nstad wrote:
> This is observed using straight out of the box v2022.09.0 on NXP IMX8MP Eval kit:
> 
> ---------
> 
> $ sudo ../drimx8/scripts/imx/imx-usb-loader ../drimx8/images/barebox-nxp-imx8mp-evk.img 
> [sudo] password for hcl: 
> found i.MX8MP USB device [1fc9:0146]
> 4 in err=-9, last_trans=0  00 00 00 00
> status failed

I just tested and have the same issue on i.MX8M Nano, which uses
the same new SDPS protocol. I've just sent out a potential fix.

> ????
> 
> Stripping off the header gap (32K) allows the binary to load using the standard NXP uuu (Ubuntu 22.04) utility,.
> 
> This further raises the question: Why have a header gap at all?
> 
> The makes sense for SD card loading, but not for eMMC boot partitions where ROM expects code to start at 0.

The realization that the eMMC boot partition usually lacks an on-disk partition
table came quite late to the NXP BootROM authors. On i.MX8M Mini, we still have
an offset for both SD-Card and eMMC boot partition.

> Maybe better just use a seek to put the code at the relevant position on the SD card?

imx-usb-loader does the correct thing and skips to the relevant position.
barebox_update should do the correct thing and skip over the header.

> For instance, I am using the Rauc boot loader slot update mechanism expecting no gap thus  requiring me to shave of 32k
> prior to shipping.

This is unfortunate, but I don't think this is something we should address at the
barebox side. barebox images for i.MX are always meant to be directly written
to an SD-Card at offset 0.

For RAUC integration, you may consider having your build system shave off the
bytes transparently. See for example:

https://github.com/rauc/meta-rauc/commit/8e049699f05483b694e6c5a3e260cd9e0fe58d2e

which does the inverse operation: pad U-Boot for older i.MX, so they are install-able
into an eMMC boot partition.

Cheers,
Ahmad

> 
> Comments??
> 
> Hans Christian
> 


-- 
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-5555 |


From a.fatoum at pengutronix.de  Tue Sep 27 10:45:42 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 27 Sep 2022 18:45:42 +0100
Subject: Broken ubifs-zstd
In-Reply-To: <lyr0zw68de.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <lyr0zw68de.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <f3f0d847-c37f-599c-fb3a-14de696e4270@pengutronix.de>

Hello Enrico,

On 27.09.22 18:21, Enrico Scholz wrote:
> Hello,
> 
> trying to mount a zstd compressed ubifs fails on an iMX6ULL with
> 
> | ERROR: UBIFS error (ubi0:0): 9fe6691d: cannot decompress 2612 bytes, compressor zstd, error -22
> | ERROR: UBIFS error (ubi0:0): 9fe6692d: cannot decompress 2612 bytes, compressor zstd, error -22
> | ERROR: UBIFS error (ubi0:0): 9fe66a65: bad data node (block 0, inode 815)
> | ERROR:  magic          0x6101831
> 
> (2022.09 and master).
> 
> 
> After reverting
> 
> | commit b4a9782d4f56333e897dccc35c2c27e2605f6b93
> | Author: Ahmad Fatoum <a.fatoum at pengutronix.de>
> | Date:   Wed Jul 13 12:09:18 2022 +0200
> | 
> |     lib: zstd: sync with Linux
> 
> it works again (both in Linux 5.15 and barebox).
> 
> 
> ubifs was created by recent OpenEmbedded kirkstone with
> 
> | MKUBIFS_ARGS = "-F -m 2048 -e 126976 -c 2048 --compr=zstd"
> 
> 
> Warnings are triggered (after fixing assert()) at
> 
> | WARNING: at lib/zstd/decompress/../common/bitstream.h:390/BIT_reloadDStreamFast()!
> 
> 
> Is anybody else experiencing these problems?


I am afraid, I didn't properly test this with UBIFS..

> 
> 
> 
> Enrico
> 
> 


-- 
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-5555 |


From a.fatoum at pengutronix.de  Wed Sep 28 01:50:52 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 28 Sep 2022 10:50:52 +0200
Subject: [PATCH] mfd: axp20x: export axp20x-regulator child for AXP152
Message-ID: <20220928085052.2599436-1-a.fatoum@pengutronix.de>

While the upstream Linux driver doesn't support regulator configuration
for the AXP152, we may need this in barebox for initial regulator setup.
Thus have the MFD driver register the appropriate child device as done
for the other drivers. While at it, pass along the axp20x driver data
object. This is needed, so the regulator driver can query the variant;
so far it was only possible to retrieve the parent regmap and redo the
revision readout.

Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/mfd/axp20x.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index da1e8ce35a7d..0a53eaea7cfa 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -141,6 +141,9 @@ static const struct mfd_cell axp152_cells[] = {
 	{
 		.name		= "axp20x-pek",
 	},
+	{
+		.name		= "axp20x-regulator",
+	},
 };
 
 static const struct mfd_cell axp288_cells[] = {
@@ -337,6 +340,8 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
 				     AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
 	}
 
+	axp20x->dev->priv = axp20x;
+
 	ret = mfd_add_devices(axp20x->dev, axp20x->cells, axp20x->nr_cells);
 	if (ret)
 		return dev_err_probe(axp20x->dev, ret, "failed to add MFD devices\n");
-- 
2.30.2



From a.fatoum at pengutronix.de  Wed Sep 28 01:56:22 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Wed, 28 Sep 2022 10:56:22 +0200
Subject: [PATCH master] bbu: fix exporting i.MX NAND bbu handler over fastboot
Message-ID: <20220928085622.2677478-1-a.fatoum@pengutronix.de>

handler->devicefile for i.MX NAND is nand0.barebox, which lacks a /dev/
prefix. This is ok for detection, as device_detect_by_name expects the
cdev name and devpath_to_name() will strip a /dev/ if available.

For stat() however, we need to add back /dev/, otherwise the file can't
be found. Rework the code to do that.

This fixes an issue where usbgadget -A '' -b would not export a i.MX
NAND barebox update handler.

Fixes: 726a802456bc ("common: bbu: only add available handlers")
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/bbu.c | 37 ++++++++++++++++++-------------------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/common/bbu.c b/common/bbu.c
index d243ac89dd9f..3ec17216cb15 100644
--- a/common/bbu.c
+++ b/common/bbu.c
@@ -24,43 +24,42 @@
 
 static LIST_HEAD(bbu_image_handlers);
 
-static void append_bbu_entry(struct bbu_handler *handler, struct file_list *files)
+static void append_bbu_entry(const char *_name,
+			     const char *devicefile,
+			     struct file_list *files)
 {
 	char *name;
 
-	name = basprintf("bbu-%s", handler->name);
+	name = basprintf("bbu-%s", _name);
 
-	if (file_list_add_entry(files, name, handler->devicefile, 0))
+	if (file_list_add_entry(files, name, devicefile, 0))
 		pr_warn("duplicate partition name %s\n", name);
 
 	free(name);
 }
 
-static bool bbu_handler_is_available(struct bbu_handler *handler)
-{
-	struct stat s;
-	int ret;
-
-	device_detect_by_name(devpath_to_name(handler->devicefile));
-
-	ret = stat(handler->devicefile, &s);
-	if (ret)
-		return false;
-
-	return true;
-}
-
 void bbu_append_handlers_to_file_list(struct file_list *files)
 {
 	struct bbu_handler *handler;
 
 	list_for_each_entry(handler, &bbu_image_handlers, list) {
-		if (bbu_handler_is_available(handler)) {
-			append_bbu_entry(handler, files);
+		const char *cdevname;
+		struct stat s;
+		char *devpath;
+
+		cdevname = devpath_to_name(handler->devicefile);
+		device_detect_by_name(cdevname);
+
+		devpath = basprintf("/dev/%s", cdevname);
+
+		if (stat(devpath, &s) == 0) {
+			append_bbu_entry(handler->name, devpath, files);
 		} else {
 			pr_info("Skipping unavailable handler bbu-%s\n",
 				handler->name);
 		}
+
+		free(devpath);
 	}
 }
 
-- 
2.30.2



From sha at pengutronix.de  Wed Sep 28 02:11:41 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 28 Sep 2022 11:11:41 +0200
Subject: [PATCH] zstd: fix assert() logic
In-Reply-To: <20220927172217.662321-1-enrico.scholz@sigma-chemnitz.de>
References: <20220927172217.662321-1-enrico.scholz@sigma-chemnitz.de>
Message-ID: <20220928091141.GV986@pengutronix.de>

On Tue, Sep 27, 2022 at 07:22:17PM +0200, Enrico Scholz wrote:
> It should warn when condition does **not** hold
> 
> Signed-off-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
> ---
>  lib/zstd/common/zstd_deps.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks.

That fixes only the warnings, not the regression, right?

Sascha

> 
> diff --git a/lib/zstd/common/zstd_deps.h b/lib/zstd/common/zstd_deps.h
> index 7a5bf44839c9..f06df065dec0 100644
> --- a/lib/zstd/common/zstd_deps.h
> +++ b/lib/zstd/common/zstd_deps.h
> @@ -84,7 +84,7 @@ static uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) {
>  
>  #include <linux/kernel.h>
>  
> -#define assert(x) WARN_ON((x))
> +#define assert(x) WARN_ON(!(x))
>  
>  #endif /* ZSTD_DEPS_ASSERT */
>  #endif /* ZSTD_DEPS_NEED_ASSERT */
> -- 
> 2.37.3
> 
> 
> 

-- 
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-5555 |


From enrico.scholz at sigma-chemnitz.de  Wed Sep 28 02:29:22 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Wed, 28 Sep 2022 11:29:22 +0200
Subject: [PATCH] zstd: fix assert() logic
In-Reply-To: <20220928091141.GV986@pengutronix.de> (Sascha Hauer's message of
	"Wed, 28 Sep 2022 11:11:41 +0200")
References: <20220927172217.662321-1-enrico.scholz@sigma-chemnitz.de>
	<20220928091141.GV986@pengutronix.de>
Message-ID: <lywn9nyhhp.fsf@ensc-pc.intern.sigma-chemnitz.de>

Sascha Hauer <sha at pengutronix.de> writes:

> On Tue, Sep 27, 2022 at 07:22:17PM +0200, Enrico Scholz wrote:
>> It should warn when condition does **not** hold
>
> That fixes only the warnings, not the regression, right?

no; sorry.  I stumpled over it while looking at this regression.


Enrico


From info at skymem.com  Wed Sep 28 03:18:04 2022
From: info at skymem.com (Info Skymem)
Date: Wed, 28 Sep 2022 12:18:04 +0200
Subject: [PATCH master] imx-usb-loader: skip initial SDP_ERROR_STATUS
 query for SDPS
In-Reply-To: <20220927173101.1696673-1-a.fatoum@pengutronix.de>
References: <20220927173101.1696673-1-a.fatoum@pengutronix.de>
Message-ID: <CAKvd=_hjXcUTcg5qz2Zwmk2Ofd7r9+1dFMp+yM-+_1BAC+aUKQ@mail.gmail.com>

Hi,
thank you for your information.

On our website you can find email addresses of companies and people.
https://www.skymem.info

In short, it?s like Google for emails.

Best regards,
Robert,
Skymem team

On Tue, Sep 27, 2022 at 7:33 PM Ahmad Fatoum <a.fatoum at pengutronix.de> wrote:
>
> We do an initial do_status() every time, which fails for i.MX8MP and
> i.MX8MN:
>
>   found i.MX8MP USB device [1fc9:0146]
>   4 in err=-9, last_trans=0  00 00 00 00
>   status failed
>
> If we instead skip it for SDPS (i.e. hid_endpoint), upload works as
> expected (tested on i.MX8M Nano).
>
> Reported-by: Hans Christian L?nstad <hcl at datarespons.no>
> Fixes: 23e2203150b6 ("imx-usb-loader: Add i.MX8MP support")
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  scripts/imx/imx-usb-loader.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
> index 1242f2dedda5..a98ab0e33f8a 100644
> --- a/scripts/imx/imx-usb-loader.c
> +++ b/scripts/imx/imx-usb-loader.c
> @@ -1628,10 +1628,12 @@ int main(int argc, char *argv[])
>                 goto out;
>         }
>
> -       err = do_status();
> -       if (err) {
> -               printf("status failed\n");
> -               goto out;
> +       if (!mach_id->hid_endpoint) {
> +               err = do_status();
> +               if (err) {
> +                       printf("status failed\n");
> +                       goto out;
> +               }
>         }
>
>         if (initfile) {
> --
> 2.30.2
>
>


From info at skymem.com  Wed Sep 28 03:18:46 2022
From: info at skymem.com (Info Skymem)
Date: Wed, 28 Sep 2022 12:18:46 +0200
Subject: Imx-usb-loader broken on IMX8MP/v2022.09.0
In-Reply-To: <e0778785-7de6-f91c-d4b1-3f828f6effe1@pengutronix.de>
References: <8CA6ADB4-FD4B-4CC8-9BD2-21DA02C08C85@datarespons.no> <e0778785-7de6-f91c-d4b1-3f828f6effe1@pengutronix.de>
Message-ID: <CAKvd=_gaOYJAvtgy83ZNWwgT2HBO0c3WZusz55DgJrzWuF=tBA@mail.gmail.com>

Hi,
thank you for your information.

On our website you can find email addresses of companies and people.
https://www.skymem.info

In short, it?s like Google for emails.

Best regards,
Robert,
Skymem team

On Tue, Sep 27, 2022 at 7:45 PM Ahmad Fatoum <a.fatoum at pengutronix.de> wrote:
>
> Hello Hans,
>
> On 17.09.22 13:04, Hans Christian L?nstad wrote:
> > This is observed using straight out of the box v2022.09.0 on NXP IMX8MP Eval kit:
> >
> > ---------
> >
> > $ sudo ../drimx8/scripts/imx/imx-usb-loader ../drimx8/images/barebox-nxp-imx8mp-evk.img
> > [sudo] password for hcl:
> > found i.MX8MP USB device [1fc9:0146]
> > 4 in err=-9, last_trans=0  00 00 00 00
> > status failed
>
> I just tested and have the same issue on i.MX8M Nano, which uses
> the same new SDPS protocol. I've just sent out a potential fix.
>
> > ????
> >
> > Stripping off the header gap (32K) allows the binary to load using the standard NXP uuu (Ubuntu 22.04) utility,.
> >
> > This further raises the question: Why have a header gap at all?
> >
> > The makes sense for SD card loading, but not for eMMC boot partitions where ROM expects code to start at 0.
>
> The realization that the eMMC boot partition usually lacks an on-disk partition
> table came quite late to the NXP BootROM authors. On i.MX8M Mini, we still have
> an offset for both SD-Card and eMMC boot partition.
>
> > Maybe better just use a seek to put the code at the relevant position on the SD card?
>
> imx-usb-loader does the correct thing and skips to the relevant position.
> barebox_update should do the correct thing and skip over the header.
>
> > For instance, I am using the Rauc boot loader slot update mechanism expecting no gap thus  requiring me to shave of 32k
> > prior to shipping.
>
> This is unfortunate, but I don't think this is something we should address at the
> barebox side. barebox images for i.MX are always meant to be directly written
> to an SD-Card at offset 0.
>
> For RAUC integration, you may consider having your build system shave off the
> bytes transparently. See for example:
>
> https://github.com/rauc/meta-rauc/commit/8e049699f05483b694e6c5a3e260cd9e0fe58d2e
>
> which does the inverse operation: pad U-Boot for older i.MX, so they are install-able
> into an eMMC boot partition.
>
> Cheers,
> Ahmad
>
> >
> > Comments??
> >
> > Hans Christian
> >
>
>
> --
> 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-5555 |
>


From info at skymem.com  Wed Sep 28 03:18:57 2022
From: info at skymem.com (Info Skymem)
Date: Wed, 28 Sep 2022 12:18:57 +0200
Subject: Broken ubifs-zstd
In-Reply-To: <f3f0d847-c37f-599c-fb3a-14de696e4270@pengutronix.de>
References: <lyr0zw68de.fsf@ensc-pc.intern.sigma-chemnitz.de> <f3f0d847-c37f-599c-fb3a-14de696e4270@pengutronix.de>
Message-ID: <CAKvd=_jNb7=ekysEKPHGyOGAu-u74FvCNLdqhgmWpHQ66PWcgA@mail.gmail.com>

Hi,
thank you for your information.

On our website you can find email addresses of companies and people.
https://www.skymem.info

In short, it?s like Google for emails.

Best regards,
Robert,
Skymem team

On Tue, Sep 27, 2022 at 7:47 PM Ahmad Fatoum <a.fatoum at pengutronix.de> wrote:
>
> Hello Enrico,
>
> On 27.09.22 18:21, Enrico Scholz wrote:
> > Hello,
> >
> > trying to mount a zstd compressed ubifs fails on an iMX6ULL with
> >
> > | ERROR: UBIFS error (ubi0:0): 9fe6691d: cannot decompress 2612 bytes, compressor zstd, error -22
> > | ERROR: UBIFS error (ubi0:0): 9fe6692d: cannot decompress 2612 bytes, compressor zstd, error -22
> > | ERROR: UBIFS error (ubi0:0): 9fe66a65: bad data node (block 0, inode 815)
> > | ERROR:  magic          0x6101831
> >
> > (2022.09 and master).
> >
> >
> > After reverting
> >
> > | commit b4a9782d4f56333e897dccc35c2c27e2605f6b93
> > | Author: Ahmad Fatoum <a.fatoum at pengutronix.de>
> > | Date:   Wed Jul 13 12:09:18 2022 +0200
> > |
> > |     lib: zstd: sync with Linux
> >
> > it works again (both in Linux 5.15 and barebox).
> >
> >
> > ubifs was created by recent OpenEmbedded kirkstone with
> >
> > | MKUBIFS_ARGS = "-F -m 2048 -e 126976 -c 2048 --compr=zstd"
> >
> >
> > Warnings are triggered (after fixing assert()) at
> >
> > | WARNING: at lib/zstd/decompress/../common/bitstream.h:390/BIT_reloadDStreamFast()!
> >
> >
> > Is anybody else experiencing these problems?
>
>
> I am afraid, I didn't properly test this with UBIFS..
>
> >
> >
> >
> > Enrico
> >
> >
>
>
> --
> 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-5555 |
>


From enrico.scholz at sigma-chemnitz.de  Wed Sep 28 03:24:23 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Wed, 28 Sep 2022 12:24:23 +0200
Subject: malloc() alignment on 32 bit
In-Reply-To: <20220920073622.GE6477@pengutronix.de> (Sascha Hauer's message of
	"Tue, 20 Sep 2022 09:36:22 +0200")
References: <ly7d1z1qvs.fsf@ensc-pc.intern.sigma-chemnitz.de>
	<20220919135751.GD6477@pengutronix.de>
	<ly35cn1lyk.fsf@ensc-pc.intern.sigma-chemnitz.de>
	<20220920073622.GE6477@pengutronix.de>
Message-ID: <lyfsgbyey0.fsf@ensc-pc.intern.sigma-chemnitz.de>

Sascha Hauer <sha at pengutronix.de> writes:

> So it seems it's really a good idea to increase malloc alignment
> accordingly.

But this does not seem to be trivial :(

A naive

| -	ALIGN_SIZE_LOG2 = 2,
| +	ALIGN_SIZE_LOG2 = 3,

triggers a lot of warnings.


I think, ALIGN_SIZE in tlsf_add_pool() and in the higher level functions
(tlsf_malloc(), _memalign(), _realloc()) should be replaced by a new,
bigger constant.

But this appears invasive and I have no idea about tlsf and the sideeffects :(


There exists https://github.com/mattconte/tlsf/issues/16 which asks for
proper alignment; but project seems to be unmaintained.


Replacing 'malloc()' with 'memalign()' on problems, seems the best idea
for now.


Enrico


From enrico.scholz at sigma-chemnitz.de  Wed Sep 28 06:22:46 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Wed, 28 Sep 2022 15:22:46 +0200
Subject: [PATCH 5/5] gpiolib: gpioinfo: add optional CONTROLLER command
 line argument
In-Reply-To: <20220905103546.1476277-6-a.fatoum@pengutronix.de> (Ahmad
	Fatoum's message of "Mon, 5 Sep 2022 12:35:46 +0200")
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
	<20220905103546.1476277-6-a.fatoum@pengutronix.de>
Message-ID: <lyzgejws49.fsf@ensc-pc.intern.sigma-chemnitz.de>

Ahmad Fatoum <a.fatoum at pengutronix.de> writes:

>  static int do_gpiolib(int argc, char *argv[])
>  {
> +	if (argc == 1) {
> +		dev = find_device(argv[1]);

'gpioinfo' without arguments will crash because this calls
'find_device(NULL)'

| :/ gpioinfo 
| BUG: failure at lib/string.c:226/strcmp()!
| BUG!



Enrico


From enrico.scholz at sigma-chemnitz.de  Wed Sep 28 06:37:30 2022
From: enrico.scholz at sigma-chemnitz.de (Enrico Scholz)
Date: Wed, 28 Sep 2022 15:37:30 +0200
Subject: [PATCH 4/5] commands: gpio: add -d argument to set/get commands
In-Reply-To: <20220905103546.1476277-5-a.fatoum@pengutronix.de> (Ahmad
	Fatoum's message of "Mon, 5 Sep 2022 12:35:45 +0200")
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
	<20220905103546.1476277-5-a.fatoum@pengutronix.de>
Message-ID: <lyv8p7wrfp.fsf@ensc-pc.intern.sigma-chemnitz.de>

Ahmad Fatoum <a.fatoum at pengutronix.de> writes:

> For debugging, it can be useful to reference GPIOs relative to a
> controller, e.g.:
>
>   gpio_direction_output -d gpio4 20 1
>
> -	if (argc < count)
> +	if (optind < count)
>  		return COMMAND_ERROR_USAGE;

This change seems to make '-d ...' mandatory.  E.g.

| :/ gpio_get_value 65
| 
| gpio_get_value - return value of a GPIO pin
| 
| Usage: gpio_get_value [-d CONTROLLER] GPIO


Enrico


From sha at pengutronix.de  Wed Sep 28 07:24:38 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 28 Sep 2022 16:24:38 +0200
Subject: [PATCH 5/5] gpiolib: gpioinfo: add optional CONTROLLER command
 line argument
In-Reply-To: <lyzgejws49.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
 <20220905103546.1476277-6-a.fatoum@pengutronix.de>
 <lyzgejws49.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <20220928142438.GW986@pengutronix.de>

On Wed, Sep 28, 2022 at 03:22:46PM +0200, Enrico Scholz wrote:
> Ahmad Fatoum <a.fatoum at pengutronix.de> writes:
> 
> >  static int do_gpiolib(int argc, char *argv[])
> >  {
> > +	if (argc == 1) {
> > +		dev = find_device(argv[1]);
> 
> 'gpioinfo' without arguments will crash because this calls
> 'find_device(NULL)'
> 
> | :/ gpioinfo 
> | BUG: failure at lib/string.c:226/strcmp()!
> | BUG!

I fixed it with the obvious change

Sascha

----------------------------8<--------------------------

>From 252c76cdf8c9d516589d72ac228ac0d19fcb2021 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer at pengutronix.de>
Date: Wed, 28 Sep 2022 16:20:48 +0200
Subject: [PATCH] gpiolib: Fix gpioinfo without args

Since a30ae2921a the gpioinfo command crashes when called without
arguments. Fix it by using argv[1] when it actually exists, not when
it doesn't exist.

Fixes: a30ae2921a ("gpiolib: gpioinfo: add optional CONTROLLER command line argument")
Reported-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/gpio/gpiolib.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 7f20709035..2503262d65 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -681,7 +681,7 @@ static int do_gpiolib(int argc, char *argv[])
 	if (argc > 2)
 		return COMMAND_ERROR_USAGE;
 
-	if (argc == 1) {
+	if (argc > 1) {
 		struct device_d *dev;
 
 		dev = find_device(argv[1]);
-- 
2.30.2

-- 
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-5555 |


From sha at pengutronix.de  Wed Sep 28 07:36:31 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 28 Sep 2022 16:36:31 +0200
Subject: [PATCH 4/5] commands: gpio: add -d argument to set/get commands
In-Reply-To: <lyv8p7wrfp.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
 <20220905103546.1476277-5-a.fatoum@pengutronix.de>
 <lyv8p7wrfp.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <20220928143631.GX986@pengutronix.de>

Hi Enrico,

On Wed, Sep 28, 2022 at 03:37:30PM +0200, Enrico Scholz wrote:
> Ahmad Fatoum <a.fatoum at pengutronix.de> writes:
> 
> > For debugging, it can be useful to reference GPIOs relative to a
> > controller, e.g.:
> >
> >   gpio_direction_output -d gpio4 20 1
> >
> > -	if (argc < count)
> > +	if (optind < count)
> >  		return COMMAND_ERROR_USAGE;
> 
> This change seems to make '-d ...' mandatory.  E.g.
> 
> | :/ gpio_get_value 65
> | 
> | gpio_get_value - return value of a GPIO pin
> | 
> | Usage: gpio_get_value [-d CONTROLLER] GPIO
> 

Thanks for reporting. Here is a fix for that

Sascha

-----------------------------8<---------------------------

>From 7c797eb87385522ce1ec1ba44315ba386d82978d Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer at pengutronix.de>
Date: Wed, 28 Sep 2022 16:33:21 +0200
Subject: [PATCH] gpio: Fix gpio commands called without -d option

04443dc5fc breaks the calculation of arguments needed which effectively
makes the -d option mandatory. Fix this.

Fixes: 04443dc5fc ("commands: gpio: add -d argument to set/get commands")
Reported-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 commands/gpio.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/commands/gpio.c b/commands/gpio.c
index d04fd65bc8..5e5eb20583 100644
--- a/commands/gpio.c
+++ b/commands/gpio.c
@@ -11,7 +11,7 @@ static int get_gpio_and_value(int argc, char *argv[],
 {
 	struct gpio_chip *chip = NULL;
 	struct device_d *dev;
-	int count = 2;
+	int count = 1;
 	int ret = 0;
 	int opt;
 
@@ -34,7 +34,7 @@ static int get_gpio_and_value(int argc, char *argv[],
 	if (value)
 		count++;
 
-	if (optind < count)
+	if (argc < optind + count)
 		return COMMAND_ERROR_USAGE;
 
 	*gpio = gpio_find_by_name(argv[optind]);
-- 
2.30.2

-- 
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-5555 |


From a.fatoum at pengutronix.de  Thu Sep 29 02:50:20 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 29 Sep 2022 10:50:20 +0100
Subject: [PATCH 4/5] commands: gpio: add -d argument to set/get commands
In-Reply-To: <lyv8p7wrfp.fsf@ensc-pc.intern.sigma-chemnitz.de>
References: <20220905103546.1476277-1-a.fatoum@pengutronix.de>
 <20220905103546.1476277-5-a.fatoum@pengutronix.de>
 <lyv8p7wrfp.fsf@ensc-pc.intern.sigma-chemnitz.de>
Message-ID: <ff7948a7-71c5-5cf4-2f96-f7c165d34e11@pengutronix.de>

On 28.09.22 14:37, Enrico Scholz wrote:
> Ahmad Fatoum <a.fatoum at pengutronix.de> writes:
> 
>> For debugging, it can be useful to reference GPIOs relative to a
>> controller, e.g.:
>>
>>   gpio_direction_output -d gpio4 20 1
>>
>> -	if (argc < count)
>> +	if (optind < count)
>>  		return COMMAND_ERROR_USAGE;
> 
> This change seems to make '-d ...' mandatory.  E.g.
> 
> | :/ gpio_get_value 65
> | 
> | gpio_get_value - return value of a GPIO pin
> | 
> | Usage: gpio_get_value [-d CONTROLLER] GPIO

Seems I had the blinders on when I drafted this patch
series. Thanks for reporting and thanks Sascha for
the fixes.


> 
> 
> Enrico
> 


-- 
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-5555 |


From a.fatoum at pengutronix.de  Thu Sep 29 03:05:02 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 29 Sep 2022 12:05:02 +0200
Subject: [PATCH] usb: have usb_rescan return count of enumerated devices
Message-ID: <20220929100502.895553-1-a.fatoum@pengutronix.de>

Some USB mass storage devices can take a comparatively long time after
vbus is applied until they can be enumerated. Board code can reissue
usb_rescan() to retry enumeration at a later time. It's useful for
board code to check whether any new devices have been detected by a
usb_rescan() call. To facilitate this, have usb_rescan() return the
number of devices found in addition to printing it to the log.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/usb/core/usb.c | 4 +++-
 include/usb/usb.h      | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 34a0f004f7bb..ed3a96cb9e5e 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -599,7 +599,7 @@ int usb_host_detect(struct usb_host *host)
 	return 0;
 }
 
-void usb_rescan(void)
+int usb_rescan(void)
 {
 	struct usb_host *host;
 	int ret;
@@ -613,6 +613,8 @@ void usb_rescan(void)
 	}
 
 	pr_info("%d USB Device(s) found\n", dev_count);
+
+	return dev_count;
 }
 
 /*-------------------------------------------------------------------
diff --git a/include/usb/usb.h b/include/usb/usb.h
index 39f475091617..04b433ba73ca 100644
--- a/include/usb/usb.h
+++ b/include/usb/usb.h
@@ -201,7 +201,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe);
 int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
 int usb_set_interface(struct usb_device *dev, int interface, int alternate);
 
-void usb_rescan(void);
+int usb_rescan(void);
 
 /* big endian -> little endian conversion */
 /* some CPUs are already little endian e.g. the ARM920T */
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Sep 29 03:25:37 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Thu, 29 Sep 2022 12:25:37 +0200
Subject: [PATCH master] Revert "lib: zstd: sync with Linux"
Message-ID: <20220929102537.1767458-1-a.fatoum@pengutronix.de>

This was part of a larger series that made it possible to use other
compression algos than LZO for device tree and to use zstd more widely
for barebox and kernel compression. The latter zstd-related parts needed
rework and were not merged, but the zstd update was applied. It broken
in turn the UBIFS zstd support. As we get nothing out of the update
without the not applied commits that need rework anyway, revert this
commit.

This reverts commit b4a9782d4f56333e897dccc35c2c27e2605f6b93.

Reported-by: Enrico Scholz <enrico.scholz at sigma-chemnitz.de>
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
Only build-tested on ARM64 with UBIFS and squashfs zstd enabled
---
 fs/squashfs/zstd_wrapper.c                    |    4 +-
 fs/ubifs/ubifs.c                              |    4 +-
 include/linux/decompress/unzstd.h             |   11 -
 include/linux/limits.h                        |    1 -
 include/linux/zstd.h                          | 1252 ++++++--
 include/linux/zstd_errors.h                   |   77 -
 include/linux/zstd_lib.h                      | 2432 ----------------
 lib/zstd/Makefile                             |   27 +-
 lib/zstd/bitstream.h                          |  374 +++
 lib/zstd/common/bitstream.h                   |  437 ---
 lib/zstd/common/compiler.h                    |  177 --
 lib/zstd/common/cpu.h                         |  194 --
 lib/zstd/common/debug.c                       |   24 -
 lib/zstd/common/debug.h                       |  101 -
 lib/zstd/common/entropy_common.c              |  357 ---
 lib/zstd/common/error_private.c               |   56 -
 lib/zstd/common/error_private.h               |   69 -
 lib/zstd/common/fse.h                         |  710 -----
 lib/zstd/common/fse_decompress.c              |  390 ---
 lib/zstd/common/huf.h                         |  356 ---
 lib/zstd/common/mem.h                         |  259 --
 lib/zstd/common/zstd_common.c                 |   83 -
 lib/zstd/common/zstd_deps.h                   |  125 -
 lib/zstd/common/zstd_internal.h               |  450 ---
 lib/zstd/decompress.c                         | 2528 +++++++++++++++++
 lib/zstd/decompress/huf_decompress.c          | 1206 --------
 lib/zstd/decompress/zstd_ddict.c              |  241 --
 lib/zstd/decompress/zstd_ddict.h              |   44 -
 lib/zstd/decompress/zstd_decompress.c         | 2085 --------------
 lib/zstd/decompress/zstd_decompress_block.c   | 1540 ----------
 lib/zstd/decompress/zstd_decompress_block.h   |   62 -
 .../decompress/zstd_decompress_internal.h     |  202 --
 lib/zstd/decompress_sources.h                 |   28 -
 lib/zstd/entropy_common.c                     |  243 ++
 lib/zstd/error_private.h                      |   53 +
 lib/zstd/fse.h                                |  575 ++++
 lib/zstd/fse_decompress.c                     |  332 +++
 lib/zstd/huf.h                                |  212 ++
 lib/zstd/huf_decompress.c                     |  960 +++++++
 lib/zstd/mem.h                                |  151 +
 lib/zstd/zstd_common.c                        |   75 +
 lib/zstd/zstd_decompress_module.c             |  105 -
 lib/zstd/zstd_internal.h                      |  263 ++
 lib/zstd/zstd_opt.h                           | 1014 +++++++
 44 files changed, 7771 insertions(+), 12118 deletions(-)
 delete mode 100644 include/linux/decompress/unzstd.h
 delete mode 100644 include/linux/zstd_errors.h
 delete mode 100644 include/linux/zstd_lib.h
 create mode 100644 lib/zstd/bitstream.h
 delete mode 100644 lib/zstd/common/bitstream.h
 delete mode 100644 lib/zstd/common/compiler.h
 delete mode 100644 lib/zstd/common/cpu.h
 delete mode 100644 lib/zstd/common/debug.c
 delete mode 100644 lib/zstd/common/debug.h
 delete mode 100644 lib/zstd/common/entropy_common.c
 delete mode 100644 lib/zstd/common/error_private.c
 delete mode 100644 lib/zstd/common/error_private.h
 delete mode 100644 lib/zstd/common/fse.h
 delete mode 100644 lib/zstd/common/fse_decompress.c
 delete mode 100644 lib/zstd/common/huf.h
 delete mode 100644 lib/zstd/common/mem.h
 delete mode 100644 lib/zstd/common/zstd_common.c
 delete mode 100644 lib/zstd/common/zstd_deps.h
 delete mode 100644 lib/zstd/common/zstd_internal.h
 create mode 100644 lib/zstd/decompress.c
 delete mode 100644 lib/zstd/decompress/huf_decompress.c
 delete mode 100644 lib/zstd/decompress/zstd_ddict.c
 delete mode 100644 lib/zstd/decompress/zstd_ddict.h
 delete mode 100644 lib/zstd/decompress/zstd_decompress.c
 delete mode 100644 lib/zstd/decompress/zstd_decompress_block.c
 delete mode 100644 lib/zstd/decompress/zstd_decompress_block.h
 delete mode 100644 lib/zstd/decompress/zstd_decompress_internal.h
 delete mode 100644 lib/zstd/decompress_sources.h
 create mode 100644 lib/zstd/entropy_common.c
 create mode 100644 lib/zstd/error_private.h
 create mode 100644 lib/zstd/fse.h
 create mode 100644 lib/zstd/fse_decompress.c
 create mode 100644 lib/zstd/huf.h
 create mode 100644 lib/zstd/huf_decompress.c
 create mode 100644 lib/zstd/mem.h
 create mode 100644 lib/zstd/zstd_common.c
 delete mode 100644 lib/zstd/zstd_decompress_module.c
 create mode 100644 lib/zstd/zstd_internal.h
 create mode 100644 lib/zstd/zstd_opt.h

diff --git a/fs/squashfs/zstd_wrapper.c b/fs/squashfs/zstd_wrapper.c
index aae981f6cee0..86740edd4855 100644
--- a/fs/squashfs/zstd_wrapper.c
+++ b/fs/squashfs/zstd_wrapper.c
@@ -39,7 +39,7 @@ static void *zstd_init(struct squashfs_sb_info *msblk, void *buff)
 		goto failed;
 	wksp->window_size = max_t(size_t,
 			msblk->block_size, SQUASHFS_METADATA_SIZE);
-	wksp->mem_size = zstd_dstream_workspace_bound(wksp->window_size);
+	wksp->mem_size = ZSTD_DStreamWorkspaceBound(wksp->window_size);
 	wksp->mem = vmalloc(wksp->mem_size);
 	if (wksp->mem == NULL)
 		goto failed;
@@ -75,7 +75,7 @@ static int zstd_uncompress(struct squashfs_sb_info *msblk, void *strm,
 	ZSTD_inBuffer in_buf = { NULL, 0, 0 };
 	ZSTD_outBuffer out_buf = { NULL, 0, 0 };
 
-	stream = zstd_init_dstream(wksp->window_size, wksp->mem, wksp->mem_size);
+	stream = ZSTD_initDStream(wksp->window_size, wksp->mem, wksp->mem_size);
 
 	if (!stream) {
 		ERROR("Failed to initialize zstd decompressor\n");
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 0b4f3de773e7..50a9ebcdcc78 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -526,13 +526,13 @@ static int zlib_decomp_init(void)
 
 static int zstd_decomp_init(void)
 {
-	const size_t wksp_size = zstd_dctx_workspace_bound();
+	const size_t wksp_size = ZSTD_DCtxWorkspaceBound();
 	void *wksp = malloc(wksp_size);
 
 	if (!wksp)
 		return -ENOMEM;
 
-	ubifs_zstd_cctx = zstd_init_dctx(wksp, wksp_size);
+	ubifs_zstd_cctx = ZSTD_initDCtx(wksp, wksp_size);
 	if (!ubifs_zstd_cctx)
 		return -EINVAL;
 
diff --git a/include/linux/decompress/unzstd.h b/include/linux/decompress/unzstd.h
deleted file mode 100644
index ac078a3ba151..000000000000
--- a/include/linux/decompress/unzstd.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LINUX_DECOMPRESS_UNZSTD_H
-#define LINUX_DECOMPRESS_UNZSTD_H
-
-int unzstd(unsigned char *inbuf, int len,
-	   int (*fill)(void*, unsigned int),
-	   int (*flush)(void*, unsigned int),
-	   unsigned char *output,
-	   int *pos,
-	   void (*error_fn)(char *x));
-#endif
diff --git a/include/linux/limits.h b/include/linux/limits.h
index e1aa2de84519..bda9c94bb5ae 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -18,7 +18,6 @@
 #define ULLONG_MAX	(~0ULL)
 #define SIZE_MAX	(~(size_t)0)
 #define PHYS_ADDR_MAX	(~(phys_addr_t)0)
-#define UINTPTR_MAX	ULONG_MAX
 
 #define U8_MAX		((u8)~0U)
 #define S8_MAX		((s8)(U8_MAX >> 1))
diff --git a/include/linux/zstd.h b/include/linux/zstd.h
index 113408eef6ec..249575e2485f 100644
--- a/include/linux/zstd.h
+++ b/include/linux/zstd.h
@@ -1,97 +1,138 @@
-/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
 /*
- * Copyright (c) Yann Collet, Facebook, Inc.
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
  * All rights reserved.
  *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of https://github.com/facebook/zstd) and
- * the GPLv2 (found in the COPYING file in the root directory of
- * https://github.com/facebook/zstd). You may select, at your option, one of the
- * above-listed licenses.
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd.
+ * An additional grant of patent rights can be found in the PATENTS file in the
+ * same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
  */
 
-#ifndef LINUX_ZSTD_H
-#define LINUX_ZSTD_H
+#ifndef ZSTD_H
+#define ZSTD_H
 
-/**
- * This is a kernel-style API that wraps the upstream zstd API, which cannot be
- * used directly because the symbols aren't exported. It exposes the minimal
- * functionality which is currently required by users of zstd in the kernel.
- * Expose extra functions from lib/zstd/zstd.h as needed.
- */
+/* ======   Dependency   ======*/
+#include <linux/types.h>   /* size_t */
 
-/* ======   Dependency   ====== */
-#include <linux/types.h>
-#include <linux/zstd_errors.h>
-#include <linux/zstd_lib.h>
 
-/* ======   Helper Functions   ====== */
-/**
- * zstd_compress_bound() - maximum compressed size in worst case scenario
- * @src_size: The size of the data to compress.
+/*-*****************************************************************************
+ * Introduction
  *
- * Return:    The maximum compressed size in the worst case scenario.
- */
-size_t zstd_compress_bound(size_t src_size);
+ * zstd, short for Zstandard, is a fast lossless compression algorithm,
+ * targeting real-time compression scenarios at zlib-level and better
+ * compression ratios. The zstd compression library provides in-memory
+ * compression and decompression functions. The library supports compression
+ * levels from 1 up to ZSTD_maxCLevel() which is 22. Levels >= 20, labeled
+ * ultra, should be used with caution, as they require more memory.
+ * Compression can be done in:
+ *  - a single step, reusing a context (described as Explicit memory management)
+ *  - unbounded multiple steps (described as Streaming compression)
+ * The compression ratio achievable on small data can be highly improved using
+ * compression with a dictionary in:
+ *  - a single step (described as Simple dictionary API)
+ *  - a single step, reusing a dictionary (described as Fast dictionary API)
+ ******************************************************************************/
 
-/**
- * zstd_is_error() - tells if a size_t function result is an error code
- * @code:  The function result to check for error.
- *
- * Return: Non-zero iff the code is an error.
- */
-unsigned int zstd_is_error(size_t code);
+/*======  Helper functions  ======*/
 
 /**
- * enum zstd_error_code - zstd error codes
+ * enum ZSTD_ErrorCode - zstd error codes
+ *
+ * Functions that return size_t can be checked for errors using ZSTD_isError()
+ * and the ZSTD_ErrorCode can be extracted using ZSTD_getErrorCode().
  */
-typedef ZSTD_ErrorCode zstd_error_code;
+typedef enum {
+	ZSTD_error_no_error,
+	ZSTD_error_GENERIC,
+	ZSTD_error_prefix_unknown,
+	ZSTD_error_version_unsupported,
+	ZSTD_error_parameter_unknown,
+	ZSTD_error_frameParameter_unsupported,
+	ZSTD_error_frameParameter_unsupportedBy32bits,
+	ZSTD_error_frameParameter_windowTooLarge,
+	ZSTD_error_compressionParameter_unsupported,
+	ZSTD_error_init_missing,
+	ZSTD_error_memory_allocation,
+	ZSTD_error_stage_wrong,
+	ZSTD_error_dstSize_tooSmall,
+	ZSTD_error_srcSize_wrong,
+	ZSTD_error_corruption_detected,
+	ZSTD_error_checksum_wrong,
+	ZSTD_error_tableLog_tooLarge,
+	ZSTD_error_maxSymbolValue_tooLarge,
+	ZSTD_error_maxSymbolValue_tooSmall,
+	ZSTD_error_dictionary_corrupted,
+	ZSTD_error_dictionary_wrong,
+	ZSTD_error_dictionaryCreation_failed,
+	ZSTD_error_maxCode
+} ZSTD_ErrorCode;
 
 /**
- * zstd_get_error_code() - translates an error function result to an error code
- * @code:  The function result for which zstd_is_error(code) is true.
+ * ZSTD_maxCLevel() - maximum compression level available
  *
- * Return: A unique error code for this error.
+ * Return: Maximum compression level available.
  */
-zstd_error_code zstd_get_error_code(size_t code);
-
+int ZSTD_maxCLevel(void);
 /**
- * zstd_get_error_name() - translates an error function result to a string
- * @code:  The function result for which zstd_is_error(code) is true.
+ * ZSTD_compressBound() - maximum compressed size in worst case scenario
+ * @srcSize: The size of the data to compress.
  *
- * Return: An error string corresponding to the error code.
+ * Return:   The maximum compressed size in the worst case scenario.
  */
-const char *zstd_get_error_name(size_t code);
-
+size_t ZSTD_compressBound(size_t srcSize);
 /**
- * zstd_min_clevel() - minimum allowed compression level
+ * ZSTD_isError() - tells if a size_t function result is an error code
+ * @code:  The function result to check for error.
  *
- * Return: The minimum allowed compression level.
+ * Return: Non-zero iff the code is an error.
  */
-int zstd_min_clevel(void);
-
+static __attribute__((unused)) unsigned int ZSTD_isError(size_t code)
+{
+	return code > (size_t)-ZSTD_error_maxCode;
+}
 /**
- * zstd_max_clevel() - maximum allowed compression level
+ * ZSTD_getErrorCode() - translates an error function result to a ZSTD_ErrorCode
+ * @functionResult: The result of a function for which ZSTD_isError() is true.
  *
- * Return: The maximum allowed compression level.
+ * Return:          The ZSTD_ErrorCode corresponding to the functionResult or 0
+ *                  if the functionResult isn't an error.
  */
-int zstd_max_clevel(void);
-
-/* ======   Parameter Selection   ====== */
+static __attribute__((unused)) ZSTD_ErrorCode ZSTD_getErrorCode(
+	size_t functionResult)
+{
+	if (!ZSTD_isError(functionResult))
+		return (ZSTD_ErrorCode)0;
+	return (ZSTD_ErrorCode)(0 - functionResult);
+}
 
 /**
- * enum zstd_strategy - zstd compression search strategy
+ * enum ZSTD_strategy - zstd compression search strategy
  *
- * From faster to stronger. See zstd_lib.h.
+ * From faster to stronger.
  */
-typedef ZSTD_strategy zstd_strategy;
+typedef enum {
+	ZSTD_fast,
+	ZSTD_dfast,
+	ZSTD_greedy,
+	ZSTD_lazy,
+	ZSTD_lazy2,
+	ZSTD_btlazy2,
+	ZSTD_btopt,
+	ZSTD_btopt2
+} ZSTD_strategy;
 
 /**
- * struct zstd_compression_parameters - zstd compression parameters
+ * struct ZSTD_compressionParameters - zstd compression parameters
  * @windowLog:    Log of the largest match distance. Larger means more
  *                compression, and more memory needed during decompression.
- * @chainLog:     Fully searched segment. Larger means more compression,
- *                slower, and more memory (useless for fast).
+ * @chainLog:     Fully searched segment. Larger means more compression, slower,
+ *                and more memory (useless for fast).
  * @hashLog:      Dispatch table. Larger means more compression,
  *                slower, and more memory.
  * @searchLog:    Number of searches. Larger means more compression and slower.
@@ -100,348 +141,1017 @@ typedef ZSTD_strategy zstd_strategy;
  * @targetLength: Acceptable match size for optimal parser (only). Larger means
  *                more compression, and slower.
  * @strategy:     The zstd compression strategy.
- *
- * See zstd_lib.h.
  */
-typedef ZSTD_compressionParameters zstd_compression_parameters;
+typedef struct {
+	unsigned int windowLog;
+	unsigned int chainLog;
+	unsigned int hashLog;
+	unsigned int searchLog;
+	unsigned int searchLength;
+	unsigned int targetLength;
+	ZSTD_strategy strategy;
+} ZSTD_compressionParameters;
 
 /**
- * struct zstd_frame_parameters - zstd frame parameters
- * @contentSizeFlag: Controls whether content size will be present in the
- *                   frame header (when known).
- * @checksumFlag:    Controls whether a 32-bit checksum is generated at the
- *                   end of the frame for error detection.
- * @noDictIDFlag:    Controls whether dictID will be saved into the frame
- *                   header when using dictionary compression.
+ * struct ZSTD_frameParameters - zstd frame parameters
+ * @contentSizeFlag: Controls whether content size will be present in the frame
+ *                   header (when known).
+ * @checksumFlag:    Controls whether a 32-bit checksum is generated at the end
+ *                   of the frame for error detection.
+ * @noDictIDFlag:    Controls whether dictID will be saved into the frame header
+ *                   when using dictionary compression.
  *
- * The default value is all fields set to 0. See zstd_lib.h.
+ * The default value is all fields set to 0.
  */
-typedef ZSTD_frameParameters zstd_frame_parameters;
+typedef struct {
+	unsigned int contentSizeFlag;
+	unsigned int checksumFlag;
+	unsigned int noDictIDFlag;
+} ZSTD_frameParameters;
 
 /**
- * struct zstd_parameters - zstd parameters
+ * struct ZSTD_parameters - zstd parameters
  * @cParams: The compression parameters.
  * @fParams: The frame parameters.
  */
-typedef ZSTD_parameters zstd_parameters;
+typedef struct {
+	ZSTD_compressionParameters cParams;
+	ZSTD_frameParameters fParams;
+} ZSTD_parameters;
 
 /**
- * zstd_get_params() - returns zstd_parameters for selected level
- * @level:              The compression level
- * @estimated_src_size: The estimated source size to compress or 0
- *                      if unknown.
+ * ZSTD_getCParams() - returns ZSTD_compressionParameters for selected level
+ * @compressionLevel: The compression level from 1 to ZSTD_maxCLevel().
+ * @estimatedSrcSize: The estimated source size to compress or 0 if unknown.
+ * @dictSize:         The dictionary size or 0 if a dictionary isn't being used.
  *
- * Return:              The selected zstd_parameters.
+ * Return:            The selected ZSTD_compressionParameters.
  */
-zstd_parameters zstd_get_params(int level,
-	unsigned long long estimated_src_size);
+ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel,
+	unsigned long long estimatedSrcSize, size_t dictSize);
 
-/* ======   Single-pass Compression   ====== */
+/**
+ * ZSTD_getParams() - returns ZSTD_parameters for selected level
+ * @compressionLevel: The compression level from 1 to ZSTD_maxCLevel().
+ * @estimatedSrcSize: The estimated source size to compress or 0 if unknown.
+ * @dictSize:         The dictionary size or 0 if a dictionary isn't being used.
+ *
+ * The same as ZSTD_getCParams() except also selects the default frame
+ * parameters (all zero).
+ *
+ * Return:            The selected ZSTD_parameters.
+ */
+ZSTD_parameters ZSTD_getParams(int compressionLevel,
+	unsigned long long estimatedSrcSize, size_t dictSize);
 
-typedef ZSTD_CCtx zstd_cctx;
+/*-*************************************
+ * Explicit memory management
+ **************************************/
 
 /**
- * zstd_cctx_workspace_bound() - max memory needed to initialize a zstd_cctx
- * @parameters: The compression parameters to be used.
+ * ZSTD_CCtxWorkspaceBound() - amount of memory needed to initialize a ZSTD_CCtx
+ * @cParams: The compression parameters to be used for compression.
  *
  * If multiple compression parameters might be used, the caller must call
- * zstd_cctx_workspace_bound() for each set of parameters and use the maximum
+ * ZSTD_CCtxWorkspaceBound() for each set of parameters and use the maximum
  * size.
  *
- * Return:      A lower bound on the size of the workspace that is passed to
- *              zstd_init_cctx().
+ * Return:   A lower bound on the size of the workspace that is passed to
+ *           ZSTD_initCCtx().
  */
-size_t zstd_cctx_workspace_bound(const zstd_compression_parameters *parameters);
+size_t ZSTD_CCtxWorkspaceBound(ZSTD_compressionParameters cParams);
 
 /**
- * zstd_init_cctx() - initialize a zstd compression context
- * @workspace:      The workspace to emplace the context into. It must outlive
- *                  the returned context.
- * @workspace_size: The size of workspace. Use zstd_cctx_workspace_bound() to
- *                  determine how large the workspace must be.
+ * struct ZSTD_CCtx - the zstd compression context
  *
- * Return:          A zstd compression context or NULL on error.
+ * When compressing many times it is recommended to allocate a context just once
+ * and reuse it for each successive compression operation.
  */
-zstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size);
+typedef struct ZSTD_CCtx_s ZSTD_CCtx;
+/**
+ * ZSTD_initCCtx() - initialize a zstd compression context
+ * @workspace:     The workspace to emplace the context into. It must outlive
+ *                 the returned context.
+ * @workspaceSize: The size of workspace. Use ZSTD_CCtxWorkspaceBound() to
+ *                 determine how large the workspace must be.
+ *
+ * Return:         A compression context emplaced into workspace.
+ */
+ZSTD_CCtx *ZSTD_initCCtx(void *workspace, size_t workspaceSize);
 
 /**
- * zstd_compress_cctx() - compress src into dst with the initialized parameters
- * @cctx:         The context. Must have been initialized with zstd_init_cctx().
- * @dst:          The buffer to compress src into.
- * @dst_capacity: The size of the destination buffer. May be any size, but
- *                ZSTD_compressBound(srcSize) is guaranteed to be large enough.
- * @src:          The data to compress.
- * @src_size:     The size of the data to compress.
- * @parameters:   The compression parameters to be used.
+ * ZSTD_compressCCtx() - compress src into dst
+ * @ctx:         The context. Must have been initialized with a workspace at
+ *               least as large as ZSTD_CCtxWorkspaceBound(params.cParams).
+ * @dst:         The buffer to compress src into.
+ * @dstCapacity: The size of the destination buffer. May be any size, but
+ *               ZSTD_compressBound(srcSize) is guaranteed to be large enough.
+ * @src:         The data to compress.
+ * @srcSize:     The size of the data to compress.
+ * @params:      The parameters to use for compression. See ZSTD_getParams().
  *
- * Return:        The compressed size or an error, which can be checked using
- *                zstd_is_error().
+ * Return:       The compressed size or an error, which can be checked using
+ *               ZSTD_isError().
  */
-size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
-	const void *src, size_t src_size, const zstd_parameters *parameters);
+size_t ZSTD_compressCCtx(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize, ZSTD_parameters params);
 
-/* ======   Single-pass Decompression   ====== */
+/**
+ * ZSTD_DCtxWorkspaceBound() - amount of memory needed to initialize a ZSTD_DCtx
+ *
+ * Return: A lower bound on the size of the workspace that is passed to
+ *         ZSTD_initDCtx().
+ */
+size_t ZSTD_DCtxWorkspaceBound(void);
 
-typedef ZSTD_DCtx zstd_dctx;
+/**
+ * struct ZSTD_DCtx - the zstd decompression context
+ *
+ * When decompressing many times it is recommended to allocate a context just
+ * once and reuse it for each successive decompression operation.
+ */
+typedef struct ZSTD_DCtx_s ZSTD_DCtx;
+/**
+ * ZSTD_initDCtx() - initialize a zstd decompression context
+ * @workspace:     The workspace to emplace the context into. It must outlive
+ *                 the returned context.
+ * @workspaceSize: The size of workspace. Use ZSTD_DCtxWorkspaceBound() to
+ *                 determine how large the workspace must be.
+ *
+ * Return:         A decompression context emplaced into workspace.
+ */
+ZSTD_DCtx *ZSTD_initDCtx(void *workspace, size_t workspaceSize);
 
 /**
- * zstd_dctx_workspace_bound() - max memory needed to initialize a zstd_dctx
+ * ZSTD_decompressDCtx() - decompress zstd compressed src into dst
+ * @ctx:         The decompression context.
+ * @dst:         The buffer to decompress src into.
+ * @dstCapacity: The size of the destination buffer. Must be at least as large
+ *               as the decompressed size. If the caller cannot upper bound the
+ *               decompressed size, then it's better to use the streaming API.
+ * @src:         The zstd compressed data to decompress. Multiple concatenated
+ *               frames and skippable frames are allowed.
+ * @srcSize:     The exact size of the data to decompress.
  *
- * Return: A lower bound on the size of the workspace that is passed to
- *         zstd_init_dctx().
+ * Return:       The decompressed size or an error, which can be checked using
+ *               ZSTD_isError().
  */
-size_t zstd_dctx_workspace_bound(void);
+size_t ZSTD_decompressDCtx(ZSTD_DCtx *ctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize);
+
+/*-************************
+ * Simple dictionary API
+ **************************/
 
 /**
- * zstd_init_dctx() - initialize a zstd decompression context
- * @workspace:      The workspace to emplace the context into. It must outlive
- *                  the returned context.
- * @workspace_size: The size of workspace. Use zstd_dctx_workspace_bound() to
- *                  determine how large the workspace must be.
+ * ZSTD_compress_usingDict() - compress src into dst using a dictionary
+ * @ctx:         The context. Must have been initialized with a workspace at
+ *               least as large as ZSTD_CCtxWorkspaceBound(params.cParams).
+ * @dst:         The buffer to compress src into.
+ * @dstCapacity: The size of the destination buffer. May be any size, but
+ *               ZSTD_compressBound(srcSize) is guaranteed to be large enough.
+ * @src:         The data to compress.
+ * @srcSize:     The size of the data to compress.
+ * @dict:        The dictionary to use for compression.
+ * @dictSize:    The size of the dictionary.
+ * @params:      The parameters to use for compression. See ZSTD_getParams().
+ *
+ * Compression using a predefined dictionary. The same dictionary must be used
+ * during decompression.
  *
- * Return:          A zstd decompression context or NULL on error.
+ * Return:       The compressed size or an error, which can be checked using
+ *               ZSTD_isError().
  */
-zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size);
+size_t ZSTD_compress_usingDict(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize, const void *dict, size_t dictSize,
+	ZSTD_parameters params);
 
 /**
- * zstd_decompress_dctx() - decompress zstd compressed src into dst
- * @dctx:         The decompression context.
- * @dst:          The buffer to decompress src into.
- * @dst_capacity: The size of the destination buffer. Must be at least as large
- *                as the decompressed size. If the caller cannot upper bound the
- *                decompressed size, then it's better to use the streaming API.
- * @src:          The zstd compressed data to decompress. Multiple concatenated
- *                frames and skippable frames are allowed.
- * @src_size:     The exact size of the data to decompress.
+ * ZSTD_decompress_usingDict() - decompress src into dst using a dictionary
+ * @ctx:         The decompression context.
+ * @dst:         The buffer to decompress src into.
+ * @dstCapacity: The size of the destination buffer. Must be at least as large
+ *               as the decompressed size. If the caller cannot upper bound the
+ *               decompressed size, then it's better to use the streaming API.
+ * @src:         The zstd compressed data to decompress. Multiple concatenated
+ *               frames and skippable frames are allowed.
+ * @srcSize:     The exact size of the data to decompress.
+ * @dict:        The dictionary to use for decompression. The same dictionary
+ *               must've been used to compress the data.
+ * @dictSize:    The size of the dictionary.
  *
- * Return:        The decompressed size or an error, which can be checked using
- *                zstd_is_error().
+ * Return:       The decompressed size or an error, which can be checked using
+ *               ZSTD_isError().
  */
-size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
-	const void *src, size_t src_size);
+size_t ZSTD_decompress_usingDict(ZSTD_DCtx *ctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize, const void *dict, size_t dictSize);
 
-/* ======   Streaming Buffers   ====== */
+/*-**************************
+ * Fast dictionary API
+ ***************************/
 
 /**
- * struct zstd_in_buffer - input buffer for streaming
+ * ZSTD_CDictWorkspaceBound() - memory needed to initialize a ZSTD_CDict
+ * @cParams: The compression parameters to be used for compression.
+ *
+ * Return:   A lower bound on the size of the workspace that is passed to
+ *           ZSTD_initCDict().
+ */
+size_t ZSTD_CDictWorkspaceBound(ZSTD_compressionParameters cParams);
+
+/**
+ * struct ZSTD_CDict - a digested dictionary to be used for compression
+ */
+typedef struct ZSTD_CDict_s ZSTD_CDict;
+
+/**
+ * ZSTD_initCDict() - initialize a digested dictionary for compression
+ * @dictBuffer:    The dictionary to digest. The buffer is referenced by the
+ *                 ZSTD_CDict so it must outlive the returned ZSTD_CDict.
+ * @dictSize:      The size of the dictionary.
+ * @params:        The parameters to use for compression. See ZSTD_getParams().
+ * @workspace:     The workspace. It must outlive the returned ZSTD_CDict.
+ * @workspaceSize: The workspace size. Must be at least
+ *                 ZSTD_CDictWorkspaceBound(params.cParams).
+ *
+ * When compressing multiple messages / blocks with the same dictionary it is
+ * recommended to load it just once. The ZSTD_CDict merely references the
+ * dictBuffer, so it must outlive the returned ZSTD_CDict.
+ *
+ * Return:         The digested dictionary emplaced into workspace.
+ */
+ZSTD_CDict *ZSTD_initCDict(const void *dictBuffer, size_t dictSize,
+	ZSTD_parameters params, void *workspace, size_t workspaceSize);
+
+/**
+ * ZSTD_compress_usingCDict() - compress src into dst using a ZSTD_CDict
+ * @ctx:         The context. Must have been initialized with a workspace at
+ *               least as large as ZSTD_CCtxWorkspaceBound(cParams) where
+ *               cParams are the compression parameters used to initialize the
+ *               cdict.
+ * @dst:         The buffer to compress src into.
+ * @dstCapacity: The size of the destination buffer. May be any size, but
+ *               ZSTD_compressBound(srcSize) is guaranteed to be large enough.
+ * @src:         The data to compress.
+ * @srcSize:     The size of the data to compress.
+ * @cdict:       The digested dictionary to use for compression.
+ * @params:      The parameters to use for compression. See ZSTD_getParams().
+ *
+ * Compression using a digested dictionary. The same dictionary must be used
+ * during decompression.
+ *
+ * Return:       The compressed size or an error, which can be checked using
+ *               ZSTD_isError().
+ */
+size_t ZSTD_compress_usingCDict(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize, const ZSTD_CDict *cdict);
+
+
+/**
+ * ZSTD_DDictWorkspaceBound() - memory needed to initialize a ZSTD_DDict
+ *
+ * Return:  A lower bound on the size of the workspace that is passed to
+ *          ZSTD_initDDict().
+ */
+size_t ZSTD_DDictWorkspaceBound(void);
+
+/**
+ * struct ZSTD_DDict - a digested dictionary to be used for decompression
+ */
+typedef struct ZSTD_DDict_s ZSTD_DDict;
+
+/**
+ * ZSTD_initDDict() - initialize a digested dictionary for decompression
+ * @dictBuffer:    The dictionary to digest. The buffer is referenced by the
+ *                 ZSTD_DDict so it must outlive the returned ZSTD_DDict.
+ * @dictSize:      The size of the dictionary.
+ * @workspace:     The workspace. It must outlive the returned ZSTD_DDict.
+ * @workspaceSize: The workspace size. Must be at least
+ *                 ZSTD_DDictWorkspaceBound().
+ *
+ * When decompressing multiple messages / blocks with the same dictionary it is
+ * recommended to load it just once. The ZSTD_DDict merely references the
+ * dictBuffer, so it must outlive the returned ZSTD_DDict.
+ *
+ * Return:         The digested dictionary emplaced into workspace.
+ */
+ZSTD_DDict *ZSTD_initDDict(const void *dictBuffer, size_t dictSize,
+	void *workspace, size_t workspaceSize);
+
+/**
+ * ZSTD_decompress_usingDDict() - decompress src into dst using a ZSTD_DDict
+ * @ctx:         The decompression context.
+ * @dst:         The buffer to decompress src into.
+ * @dstCapacity: The size of the destination buffer. Must be at least as large
+ *               as the decompressed size. If the caller cannot upper bound the
+ *               decompressed size, then it's better to use the streaming API.
+ * @src:         The zstd compressed data to decompress. Multiple concatenated
+ *               frames and skippable frames are allowed.
+ * @srcSize:     The exact size of the data to decompress.
+ * @ddict:       The digested dictionary to use for decompression. The same
+ *               dictionary must've been used to compress the data.
+ *
+ * Return:       The decompressed size or an error, which can be checked using
+ *               ZSTD_isError().
+ */
+size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst,
+	size_t dstCapacity, const void *src, size_t srcSize,
+	const ZSTD_DDict *ddict);
+
+
+/*-**************************
+ * Streaming
+ ***************************/
+
+/**
+ * struct ZSTD_inBuffer - input buffer for streaming
  * @src:  Start of the input buffer.
  * @size: Size of the input buffer.
  * @pos:  Position where reading stopped. Will be updated.
  *        Necessarily 0 <= pos <= size.
- *
- * See zstd_lib.h.
  */
-typedef ZSTD_inBuffer zstd_in_buffer;
+typedef struct ZSTD_inBuffer_s {
+	const void *src;
+	size_t size;
+	size_t pos;
+} ZSTD_inBuffer;
 
 /**
- * struct zstd_out_buffer - output buffer for streaming
+ * struct ZSTD_outBuffer - output buffer for streaming
  * @dst:  Start of the output buffer.
  * @size: Size of the output buffer.
  * @pos:  Position where writing stopped. Will be updated.
  *        Necessarily 0 <= pos <= size.
- *
- * See zstd_lib.h.
  */
-typedef ZSTD_outBuffer zstd_out_buffer;
+typedef struct ZSTD_outBuffer_s {
+	void *dst;
+	size_t size;
+	size_t pos;
+} ZSTD_outBuffer;
 
-/* ======   Streaming Compression   ====== */
 
-typedef ZSTD_CStream zstd_cstream;
+
+/*-*****************************************************************************
+ * Streaming compression - HowTo
+ *
+ * A ZSTD_CStream object is required to track streaming operation.
+ * Use ZSTD_initCStream() to initialize a ZSTD_CStream object.
+ * ZSTD_CStream objects can be reused multiple times on consecutive compression
+ * operations. It is recommended to re-use ZSTD_CStream in situations where many
+ * streaming operations will be achieved consecutively. Use one separate
+ * ZSTD_CStream per thread for parallel execution.
+ *
+ * Use ZSTD_compressStream() repetitively to consume input stream.
+ * The function will automatically update both `pos` fields.
+ * Note that it may not consume the entire input, in which case `pos < size`,
+ * and it's up to the caller to present again remaining data.
+ * It returns a hint for the preferred number of bytes to use as an input for
+ * the next function call.
+ *
+ * At any moment, it's possible to flush whatever data remains within internal
+ * buffer, using ZSTD_flushStream(). `output->pos` will be updated. There might
+ * still be some content left within the internal buffer if `output->size` is
+ * too small. It returns the number of bytes left in the internal buffer and
+ * must be called until it returns 0.
+ *
+ * ZSTD_endStream() instructs to finish a frame. It will perform a flush and
+ * write frame epilogue. The epilogue is required for decoders to consider a
+ * frame completed. Similar to ZSTD_flushStream(), it may not be able to flush
+ * the full content if `output->size` is too small. In which case, call again
+ * ZSTD_endStream() to complete the flush. It returns the number of bytes left
+ * in the internal buffer and must be called until it returns 0.
+ ******************************************************************************/
 
 /**
- * zstd_cstream_workspace_bound() - memory needed to initialize a zstd_cstream
- * @cparams: The compression parameters to be used for compression.
+ * ZSTD_CStreamWorkspaceBound() - memory needed to initialize a ZSTD_CStream
+ * @cParams: The compression parameters to be used for compression.
  *
  * Return:   A lower bound on the size of the workspace that is passed to
- *           zstd_init_cstream().
+ *           ZSTD_initCStream() and ZSTD_initCStream_usingCDict().
+ */
+size_t ZSTD_CStreamWorkspaceBound(ZSTD_compressionParameters cParams);
+
+/**
+ * struct ZSTD_CStream - the zstd streaming compression context
+ */
+typedef struct ZSTD_CStream_s ZSTD_CStream;
+
+/*===== ZSTD_CStream management functions =====*/
+/**
+ * ZSTD_initCStream() - initialize a zstd streaming compression context
+ * @params:         The zstd compression parameters.
+ * @pledgedSrcSize: If params.fParams.contentSizeFlag == 1 then the caller must
+ *                  pass the source size (zero means empty source). Otherwise,
+ *                  the caller may optionally pass the source size, or zero if
+ *                  unknown.
+ * @workspace:      The workspace to emplace the context into. It must outlive
+ *                  the returned context.
+ * @workspaceSize:  The size of workspace.
+ *                  Use ZSTD_CStreamWorkspaceBound(params.cParams) to determine
+ *                  how large the workspace must be.
+ *
+ * Return:          The zstd streaming compression context.
  */
-size_t zstd_cstream_workspace_bound(const zstd_compression_parameters *cparams);
+ZSTD_CStream *ZSTD_initCStream(ZSTD_parameters params,
+	unsigned long long pledgedSrcSize, void *workspace,
+	size_t workspaceSize);
 
 /**
- * zstd_init_cstream() - initialize a zstd streaming compression context
- * @parameters        The zstd parameters to use for compression.
- * @pledged_src_size: If params.fParams.contentSizeFlag == 1 then the caller
- *                    must pass the source size (zero means empty source).
- *                    Otherwise, the caller may optionally pass the source
- *                    size, or zero if unknown.
- * @workspace:        The workspace to emplace the context into. It must outlive
- *                    the returned context.
- * @workspace_size:   The size of workspace.
- *                    Use zstd_cstream_workspace_bound(params->cparams) to
- *                    determine how large the workspace must be.
+ * ZSTD_initCStream_usingCDict() - initialize a streaming compression context
+ * @cdict:          The digested dictionary to use for compression.
+ * @pledgedSrcSize: Optionally the source size, or zero if unknown.
+ * @workspace:      The workspace to emplace the context into. It must outlive
+ *                  the returned context.
+ * @workspaceSize:  The size of workspace. Call ZSTD_CStreamWorkspaceBound()
+ *                  with the cParams used to initialize the cdict to determine
+ *                  how large the workspace must be.
  *
- * Return:            The zstd streaming compression context or NULL on error.
+ * Return:          The zstd streaming compression context.
  */
-zstd_cstream *zstd_init_cstream(const zstd_parameters *parameters,
-	unsigned long long pledged_src_size, void *workspace, size_t workspace_size);
+ZSTD_CStream *ZSTD_initCStream_usingCDict(const ZSTD_CDict *cdict,
+	unsigned long long pledgedSrcSize, void *workspace,
+	size_t workspaceSize);
 
+/*===== Streaming compression functions =====*/
 /**
- * zstd_reset_cstream() - reset the context using parameters from creation
- * @cstream:          The zstd streaming compression context to reset.
- * @pledged_src_size: Optionally the source size, or zero if unknown.
+ * ZSTD_resetCStream() - reset the context using parameters from creation
+ * @zcs:            The zstd streaming compression context to reset.
+ * @pledgedSrcSize: Optionally the source size, or zero if unknown.
  *
  * Resets the context using the parameters from creation. Skips dictionary
- * loading, since it can be reused. If `pledged_src_size` is non-zero the frame
+ * loading, since it can be reused. If `pledgedSrcSize` is non-zero the frame
  * content size is always written into the frame header.
  *
- * Return:            Zero or an error, which can be checked using
- *                    zstd_is_error().
+ * Return:          Zero or an error, which can be checked using ZSTD_isError().
  */
-size_t zstd_reset_cstream(zstd_cstream *cstream,
-	unsigned long long pledged_src_size);
-
+size_t ZSTD_resetCStream(ZSTD_CStream *zcs, unsigned long long pledgedSrcSize);
 /**
- * zstd_compress_stream() - streaming compress some of input into output
- * @cstream: The zstd streaming compression context.
- * @output:  Destination buffer. `output->pos` is updated to indicate how much
- *           compressed data was written.
- * @input:   Source buffer. `input->pos` is updated to indicate how much data
- *           was read. Note that it may not consume the entire input, in which
- *           case `input->pos < input->size`, and it's up to the caller to
- *           present remaining data again.
+ * ZSTD_compressStream() - streaming compress some of input into output
+ * @zcs:    The zstd streaming compression context.
+ * @output: Destination buffer. `output->pos` is updated to indicate how much
+ *          compressed data was written.
+ * @input:  Source buffer. `input->pos` is updated to indicate how much data was
+ *          read. Note that it may not consume the entire input, in which case
+ *          `input->pos < input->size`, and it's up to the caller to present
+ *          remaining data again.
  *
  * The `input` and `output` buffers may be any size. Guaranteed to make some
  * forward progress if `input` and `output` are not empty.
  *
- * Return:   A hint for the number of bytes to use as the input for the next
- *           function call or an error, which can be checked using
- *           zstd_is_error().
+ * Return:  A hint for the number of bytes to use as the input for the next
+ *          function call or an error, which can be checked using
+ *          ZSTD_isError().
  */
-size_t zstd_compress_stream(zstd_cstream *cstream, zstd_out_buffer *output,
-	zstd_in_buffer *input);
-
+size_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output,
+	ZSTD_inBuffer *input);
 /**
- * zstd_flush_stream() - flush internal buffers into output
- * @cstream: The zstd streaming compression context.
- * @output:  Destination buffer. `output->pos` is updated to indicate how much
- *           compressed data was written.
+ * ZSTD_flushStream() - flush internal buffers into output
+ * @zcs:    The zstd streaming compression context.
+ * @output: Destination buffer. `output->pos` is updated to indicate how much
+ *          compressed data was written.
  *
- * zstd_flush_stream() must be called until it returns 0, meaning all the data
- * has been flushed. Since zstd_flush_stream() causes a block to be ended,
+ * ZSTD_flushStream() must be called until it returns 0, meaning all the data
+ * has been flushed. Since ZSTD_flushStream() causes a block to be ended,
  * calling it too often will degrade the compression ratio.
  *
- * Return:   The number of bytes still present within internal buffers or an
- *           error, which can be checked using zstd_is_error().
+ * Return:  The number of bytes still present within internal buffers or an
+ *          error, which can be checked using ZSTD_isError().
  */
-size_t zstd_flush_stream(zstd_cstream *cstream, zstd_out_buffer *output);
-
+size_t ZSTD_flushStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output);
 /**
- * zstd_end_stream() - flush internal buffers into output and end the frame
- * @cstream: The zstd streaming compression context.
- * @output:  Destination buffer. `output->pos` is updated to indicate how much
- *           compressed data was written.
+ * ZSTD_endStream() - flush internal buffers into output and end the frame
+ * @zcs:    The zstd streaming compression context.
+ * @output: Destination buffer. `output->pos` is updated to indicate how much
+ *          compressed data was written.
  *
- * zstd_end_stream() must be called until it returns 0, meaning all the data has
+ * ZSTD_endStream() must be called until it returns 0, meaning all the data has
  * been flushed and the frame epilogue has been written.
  *
- * Return:   The number of bytes still present within internal buffers or an
- *           error, which can be checked using zstd_is_error().
+ * Return:  The number of bytes still present within internal buffers or an
+ *          error, which can be checked using ZSTD_isError().
  */
-size_t zstd_end_stream(zstd_cstream *cstream, zstd_out_buffer *output);
+size_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output);
+
+/**
+ * ZSTD_CStreamInSize() - recommended size for the input buffer
+ *
+ * Return: The recommended size for the input buffer.
+ */
+size_t ZSTD_CStreamInSize(void);
+/**
+ * ZSTD_CStreamOutSize() - recommended size for the output buffer
+ *
+ * When the output buffer is at least this large, it is guaranteed to be large
+ * enough to flush at least one complete compressed block.
+ *
+ * Return: The recommended size for the output buffer.
+ */
+size_t ZSTD_CStreamOutSize(void);
 
-/* ======   Streaming Decompression   ====== */
 
-typedef ZSTD_DStream zstd_dstream;
+
+/*-*****************************************************************************
+ * Streaming decompression - HowTo
+ *
+ * A ZSTD_DStream object is required to track streaming operations.
+ * Use ZSTD_initDStream() to initialize a ZSTD_DStream object.
+ * ZSTD_DStream objects can be re-used multiple times.
+ *
+ * Use ZSTD_decompressStream() repetitively to consume your input.
+ * The function will update both `pos` fields.
+ * If `input->pos < input->size`, some input has not been consumed.
+ * It's up to the caller to present again remaining data.
+ * If `output->pos < output->size`, decoder has flushed everything it could.
+ * Returns 0 iff a frame is completely decoded and fully flushed.
+ * Otherwise it returns a suggested next input size that will never load more
+ * than the current frame.
+ ******************************************************************************/
 
 /**
- * zstd_dstream_workspace_bound() - memory needed to initialize a zstd_dstream
- * @max_window_size: The maximum window size allowed for compressed frames.
+ * ZSTD_DStreamWorkspaceBound() - memory needed to initialize a ZSTD_DStream
+ * @maxWindowSize: The maximum window size allowed for compressed frames.
  *
- * Return:           A lower bound on the size of the workspace that is passed
- *                   to zstd_init_dstream().
+ * Return:         A lower bound on the size of the workspace that is passed to
+ *                 ZSTD_initDStream() and ZSTD_initDStream_usingDDict().
  */
-size_t zstd_dstream_workspace_bound(size_t max_window_size);
+size_t ZSTD_DStreamWorkspaceBound(size_t maxWindowSize);
 
 /**
- * zstd_init_dstream() - initialize a zstd streaming decompression context
- * @max_window_size: The maximum window size allowed for compressed frames.
- * @workspace:       The workspace to emplace the context into. It must outlive
- *                   the returned context.
- * @workspaceSize:   The size of workspace.
- *                   Use zstd_dstream_workspace_bound(max_window_size) to
- *                   determine how large the workspace must be.
+ * struct ZSTD_DStream - the zstd streaming decompression context
+ */
+typedef struct ZSTD_DStream_s ZSTD_DStream;
+/*===== ZSTD_DStream management functions =====*/
+/**
+ * ZSTD_initDStream() - initialize a zstd streaming decompression context
+ * @maxWindowSize: The maximum window size allowed for compressed frames.
+ * @workspace:     The workspace to emplace the context into. It must outlive
+ *                 the returned context.
+ * @workspaceSize: The size of workspace.
+ *                 Use ZSTD_DStreamWorkspaceBound(maxWindowSize) to determine
+ *                 how large the workspace must be.
+ *
+ * Return:         The zstd streaming decompression context.
+ */
+ZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace,
+	size_t workspaceSize);
+/**
+ * ZSTD_initDStream_usingDDict() - initialize streaming decompression context
+ * @maxWindowSize: The maximum window size allowed for compressed frames.
+ * @ddict:         The digested dictionary to use for decompression.
+ * @workspace:     The workspace to emplace the context into. It must outlive
+ *                 the returned context.
+ * @workspaceSize: The size of workspace.
+ *                 Use ZSTD_DStreamWorkspaceBound(maxWindowSize) to determine
+ *                 how large the workspace must be.
  *
- * Return:           The zstd streaming decompression context.
+ * Return:         The zstd streaming decompression context.
  */
-zstd_dstream *zstd_init_dstream(size_t max_window_size, void *workspace,
-	size_t workspace_size);
+ZSTD_DStream *ZSTD_initDStream_usingDDict(size_t maxWindowSize,
+	const ZSTD_DDict *ddict, void *workspace, size_t workspaceSize);
 
+/*===== Streaming decompression functions =====*/
 /**
- * zstd_reset_dstream() - reset the context using parameters from creation
- * @dstream: The zstd streaming decompression context to reset.
+ * ZSTD_resetDStream() - reset the context using parameters from creation
+ * @zds:   The zstd streaming decompression context to reset.
  *
  * Resets the context using the parameters from creation. Skips dictionary
  * loading, since it can be reused.
  *
- * Return:   Zero or an error, which can be checked using zstd_is_error().
+ * Return: Zero or an error, which can be checked using ZSTD_isError().
  */
-size_t zstd_reset_dstream(zstd_dstream *dstream);
-
+size_t ZSTD_resetDStream(ZSTD_DStream *zds);
 /**
- * zstd_decompress_stream() - streaming decompress some of input into output
- * @dstream: The zstd streaming decompression context.
- * @output:  Destination buffer. `output.pos` is updated to indicate how much
- *           decompressed data was written.
- * @input:   Source buffer. `input.pos` is updated to indicate how much data was
- *           read. Note that it may not consume the entire input, in which case
- *           `input.pos < input.size`, and it's up to the caller to present
- *           remaining data again.
+ * ZSTD_decompressStream() - streaming decompress some of input into output
+ * @zds:    The zstd streaming decompression context.
+ * @output: Destination buffer. `output.pos` is updated to indicate how much
+ *          decompressed data was written.
+ * @input:  Source buffer. `input.pos` is updated to indicate how much data was
+ *          read. Note that it may not consume the entire input, in which case
+ *          `input.pos < input.size`, and it's up to the caller to present
+ *          remaining data again.
  *
  * The `input` and `output` buffers may be any size. Guaranteed to make some
  * forward progress if `input` and `output` are not empty.
- * zstd_decompress_stream() will not consume the last byte of the frame until
+ * ZSTD_decompressStream() will not consume the last byte of the frame until
  * the entire frame is flushed.
  *
- * Return:   Returns 0 iff a frame is completely decoded and fully flushed.
- *           Otherwise returns a hint for the number of bytes to use as the
- *           input for the next function call or an error, which can be checked
- *           using zstd_is_error(). The size hint will never load more than the
- *           frame.
+ * Return:  Returns 0 iff a frame is completely decoded and fully flushed.
+ *          Otherwise returns a hint for the number of bytes to use as the input
+ *          for the next function call or an error, which can be checked using
+ *          ZSTD_isError(). The size hint will never load more than the frame.
  */
-size_t zstd_decompress_stream(zstd_dstream *dstream, zstd_out_buffer *output,
-	zstd_in_buffer *input);
+size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output,
+	ZSTD_inBuffer *input);
 
-/* ======   Frame Inspection Functions ====== */
+/**
+ * ZSTD_DStreamInSize() - recommended size for the input buffer
+ *
+ * Return: The recommended size for the input buffer.
+ */
+size_t ZSTD_DStreamInSize(void);
+/**
+ * ZSTD_DStreamOutSize() - recommended size for the output buffer
+ *
+ * When the output buffer is at least this large, it is guaranteed to be large
+ * enough to flush at least one complete decompressed block.
+ *
+ * Return: The recommended size for the output buffer.
+ */
+size_t ZSTD_DStreamOutSize(void);
+
+
+/* --- Constants ---*/
+#define ZSTD_MAGICNUMBER            0xFD2FB528   /* >= v0.8.0 */
+#define ZSTD_MAGIC_SKIPPABLE_START  0x184D2A50U
+
+#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
+#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)
+
+#define ZSTD_WINDOWLOG_MAX_32  27
+#define ZSTD_WINDOWLOG_MAX_64  27
+#define ZSTD_WINDOWLOG_MAX \
+	((unsigned int)(sizeof(size_t) == 4 \
+		? ZSTD_WINDOWLOG_MAX_32 \
+		: ZSTD_WINDOWLOG_MAX_64))
+#define ZSTD_WINDOWLOG_MIN 10
+#define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX
+#define ZSTD_HASHLOG_MIN        6
+#define ZSTD_CHAINLOG_MAX     (ZSTD_WINDOWLOG_MAX+1)
+#define ZSTD_CHAINLOG_MIN      ZSTD_HASHLOG_MIN
+#define ZSTD_HASHLOG3_MAX      17
+#define ZSTD_SEARCHLOG_MAX    (ZSTD_WINDOWLOG_MAX-1)
+#define ZSTD_SEARCHLOG_MIN      1
+/* only for ZSTD_fast, other strategies are limited to 6 */
+#define ZSTD_SEARCHLENGTH_MAX   7
+/* only for ZSTD_btopt, other strategies are limited to 4 */
+#define ZSTD_SEARCHLENGTH_MIN   3
+#define ZSTD_TARGETLENGTH_MIN   4
+#define ZSTD_TARGETLENGTH_MAX 999
+
+/* for static allocation */
+#define ZSTD_FRAMEHEADERSIZE_MAX 18
+#define ZSTD_FRAMEHEADERSIZE_MIN  6
+static const size_t ZSTD_frameHeaderSize_prefix = 5;
+static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN;
+static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
+/* magic number + skippable frame length */
+static const size_t ZSTD_skippableHeaderSize = 8;
+
+
+/*-*************************************
+ * Compressed size functions
+ **************************************/
+
+/**
+ * ZSTD_findFrameCompressedSize() - returns the size of a compressed frame
+ * @src:     Source buffer. It should point to the start of a zstd encoded frame
+ *           or a skippable frame.
+ * @srcSize: The size of the source buffer. It must be at least as large as the
+ *           size of the frame.
+ *
+ * Return:   The compressed size of the frame pointed to by `src` or an error,
+ *           which can be check with ZSTD_isError().
+ *           Suitable to pass to ZSTD_decompress() or similar functions.
+ */
+size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize);
+
+/*-*************************************
+ * Decompressed size functions
+ **************************************/
+/**
+ * ZSTD_getFrameContentSize() - returns the content size in a zstd frame header
+ * @src:     It should point to the start of a zstd encoded frame.
+ * @srcSize: The size of the source buffer. It must be at least as large as the
+ *           frame header. `ZSTD_frameHeaderSize_max` is always large enough.
+ *
+ * Return:   The frame content size stored in the frame header if known.
+ *           `ZSTD_CONTENTSIZE_UNKNOWN` if the content size isn't stored in the
+ *           frame header. `ZSTD_CONTENTSIZE_ERROR` on invalid input.
+ */
+unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
 
 /**
- * zstd_find_frame_compressed_size() - returns the size of a compressed frame
- * @src:      Source buffer. It should point to the start of a zstd encoded
- *            frame or a skippable frame.
- * @src_size: The size of the source buffer. It must be at least as large as the
- *            size of the frame.
+ * ZSTD_findDecompressedSize() - returns decompressed size of a series of frames
+ * @src:     It should point to the start of a series of zstd encoded and/or
+ *           skippable frames.
+ * @srcSize: The exact size of the series of frames.
  *
- * Return:    The compressed size of the frame pointed to by `src` or an error,
- *            which can be check with zstd_is_error().
- *            Suitable to pass to ZSTD_decompress() or similar functions.
+ * If any zstd encoded frame in the series doesn't have the frame content size
+ * set, `ZSTD_CONTENTSIZE_UNKNOWN` is returned. But frame content size is always
+ * set when using ZSTD_compress(). The decompressed size can be very large.
+ * If the source is untrusted, the decompressed size could be wrong or
+ * intentionally modified. Always ensure the result fits within the
+ * application's authorized limits. ZSTD_findDecompressedSize() handles multiple
+ * frames, and so it must traverse the input to read each frame header. This is
+ * efficient as most of the data is skipped, however it does mean that all frame
+ * data must be present and valid.
+ *
+ * Return:   Decompressed size of all the data contained in the frames if known.
+ *           `ZSTD_CONTENTSIZE_UNKNOWN` if the decompressed size is unknown.
+ *           `ZSTD_CONTENTSIZE_ERROR` if an error occurred.
+ */
+unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize);
+
+/*-*************************************
+ * Advanced compression functions
+ **************************************/
+/**
+ * ZSTD_checkCParams() - ensure parameter values remain within authorized range
+ * @cParams: The zstd compression parameters.
+ *
+ * Return:   Zero or an error, which can be checked using ZSTD_isError().
  */
-size_t zstd_find_frame_compressed_size(const void *src, size_t src_size);
+size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams);
 
 /**
- * struct zstd_frame_params - zstd frame parameters stored in the frame header
- * @frameContentSize: The frame content size, or ZSTD_CONTENTSIZE_UNKNOWN if not
- *                    present.
+ * ZSTD_adjustCParams() - optimize parameters for a given srcSize and dictSize
+ * @srcSize:  Optionally the estimated source size, or zero if unknown.
+ * @dictSize: Optionally the estimated dictionary size, or zero if unknown.
+ *
+ * Return:    The optimized parameters.
+ */
+ZSTD_compressionParameters ZSTD_adjustCParams(
+	ZSTD_compressionParameters cParams, unsigned long long srcSize,
+	size_t dictSize);
+
+/*--- Advanced decompression functions ---*/
+
+/**
+ * ZSTD_isFrame() - returns true iff the buffer starts with a valid frame
+ * @buffer: The source buffer to check.
+ * @size:   The size of the source buffer, must be at least 4 bytes.
+ *
+ * Return: True iff the buffer starts with a zstd or skippable frame identifier.
+ */
+unsigned int ZSTD_isFrame(const void *buffer, size_t size);
+
+/**
+ * ZSTD_getDictID_fromDict() - returns the dictionary id stored in a dictionary
+ * @dict:     The dictionary buffer.
+ * @dictSize: The size of the dictionary buffer.
+ *
+ * Return:    The dictionary id stored within the dictionary or 0 if the
+ *            dictionary is not a zstd dictionary. If it returns 0 the
+ *            dictionary can still be loaded as a content-only dictionary.
+ */
+unsigned int ZSTD_getDictID_fromDict(const void *dict, size_t dictSize);
+
+/**
+ * ZSTD_getDictID_fromDDict() - returns the dictionary id stored in a ZSTD_DDict
+ * @ddict: The ddict to find the id of.
+ *
+ * Return: The dictionary id stored within `ddict` or 0 if the dictionary is not
+ *         a zstd dictionary. If it returns 0 `ddict` will be loaded as a
+ *         content-only dictionary.
+ */
+unsigned int ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict);
+
+/**
+ * ZSTD_getDictID_fromFrame() - returns the dictionary id stored in a zstd frame
+ * @src:     Source buffer. It must be a zstd encoded frame.
+ * @srcSize: The size of the source buffer. It must be at least as large as the
+ *           frame header. `ZSTD_frameHeaderSize_max` is always large enough.
+ *
+ * Return:   The dictionary id required to decompress the frame stored within
+ *           `src` or 0 if the dictionary id could not be decoded. It can return
+ *           0 if the frame does not require a dictionary, the dictionary id
+ *           wasn't stored in the frame, `src` is not a zstd frame, or `srcSize`
+ *           is too small.
+ */
+unsigned int ZSTD_getDictID_fromFrame(const void *src, size_t srcSize);
+
+/**
+ * struct ZSTD_frameParams - zstd frame parameters stored in the frame header
+ * @frameContentSize: The frame content size, or 0 if not present.
  * @windowSize:       The window size, or 0 if the frame is a skippable frame.
- * @blockSizeMax:     The maximum block size.
- * @frameType:        The frame type (zstd or skippable)
- * @headerSize:       The size of the frame header.
  * @dictID:           The dictionary id, or 0 if not present.
  * @checksumFlag:     Whether a checksum was used.
- *
- * See zstd_lib.h.
  */
-typedef ZSTD_frameHeader zstd_frame_header;
+typedef struct {
+	unsigned long long frameContentSize;
+	unsigned int windowSize;
+	unsigned int dictID;
+	unsigned int checksumFlag;
+} ZSTD_frameParams;
 
 /**
- * zstd_get_frame_header() - extracts parameters from a zstd or skippable frame
- * @params:   On success the frame parameters are written here.
- * @src:      The source buffer. It must point to a zstd or skippable frame.
- * @src_size: The size of the source buffer.
+ * ZSTD_getFrameParams() - extracts parameters from a zstd or skippable frame
+ * @fparamsPtr: On success the frame parameters are written here.
+ * @src:        The source buffer. It must point to a zstd or skippable frame.
+ * @srcSize:    The size of the source buffer. `ZSTD_frameHeaderSize_max` is
+ *              always large enough to succeed.
  *
- * Return:    0 on success. If more data is required it returns how many bytes
- *            must be provided to make forward progress. Otherwise it returns
- *            an error, which can be checked using zstd_is_error().
+ * Return:      0 on success. If more data is required it returns how many bytes
+ *              must be provided to make forward progress. Otherwise it returns
+ *              an error, which can be checked using ZSTD_isError().
  */
-size_t zstd_get_frame_header(zstd_frame_header *params, const void *src,
-	size_t src_size);
+size_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src,
+	size_t srcSize);
+
+/*-*****************************************************************************
+ * Buffer-less and synchronous inner streaming functions
+ *
+ * This is an advanced API, giving full control over buffer management, for
+ * users which need direct control over memory.
+ * But it's also a complex one, with many restrictions (documented below).
+ * Prefer using normal streaming API for an easier experience
+ ******************************************************************************/
+
+/*-*****************************************************************************
+ * Buffer-less streaming compression (synchronous mode)
+ *
+ * A ZSTD_CCtx object is required to track streaming operations.
+ * Use ZSTD_initCCtx() to initialize a context.
+ * ZSTD_CCtx object can be re-used multiple times within successive compression
+ * operations.
+ *
+ * Start by initializing a context.
+ * Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary
+ * compression,
+ * or ZSTD_compressBegin_advanced(), for finer parameter control.
+ * It's also possible to duplicate a reference context which has already been
+ * initialized, using ZSTD_copyCCtx()
+ *
+ * Then, consume your input using ZSTD_compressContinue().
+ * There are some important considerations to keep in mind when using this
+ * advanced function :
+ * - ZSTD_compressContinue() has no internal buffer. It uses externally provided
+ *   buffer only.
+ * - Interface is synchronous : input is consumed entirely and produce 1+
+ *   (or more) compressed blocks.
+ * - Caller must ensure there is enough space in `dst` to store compressed data
+ *   under worst case scenario. Worst case evaluation is provided by
+ *   ZSTD_compressBound().
+ *   ZSTD_compressContinue() doesn't guarantee recover after a failed
+ *   compression.
+ * - ZSTD_compressContinue() presumes prior input ***is still accessible and
+ *   unmodified*** (up to maximum distance size, see WindowLog).
+ *   It remembers all previous contiguous blocks, plus one separated memory
+ *   segment (which can itself consists of multiple contiguous blocks)
+ * - ZSTD_compressContinue() detects that prior input has been overwritten when
+ *   `src` buffer overlaps. In which case, it will "discard" the relevant memory
+ *   section from its history.
+ *
+ * Finish a frame with ZSTD_compressEnd(), which will write the last block(s)
+ * and optional checksum. It's possible to use srcSize==0, in which case, it
+ * will write a final empty block to end the frame. Without last block mark,
+ * frames will be considered unfinished (corrupted) by decoders.
+ *
+ * `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress some new
+ * frame.
+ ******************************************************************************/
+
+/*=====   Buffer-less streaming compression functions  =====*/
+size_t ZSTD_compressBegin(ZSTD_CCtx *cctx, int compressionLevel);
+size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx *cctx, const void *dict,
+	size_t dictSize, int compressionLevel);
+size_t ZSTD_compressBegin_advanced(ZSTD_CCtx *cctx, const void *dict,
+	size_t dictSize, ZSTD_parameters params,
+	unsigned long long pledgedSrcSize);
+size_t ZSTD_copyCCtx(ZSTD_CCtx *cctx, const ZSTD_CCtx *preparedCCtx,
+	unsigned long long pledgedSrcSize);
+size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx *cctx, const ZSTD_CDict *cdict,
+	unsigned long long pledgedSrcSize);
+size_t ZSTD_compressContinue(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize);
+size_t ZSTD_compressEnd(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize);
+
+
+
+/*-*****************************************************************************
+ * Buffer-less streaming decompression (synchronous mode)
+ *
+ * A ZSTD_DCtx object is required to track streaming operations.
+ * Use ZSTD_initDCtx() to initialize a context.
+ * A ZSTD_DCtx object can be re-used multiple times.
+ *
+ * First typical operation is to retrieve frame parameters, using
+ * ZSTD_getFrameParams(). It fills a ZSTD_frameParams structure which provide
+ * important information to correctly decode the frame, such as the minimum
+ * rolling buffer size to allocate to decompress data (`windowSize`), and the
+ * dictionary ID used.
+ * Note: content size is optional, it may not be present. 0 means unknown.
+ * Note that these values could be wrong, either because of data malformation,
+ * or because an attacker is spoofing deliberate false information. As a
+ * consequence, check that values remain within valid application range,
+ * especially `windowSize`, before allocation. Each application can set its own
+ * limit, depending on local restrictions. For extended interoperability, it is
+ * recommended to support at least 8 MB.
+ * Frame parameters are extracted from the beginning of the compressed frame.
+ * Data fragment must be large enough to ensure successful decoding, typically
+ * `ZSTD_frameHeaderSize_max` bytes.
+ * Result: 0: successful decoding, the `ZSTD_frameParams` structure is filled.
+ *        >0: `srcSize` is too small, provide at least this many bytes.
+ *        errorCode, which can be tested using ZSTD_isError().
+ *
+ * Start decompression, with ZSTD_decompressBegin() or
+ * ZSTD_decompressBegin_usingDict(). Alternatively, you can copy a prepared
+ * context, using ZSTD_copyDCtx().
+ *
+ * Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue()
+ * alternatively.
+ * ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize'
+ * to ZSTD_decompressContinue().
+ * ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will
+ * fail.
+ *
+ * The result of ZSTD_decompressContinue() is the number of bytes regenerated
+ * within 'dst' (necessarily <= dstCapacity). It can be zero, which is not an
+ * error; it just means ZSTD_decompressContinue() has decoded some metadata
+ * item. It can also be an error code, which can be tested with ZSTD_isError().
+ *
+ * ZSTD_decompressContinue() needs previous data blocks during decompression, up
+ * to `windowSize`. They should preferably be located contiguously, prior to
+ * current block. Alternatively, a round buffer of sufficient size is also
+ * possible. Sufficient size is determined by frame parameters.
+ * ZSTD_decompressContinue() is very sensitive to contiguity, if 2 blocks don't
+ * follow each other, make sure that either the compressor breaks contiguity at
+ * the same place, or that previous contiguous segment is large enough to
+ * properly handle maximum back-reference.
+ *
+ * A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.
+ * Context can then be reset to start a new decompression.
+ *
+ * Note: it's possible to know if next input to present is a header or a block,
+ * using ZSTD_nextInputType(). This information is not required to properly
+ * decode a frame.
+ *
+ * == Special case: skippable frames ==
+ *
+ * Skippable frames allow integration of user-defined data into a flow of
+ * concatenated frames. Skippable frames will be ignored (skipped) by a
+ * decompressor. The format of skippable frames is as follows:
+ * a) Skippable frame ID - 4 Bytes, Little endian format, any value from
+ *    0x184D2A50 to 0x184D2A5F
+ * b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
+ * c) Frame Content - any content (User Data) of length equal to Frame Size
+ * For skippable frames ZSTD_decompressContinue() always returns 0.
+ * For skippable frames ZSTD_getFrameParams() returns fparamsPtr->windowLog==0
+ * what means that a frame is skippable.
+ * Note: If fparamsPtr->frameContentSize==0, it is ambiguous: the frame might
+ *       actually be a zstd encoded frame with no content. For purposes of
+ *       decompression, it is valid in both cases to skip the frame using
+ *       ZSTD_findFrameCompressedSize() to find its size in bytes.
+ * It also returns frame size as fparamsPtr->frameContentSize.
+ ******************************************************************************/
+
+/*=====   Buffer-less streaming decompression functions  =====*/
+size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx);
+size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict,
+	size_t dictSize);
+void   ZSTD_copyDCtx(ZSTD_DCtx *dctx, const ZSTD_DCtx *preparedDCtx);
+size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx);
+size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize);
+typedef enum {
+	ZSTDnit_frameHeader,
+	ZSTDnit_blockHeader,
+	ZSTDnit_block,
+	ZSTDnit_lastBlock,
+	ZSTDnit_checksum,
+	ZSTDnit_skippableFrame
+} ZSTD_nextInputType_e;
+ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx);
+
+/*-*****************************************************************************
+ * Block functions
+ *
+ * Block functions produce and decode raw zstd blocks, without frame metadata.
+ * Frame metadata cost is typically ~18 bytes, which can be non-negligible for
+ * very small blocks (< 100 bytes). User will have to take in charge required
+ * information to regenerate data, such as compressed and content sizes.
+ *
+ * A few rules to respect:
+ * - Compressing and decompressing require a context structure
+ *   + Use ZSTD_initCCtx() and ZSTD_initDCtx()
+ * - It is necessary to init context before starting
+ *   + compression : ZSTD_compressBegin()
+ *   + decompression : ZSTD_decompressBegin()
+ *   + variants _usingDict() are also allowed
+ *   + copyCCtx() and copyDCtx() work too
+ * - Block size is limited, it must be <= ZSTD_getBlockSizeMax()
+ *   + If you need to compress more, cut data into multiple blocks
+ *   + Consider using the regular ZSTD_compress() instead, as frame metadata
+ *     costs become negligible when source size is large.
+ * - When a block is considered not compressible enough, ZSTD_compressBlock()
+ *   result will be zero. In which case, nothing is produced into `dst`.
+ *   + User must test for such outcome and deal directly with uncompressed data
+ *   + ZSTD_decompressBlock() doesn't accept uncompressed data as input!!!
+ *   + In case of multiple successive blocks, decoder must be informed of
+ *     uncompressed block existence to follow proper history. Use
+ *     ZSTD_insertBlock() in such a case.
+ ******************************************************************************/
+
+/* Define for static allocation */
+#define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024)
+/*=====   Raw zstd block functions  =====*/
+size_t ZSTD_getBlockSizeMax(ZSTD_CCtx *cctx);
+size_t ZSTD_compressBlock(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize);
+size_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity,
+	const void *src, size_t srcSize);
+size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart,
+	size_t blockSize);
 
-#endif  /* LINUX_ZSTD_H */
+#endif  /* ZSTD_H */
diff --git a/include/linux/zstd_errors.h b/include/linux/zstd_errors.h
deleted file mode 100644
index 58b6dd45a969..000000000000
--- a/include/linux/zstd_errors.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-#ifndef ZSTD_ERRORS_H_398273423
-#define ZSTD_ERRORS_H_398273423
-
-
-/*===== dependency =====*/
-#include <linux/types.h>   /* size_t */
-
-
-/* =====   ZSTDERRORLIB_API : control library symbols visibility   ===== */
-#define ZSTDERRORLIB_VISIBILITY 
-#define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY
-
-/*-*********************************************
- *  Error codes list
- *-*********************************************
- *  Error codes _values_ are pinned down since v1.3.1 only.
- *  Therefore, don't rely on values if you may link to any version < v1.3.1.
- *
- *  Only values < 100 are considered stable.
- *
- *  note 1 : this API shall be used with static linking only.
- *           dynamic linking is not yet officially supported.
- *  note 2 : Prefer relying on the enum than on its value whenever possible
- *           This is the only supported way to use the error list < v1.3.1
- *  note 3 : ZSTD_isError() is always correct, whatever the library version.
- **********************************************/
-typedef enum {
-  ZSTD_error_no_error = 0,
-  ZSTD_error_GENERIC  = 1,
-  ZSTD_error_prefix_unknown                = 10,
-  ZSTD_error_version_unsupported           = 12,
-  ZSTD_error_frameParameter_unsupported    = 14,
-  ZSTD_error_frameParameter_windowTooLarge = 16,
-  ZSTD_error_corruption_detected = 20,
-  ZSTD_error_checksum_wrong      = 22,
-  ZSTD_error_dictionary_corrupted      = 30,
-  ZSTD_error_dictionary_wrong          = 32,
-  ZSTD_error_dictionaryCreation_failed = 34,
-  ZSTD_error_parameter_unsupported   = 40,
-  ZSTD_error_parameter_outOfBound    = 42,
-  ZSTD_error_tableLog_tooLarge       = 44,
-  ZSTD_error_maxSymbolValue_tooLarge = 46,
-  ZSTD_error_maxSymbolValue_tooSmall = 48,
-  ZSTD_error_stage_wrong       = 60,
-  ZSTD_error_init_missing      = 62,
-  ZSTD_error_memory_allocation = 64,
-  ZSTD_error_workSpace_tooSmall= 66,
-  ZSTD_error_dstSize_tooSmall = 70,
-  ZSTD_error_srcSize_wrong    = 72,
-  ZSTD_error_dstBuffer_null   = 74,
-  /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
-  ZSTD_error_frameIndex_tooLarge = 100,
-  ZSTD_error_seekableIO          = 102,
-  ZSTD_error_dstBuffer_wrong     = 104,
-  ZSTD_error_srcBuffer_wrong     = 105,
-  ZSTD_error_maxCode = 120  /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
-} ZSTD_ErrorCode;
-
-/*! ZSTD_getErrorCode() :
-    convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
-    which can be used to compare with enum list published above */
-ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
-ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);   /*< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
-
-
-
-#endif /* ZSTD_ERRORS_H_398273423 */
diff --git a/include/linux/zstd_lib.h b/include/linux/zstd_lib.h
deleted file mode 100644
index b8c7dbf98390..000000000000
--- a/include/linux/zstd_lib.h
+++ /dev/null
@@ -1,2432 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-#ifndef ZSTD_H_235446
-#define ZSTD_H_235446
-
-/* ======   Dependency   ======*/
-#include <linux/limits.h>   /* INT_MAX */
-#include <linux/types.h>   /* size_t */
-
-
-/* =====   ZSTDLIB_API : control library symbols visibility   ===== */
-#define ZSTDLIB_VISIBILITY 
-#define ZSTDLIB_API ZSTDLIB_VISIBILITY
-
-
-/* *****************************************************************************
-  Introduction
-
-  zstd, short for Zstandard, is a fast lossless compression algorithm, targeting
-  real-time compression scenarios at zlib-level and better compression ratios.
-  The zstd compression library provides in-memory compression and decompression
-  functions.
-
-  The library supports regular compression levels from 1 up to ZSTD_maxCLevel(),
-  which is currently 22. Levels >= 20, labeled `--ultra`, should be used with
-  caution, as they require more memory. The library also offers negative
-  compression levels, which extend the range of speed vs. ratio preferences.
-  The lower the level, the faster the speed (at the cost of compression).
-
-  Compression can be done in:
-    - a single step (described as Simple API)
-    - a single step, reusing a context (described as Explicit context)
-    - unbounded multiple steps (described as Streaming compression)
-
-  The compression ratio achievable on small data can be highly improved using
-  a dictionary. Dictionary compression can be performed in:
-    - a single step (described as Simple dictionary API)
-    - a single step, reusing a dictionary (described as Bulk-processing
-      dictionary API)
-
-  Advanced experimental functions can be accessed using
-  `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h.
-
-  Advanced experimental APIs should never be used with a dynamically-linked
-  library. They are not "stable"; their definitions or signatures may change in
-  the future. Only static linking is allowed.
-*******************************************************************************/
-
-/*------   Version   ------*/
-#define ZSTD_VERSION_MAJOR    1
-#define ZSTD_VERSION_MINOR    4
-#define ZSTD_VERSION_RELEASE  10
-#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
-
-/*! ZSTD_versionNumber() :
- *  Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */
-ZSTDLIB_API unsigned ZSTD_versionNumber(void);
-
-#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
-#define ZSTD_QUOTE(str) #str
-#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)
-#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
-
-/*! ZSTD_versionString() :
- *  Return runtime library version, like "1.4.5". Requires v1.3.0+. */
-ZSTDLIB_API const char* ZSTD_versionString(void);
-
-/* *************************************
- *  Default constant
- ***************************************/
-#ifndef ZSTD_CLEVEL_DEFAULT
-#  define ZSTD_CLEVEL_DEFAULT 3
-#endif
-
-/* *************************************
- *  Constants
- ***************************************/
-
-/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */
-#define ZSTD_MAGICNUMBER            0xFD2FB528    /* valid since v0.8.0 */
-#define ZSTD_MAGIC_DICTIONARY       0xEC30A437    /* valid since v0.7.0 */
-#define ZSTD_MAGIC_SKIPPABLE_START  0x184D2A50    /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */
-#define ZSTD_MAGIC_SKIPPABLE_MASK   0xFFFFFFF0
-
-#define ZSTD_BLOCKSIZELOG_MAX  17
-#define ZSTD_BLOCKSIZE_MAX     (1<<ZSTD_BLOCKSIZELOG_MAX)
-
-
-
-/* *************************************
-*  Simple API
-***************************************/
-/*! ZSTD_compress() :
- *  Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
- *  Hint : compression runs faster if `dstCapacity` >=  `ZSTD_compressBound(srcSize)`.
- *  @return : compressed size written into `dst` (<= `dstCapacity),
- *            or an error code if it fails (which can be tested using ZSTD_isError()). */
-ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
-                            const void* src, size_t srcSize,
-                                  int compressionLevel);
-
-/*! ZSTD_decompress() :
- *  `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.
- *  `dstCapacity` is an upper bound of originalSize to regenerate.
- *  If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data.
- *  @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
- *            or an errorCode if it fails (which can be tested using ZSTD_isError()). */
-ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
-                              const void* src, size_t compressedSize);
-
-/*! ZSTD_getFrameContentSize() : requires v1.3.0+
- *  `src` should point to the start of a ZSTD encoded frame.
- *  `srcSize` must be at least as large as the frame header.
- *            hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.
- *  @return : - decompressed size of `src` frame content, if known
- *            - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
- *            - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)
- *   note 1 : a 0 return value means the frame is valid but "empty".
- *   note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode.
- *            When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.
- *            In which case, it's necessary to use streaming mode to decompress data.
- *            Optionally, application can rely on some implicit limit,
- *            as ZSTD_decompress() only needs an upper bound of decompressed size.
- *            (For example, data could be necessarily cut into blocks <= 16 KB).
- *   note 3 : decompressed size is always present when compression is completed using single-pass functions,
- *            such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict().
- *   note 4 : decompressed size can be very large (64-bits value),
- *            potentially larger than what local system can handle as a single memory segment.
- *            In which case, it's necessary to use streaming mode to decompress data.
- *   note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified.
- *            Always ensure return value fits within application's authorized limits.
- *            Each application can set its own limits.
- *   note 6 : This function replaces ZSTD_getDecompressedSize() */
-#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
-#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)
-ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
-
-/*! ZSTD_getDecompressedSize() :
- *  NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize().
- *  Both functions work the same way, but ZSTD_getDecompressedSize() blends
- *  "empty", "unknown" and "error" results to the same return value (0),
- *  while ZSTD_getFrameContentSize() gives them separate return values.
- * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
-ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
-
-/*! ZSTD_findFrameCompressedSize() :
- * `src` should point to the start of a ZSTD frame or skippable frame.
- * `srcSize` must be >= first frame size
- * @return : the compressed size of the first frame starting at `src`,
- *           suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
- *        or an error code if input is invalid */
-ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
-
-
-/*======  Helper functions  ======*/
-#define ZSTD_COMPRESSBOUND(srcSize)   ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0))  /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
-ZSTDLIB_API size_t      ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
-ZSTDLIB_API unsigned    ZSTD_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */
-ZSTDLIB_API const char* ZSTD_getErrorName(size_t code);     /*!< provides readable string from an error code */
-ZSTDLIB_API int         ZSTD_minCLevel(void);               /*!< minimum negative compression level allowed */
-ZSTDLIB_API int         ZSTD_maxCLevel(void);               /*!< maximum compression level available */
-
-
-/* *************************************
-*  Explicit context
-***************************************/
-/*= Compression context
- *  When compressing many times,
- *  it is recommended to allocate a context just once,
- *  and re-use it for each successive compression operation.
- *  This will make workload friendlier for system's memory.
- *  Note : re-using context is just a speed / resource optimization.
- *         It doesn't change the compression ratio, which remains identical.
- *  Note 2 : In multi-threaded environments,
- *         use one different context per thread for parallel execution.
- */
-typedef struct ZSTD_CCtx_s ZSTD_CCtx;
-ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
-ZSTDLIB_API size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* accept NULL pointer */
-
-/*! ZSTD_compressCCtx() :
- *  Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
- *  Important : in order to behave similarly to `ZSTD_compress()`,
- *  this function compresses at requested compression level,
- *  __ignoring any other parameter__ .
- *  If any advanced parameter was set using the advanced API,
- *  they will all be reset. Only `compressionLevel` remains.
- */
-ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
-                                     void* dst, size_t dstCapacity,
-                               const void* src, size_t srcSize,
-                                     int compressionLevel);
-
-/*= Decompression context
- *  When decompressing many times,
- *  it is recommended to allocate a context only once,
- *  and re-use it for each successive compression operation.
- *  This will make workload friendlier for system's memory.
- *  Use one context per thread for parallel execution. */
-typedef struct ZSTD_DCtx_s ZSTD_DCtx;
-ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
-ZSTDLIB_API size_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);  /* accept NULL pointer */
-
-/*! ZSTD_decompressDCtx() :
- *  Same as ZSTD_decompress(),
- *  requires an allocated ZSTD_DCtx.
- *  Compatible with sticky parameters.
- */
-ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
-                                       void* dst, size_t dstCapacity,
-                                 const void* src, size_t srcSize);
-
-
-/* *************************************
-*  Advanced compression API
-***************************************/
-
-/* API design :
- *   Parameters are pushed one by one into an existing context,
- *   using ZSTD_CCtx_set*() functions.
- *   Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame.
- *   "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` !
- *   __They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()__ .
- *
- *   It's possible to reset all parameters to "default" using ZSTD_CCtx_reset().
- *
- *   This API supercedes all other "advanced" API entry points in the experimental section.
- *   In the future, we expect to remove from experimental API entry points which are redundant with this API.
- */
-
-
-/* Compression strategies, listed from fastest to strongest */
-typedef enum { ZSTD_fast=1,
-               ZSTD_dfast=2,
-               ZSTD_greedy=3,
-               ZSTD_lazy=4,
-               ZSTD_lazy2=5,
-               ZSTD_btlazy2=6,
-               ZSTD_btopt=7,
-               ZSTD_btultra=8,
-               ZSTD_btultra2=9
-               /* note : new strategies _might_ be added in the future.
-                         Only the order (from fast to strong) is guaranteed */
-} ZSTD_strategy;
-
-
-typedef enum {
-
-    /* compression parameters
-     * Note: When compressing with a ZSTD_CDict these parameters are superseded
-     * by the parameters used to construct the ZSTD_CDict.
-     * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */
-    ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table.
-                              * Note that exact compression parameters are dynamically determined,
-                              * depending on both compression level and srcSize (when known).
-                              * Default level is ZSTD_CLEVEL_DEFAULT==3.
-                              * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
-                              * Note 1 : it's possible to pass a negative compression level.
-                              * Note 2 : setting a level does not automatically set all other compression parameters
-                              *   to default. Setting this will however eventually dynamically impact the compression
-                              *   parameters which have not been manually set. The manually set
-                              *   ones will 'stick'. */
-    /* Advanced compression parameters :
-     * It's possible to pin down compression parameters to some specific values.
-     * In which case, these values are no longer dynamically selected by the compressor */
-    ZSTD_c_windowLog=101,    /* Maximum allowed back-reference distance, expressed as power of 2.
-                              * This will set a memory budget for streaming decompression,
-                              * with larger values requiring more memory
-                              * and typically compressing more.
-                              * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.
-                              * Special: value 0 means "use default windowLog".
-                              * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT
-                              *       requires explicitly allowing such size at streaming decompression stage. */
-    ZSTD_c_hashLog=102,      /* Size of the initial probe table, as a power of 2.
-                              * Resulting memory usage is (1 << (hashLog+2)).
-                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.
-                              * Larger tables improve compression ratio of strategies <= dFast,
-                              * and improve speed of strategies > dFast.
-                              * Special: value 0 means "use default hashLog". */
-    ZSTD_c_chainLog=103,     /* Size of the multi-probe search table, as a power of 2.
-                              * Resulting memory usage is (1 << (chainLog+2)).
-                              * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX.
-                              * Larger tables result in better and slower compression.
-                              * This parameter is useless for "fast" strategy.
-                              * It's still useful when using "dfast" strategy,
-                              * in which case it defines a secondary probe table.
-                              * Special: value 0 means "use default chainLog". */
-    ZSTD_c_searchLog=104,    /* Number of search attempts, as a power of 2.
-                              * More attempts result in better and slower compression.
-                              * This parameter is useless for "fast" and "dFast" strategies.
-                              * Special: value 0 means "use default searchLog". */
-    ZSTD_c_minMatch=105,     /* Minimum size of searched matches.
-                              * Note that Zstandard can still find matches of smaller size,
-                              * it just tweaks its search algorithm to look for this size and larger.
-                              * Larger values increase compression and decompression speed, but decrease ratio.
-                              * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX.
-                              * Note that currently, for all strategies < btopt, effective minimum is 4.
-                              *                    , for all strategies > fast, effective maximum is 6.
-                              * Special: value 0 means "use default minMatchLength". */
-    ZSTD_c_targetLength=106, /* Impact of this field depends on strategy.
-                              * For strategies btopt, btultra & btultra2:
-                              *     Length of Match considered "good enough" to stop search.
-                              *     Larger values make compression stronger, and slower.
-                              * For strategy fast:
-                              *     Distance between match sampling.
-                              *     Larger values make compression faster, and weaker.
-                              * Special: value 0 means "use default targetLength". */
-    ZSTD_c_strategy=107,     /* See ZSTD_strategy enum definition.
-                              * The higher the value of selected strategy, the more complex it is,
-                              * resulting in stronger and slower compression.
-                              * Special: value 0 means "use default strategy". */
-
-    /* LDM mode parameters */
-    ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.
-                                     * This parameter is designed to improve compression ratio
-                                     * for large inputs, by finding large matches at long distance.
-                                     * It increases memory usage and window size.
-                                     * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB
-                                     * except when expressly set to a different value.
-                                     * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and
-                                     * compression strategy >= ZSTD_btopt (== compression level 16+) */
-    ZSTD_c_ldmHashLog=161,   /* Size of the table for long distance matching, as a power of 2.
-                              * Larger values increase memory usage and compression ratio,
-                              * but decrease compression speed.
-                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX
-                              * default: windowlog - 7.
-                              * Special: value 0 means "automatically determine hashlog". */
-    ZSTD_c_ldmMinMatch=162,  /* Minimum match size for long distance matcher.
-                              * Larger/too small values usually decrease compression ratio.
-                              * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.
-                              * Special: value 0 means "use default value" (default: 64). */
-    ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution.
-                              * Larger values improve collision resolution but decrease compression speed.
-                              * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX.
-                              * Special: value 0 means "use default value" (default: 3). */
-    ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table.
-                              * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).
-                              * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.
-                              * Larger values improve compression speed.
-                              * Deviating far from default value will likely result in a compression ratio decrease.
-                              * Special: value 0 means "automatically determine hashRateLog". */
-
-    /* frame parameters */
-    ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1)
-                              * Content size must be known at the beginning of compression.
-                              * This is automatically the case when using ZSTD_compress2(),
-                              * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */
-    ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */
-    ZSTD_c_dictIDFlag=202,   /* When applicable, dictionary's ID is written into frame header (default:1) */
-
-    /* multi-threading parameters */
-    /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
-     * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.
-     * In a situation where it's unknown if the linked library supports multi-threading or not,
-     * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.
-     */
-    ZSTD_c_nbWorkers=400,    /* Select how many threads will be spawned to compress in parallel.
-                              * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :
-                              * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,
-                              * while compression is performed in parallel, within worker thread(s).
-                              * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :
-                              *  in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).
-                              * More workers improve speed, but also increase memory usage.
-                              * Default value is `0`, aka "single-threaded mode" : no worker is spawned,
-                              * compression is performed inside Caller's thread, and all invocations are blocking */
-    ZSTD_c_jobSize=401,      /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
-                              * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
-                              * 0 means default, which is dynamically determined based on compression parameters.
-                              * Job size must be a minimum of overlap size, or 1 MB, whichever is largest.
-                              * The minimum size is automatically and transparently enforced. */
-    ZSTD_c_overlapLog=402,   /* Control the overlap size, as a fraction of window size.
-                              * The overlap size is an amount of data reloaded from previous job at the beginning of a new job.
-                              * It helps preserve compression ratio, while each job is compressed in parallel.
-                              * This value is enforced only when nbWorkers >= 1.
-                              * Larger values increase compression ratio, but decrease speed.
-                              * Possible values range from 0 to 9 :
-                              * - 0 means "default" : value will be determined by the library, depending on strategy
-                              * - 1 means "no overlap"
-                              * - 9 means "full overlap", using a full window size.
-                              * Each intermediate rank increases/decreases load size by a factor 2 :
-                              * 9: full window;  8: w/2;  7: w/4;  6: w/8;  5:w/16;  4: w/32;  3:w/64;  2:w/128;  1:no overlap;  0:default
-                              * default value varies between 6 and 9, depending on strategy */
-
-    /* note : additional experimental parameters are also available
-     * within the experimental section of the API.
-     * At the time of this writing, they include :
-     * ZSTD_c_rsyncable
-     * ZSTD_c_format
-     * ZSTD_c_forceMaxWindow
-     * ZSTD_c_forceAttachDict
-     * ZSTD_c_literalCompressionMode
-     * ZSTD_c_targetCBlockSize
-     * ZSTD_c_srcSizeHint
-     * ZSTD_c_enableDedicatedDictSearch
-     * ZSTD_c_stableInBuffer
-     * ZSTD_c_stableOutBuffer
-     * ZSTD_c_blockDelimiters
-     * ZSTD_c_validateSequences
-     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
-     * note : never ever use experimentalParam? names directly;
-     *        also, the enums values themselves are unstable and can still change.
-     */
-     ZSTD_c_experimentalParam1=500,
-     ZSTD_c_experimentalParam2=10,
-     ZSTD_c_experimentalParam3=1000,
-     ZSTD_c_experimentalParam4=1001,
-     ZSTD_c_experimentalParam5=1002,
-     ZSTD_c_experimentalParam6=1003,
-     ZSTD_c_experimentalParam7=1004,
-     ZSTD_c_experimentalParam8=1005,
-     ZSTD_c_experimentalParam9=1006,
-     ZSTD_c_experimentalParam10=1007,
-     ZSTD_c_experimentalParam11=1008,
-     ZSTD_c_experimentalParam12=1009
-} ZSTD_cParameter;
-
-typedef struct {
-    size_t error;
-    int lowerBound;
-    int upperBound;
-} ZSTD_bounds;
-
-/*! ZSTD_cParam_getBounds() :
- *  All parameters must belong to an interval with lower and upper bounds,
- *  otherwise they will either trigger an error or be automatically clamped.
- * @return : a structure, ZSTD_bounds, which contains
- *         - an error status field, which must be tested using ZSTD_isError()
- *         - lower and upper bounds, both inclusive
- */
-ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam);
-
-/*! ZSTD_CCtx_setParameter() :
- *  Set one compression parameter, selected by enum ZSTD_cParameter.
- *  All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds().
- *  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
- *  Setting a parameter is generally only possible during frame initialization (before starting compression).
- *  Exception : when using multi-threading mode (nbWorkers >= 1),
- *              the following parameters can be updated _during_ compression (within same frame):
- *              => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.
- *              new parameters will be active for next job only (after a flush()).
- * @return : an error code (which can be tested using ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value);
-
-/*! ZSTD_CCtx_setPledgedSrcSize() :
- *  Total input data size to be compressed as a single frame.
- *  Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag.
- *  This value will also be controlled at end of frame, and trigger an error if not respected.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- *  Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame.
- *           In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN.
- *           ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame.
- *  Note 2 : pledgedSrcSize is only valid once, for the next frame.
- *           It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN.
- *  Note 3 : Whenever all input data is provided and consumed in a single round,
- *           for example with ZSTD_compress2(),
- *           or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),
- *           this value is automatically overridden by srcSize instead.
- */
-ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
-
-typedef enum {
-    ZSTD_reset_session_only = 1,
-    ZSTD_reset_parameters = 2,
-    ZSTD_reset_session_and_parameters = 3
-} ZSTD_ResetDirective;
-
-/*! ZSTD_CCtx_reset() :
- *  There are 2 different things that can be reset, independently or jointly :
- *  - The session : will stop compressing current frame, and make CCtx ready to start a new one.
- *                  Useful after an error, or to interrupt any ongoing compression.
- *                  Any internal data not yet flushed is cancelled.
- *                  Compression parameters and dictionary remain unchanged.
- *                  They will be used to compress next frame.
- *                  Resetting session never fails.
- *  - The parameters : changes all parameters back to "default".
- *                  This removes any reference to any dictionary too.
- *                  Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
- *                  otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
- *  - Both : similar to resetting the session, followed by resetting parameters.
- */
-ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);
-
-/*! ZSTD_compress2() :
- *  Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
- *  ZSTD_compress2() always starts a new frame.
- *  Should cctx hold data from a previously unfinished frame, everything about it is forgotten.
- *  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
- *  - The function is always blocking, returns when compression is completed.
- *  Hint : compression runs faster if `dstCapacity` >=  `ZSTD_compressBound(srcSize)`.
- * @return : compressed size written into `dst` (<= `dstCapacity),
- *           or an error code if it fails (which can be tested using ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
-                                   void* dst, size_t dstCapacity,
-                             const void* src, size_t srcSize);
-
-
-/* *************************************
-*  Advanced decompression API
-***************************************/
-
-/* The advanced API pushes parameters one by one into an existing DCtx context.
- * Parameters are sticky, and remain valid for all following frames
- * using the same DCtx context.
- * It's possible to reset parameters to default values using ZSTD_DCtx_reset().
- * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().
- *        Therefore, no new decompression function is necessary.
- */
-
-typedef enum {
-
-    ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which
-                              * the streaming API will refuse to allocate memory buffer
-                              * in order to protect the host from unreasonable memory requirements.
-                              * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
-                              * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).
-                              * Special: value 0 means "use default maximum windowLog". */
-
-    /* note : additional experimental parameters are also available
-     * within the experimental section of the API.
-     * At the time of this writing, they include :
-     * ZSTD_d_format
-     * ZSTD_d_stableOutBuffer
-     * ZSTD_d_forceIgnoreChecksum
-     * ZSTD_d_refMultipleDDicts
-     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
-     * note : never ever use experimentalParam? names directly
-     */
-     ZSTD_d_experimentalParam1=1000,
-     ZSTD_d_experimentalParam2=1001,
-     ZSTD_d_experimentalParam3=1002,
-     ZSTD_d_experimentalParam4=1003
-
-} ZSTD_dParameter;
-
-/*! ZSTD_dParam_getBounds() :
- *  All parameters must belong to an interval with lower and upper bounds,
- *  otherwise they will either trigger an error or be automatically clamped.
- * @return : a structure, ZSTD_bounds, which contains
- *         - an error status field, which must be tested using ZSTD_isError()
- *         - both lower and upper bounds, inclusive
- */
-ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);
-
-/*! ZSTD_DCtx_setParameter() :
- *  Set one compression parameter, selected by enum ZSTD_dParameter.
- *  All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().
- *  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
- *  Setting a parameter is only possible during frame initialization (before starting decompression).
- * @return : 0, or an error code (which can be tested using ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);
-
-/*! ZSTD_DCtx_reset() :
- *  Return a DCtx to clean state.
- *  Session and parameters can be reset jointly or separately.
- *  Parameters can only be reset when no active frame is being decompressed.
- * @return : 0, or an error code, which can be tested with ZSTD_isError()
- */
-ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
-
-
-/* **************************
-*  Streaming
-****************************/
-
-typedef struct ZSTD_inBuffer_s {
-  const void* src;    /*< start of input buffer */
-  size_t size;        /*< size of input buffer */
-  size_t pos;         /*< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
-} ZSTD_inBuffer;
-
-typedef struct ZSTD_outBuffer_s {
-  void*  dst;         /*< start of output buffer */
-  size_t size;        /*< size of output buffer */
-  size_t pos;         /*< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
-} ZSTD_outBuffer;
-
-
-
-/*-***********************************************************************
-*  Streaming compression - HowTo
-*
-*  A ZSTD_CStream object is required to track streaming operation.
-*  Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
-*  ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
-*  It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
-*
-*  For parallel execution, use one separate ZSTD_CStream per thread.
-*
-*  note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
-*
-*  Parameters are sticky : when starting a new compression on the same context,
-*  it will re-use the same sticky parameters as previous compression session.
-*  When in doubt, it's recommended to fully initialize the context before usage.
-*  Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),
-*  ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to
-*  set more specific parameters, the pledged source size, or load a dictionary.
-*
-*  Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to
-*  consume input stream. The function will automatically update both `pos`
-*  fields within `input` and `output`.
-*  Note that the function may not consume the entire input, for example, because
-*  the output buffer is already full, in which case `input.pos < input.size`.
-*  The caller must check if input has been entirely consumed.
-*  If not, the caller must make some room to receive more compressed data,
-*  and then present again remaining input data.
-*  note: ZSTD_e_continue is guaranteed to make some forward progress when called,
-*        but doesn't guarantee maximal forward progress. This is especially relevant
-*        when compressing with multiple threads. The call won't block if it can
-*        consume some input, but if it can't it will wait for some, but not all,
-*        output to be flushed.
-* @return : provides a minimum amount of data remaining to be flushed from internal buffers
-*           or an error code, which can be tested using ZSTD_isError().
-*
-*  At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
-*  using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.
-*  Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).
-*  In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.
-*  You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the
-*  operation.
-*  note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will
-*        block until the flush is complete or the output buffer is full.
-*  @return : 0 if internal buffers are entirely flushed,
-*            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
-*            or an error code, which can be tested using ZSTD_isError().
-*
-*  Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.
-*  It will perform a flush and write frame epilogue.
-*  The epilogue is required for decoders to consider a frame completed.
-*  flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.
-*  You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to
-*  start a new frame.
-*  note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will
-*        block until the flush is complete or the output buffer is full.
-*  @return : 0 if frame fully completed and fully flushed,
-*            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
-*            or an error code, which can be tested using ZSTD_isError().
-*
-* *******************************************************************/
-
-typedef ZSTD_CCtx ZSTD_CStream;  /*< CCtx and CStream are now effectively same object (>= v1.3.0) */
-                                 /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
-/*===== ZSTD_CStream management functions =====*/
-ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
-ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);  /* accept NULL pointer */
-
-/*===== Streaming compression functions =====*/
-typedef enum {
-    ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */
-    ZSTD_e_flush=1,    /* flush any data provided so far,
-                        * it creates (at least) one new block, that can be decoded immediately on reception;
-                        * frame will continue: any future data can still reference previously compressed data, improving compression.
-                        * note : multithreaded compression will block to flush as much output as possible. */
-    ZSTD_e_end=2       /* flush any remaining data _and_ close current frame.
-                        * note that frame is only closed after compressed data is fully flushed (return value == 0).
-                        * After that point, any additional data starts a new frame.
-                        * note : each frame is independent (does not reference any content from previous frame).
-                        : note : multithreaded compression will block to flush as much output as possible. */
-} ZSTD_EndDirective;
-
-/*! ZSTD_compressStream2() :
- *  Behaves about the same as ZSTD_compressStream, with additional control on end directive.
- *  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
- *  - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
- *  - output->pos must be <= dstCapacity, input->pos must be <= srcSize
- *  - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
- *  - endOp must be a valid directive
- *  - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
- *  - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,
- *                                                  and then immediately returns, just indicating that there is some data remaining to be flushed.
- *                                                  The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
- *  - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
- *  - @return provides a minimum amount of data remaining to be flushed from internal buffers
- *            or an error code, which can be tested using ZSTD_isError().
- *            if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
- *            This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
- *            For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
- *  - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
- *            only ZSTD_e_end or ZSTD_e_flush operations are allowed.
- *            Before starting a new compression job, or changing compression parameters,
- *            it is required to fully flush internal buffers.
- */
-ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
-                                         ZSTD_outBuffer* output,
-                                         ZSTD_inBuffer* input,
-                                         ZSTD_EndDirective endOp);
-
-
-/* These buffer sizes are softly recommended.
- * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output.
- * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(),
- * reducing the amount of memory shuffling and buffering, resulting in minor performance savings.
- *
- * However, note that these recommendations are from the perspective of a C caller program.
- * If the streaming interface is invoked from some other language,
- * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo,
- * a major performance rule is to reduce crossing such interface to an absolute minimum.
- * It's not rare that performance ends being spent more into the interface, rather than compression itself.
- * In which cases, prefer using large buffers, as large as practical,
- * for both input and output, to reduce the nb of roundtrips.
- */
-ZSTDLIB_API size_t ZSTD_CStreamInSize(void);    /*< recommended size for input buffer */
-ZSTDLIB_API size_t ZSTD_CStreamOutSize(void);   /*< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */
-
-
-/* *****************************************************************************
- * This following is a legacy streaming API.
- * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().
- * It is redundant, but remains fully supported.
- * Advanced parameters and dictionary compression can only be used through the
- * new API.
- ******************************************************************************/
-
-/*!
- * Equivalent to:
- *
- *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
- *     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
- *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
- */
-ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
-/*!
- * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
- * NOTE: The return value is different. ZSTD_compressStream() returns a hint for
- * the next read size (if non-zero and not an error). ZSTD_compressStream2()
- * returns the minimum nb of bytes left to flush (if non-zero and not an error).
- */
-ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
-/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */
-ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
-/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */
-ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
-
-
-/*-***************************************************************************
-*  Streaming decompression - HowTo
-*
-*  A ZSTD_DStream object is required to track streaming operations.
-*  Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
-*  ZSTD_DStream objects can be re-used multiple times.
-*
-*  Use ZSTD_initDStream() to start a new decompression operation.
-* @return : recommended first input size
-*  Alternatively, use advanced API to set specific properties.
-*
-*  Use ZSTD_decompressStream() repetitively to consume your input.
-*  The function will update both `pos` fields.
-*  If `input.pos < input.size`, some input has not been consumed.
-*  It's up to the caller to present again remaining data.
-*  The function tries to flush all data decoded immediately, respecting output buffer size.
-*  If `output.pos < output.size`, decoder has flushed everything it could.
-*  But if `output.pos == output.size`, there might be some data left within internal buffers.,
-*  In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
-*  Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
-* @return : 0 when a frame is completely decoded and fully flushed,
-*        or an error code, which can be tested using ZSTD_isError(),
-*        or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
-*                                the return value is a suggested next input size (just a hint for better latency)
-*                                that will never request more than the remaining frame size.
-* *******************************************************************************/
-
-typedef ZSTD_DCtx ZSTD_DStream;  /*< DCtx and DStream are now effectively same object (>= v1.3.0) */
-                                 /* For compatibility with versions <= v1.2.0, prefer differentiating them. */
-/*===== ZSTD_DStream management functions =====*/
-ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
-ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);  /* accept NULL pointer */
-
-/*===== Streaming decompression functions =====*/
-
-/* This function is redundant with the advanced API and equivalent to:
- *
- *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
- *     ZSTD_DCtx_refDDict(zds, NULL);
- */
-ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
-
-ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
-
-ZSTDLIB_API size_t ZSTD_DStreamInSize(void);    /*!< recommended size for input buffer */
-ZSTDLIB_API size_t ZSTD_DStreamOutSize(void);   /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
-
-
-/* ************************
-*  Simple dictionary API
-***************************/
-/*! ZSTD_compress_usingDict() :
- *  Compression at an explicit compression level using a Dictionary.
- *  A dictionary can be any arbitrary data segment (also called a prefix),
- *  or a buffer with specified information (see dictBuilder/zdict.h).
- *  Note : This function loads the dictionary, resulting in significant startup delay.
- *         It's intended for a dictionary used only once.
- *  Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
-ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
-                                           void* dst, size_t dstCapacity,
-                                     const void* src, size_t srcSize,
-                                     const void* dict,size_t dictSize,
-                                           int compressionLevel);
-
-/*! ZSTD_decompress_usingDict() :
- *  Decompression using a known Dictionary.
- *  Dictionary must be identical to the one used during compression.
- *  Note : This function loads the dictionary, resulting in significant startup delay.
- *         It's intended for a dictionary used only once.
- *  Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
-ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
-                                             void* dst, size_t dstCapacity,
-                                       const void* src, size_t srcSize,
-                                       const void* dict,size_t dictSize);
-
-
-/* *********************************
- *  Bulk processing dictionary API
- **********************************/
-typedef struct ZSTD_CDict_s ZSTD_CDict;
-
-/*! ZSTD_createCDict() :
- *  When compressing multiple messages or blocks using the same dictionary,
- *  it's recommended to digest the dictionary only once, since it's a costly operation.
- *  ZSTD_createCDict() will create a state from digesting a dictionary.
- *  The resulting state can be used for future compression operations with very limited startup cost.
- *  ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
- * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict.
- *  Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content.
- *  Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer,
- *      in which case the only thing that it transports is the @compressionLevel.
- *      This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively,
- *      expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
-                                         int compressionLevel);
-
-/*! ZSTD_freeCDict() :
- *  Function frees memory allocated by ZSTD_createCDict().
- *  If a NULL pointer is passed, no operation is performed. */
-ZSTDLIB_API size_t      ZSTD_freeCDict(ZSTD_CDict* CDict);
-
-/*! ZSTD_compress_usingCDict() :
- *  Compression using a digested Dictionary.
- *  Recommended when same dictionary is used multiple times.
- *  Note : compression level is _decided at dictionary creation time_,
- *     and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
-ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
-                                            void* dst, size_t dstCapacity,
-                                      const void* src, size_t srcSize,
-                                      const ZSTD_CDict* cdict);
-
-
-typedef struct ZSTD_DDict_s ZSTD_DDict;
-
-/*! ZSTD_createDDict() :
- *  Create a digested dictionary, ready to start decompression operation without startup delay.
- *  dictBuffer can be released after DDict creation, as its content is copied inside DDict. */
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
-
-/*! ZSTD_freeDDict() :
- *  Function frees memory allocated with ZSTD_createDDict()
- *  If a NULL pointer is passed, no operation is performed. */
-ZSTDLIB_API size_t      ZSTD_freeDDict(ZSTD_DDict* ddict);
-
-/*! ZSTD_decompress_usingDDict() :
- *  Decompression using a digested Dictionary.
- *  Recommended when same dictionary is used multiple times. */
-ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
-                                              void* dst, size_t dstCapacity,
-                                        const void* src, size_t srcSize,
-                                        const ZSTD_DDict* ddict);
-
-
-/* ******************************
- *  Dictionary helper functions
- *******************************/
-
-/*! ZSTD_getDictID_fromDict() :
- *  Provides the dictID stored within dictionary.
- *  if @return == 0, the dictionary is not conformant with Zstandard specification.
- *  It can still be loaded, but as a content-only dictionary. */
-ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
-
-/*! ZSTD_getDictID_fromDDict() :
- *  Provides the dictID of the dictionary loaded into `ddict`.
- *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
- *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
-ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
-
-/*! ZSTD_getDictID_fromFrame() :
- *  Provides the dictID required to decompressed the frame stored within `src`.
- *  If @return == 0, the dictID could not be decoded.
- *  This could for one of the following reasons :
- *  - The frame does not require a dictionary to be decoded (most common case).
- *  - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
- *    Note : this use case also happens when using a non-conformant dictionary.
- *  - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
- *  - This is not a Zstandard frame.
- *  When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
-ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
-
-
-/* *****************************************************************************
- * Advanced dictionary and prefix API
- *
- * This API allows dictionaries to be used with ZSTD_compress2(),
- * ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
- * only reset with the context is reset with ZSTD_reset_parameters or
- * ZSTD_reset_session_and_parameters. Prefixes are single-use.
- ******************************************************************************/
-
-
-/*! ZSTD_CCtx_loadDictionary() :
- *  Create an internal CDict from `dict` buffer.
- *  Decompression will have to use same dictionary.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- *  Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
- *           meaning "return to no-dictionary mode".
- *  Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
- *           To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
- *  Note 2 : Loading a dictionary involves building tables.
- *           It's also a CPU consuming operation, with non-negligible impact on latency.
- *           Tables are dependent on compression parameters, and for this reason,
- *           compression parameters can no longer be changed after loading a dictionary.
- *  Note 3 :`dict` content will be copied internally.
- *           Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.
- *           In such a case, dictionary buffer must outlive its users.
- *  Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
- *           to precisely select how dictionary content must be interpreted. */
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
-
-/*! ZSTD_CCtx_refCDict() :
- *  Reference a prepared dictionary, to be used for all next compressed frames.
- *  Note that compression parameters are enforced from within CDict,
- *  and supersede any compression parameter previously set within CCtx.
- *  The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
- *  The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
- *  The dictionary will remain valid for future compressed frames using same CCtx.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- *  Special : Referencing a NULL CDict means "return to no-dictionary mode".
- *  Note 1 : Currently, only one dictionary can be managed.
- *           Referencing a new dictionary effectively "discards" any previous one.
- *  Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */
-ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
-
-/*! ZSTD_CCtx_refPrefix() :
- *  Reference a prefix (single-usage dictionary) for next compressed frame.
- *  A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
- *  Decompression will need same prefix to properly regenerate data.
- *  Compressing with a prefix is similar in outcome as performing a diff and compressing it,
- *  but performs much faster, especially during decompression (compression speed is tunable with compression level).
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- *  Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
- *  Note 1 : Prefix buffer is referenced. It **must** outlive compression.
- *           Its content must remain unmodified during compression.
- *  Note 2 : If the intention is to diff some large src data blob with some prior version of itself,
- *           ensure that the window size is large enough to contain the entire source.
- *           See ZSTD_c_windowLog.
- *  Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.
- *           It's a CPU consuming operation, with non-negligible impact on latency.
- *           If there is a need to use the same prefix multiple times, consider loadDictionary instead.
- *  Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent).
- *           Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */
-ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
-                                 const void* prefix, size_t prefixSize);
-
-/*! ZSTD_DCtx_loadDictionary() :
- *  Create an internal DDict from dict buffer,
- *  to be used to decompress next frames.
- *  The dictionary remains valid for all future frames, until explicitly invalidated.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- *  Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
- *            meaning "return to no-dictionary mode".
- *  Note 1 : Loading a dictionary involves building tables,
- *           which has a non-negligible impact on CPU usage and latency.
- *           It's recommended to "load once, use many times", to amortize the cost
- *  Note 2 :`dict` content will be copied internally, so `dict` can be released after loading.
- *           Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead.
- *  Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of
- *           how dictionary content is loaded and interpreted.
- */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-
-/*! ZSTD_DCtx_refDDict() :
- *  Reference a prepared dictionary, to be used to decompress next frames.
- *  The dictionary remains active for decompression of future frames using same DCtx.
- *
- *  If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function
- *  will store the DDict references in a table, and the DDict used for decompression
- *  will be determined at decompression time, as per the dict ID in the frame.
- *  The memory for the table is allocated on the first call to refDDict, and can be
- *  freed with ZSTD_freeDCtx().
- *
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- *  Note 1 : Currently, only one dictionary can be managed.
- *           Referencing a new dictionary effectively "discards" any previous one.
- *  Special: referencing a NULL DDict means "return to no-dictionary mode".
- *  Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.
- */
-ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
-
-/*! ZSTD_DCtx_refPrefix() :
- *  Reference a prefix (single-usage dictionary) to decompress next frame.
- *  This is the reverse operation of ZSTD_CCtx_refPrefix(),
- *  and must use the same prefix as the one used during compression.
- *  Prefix is **only used once**. Reference is discarded at end of frame.
- *  End of frame is reached when ZSTD_decompressStream() returns 0.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- *  Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary
- *  Note 2 : Prefix buffer is referenced. It **must** outlive decompression.
- *           Prefix buffer must remain unmodified up to the end of frame,
- *           reached when ZSTD_decompressStream() returns 0.
- *  Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent).
- *           Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section)
- *  Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.
- *           A full dictionary is more costly, as it requires building tables.
- */
-ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,
-                                 const void* prefix, size_t prefixSize);
-
-/* ===   Memory management   === */
-
-/*! ZSTD_sizeof_*() :
- *  These functions give the _current_ memory usage of selected object.
- *  Note that object memory usage can evolve (increase or decrease) over time. */
-ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
-ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
-ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
-ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
-ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
-ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
-
-#endif  /* ZSTD_H_235446 */
-
-
-/* **************************************************************************************
- *   ADVANCED AND EXPERIMENTAL FUNCTIONS
- ****************************************************************************************
- * The definitions in the following section are considered experimental.
- * They are provided for advanced scenarios.
- * They should never be used with a dynamic library, as prototypes may change in the future.
- * Use them only in association with static linking.
- * ***************************************************************************************/
-
-#if !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
-#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
-
-/* **************************************************************************************
- *   experimental API (static linking only)
- ****************************************************************************************
- * The following symbols and constants
- * are not planned to join "stable API" status in the near future.
- * They can still change in future versions.
- * Some of them are planned to remain in the static_only section indefinitely.
- * Some of them might be removed in the future (especially when redundant with existing stable functions)
- * ***************************************************************************************/
-
-#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1)   /* minimum input size required to query frame header size */
-#define ZSTD_FRAMEHEADERSIZE_MIN(format)    ((format) == ZSTD_f_zstd1 ? 6 : 2)
-#define ZSTD_FRAMEHEADERSIZE_MAX   18   /* can be useful for static allocation */
-#define ZSTD_SKIPPABLEHEADERSIZE    8
-
-/* compression parameter bounds */
-#define ZSTD_WINDOWLOG_MAX_32    30
-#define ZSTD_WINDOWLOG_MAX_64    31
-#define ZSTD_WINDOWLOG_MAX     ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
-#define ZSTD_WINDOWLOG_MIN       10
-#define ZSTD_HASHLOG_MAX       ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30)
-#define ZSTD_HASHLOG_MIN          6
-#define ZSTD_CHAINLOG_MAX_32     29
-#define ZSTD_CHAINLOG_MAX_64     30
-#define ZSTD_CHAINLOG_MAX      ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64))
-#define ZSTD_CHAINLOG_MIN        ZSTD_HASHLOG_MIN
-#define ZSTD_SEARCHLOG_MAX      (ZSTD_WINDOWLOG_MAX-1)
-#define ZSTD_SEARCHLOG_MIN        1
-#define ZSTD_MINMATCH_MAX         7   /* only for ZSTD_fast, other strategies are limited to 6 */
-#define ZSTD_MINMATCH_MIN         3   /* only for ZSTD_btopt+, faster strategies are limited to 4 */
-#define ZSTD_TARGETLENGTH_MAX    ZSTD_BLOCKSIZE_MAX
-#define ZSTD_TARGETLENGTH_MIN     0   /* note : comparing this constant to an unsigned results in a tautological test */
-#define ZSTD_STRATEGY_MIN        ZSTD_fast
-#define ZSTD_STRATEGY_MAX        ZSTD_btultra2
-
-
-#define ZSTD_OVERLAPLOG_MIN       0
-#define ZSTD_OVERLAPLOG_MAX       9
-
-#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27   /* by default, the streaming decoder will refuse any frame
-                                           * requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size,
-                                           * to preserve host's memory from unreasonable requirements.
-                                           * This limit can be overridden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).
-                                           * The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */
-
-
-/* LDM parameter bounds */
-#define ZSTD_LDM_HASHLOG_MIN      ZSTD_HASHLOG_MIN
-#define ZSTD_LDM_HASHLOG_MAX      ZSTD_HASHLOG_MAX
-#define ZSTD_LDM_MINMATCH_MIN        4
-#define ZSTD_LDM_MINMATCH_MAX     4096
-#define ZSTD_LDM_BUCKETSIZELOG_MIN   1
-#define ZSTD_LDM_BUCKETSIZELOG_MAX   8
-#define ZSTD_LDM_HASHRATELOG_MIN     0
-#define ZSTD_LDM_HASHRATELOG_MAX (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
-
-/* Advanced parameter bounds */
-#define ZSTD_TARGETCBLOCKSIZE_MIN   64
-#define ZSTD_TARGETCBLOCKSIZE_MAX   ZSTD_BLOCKSIZE_MAX
-#define ZSTD_SRCSIZEHINT_MIN        0
-#define ZSTD_SRCSIZEHINT_MAX        INT_MAX
-
-/* internal */
-#define ZSTD_HASHLOG3_MAX           17
-
-
-/* ---  Advanced types  --- */
-
-typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;
-
-typedef struct {
-    unsigned int offset;      /* The offset of the match. (NOT the same as the offset code)
-                               * If offset == 0 and matchLength == 0, this sequence represents the last
-                               * literals in the block of litLength size.
-                               */
-
-    unsigned int litLength;   /* Literal length of the sequence. */
-    unsigned int matchLength; /* Match length of the sequence. */
-
-                              /* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0.
-                               * In this case, we will treat the sequence as a marker for a block boundary.
-                               */
-
-    unsigned int rep;         /* Represents which repeat offset is represented by the field 'offset'.
-                               * Ranges from [0, 3].
-                               *
-                               * Repeat offsets are essentially previous offsets from previous sequences sorted in
-                               * recency order. For more detail, see doc/zstd_compression_format.md
-                               *
-                               * If rep == 0, then 'offset' does not contain a repeat offset.
-                               * If rep > 0:
-                               *  If litLength != 0:
-                               *      rep == 1 --> offset == repeat_offset_1
-                               *      rep == 2 --> offset == repeat_offset_2
-                               *      rep == 3 --> offset == repeat_offset_3
-                               *  If litLength == 0:
-                               *      rep == 1 --> offset == repeat_offset_2
-                               *      rep == 2 --> offset == repeat_offset_3
-                               *      rep == 3 --> offset == repeat_offset_1 - 1
-                               *
-                               * Note: This field is optional. ZSTD_generateSequences() will calculate the value of
-                               * 'rep', but repeat offsets do not necessarily need to be calculated from an external
-                               * sequence provider's perspective. For example, ZSTD_compressSequences() does not
-                               * use this 'rep' field at all (as of now).
-                               */
-} ZSTD_Sequence;
-
-typedef struct {
-    unsigned windowLog;       /*< largest match distance : larger == more compression, more memory needed during decompression */
-    unsigned chainLog;        /*< fully searched segment : larger == more compression, slower, more memory (useless for fast) */
-    unsigned hashLog;         /*< dispatch table : larger == faster, more memory */
-    unsigned searchLog;       /*< nb of searches : larger == more compression, slower */
-    unsigned minMatch;        /*< match length searched : larger == faster decompression, sometimes less compression */
-    unsigned targetLength;    /*< acceptable match size for optimal parser (only) : larger == more compression, slower */
-    ZSTD_strategy strategy;   /*< see ZSTD_strategy definition above */
-} ZSTD_compressionParameters;
-
-typedef struct {
-    int contentSizeFlag; /*< 1: content size will be in frame header (when known) */
-    int checksumFlag;    /*< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */
-    int noDictIDFlag;    /*< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */
-} ZSTD_frameParameters;
-
-typedef struct {
-    ZSTD_compressionParameters cParams;
-    ZSTD_frameParameters fParams;
-} ZSTD_parameters;
-
-typedef enum {
-    ZSTD_dct_auto = 0,       /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
-    ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
-    ZSTD_dct_fullDict = 2    /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */
-} ZSTD_dictContentType_e;
-
-typedef enum {
-    ZSTD_dlm_byCopy = 0,  /*< Copy dictionary content internally */
-    ZSTD_dlm_byRef = 1    /*< Reference dictionary content -- the dictionary buffer must outlive its users. */
-} ZSTD_dictLoadMethod_e;
-
-typedef enum {
-    ZSTD_f_zstd1 = 0,           /* zstd frame format, specified in zstd_compression_format.md (default) */
-    ZSTD_f_zstd1_magicless = 1  /* Variant of zstd frame format, without initial 4-bytes magic number.
-                                 * Useful to save 4 bytes per generated frame.
-                                 * Decoder cannot recognise automatically this format, requiring this instruction. */
-} ZSTD_format_e;
-
-typedef enum {
-    /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */
-    ZSTD_d_validateChecksum = 0,
-    ZSTD_d_ignoreChecksum = 1
-} ZSTD_forceIgnoreChecksum_e;
-
-typedef enum {
-    /* Note: this enum controls ZSTD_d_refMultipleDDicts */
-    ZSTD_rmd_refSingleDDict = 0,
-    ZSTD_rmd_refMultipleDDicts = 1
-} ZSTD_refMultipleDDicts_e;
-
-typedef enum {
-    /* Note: this enum and the behavior it controls are effectively internal
-     * implementation details of the compressor. They are expected to continue
-     * to evolve and should be considered only in the context of extremely
-     * advanced performance tuning.
-     *
-     * Zstd currently supports the use of a CDict in three ways:
-     *
-     * - The contents of the CDict can be copied into the working context. This
-     *   means that the compression can search both the dictionary and input
-     *   while operating on a single set of internal tables. This makes
-     *   the compression faster per-byte of input. However, the initial copy of
-     *   the CDict's tables incurs a fixed cost at the beginning of the
-     *   compression. For small compressions (< 8 KB), that copy can dominate
-     *   the cost of the compression.
-     *
-     * - The CDict's tables can be used in-place. In this model, compression is
-     *   slower per input byte, because the compressor has to search two sets of
-     *   tables. However, this model incurs no start-up cost (as long as the
-     *   working context's tables can be reused). For small inputs, this can be
-     *   faster than copying the CDict's tables.
-     *
-     * - The CDict's tables are not used at all, and instead we use the working
-     *   context alone to reload the dictionary and use params based on the source
-     *   size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict().
-     *   This method is effective when the dictionary sizes are very small relative
-     *   to the input size, and the input size is fairly large to begin with.
-     *
-     * Zstd has a simple internal heuristic that selects which strategy to use
-     * at the beginning of a compression. However, if experimentation shows that
-     * Zstd is making poor choices, it is possible to override that choice with
-     * this enum.
-     */
-    ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */
-    ZSTD_dictForceAttach   = 1, /* Never copy the dictionary. */
-    ZSTD_dictForceCopy     = 2, /* Always copy the dictionary. */
-    ZSTD_dictForceLoad     = 3  /* Always reload the dictionary */
-} ZSTD_dictAttachPref_e;
-
-typedef enum {
-  ZSTD_lcm_auto = 0,          /*< Automatically determine the compression mode based on the compression level.
-                               *   Negative compression levels will be uncompressed, and positive compression
-                               *   levels will be compressed. */
-  ZSTD_lcm_huffman = 1,       /*< Always attempt Huffman compression. Uncompressed literals will still be
-                               *   emitted if Huffman compression is not profitable. */
-  ZSTD_lcm_uncompressed = 2   /*< Always emit uncompressed literals. */
-} ZSTD_literalCompressionMode_e;
-
-
-/* *************************************
-*  Frame size functions
-***************************************/
-
-/*! ZSTD_findDecompressedSize() :
- *  `src` should point to the start of a series of ZSTD encoded and/or skippable frames
- *  `srcSize` must be the _exact_ size of this series
- *       (i.e. there should be a frame boundary at `src + srcSize`)
- *  @return : - decompressed size of all data in all successive frames
- *            - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN
- *            - if an error occurred: ZSTD_CONTENTSIZE_ERROR
- *
- *   note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.
- *            When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.
- *            In which case, it's necessary to use streaming mode to decompress data.
- *   note 2 : decompressed size is always present when compression is done with ZSTD_compress()
- *   note 3 : decompressed size can be very large (64-bits value),
- *            potentially larger than what local system can handle as a single memory segment.
- *            In which case, it's necessary to use streaming mode to decompress data.
- *   note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.
- *            Always ensure result fits within application's authorized limits.
- *            Each application can set its own limits.
- *   note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to
- *            read each contained frame header.  This is fast as most of the data is skipped,
- *            however it does mean that all frame data must be present and valid. */
-ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
-
-/*! ZSTD_decompressBound() :
- *  `src` should point to the start of a series of ZSTD encoded and/or skippable frames
- *  `srcSize` must be the _exact_ size of this series
- *       (i.e. there should be a frame boundary at `src + srcSize`)
- *  @return : - upper-bound for the decompressed size of all data in all successive frames
- *            - if an error occurred: ZSTD_CONTENTSIZE_ERROR
- *
- *  note 1  : an error can occur if `src` contains an invalid or incorrectly formatted frame.
- *  note 2  : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
- *            in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.
- *  note 3  : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
- *              upper-bound = # blocks * min(128 KB, Window_Size)
- */
-ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
-
-/*! ZSTD_frameHeaderSize() :
- *  srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
- * @return : size of the Frame Header,
- *           or an error code (if srcSize is too small) */
-ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
-
-typedef enum {
-  ZSTD_sf_noBlockDelimiters = 0,         /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
-  ZSTD_sf_explicitBlockDelimiters = 1    /* Representation of ZSTD_Sequence contains explicit block delimiters */
-} ZSTD_sequenceFormat_e;
-
-/*! ZSTD_generateSequences() :
- * Generate sequences using ZSTD_compress2, given a source buffer.
- *
- * Each block will end with a dummy sequence
- * with offset == 0, matchLength == 0, and litLength == length of last literals.
- * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0)
- * simply acts as a block delimiter.
- *
- * zc can be used to insert custom compression params.
- * This function invokes ZSTD_compress2
- *
- * The output of this function can be fed into ZSTD_compressSequences() with CCtx
- * setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters
- * @return : number of sequences generated
- */
-
-ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
-                                          size_t outSeqsSize, const void* src, size_t srcSize);
-
-/*! ZSTD_mergeBlockDelimiters() :
- * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals
- * by merging them into into the literals of the next sequence.
- *
- * As such, the final generated result has no explicit representation of block boundaries,
- * and the final last literals segment is not represented in the sequences.
- *
- * The output of this function can be fed into ZSTD_compressSequences() with CCtx
- * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters
- * @return : number of sequences left after merging
- */
-ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
-
-/*! ZSTD_compressSequences() :
- * Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst.
- * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.)
- * The entire source is compressed into a single frame.
- *
- * The compression behavior changes based on cctx params. In particular:
- *    If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain
- *    no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on
- *    the block size derived from the cctx, and sequences may be split. This is the default setting.
- *
- *    If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain
- *    block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided.
- *
- *    If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined
- *    behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for
- *    specifics regarding offset/matchlength requirements) then the function will bail out and return an error.
- *
- *    In addition to the two adjustable experimental params, there are other important cctx params.
- *    - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN.
- *    - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression.
- *    - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset
- *      is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md
- *
- * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused.
- * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly,
- *         and cannot emit an RLE block that disagrees with the repcode history
- * @return : final compressed size or a ZSTD error.
- */
-ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
-                                  const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
-                                  const void* src, size_t srcSize);
-
-
-/*! ZSTD_writeSkippableFrame() :
- * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.
- *
- * Skippable frames begin with a a 4-byte magic number. There are 16 possible choices of magic number,
- * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.
- * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so
- * the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.
- *
- * Returns an error if destination buffer is not large enough, if the source size is not representable
- * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).
- *
- * @return : number of bytes written or a ZSTD error.
- */
-ZSTDLIB_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
-                                            const void* src, size_t srcSize, unsigned magicVariant);
-
-
-/* *************************************
-*  Memory management
-***************************************/
-
-/*! ZSTD_estimate*() :
- *  These functions make it possible to estimate memory usage
- *  of a future {D,C}Ctx, before its creation.
- *
- *  ZSTD_estimateCCtxSize() will provide a memory budget large enough
- *  for any compression level up to selected one.
- *  Note : Unlike ZSTD_estimateCStreamSize*(), this estimate
- *         does not include space for a window buffer.
- *         Therefore, the estimation is only guaranteed for single-shot compressions, not streaming.
- *  The estimate will assume the input may be arbitrarily large,
- *  which is the worst case.
- *
- *  When srcSize can be bound by a known and rather "small" value,
- *  this fact can be used to provide a tighter estimation
- *  because the CCtx compression context will need less memory.
- *  This tighter estimation can be provided by more advanced functions
- *  ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(),
- *  and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter().
- *  Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits.
- *
- *  Note 2 : only single-threaded compression is supported.
- *  ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
- */
-ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
-ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
-ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
-
-/*! ZSTD_estimateCStreamSize() :
- *  ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one.
- *  It will also consider src size to be arbitrarily "large", which is worst case.
- *  If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
- *  ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
- *  ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
- *  Note : CStream size estimation is only correct for single-threaded compression.
- *  ZSTD_DStream memory budget depends on window Size.
- *  This information can be passed manually, using ZSTD_estimateDStreamSize,
- *  or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();
- *  Note : if streaming is init with function ZSTD_init?Stream_usingDict(),
- *         an internal ?Dict will be created, which additional size is not estimated here.
- *         In this case, get total size by adding ZSTD_estimate?DictSize */
-ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
-ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
-ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
-ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
-
-/*! ZSTD_estimate?DictSize() :
- *  ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict().
- *  ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().
- *  Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.
- */
-ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
-ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
-
-/*! ZSTD_initStatic*() :
- *  Initialize an object using a pre-allocated fixed-size buffer.
- *  workspace: The memory area to emplace the object into.
- *             Provided pointer *must be 8-bytes aligned*.
- *             Buffer must outlive object.
- *  workspaceSize: Use ZSTD_estimate*Size() to determine
- *                 how large workspace must be to support target scenario.
- * @return : pointer to object (same address as workspace, just different type),
- *           or NULL if error (size too small, incorrect alignment, etc.)
- *  Note : zstd will never resize nor malloc() when using a static buffer.
- *         If the object requires more memory than available,
- *         zstd will just error out (typically ZSTD_error_memory_allocation).
- *  Note 2 : there is no corresponding "free" function.
- *           Since workspace is allocated externally, it must be freed externally too.
- *  Note 3 : cParams : use ZSTD_getCParams() to convert a compression level
- *           into its associated cParams.
- *  Limitation 1 : currently not compatible with internal dictionary creation, triggered by
- *                 ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict().
- *  Limitation 2 : static cctx currently not compatible with multi-threading.
- *  Limitation 3 : static dctx is incompatible with legacy support.
- */
-ZSTDLIB_API ZSTD_CCtx*    ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
-ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize);    /*< same as ZSTD_initStaticCCtx() */
-
-ZSTDLIB_API ZSTD_DCtx*    ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
-ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize);    /*< same as ZSTD_initStaticDCtx() */
-
-ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict(
-                                        void* workspace, size_t workspaceSize,
-                                        const void* dict, size_t dictSize,
-                                        ZSTD_dictLoadMethod_e dictLoadMethod,
-                                        ZSTD_dictContentType_e dictContentType,
-                                        ZSTD_compressionParameters cParams);
-
-ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict(
-                                        void* workspace, size_t workspaceSize,
-                                        const void* dict, size_t dictSize,
-                                        ZSTD_dictLoadMethod_e dictLoadMethod,
-                                        ZSTD_dictContentType_e dictContentType);
-
-
-/*! Custom memory allocation :
- *  These prototypes make it possible to pass your own allocation/free functions.
- *  ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below.
- *  All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones.
- */
-typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
-typedef void  (*ZSTD_freeFunction) (void* opaque, void* address);
-typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
-static
-__attribute__((__unused__))
-ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };  /*< this constant defers to stdlib's functions */
-
-ZSTDLIB_API ZSTD_CCtx*    ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_DCtx*    ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
-
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
-                                                  ZSTD_dictLoadMethod_e dictLoadMethod,
-                                                  ZSTD_dictContentType_e dictContentType,
-                                                  ZSTD_compressionParameters cParams,
-                                                  ZSTD_customMem customMem);
-
-/* ! Thread pool :
- * These prototypes make it possible to share a thread pool among multiple compression contexts.
- * This can limit resources for applications with multiple threads where each one uses
- * a threaded compression mode (via ZSTD_c_nbWorkers parameter).
- * ZSTD_createThreadPool creates a new thread pool with a given number of threads.
- * Note that the lifetime of such pool must exist while being used.
- * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
- * to use an internal thread pool).
- * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
- */
-typedef struct POOL_ctx_s ZSTD_threadPool;
-ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
-ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool);  /* accept NULL pointer */
-ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
-
-
-/*
- * This API is temporary and is expected to change or disappear in the future!
- */
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
-    const void* dict, size_t dictSize,
-    ZSTD_dictLoadMethod_e dictLoadMethod,
-    ZSTD_dictContentType_e dictContentType,
-    const ZSTD_CCtx_params* cctxParams,
-    ZSTD_customMem customMem);
-
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(
-    const void* dict, size_t dictSize,
-    ZSTD_dictLoadMethod_e dictLoadMethod,
-    ZSTD_dictContentType_e dictContentType,
-    ZSTD_customMem customMem);
-
-
-/* *************************************
-*  Advanced compression functions
-***************************************/
-
-/*! ZSTD_createCDict_byReference() :
- *  Create a digested dictionary for compression
- *  Dictionary content is just referenced, not duplicated.
- *  As a consequence, `dictBuffer` **must** outlive CDict,
- *  and its content must remain unmodified throughout the lifetime of CDict.
- *  note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
-
-/*! ZSTD_getDictID_fromCDict() :
- *  Provides the dictID of the dictionary loaded into `cdict`.
- *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
- *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
-ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);
-
-/*! ZSTD_getCParams() :
- * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
- * `estimatedSrcSize` value is optional, select 0 if not known */
-ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
-
-/*! ZSTD_getParams() :
- *  same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
- *  All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
-ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
-
-/*! ZSTD_checkCParams() :
- *  Ensure param values remain within authorized range.
- * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
-ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
-
-/*! ZSTD_adjustCParams() :
- *  optimize params for a given `srcSize` and `dictSize`.
- * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
- * `dictSize` must be `0` when there is no dictionary.
- *  cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
- *  This function never fails (wide contract) */
-ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
-
-/*! ZSTD_compress_advanced() :
- *  Note : this function is now DEPRECATED.
- *         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.
- *  This prototype will be marked as deprecated and generate compilation warning on reaching v1.5.x */
-ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
-                                          void* dst, size_t dstCapacity,
-                                    const void* src, size_t srcSize,
-                                    const void* dict,size_t dictSize,
-                                          ZSTD_parameters params);
-
-/*! ZSTD_compress_usingCDict_advanced() :
- *  Note : this function is now REDUNDANT.
- *         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.
- *  This prototype will be marked as deprecated and generate compilation warning in some future version */
-ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
-                                              void* dst, size_t dstCapacity,
-                                        const void* src, size_t srcSize,
-                                        const ZSTD_CDict* cdict,
-                                              ZSTD_frameParameters fParams);
-
-
-/*! ZSTD_CCtx_loadDictionary_byReference() :
- *  Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.
- *  It saves some memory, but also requires that `dict` outlives its usage within `cctx` */
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
-
-/*! ZSTD_CCtx_loadDictionary_advanced() :
- *  Same as ZSTD_CCtx_loadDictionary(), but gives finer control over
- *  how to load the dictionary (by copy ? by reference ?)
- *  and how to interpret it (automatic ? force raw mode ? full mode only ?) */
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
-
-/*! ZSTD_CCtx_refPrefix_advanced() :
- *  Same as ZSTD_CCtx_refPrefix(), but gives finer control over
- *  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
-ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
-
-/* ===   experimental parameters   === */
-/* these parameters can be used with ZSTD_setParameter()
- * they are not guaranteed to remain supported in the future */
-
- /* Enables rsyncable mode,
-  * which makes compressed files more rsync friendly
-  * by adding periodic synchronization points to the compressed data.
-  * The target average block size is ZSTD_c_jobSize / 2.
-  * It's possible to modify the job size to increase or decrease
-  * the granularity of the synchronization point.
-  * Once the jobSize is smaller than the window size,
-  * it will result in compression ratio degradation.
-  * NOTE 1: rsyncable mode only works when multithreading is enabled.
-  * NOTE 2: rsyncable performs poorly in combination with long range mode,
-  * since it will decrease the effectiveness of synchronization points,
-  * though mileage may vary.
-  * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s.
-  * If the selected compression level is already running significantly slower,
-  * the overall speed won't be significantly impacted.
-  */
- #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1
-
-/* Select a compression format.
- * The value must be of type ZSTD_format_e.
- * See ZSTD_format_e enum definition for details */
-#define ZSTD_c_format ZSTD_c_experimentalParam2
-
-/* Force back-reference distances to remain < windowSize,
- * even when referencing into Dictionary content (default:0) */
-#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3
-
-/* Controls whether the contents of a CDict
- * are used in place, or copied into the working context.
- * Accepts values from the ZSTD_dictAttachPref_e enum.
- * See the comments on that enum for an explanation of the feature. */
-#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4
-
-/* Controls how the literals are compressed (default is auto).
- * The value must be of type ZSTD_literalCompressionMode_e.
- * See ZSTD_literalCompressionMode_t enum definition for details.
- */
-#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
-
-/* Tries to fit compressed block size to be around targetCBlockSize.
- * No target when targetCBlockSize == 0.
- * There is no guarantee on compressed block size (default:0) */
-#define ZSTD_c_targetCBlockSize ZSTD_c_experimentalParam6
-
-/* User's best guess of source size.
- * Hint is not valid when srcSizeHint == 0.
- * There is no guarantee that hint is close to actual source size,
- * but compression ratio may regress significantly if guess considerably underestimates */
-#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7
-
-/* Controls whether the new and experimental "dedicated dictionary search
- * structure" can be used. This feature is still rough around the edges, be
- * prepared for surprising behavior!
- *
- * How to use it:
- *
- * When using a CDict, whether to use this feature or not is controlled at
- * CDict creation, and it must be set in a CCtxParams set passed into that
- * construction (via ZSTD_createCDict_advanced2()). A compression will then
- * use the feature or not based on how the CDict was constructed; the value of
- * this param, set in the CCtx, will have no effect.
- *
- * However, when a dictionary buffer is passed into a CCtx, such as via
- * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control
- * whether the CDict that is created internally can use the feature or not.
- *
- * What it does:
- *
- * Normally, the internal data structures of the CDict are analogous to what
- * would be stored in a CCtx after compressing the contents of a dictionary.
- * To an approximation, a compression using a dictionary can then use those
- * data structures to simply continue what is effectively a streaming
- * compression where the simulated compression of the dictionary left off.
- * Which is to say, the search structures in the CDict are normally the same
- * format as in the CCtx.
- *
- * It is possible to do better, since the CDict is not like a CCtx: the search
- * structures are written once during CDict creation, and then are only read
- * after that, while the search structures in the CCtx are both read and
- * written as the compression goes along. This means we can choose a search
- * structure for the dictionary that is read-optimized.
- *
- * This feature enables the use of that different structure.
- *
- * Note that some of the members of the ZSTD_compressionParameters struct have
- * different semantics and constraints in the dedicated search structure. It is
- * highly recommended that you simply set a compression level in the CCtxParams
- * you pass into the CDict creation call, and avoid messing with the cParams
- * directly.
- *
- * Effects:
- *
- * This will only have any effect when the selected ZSTD_strategy
- * implementation supports this feature. Currently, that's limited to
- * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2.
- *
- * Note that this means that the CDict tables can no longer be copied into the
- * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be
- * useable. The dictionary can only be attached or reloaded.
- *
- * In general, you should expect compression to be faster--sometimes very much
- * so--and CDict creation to be slightly slower. Eventually, we will probably
- * make this mode the default.
- */
-#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8
-
-/* ZSTD_c_stableInBuffer
- * Experimental parameter.
- * Default is 0 == disabled. Set to 1 to enable.
- *
- * Tells the compressor that the ZSTD_inBuffer will ALWAYS be the same
- * between calls, except for the modifications that zstd makes to pos (the
- * caller must not modify pos). This is checked by the compressor, and
- * compression will fail if it ever changes. This means the only flush
- * mode that makes sense is ZSTD_e_end, so zstd will error if ZSTD_e_end
- * is not used. The data in the ZSTD_inBuffer in the range [src, src + pos)
- * MUST not be modified during compression or you will get data corruption.
- *
- * When this flag is enabled zstd won't allocate an input window buffer,
- * because the user guarantees it can reference the ZSTD_inBuffer until
- * the frame is complete. But, it will still allocate an output buffer
- * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also
- * avoid the memcpy() from the input buffer to the input window buffer.
- *
- * NOTE: ZSTD_compressStream2() will error if ZSTD_e_end is not used.
- * That means this flag cannot be used with ZSTD_compressStream().
- *
- * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using
- * this flag is ALWAYS memory safe, and will never access out-of-bounds
- * memory. However, compression WILL fail if you violate the preconditions.
- *
- * WARNING: The data in the ZSTD_inBuffer in the range [dst, dst + pos) MUST
- * not be modified during compression or you will get data corruption. This
- * is because zstd needs to reference data in the ZSTD_inBuffer to find
- * matches. Normally zstd maintains its own window buffer for this purpose,
- * but passing this flag tells zstd to use the user provided buffer.
- */
-#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9
-
-/* ZSTD_c_stableOutBuffer
- * Experimental parameter.
- * Default is 0 == disabled. Set to 1 to enable.
- *
- * Tells he compressor that the ZSTD_outBuffer will not be resized between
- * calls. Specifically: (out.size - out.pos) will never grow. This gives the
- * compressor the freedom to say: If the compressed data doesn't fit in the
- * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to
- * always decompress directly into the output buffer, instead of decompressing
- * into an internal buffer and copying to the output buffer.
- *
- * When this flag is enabled zstd won't allocate an output buffer, because
- * it can write directly to the ZSTD_outBuffer. It will still allocate the
- * input window buffer (see ZSTD_c_stableInBuffer).
- *
- * Zstd will check that (out.size - out.pos) never grows and return an error
- * if it does. While not strictly necessary, this should prevent surprises.
- */
-#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10
-
-/* ZSTD_c_blockDelimiters
- * Default is 0 == ZSTD_sf_noBlockDelimiters.
- *
- * For use with sequence compression API: ZSTD_compressSequences().
- *
- * Designates whether or not the given array of ZSTD_Sequence contains block delimiters
- * and last literals, which are defined as sequences with offset == 0 and matchLength == 0.
- * See the definition of ZSTD_Sequence for more specifics.
- */
-#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11
-
-/* ZSTD_c_validateSequences
- * Default is 0 == disabled. Set to 1 to enable sequence validation.
- *
- * For use with sequence compression API: ZSTD_compressSequences().
- * Designates whether or not we validate sequences provided to ZSTD_compressSequences()
- * during function execution.
- *
- * Without validation, providing a sequence that does not conform to the zstd spec will cause
- * undefined behavior, and may produce a corrupted block.
- *
- * With validation enabled, a if sequence is invalid (see doc/zstd_compression_format.md for
- * specifics regarding offset/matchlength requirements) then the function will bail out and
- * return an error.
- *
- */
-#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12
-
-/*! ZSTD_CCtx_getParameter() :
- *  Get the requested compression parameter value, selected by enum ZSTD_cParameter,
- *  and store it into int* value.
- * @return : 0, or an error code (which can be tested with ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
-
-
-/*! ZSTD_CCtx_params :
- *  Quick howto :
- *  - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
- *  - ZSTD_CCtxParams_setParameter() : Push parameters one by one into
- *                                     an existing ZSTD_CCtx_params structure.
- *                                     This is similar to
- *                                     ZSTD_CCtx_setParameter().
- *  - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
- *                                    an existing CCtx.
- *                                    These parameters will be applied to
- *                                    all subsequent frames.
- *  - ZSTD_compressStream2() : Do compression using the CCtx.
- *  - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer.
- *
- *  This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
- *  for static allocation of CCtx for single-threaded compression.
- */
-ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
-ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);  /* accept NULL pointer */
-
-/*! ZSTD_CCtxParams_reset() :
- *  Reset params to default values.
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
-
-/*! ZSTD_CCtxParams_init() :
- *  Initializes the compression parameters of cctxParams according to
- *  compression level. All other parameters are reset to their default values.
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
-
-/*! ZSTD_CCtxParams_init_advanced() :
- *  Initializes the compression and frame parameters of cctxParams according to
- *  params. All other parameters are reset to their default values.
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
-
-/*! ZSTD_CCtxParams_setParameter() :
- *  Similar to ZSTD_CCtx_setParameter.
- *  Set one compression parameter, selected by enum ZSTD_cParameter.
- *  Parameters must be applied to a ZSTD_CCtx using
- *  ZSTD_CCtx_setParametersUsingCCtxParams().
- * @result : a code representing success or failure (which can be tested with
- *           ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
-
-/*! ZSTD_CCtxParams_getParameter() :
- * Similar to ZSTD_CCtx_getParameter.
- * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
- * @result : 0, or an error code (which can be tested with ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
-
-/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
- *  Apply a set of ZSTD_CCtx_params to the compression context.
- *  This can be done even after compression is started,
- *    if nbWorkers==0, this will have no impact until a new compression is started.
- *    if nbWorkers>=1, new parameters will be picked up at next job,
- *       with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).
- */
-ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
-        ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
-
-/*! ZSTD_compressStream2_simpleArgs() :
- *  Same as ZSTD_compressStream2(),
- *  but using only integral types as arguments.
- *  This variant might be helpful for binders from dynamic languages
- *  which have troubles handling structures containing memory pointers.
- */
-ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs (
-                            ZSTD_CCtx* cctx,
-                            void* dst, size_t dstCapacity, size_t* dstPos,
-                      const void* src, size_t srcSize, size_t* srcPos,
-                            ZSTD_EndDirective endOp);
-
-
-/* *************************************
-*  Advanced decompression functions
-***************************************/
-
-/*! ZSTD_isFrame() :
- *  Tells if the content of `buffer` starts with a valid Frame Identifier.
- *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
- *  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
- *  Note 3 : Skippable Frame Identifiers are considered valid. */
-ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
-
-/*! ZSTD_createDDict_byReference() :
- *  Create a digested dictionary, ready to start decompression operation without startup delay.
- *  Dictionary content is referenced, and therefore stays in dictBuffer.
- *  It is important that dictBuffer outlives DDict,
- *  it must remain read accessible throughout the lifetime of DDict */
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
-
-/*! ZSTD_DCtx_loadDictionary_byReference() :
- *  Same as ZSTD_DCtx_loadDictionary(),
- *  but references `dict` content instead of copying it into `dctx`.
- *  This saves memory if `dict` remains around.,
- *  However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-
-/*! ZSTD_DCtx_loadDictionary_advanced() :
- *  Same as ZSTD_DCtx_loadDictionary(),
- *  but gives direct control over
- *  how to load the dictionary (by copy ? by reference ?)
- *  and how to interpret it (automatic ? force raw mode ? full mode only ?). */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
-
-/*! ZSTD_DCtx_refPrefix_advanced() :
- *  Same as ZSTD_DCtx_refPrefix(), but gives finer control over
- *  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
-ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
-
-/*! ZSTD_DCtx_setMaxWindowSize() :
- *  Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
- *  This protects a decoder context from reserving too much memory for itself (potential attack scenario).
- *  This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
- *  By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)
- * @return : 0, or an error code (which can be tested using ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
-
-/*! ZSTD_DCtx_getParameter() :
- *  Get the requested decompression parameter value, selected by enum ZSTD_dParameter,
- *  and store it into int* value.
- * @return : 0, or an error code (which can be tested with ZSTD_isError()).
- */
-ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
-
-/* ZSTD_d_format
- * experimental parameter,
- * allowing selection between ZSTD_format_e input compression formats
- */
-#define ZSTD_d_format ZSTD_d_experimentalParam1
-/* ZSTD_d_stableOutBuffer
- * Experimental parameter.
- * Default is 0 == disabled. Set to 1 to enable.
- *
- * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same
- * between calls, except for the modifications that zstd makes to pos (the
- * caller must not modify pos). This is checked by the decompressor, and
- * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer
- * MUST be large enough to fit the entire decompressed frame. This will be
- * checked when the frame content size is known. The data in the ZSTD_outBuffer
- * in the range [dst, dst + pos) MUST not be modified during decompression
- * or you will get data corruption.
- *
- * When this flags is enabled zstd won't allocate an output buffer, because
- * it can write directly to the ZSTD_outBuffer, but it will still allocate
- * an input buffer large enough to fit any compressed block. This will also
- * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer.
- * If you need to avoid the input buffer allocation use the buffer-less
- * streaming API.
- *
- * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using
- * this flag is ALWAYS memory safe, and will never access out-of-bounds
- * memory. However, decompression WILL fail if you violate the preconditions.
- *
- * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST
- * not be modified during decompression or you will get data corruption. This
- * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate
- * matches. Normally zstd maintains its own buffer for this purpose, but passing
- * this flag tells zstd to use the user provided buffer.
- */
-#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2
-
-/* ZSTD_d_forceIgnoreChecksum
- * Experimental parameter.
- * Default is 0 == disabled. Set to 1 to enable
- *
- * Tells the decompressor to skip checksum validation during decompression, regardless
- * of whether checksumming was specified during compression. This offers some
- * slight performance benefits, and may be useful for debugging.
- * Param has values of type ZSTD_forceIgnoreChecksum_e
- */
-#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3
-
-/* ZSTD_d_refMultipleDDicts
- * Experimental parameter.
- * Default is 0 == disabled. Set to 1 to enable
- *
- * If enabled and dctx is allocated on the heap, then additional memory will be allocated
- * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict()
- * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead
- * store all references. At decompression time, the appropriate dictID is selected
- * from the set of DDicts based on the dictID in the frame.
- *
- * Usage is simply calling ZSTD_refDDict() on multiple dict buffers.
- *
- * Param has values of byte ZSTD_refMultipleDDicts_e
- *
- * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory
- * allocation for the hash table. ZSTD_freeDCtx() also frees this memory.
- * Memory is allocated as per ZSTD_DCtx::customMem.
- *
- * Although this function allocates memory for the table, the user is still responsible for
- * memory management of the underlying ZSTD_DDict* themselves.
- */
-#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4
-
-
-/*! ZSTD_DCtx_setFormat() :
- *  Instruct the decoder context about what kind of data to decode next.
- *  This instruction is mandatory to decode data without a fully-formed header,
- *  such ZSTD_f_zstd1_magicless for example.
- * @return : 0, or an error code (which can be tested using ZSTD_isError()). */
-ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
-
-/*! ZSTD_decompressStream_simpleArgs() :
- *  Same as ZSTD_decompressStream(),
- *  but using only integral types as arguments.
- *  This can be helpful for binders from dynamic languages
- *  which have troubles handling structures containing memory pointers.
- */
-ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
-                            ZSTD_DCtx* dctx,
-                            void* dst, size_t dstCapacity, size_t* dstPos,
-                      const void* src, size_t srcSize, size_t* srcPos);
-
-
-/* ******************************************************************
-*  Advanced streaming functions
-*  Warning : most of these functions are now redundant with the Advanced API.
-*  Once Advanced API reaches "stable" status,
-*  redundant functions will be deprecated, and then at some point removed.
-********************************************************************/
-
-/*=====   Advanced Streaming compression functions  =====*/
-
-/*! ZSTD_initCStream_srcSize() :
- * This function is deprecated, and equivalent to:
- *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
- *     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
- *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
- *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
- *
- * pledgedSrcSize must be correct. If it is not known at init time, use
- * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
- * "0" also disables frame content size field. It may be enabled in the future.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t
-ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
-                         int compressionLevel,
-                         unsigned long long pledgedSrcSize);
-
-/*! ZSTD_initCStream_usingDict() :
- * This function is deprecated, and is equivalent to:
- *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
- *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
- *     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
- *
- * Creates of an internal CDict (incompatible with static CCtx), except if
- * dict == NULL or dictSize < 8, in which case no dict is used.
- * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if
- * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t
-ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
-                     const void* dict, size_t dictSize,
-                           int compressionLevel);
-
-/*! ZSTD_initCStream_advanced() :
- * This function is deprecated, and is approximately equivalent to:
- *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
- *     // Pseudocode: Set each zstd parameter and leave the rest as-is.
- *     for ((param, value) : params) {
- *         ZSTD_CCtx_setParameter(zcs, param, value);
- *     }
- *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
- *     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
- *
- * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.
- * pledgedSrcSize must be correct.
- * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t
-ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
-                    const void* dict, size_t dictSize,
-                          ZSTD_parameters params,
-                          unsigned long long pledgedSrcSize);
-
-/*! ZSTD_initCStream_usingCDict() :
- * This function is deprecated, and equivalent to:
- *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
- *     ZSTD_CCtx_refCDict(zcs, cdict);
- *
- * note : cdict will just be referenced, and must outlive compression session
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
-
-/*! ZSTD_initCStream_usingCDict_advanced() :
- *   This function is DEPRECATED, and is approximately equivalent to:
- *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
- *     // Pseudocode: Set each zstd frame parameter and leave the rest as-is.
- *     for ((fParam, value) : fParams) {
- *         ZSTD_CCtx_setParameter(zcs, fParam, value);
- *     }
- *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
- *     ZSTD_CCtx_refCDict(zcs, cdict);
- *
- * same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
- * pledgedSrcSize must be correct. If srcSize is not known at init time, use
- * value ZSTD_CONTENTSIZE_UNKNOWN.
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t
-ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
-                               const ZSTD_CDict* cdict,
-                                     ZSTD_frameParameters fParams,
-                                     unsigned long long pledgedSrcSize);
-
-/*! ZSTD_resetCStream() :
- * This function is deprecated, and is equivalent to:
- *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
- *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
- *
- *  start a new frame, using same parameters from previous frame.
- *  This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
- *  Note that zcs must be init at least once before using ZSTD_resetCStream().
- *  If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.
- *  If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
- *  For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs,
- *  but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.
- * @return : 0, or an error code (which can be tested using ZSTD_isError())
- *  Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
-
-
-typedef struct {
-    unsigned long long ingested;   /* nb input bytes read and buffered */
-    unsigned long long consumed;   /* nb input bytes actually compressed */
-    unsigned long long produced;   /* nb of compressed bytes generated and buffered */
-    unsigned long long flushed;    /* nb of compressed bytes flushed : not provided; can be tracked from caller side */
-    unsigned currentJobID;         /* MT only : latest started job nb */
-    unsigned nbActiveWorkers;      /* MT only : nb of workers actively compressing at probe time */
-} ZSTD_frameProgression;
-
-/* ZSTD_getFrameProgression() :
- * tells how much data has been ingested (read from input)
- * consumed (input actually compressed) and produced (output) for current frame.
- * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed.
- * Aggregates progression inside active worker threads.
- */
-ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
-
-/*! ZSTD_toFlushNow() :
- *  Tell how many bytes are ready to be flushed immediately.
- *  Useful for multithreading scenarios (nbWorkers >= 1).
- *  Probe the oldest active job, defined as oldest job not yet entirely flushed,
- *  and check its output buffer.
- * @return : amount of data stored in oldest job and ready to be flushed immediately.
- *  if @return == 0, it means either :
- *  + there is no active job (could be checked with ZSTD_frameProgression()), or
- *  + oldest job is still actively compressing data,
- *    but everything it has produced has also been flushed so far,
- *    therefore flush speed is limited by production speed of oldest job
- *    irrespective of the speed of concurrent (and newer) jobs.
- */
-ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
-
-
-/*=====   Advanced Streaming decompression functions  =====*/
-
-/*!
- * This function is deprecated, and is equivalent to:
- *
- *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
- *     ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
- *
- * note: no dictionary will be used if dict == NULL or dictSize < 8
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
-
-/*!
- * This function is deprecated, and is equivalent to:
- *
- *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
- *     ZSTD_DCtx_refDDict(zds, ddict);
- *
- * note : ddict is referenced, it must outlive decompression session
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
-
-/*!
- * This function is deprecated, and is equivalent to:
- *
- *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
- *
- * re-use decompression parameters from previous init; saves dictionary loading
- * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
- */
-ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
-
-
-/* *******************************************************************
-*  Buffer-less and synchronous inner streaming functions
-*
-*  This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
-*  But it's also a complex one, with several restrictions, documented below.
-*  Prefer normal streaming API for an easier experience.
-********************************************************************* */
-
-/*
-  Buffer-less streaming compression (synchronous mode)
-
-  A ZSTD_CCtx object is required to track streaming operations.
-  Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
-  ZSTD_CCtx object can be re-used multiple times within successive compression operations.
-
-  Start by initializing a context.
-  Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression,
-  or ZSTD_compressBegin_advanced(), for finer parameter control.
-  It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx()
-
-  Then, consume your input using ZSTD_compressContinue().
-  There are some important considerations to keep in mind when using this advanced function :
-  - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only.
-  - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks.
-  - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario.
-    Worst case evaluation is provided by ZSTD_compressBound().
-    ZSTD_compressContinue() doesn't guarantee recover after a failed compression.
-  - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog).
-    It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks)
-  - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps.
-    In which case, it will "discard" the relevant memory section from its history.
-
-  Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.
-  It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.
-  Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.
-
-  `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again.
-*/
-
-/*=====   Buffer-less streaming compression functions  =====*/
-ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /*< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */
-ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /*< note: fails if cdict==NULL */
-ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize);   /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
-ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /*<  note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
-
-ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-
-
-/*
-  Buffer-less streaming decompression (synchronous mode)
-
-  A ZSTD_DCtx object is required to track streaming operations.
-  Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
-  A ZSTD_DCtx object can be re-used multiple times.
-
-  First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().
-  Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.
-  Data fragment must be large enough to ensure successful decoding.
- `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.
-  @result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.
-           >0 : `srcSize` is too small, please provide at least @result bytes on next attempt.
-           errorCode, which can be tested using ZSTD_isError().
-
-  It fills a ZSTD_frameHeader structure with important information to correctly decode the frame,
-  such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`).
-  Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information.
-  As a consequence, check that values remain within valid application range.
-  For example, do not allocate memory blindly, check that `windowSize` is within expectation.
-  Each application can set its own limits, depending on local restrictions.
-  For extended interoperability, it is recommended to support `windowSize` of at least 8 MB.
-
-  ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes.
-  ZSTD_decompressContinue() is very sensitive to contiguity,
-  if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,
-  or that previous contiguous segment is large enough to properly handle maximum back-reference distance.
-  There are multiple ways to guarantee this condition.
-
-  The most memory efficient way is to use a round buffer of sufficient size.
-  Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(),
-  which can @return an error code if required value is too large for current system (in 32-bits mode).
-  In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one,
-  up to the moment there is not enough room left in the buffer to guarantee decoding another full block,
-  which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`.
-  At which point, decoding can resume from the beginning of the buffer.
-  Note that already decoded data stored in the buffer should be flushed before being overwritten.
-
-  There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory.
-
-  Finally, if you control the compression process, you can also ignore all buffer size rules,
-  as long as the encoder and decoder progress in "lock-step",
-  aka use exactly the same buffer sizes, break contiguity at the same place, etc.
-
-  Once buffers are setup, start decompression, with ZSTD_decompressBegin().
-  If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict().
-
-  Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.
-  ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().
-  ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.
-
- @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
-  It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item.
-  It can also be an error code, which can be tested with ZSTD_isError().
-
-  A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.
-  Context can then be reset to start a new decompression.
-
-  Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType().
-  This information is not required to properly decode a frame.
-
-  == Special case : skippable frames ==
-
-  Skippable frames allow integration of user-defined data into a flow of concatenated frames.
-  Skippable frames will be ignored (skipped) by decompressor.
-  The format of skippable frames is as follows :
-  a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F
-  b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
-  c) Frame Content - any content (User Data) of length equal to Frame Size
-  For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame.
-  For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content.
-*/
-
-/*=====   Buffer-less streaming decompression functions  =====*/
-typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e;
-typedef struct {
-    unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */
-    unsigned long long windowSize;       /* can be very large, up to <= frameContentSize */
-    unsigned blockSizeMax;
-    ZSTD_frameType_e frameType;          /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */
-    unsigned headerSize;
-    unsigned dictID;
-    unsigned checksumFlag;
-} ZSTD_frameHeader;
-
-/*! ZSTD_getFrameHeader() :
- *  decode Frame Header, or requires larger `srcSize`.
- * @return : 0, `zfhPtr` is correctly filled,
- *          >0, `srcSize` is too small, value is wanted `srcSize` amount,
- *           or an error code, which can be tested using ZSTD_isError() */
-ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize);   /*< doesn't consume input */
-/*! ZSTD_getFrameHeader_advanced() :
- *  same as ZSTD_getFrameHeader(),
- *  with added capability to select a format (like ZSTD_f_zstd1_magicless) */
-ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
-ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize);  /*< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
-
-ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
-ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
-
-ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
-ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-
-/* misc */
-ZSTDLIB_API void   ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
-typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
-ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
-
-
-
-
-/* ============================ */
-/*       Block level API       */
-/* ============================ */
-
-/*!
-    Block functions produce and decode raw zstd blocks, without frame metadata.
-    Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes).
-    But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes.
-
-    A few rules to respect :
-    - Compressing and decompressing require a context structure
-      + Use ZSTD_createCCtx() and ZSTD_createDCtx()
-    - It is necessary to init context before starting
-      + compression : any ZSTD_compressBegin*() variant, including with dictionary
-      + decompression : any ZSTD_decompressBegin*() variant, including with dictionary
-      + copyCCtx() and copyDCtx() can be used too
-    - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB
-      + If input is larger than a block size, it's necessary to split input data into multiple blocks
-      + For inputs larger than a single block, consider using regular ZSTD_compress() instead.
-        Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block.
-    - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) !
-      ===> In which case, nothing is produced into `dst` !
-      + User __must__ test for such outcome and deal directly with uncompressed data
-      + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0.
-        Doing so would mess up with statistics history, leading to potential data corruption.
-      + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !!
-      + In case of multiple successive blocks, should some of them be uncompressed,
-        decoder must be informed of their existence in order to follow proper history.
-        Use ZSTD_insertBlock() for such a case.
-*/
-
-/*=====   Raw zstd block functions  =====*/
-ZSTDLIB_API size_t ZSTD_getBlockSize   (const ZSTD_CCtx* cctx);
-ZSTDLIB_API size_t ZSTD_compressBlock  (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_insertBlock    (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize);  /*< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
-
-
-#endif   /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
-
diff --git a/lib/zstd/Makefile b/lib/zstd/Makefile
index 528d3a870bb9..4e8689a4855d 100644
--- a/lib/zstd/Makefile
+++ b/lib/zstd/Makefile
@@ -1,23 +1,8 @@
-# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
-# ################################################################
-# Copyright (c) Facebook, Inc.
-# All rights reserved.
-#
-# This source code is licensed under both the BSD-style license (found in the
-# LICENSE file in the root directory of this source tree) and the GPLv2 (found
-# in the COPYING file in the root directory of this source tree).
-# You may select, at your option, one of the above-listed licenses.
-# ################################################################
+# SPDX-License-Identifier: GPL-2.0-only
+
 obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd_decompress.o
 
-zstd_decompress-y := \
-		zstd_decompress_module.o \
-		common/debug.o \
-		common/entropy_common.o \
-		common/error_private.o \
-		common/fse_decompress.o \
-		common/zstd_common.o \
-		decompress/huf_decompress.o \
-		decompress/zstd_ddict.o \
-		decompress/zstd_decompress.o \
-		decompress/zstd_decompress_block.o \
+ccflags-y += -O3
+
+zstd_decompress-y := huf_decompress.o decompress.o
+zstd_decompress-y += entropy_common.o fse_decompress.o zstd_common.o
diff --git a/lib/zstd/bitstream.h b/lib/zstd/bitstream.h
new file mode 100644
index 000000000000..a826b99e1d63
--- /dev/null
+++ b/lib/zstd/bitstream.h
@@ -0,0 +1,374 @@
+/*
+ * bitstream
+ * Part of FSE library
+ * header file (to include)
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+#ifndef BITSTREAM_H_MODULE
+#define BITSTREAM_H_MODULE
+
+/*
+*  This API consists of small unitary functions, which must be inlined for best performance.
+*  Since link-time-optimization is not available for all compilers,
+*  these functions are defined into a .h to be included.
+*/
+
+/*-****************************************
+*  Dependencies
+******************************************/
+#include "error_private.h" /* error codes and messages */
+#include "mem.h"	   /* unaligned access routines */
+
+/*=========================================
+*  Target specific
+=========================================*/
+#define STREAM_ACCUMULATOR_MIN_32 25
+#define STREAM_ACCUMULATOR_MIN_64 57
+#define STREAM_ACCUMULATOR_MIN ((U32)(ZSTD_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
+
+/*-******************************************
+*  bitStream encoding API (write forward)
+********************************************/
+/* bitStream can mix input from multiple sources.
+*  A critical property of these streams is that they encode and decode in **reverse** direction.
+*  So the first bit sequence you add will be the last to be read, like a LIFO stack.
+*/
+typedef struct {
+	size_t bitContainer;
+	int bitPos;
+	char *startPtr;
+	char *ptr;
+	char *endPtr;
+} BIT_CStream_t;
+
+ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *dstBuffer, size_t dstCapacity);
+ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
+ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC);
+ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC);
+
+/* Start with initCStream, providing the size of buffer to write into.
+*  bitStream will never write outside of this buffer.
+*  `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
+*
+*  bits are first added to a local register.
+*  Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
+*  Writing data into memory is an explicit operation, performed by the flushBits function.
+*  Hence keep track how many bits are potentially stored into local register to avoid register overflow.
+*  After a flushBits, a maximum of 7 bits might still be stored into local register.
+*
+*  Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
+*
+*  Last operation is to close the bitStream.
+*  The function returns the final size of CStream in bytes.
+*  If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
+*/
+
+/*-********************************************
+*  bitStream decoding API (read backward)
+**********************************************/
+typedef struct {
+	size_t bitContainer;
+	unsigned bitsConsumed;
+	const char *ptr;
+	const char *start;
+} BIT_DStream_t;
+
+typedef enum {
+	BIT_DStream_unfinished = 0,
+	BIT_DStream_endOfBuffer = 1,
+	BIT_DStream_completed = 2,
+	BIT_DStream_overflow = 3
+} BIT_DStream_status; /* result of BIT_reloadDStream() */
+/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
+
+ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, size_t srcSize);
+ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, unsigned nbBits);
+ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD);
+ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *bitD);
+
+/* Start by invoking BIT_initDStream().
+*  A chunk of the bitStream is then stored into a local register.
+*  Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
+*  You can then retrieve bitFields stored into the local register, **in reverse order**.
+*  Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
+*  A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
+*  Otherwise, it can be less than that, so proceed accordingly.
+*  Checking if DStream has reached its end can be performed with BIT_endOfDStream().
+*/
+
+/*-****************************************
+*  unsafe API
+******************************************/
+ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
+/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
+
+ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC);
+/* unsafe version; does not check buffer overflow */
+
+ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, unsigned nbBits);
+/* faster, but works only if nbBits >= 1 */
+
+/*-**************************************************************
+*  Internal functions
+****************************************************************/
+ZSTD_STATIC unsigned BIT_highbit32(register U32 val) { return 31 - __builtin_clz(val); }
+
+/*=====    Local Constants   =====*/
+static const unsigned BIT_mask[] = {0,       1,       3,       7,	0xF,      0x1F,     0x3F,     0x7F,      0xFF,
+				    0x1FF,   0x3FF,   0x7FF,   0xFFF,    0x1FFF,   0x3FFF,   0x7FFF,   0xFFFF,    0x1FFFF,
+				    0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF}; /* up to 26 bits */
+
+/*-**************************************************************
+*  bitStream encoding
+****************************************************************/
+/*! BIT_initCStream() :
+ *  `dstCapacity` must be > sizeof(void*)
+ *  @return : 0 if success,
+			  otherwise an error code (can be tested using ERR_isError() ) */
+ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *startPtr, size_t dstCapacity)
+{
+	bitC->bitContainer = 0;
+	bitC->bitPos = 0;
+	bitC->startPtr = (char *)startPtr;
+	bitC->ptr = bitC->startPtr;
+	bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
+	if (dstCapacity <= sizeof(bitC->ptr))
+		return ERROR(dstSize_tooSmall);
+	return 0;
+}
+
+/*! BIT_addBits() :
+	can add up to 26 bits into `bitC`.
+	Does not check for register overflow ! */
+ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
+{
+	bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
+	bitC->bitPos += nbBits;
+}
+
+/*! BIT_addBitsFast() :
+ *  works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
+ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
+{
+	bitC->bitContainer |= value << bitC->bitPos;
+	bitC->bitPos += nbBits;
+}
+
+/*! BIT_flushBitsFast() :
+ *  unsafe version; does not check buffer overflow */
+ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC)
+{
+	size_t const nbBytes = bitC->bitPos >> 3;
+	ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
+	bitC->ptr += nbBytes;
+	bitC->bitPos &= 7;
+	bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
+}
+
+/*! BIT_flushBits() :
+ *  safe version; check for buffer overflow, and prevents it.
+ *  note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
+ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC)
+{
+	size_t const nbBytes = bitC->bitPos >> 3;
+	ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
+	bitC->ptr += nbBytes;
+	if (bitC->ptr > bitC->endPtr)
+		bitC->ptr = bitC->endPtr;
+	bitC->bitPos &= 7;
+	bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
+}
+
+/*! BIT_closeCStream() :
+ *  @return : size of CStream, in bytes,
+			  or 0 if it could not fit into dstBuffer */
+ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC)
+{
+	BIT_addBitsFast(bitC, 1, 1); /* endMark */
+	BIT_flushBits(bitC);
+
+	if (bitC->ptr >= bitC->endPtr)
+		return 0; /* doesn't fit within authorized budget : cancel */
+
+	return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
+}
+
+/*-********************************************************
+* bitStream decoding
+**********************************************************/
+/*! BIT_initDStream() :
+*   Initialize a BIT_DStream_t.
+*   `bitD` : a pointer to an already allocated BIT_DStream_t structure.
+*   `srcSize` must be the *exact* size of the bitStream, in bytes.
+*   @return : size of stream (== srcSize) or an errorCode if a problem is detected
+*/
+ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, size_t srcSize)
+{
+	if (srcSize < 1) {
+		memset(bitD, 0, sizeof(*bitD));
+		return ERROR(srcSize_wrong);
+	}
+
+	if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
+		bitD->start = (const char *)srcBuffer;
+		bitD->ptr = (const char *)srcBuffer + srcSize - sizeof(bitD->bitContainer);
+		bitD->bitContainer = ZSTD_readLEST(bitD->ptr);
+		{
+			BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
+			bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
+			if (lastByte == 0)
+				return ERROR(GENERIC); /* endMark not present */
+		}
+	} else {
+		bitD->start = (const char *)srcBuffer;
+		bitD->ptr = bitD->start;
+		bitD->bitContainer = *(const BYTE *)(bitD->start);
+		switch (srcSize) {
+		case 7: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[6]) << (sizeof(bitD->bitContainer) * 8 - 16);
+		case 6: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[5]) << (sizeof(bitD->bitContainer) * 8 - 24);
+		case 5: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[4]) << (sizeof(bitD->bitContainer) * 8 - 32);
+		case 4: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[3]) << 24;
+		case 3: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[2]) << 16;
+		case 2: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[1]) << 8;
+		default:;
+		}
+		{
+			BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
+			bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
+			if (lastByte == 0)
+				return ERROR(GENERIC); /* endMark not present */
+		}
+		bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize) * 8;
+	}
+
+	return srcSize;
+}
+
+ZSTD_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) { return bitContainer >> start; }
+
+ZSTD_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) { return (bitContainer >> start) & BIT_mask[nbBits]; }
+
+ZSTD_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { return bitContainer & BIT_mask[nbBits]; }
+
+/*! BIT_lookBits() :
+ *  Provides next n bits from local register.
+ *  local register is not modified.
+ *  On 32-bits, maxNbBits==24.
+ *  On 64-bits, maxNbBits==56.
+ *  @return : value extracted
+ */
+ZSTD_STATIC size_t BIT_lookBits(const BIT_DStream_t *bitD, U32 nbBits)
+{
+	U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
+	return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask - nbBits) & bitMask);
+}
+
+/*! BIT_lookBitsFast() :
+*   unsafe version; only works only if nbBits >= 1 */
+ZSTD_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t *bitD, U32 nbBits)
+{
+	U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
+	return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask + 1) - nbBits) & bitMask);
+}
+
+ZSTD_STATIC void BIT_skipBits(BIT_DStream_t *bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; }
+
+/*! BIT_readBits() :
+ *  Read (consume) next n bits from local register and update.
+ *  Pay attention to not read more than nbBits contained into local register.
+ *  @return : extracted value.
+ */
+ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, U32 nbBits)
+{
+	size_t const value = BIT_lookBits(bitD, nbBits);
+	BIT_skipBits(bitD, nbBits);
+	return value;
+}
+
+/*! BIT_readBitsFast() :
+*   unsafe version; only works only if nbBits >= 1 */
+ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, U32 nbBits)
+{
+	size_t const value = BIT_lookBitsFast(bitD, nbBits);
+	BIT_skipBits(bitD, nbBits);
+	return value;
+}
+
+/*! BIT_reloadDStream() :
+*   Refill `bitD` from buffer previously set in BIT_initDStream() .
+*   This function is safe, it guarantees it will not read beyond src buffer.
+*   @return : status of `BIT_DStream_t` internal register.
+			  if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
+ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD)
+{
+	if (bitD->bitsConsumed > (sizeof(bitD->bitContainer) * 8)) /* should not happen => corruption detected */
+		return BIT_DStream_overflow;
+
+	if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
+		bitD->ptr -= bitD->bitsConsumed >> 3;
+		bitD->bitsConsumed &= 7;
+		bitD->bitContainer = ZSTD_readLEST(bitD->ptr);
+		return BIT_DStream_unfinished;
+	}
+	if (bitD->ptr == bitD->start) {
+		if (bitD->bitsConsumed < sizeof(bitD->bitContainer) * 8)
+			return BIT_DStream_endOfBuffer;
+		return BIT_DStream_completed;
+	}
+	{
+		U32 nbBytes = bitD->bitsConsumed >> 3;
+		BIT_DStream_status result = BIT_DStream_unfinished;
+		if (bitD->ptr - nbBytes < bitD->start) {
+			nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
+			result = BIT_DStream_endOfBuffer;
+		}
+		bitD->ptr -= nbBytes;
+		bitD->bitsConsumed -= nbBytes * 8;
+		bitD->bitContainer = ZSTD_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
+		return result;
+	}
+}
+
+/*! BIT_endOfDStream() :
+*   @return Tells if DStream has exactly reached its end (all bits consumed).
+*/
+ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *DStream)
+{
+	return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer) * 8));
+}
+
+#endif /* BITSTREAM_H_MODULE */
diff --git a/lib/zstd/common/bitstream.h b/lib/zstd/common/bitstream.h
deleted file mode 100644
index 28248abe8612..000000000000
--- a/lib/zstd/common/bitstream.h
+++ /dev/null
@@ -1,437 +0,0 @@
-/* ******************************************************************
- * bitstream
- * Part of FSE library
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-#ifndef BITSTREAM_H_MODULE
-#define BITSTREAM_H_MODULE
-
-/*
-*  This API consists of small unitary functions, which must be inlined for best performance.
-*  Since link-time-optimization is not available for all compilers,
-*  these functions are defined into a .h to be included.
-*/
-
-/*-****************************************
-*  Dependencies
-******************************************/
-#include "mem.h"            /* unaligned access routines */
-#include "compiler.h"       /* UNLIKELY() */
-#include "debug.h"          /* assert(), DEBUGLOG(), RAWLOG() */
-#include "error_private.h"  /* error codes and messages */
-
-
-/*=========================================
-*  Target specific
-=========================================*/
-
-#define STREAM_ACCUMULATOR_MIN_32  25
-#define STREAM_ACCUMULATOR_MIN_64  57
-#define STREAM_ACCUMULATOR_MIN    ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
-
-
-/*-******************************************
-*  bitStream encoding API (write forward)
-********************************************/
-/* bitStream can mix input from multiple sources.
- * A critical property of these streams is that they encode and decode in **reverse** direction.
- * So the first bit sequence you add will be the last to be read, like a LIFO stack.
- */
-typedef struct {
-    size_t bitContainer;
-    unsigned bitPos;
-    char*  startPtr;
-    char*  ptr;
-    char*  endPtr;
-} BIT_CStream_t;
-
-MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
-MEM_STATIC void   BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
-MEM_STATIC void   BIT_flushBits(BIT_CStream_t* bitC);
-MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
-
-/* Start with initCStream, providing the size of buffer to write into.
-*  bitStream will never write outside of this buffer.
-*  `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
-*
-*  bits are first added to a local register.
-*  Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
-*  Writing data into memory is an explicit operation, performed by the flushBits function.
-*  Hence keep track how many bits are potentially stored into local register to avoid register overflow.
-*  After a flushBits, a maximum of 7 bits might still be stored into local register.
-*
-*  Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
-*
-*  Last operation is to close the bitStream.
-*  The function returns the final size of CStream in bytes.
-*  If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
-*/
-
-
-/*-********************************************
-*  bitStream decoding API (read backward)
-**********************************************/
-typedef struct {
-    size_t   bitContainer;
-    unsigned bitsConsumed;
-    const char* ptr;
-    const char* start;
-    const char* limitPtr;
-} BIT_DStream_t;
-
-typedef enum { BIT_DStream_unfinished = 0,
-               BIT_DStream_endOfBuffer = 1,
-               BIT_DStream_completed = 2,
-               BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */
-               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
-
-MEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
-MEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
-MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
-MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
-
-
-/* Start by invoking BIT_initDStream().
-*  A chunk of the bitStream is then stored into a local register.
-*  Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
-*  You can then retrieve bitFields stored into the local register, **in reverse order**.
-*  Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
-*  A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
-*  Otherwise, it can be less than that, so proceed accordingly.
-*  Checking if DStream has reached its end can be performed with BIT_endOfDStream().
-*/
-
-
-/*-****************************************
-*  unsafe API
-******************************************/
-MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
-/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
-
-MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
-/* unsafe version; does not check buffer overflow */
-
-MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
-/* faster, but works only if nbBits >= 1 */
-
-
-
-/*-**************************************************************
-*  Internal functions
-****************************************************************/
-MEM_STATIC unsigned BIT_highbit32 (U32 val)
-{
-    assert(val != 0);
-    {
-#   if (__GNUC__ >= 3)   /* Use GCC Intrinsic */
-        return __builtin_clz (val) ^ 31;
-#   else   /* Software version */
-        static const unsigned DeBruijnClz[32] = { 0,  9,  1, 10, 13, 21,  2, 29,
-                                                 11, 14, 16, 18, 22, 25,  3, 30,
-                                                  8, 12, 20, 28, 15, 17, 24,  7,
-                                                 19, 27, 23,  6, 26,  5,  4, 31 };
-        U32 v = val;
-        v |= v >> 1;
-        v |= v >> 2;
-        v |= v >> 4;
-        v |= v >> 8;
-        v |= v >> 16;
-        return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
-#   endif
-    }
-}
-
-/*=====    Local Constants   =====*/
-static const unsigned BIT_mask[] = {
-    0,          1,         3,         7,         0xF,       0x1F,
-    0x3F,       0x7F,      0xFF,      0x1FF,     0x3FF,     0x7FF,
-    0xFFF,      0x1FFF,    0x3FFF,    0x7FFF,    0xFFFF,    0x1FFFF,
-    0x3FFFF,    0x7FFFF,   0xFFFFF,   0x1FFFFF,  0x3FFFFF,  0x7FFFFF,
-    0xFFFFFF,   0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
-    0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
-#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
-
-/*-**************************************************************
-*  bitStream encoding
-****************************************************************/
-/*! BIT_initCStream() :
- *  `dstCapacity` must be > sizeof(size_t)
- *  @return : 0 if success,
- *            otherwise an error code (can be tested using ERR_isError()) */
-MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
-                                  void* startPtr, size_t dstCapacity)
-{
-    bitC->bitContainer = 0;
-    bitC->bitPos = 0;
-    bitC->startPtr = (char*)startPtr;
-    bitC->ptr = bitC->startPtr;
-    bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
-    if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
-    return 0;
-}
-
-/*! BIT_addBits() :
- *  can add up to 31 bits into `bitC`.
- *  Note : does not check for register overflow ! */
-MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
-                            size_t value, unsigned nbBits)
-{
-    DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32);
-    assert(nbBits < BIT_MASK_SIZE);
-    assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
-    bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
-    bitC->bitPos += nbBits;
-}
-
-/*! BIT_addBitsFast() :
- *  works only if `value` is _clean_,
- *  meaning all high bits above nbBits are 0 */
-MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
-                                size_t value, unsigned nbBits)
-{
-    assert((value>>nbBits) == 0);
-    assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
-    bitC->bitContainer |= value << bitC->bitPos;
-    bitC->bitPos += nbBits;
-}
-
-/*! BIT_flushBitsFast() :
- *  assumption : bitContainer has not overflowed
- *  unsafe version; does not check buffer overflow */
-MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
-{
-    size_t const nbBytes = bitC->bitPos >> 3;
-    assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
-    assert(bitC->ptr <= bitC->endPtr);
-    MEM_writeLEST(bitC->ptr, bitC->bitContainer);
-    bitC->ptr += nbBytes;
-    bitC->bitPos &= 7;
-    bitC->bitContainer >>= nbBytes*8;
-}
-
-/*! BIT_flushBits() :
- *  assumption : bitContainer has not overflowed
- *  safe version; check for buffer overflow, and prevents it.
- *  note : does not signal buffer overflow.
- *  overflow will be revealed later on using BIT_closeCStream() */
-MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
-{
-    size_t const nbBytes = bitC->bitPos >> 3;
-    assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
-    assert(bitC->ptr <= bitC->endPtr);
-    MEM_writeLEST(bitC->ptr, bitC->bitContainer);
-    bitC->ptr += nbBytes;
-    if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
-    bitC->bitPos &= 7;
-    bitC->bitContainer >>= nbBytes*8;
-}
-
-/*! BIT_closeCStream() :
- *  @return : size of CStream, in bytes,
- *            or 0 if it could not fit into dstBuffer */
-MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
-{
-    BIT_addBitsFast(bitC, 1, 1);   /* endMark */
-    BIT_flushBits(bitC);
-    if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
-    return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
-}
-
-
-/*-********************************************************
-*  bitStream decoding
-**********************************************************/
-/*! BIT_initDStream() :
- *  Initialize a BIT_DStream_t.
- * `bitD` : a pointer to an already allocated BIT_DStream_t structure.
- * `srcSize` must be the *exact* size of the bitStream, in bytes.
- * @return : size of stream (== srcSize), or an errorCode if a problem is detected
- */
-MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
-{
-    if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
-
-    bitD->start = (const char*)srcBuffer;
-    bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
-
-    if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */
-        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
-        bitD->bitContainer = MEM_readLEST(bitD->ptr);
-        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
-          bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;  /* ensures bitsConsumed is always set */
-          if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
-    } else {
-        bitD->ptr   = bitD->start;
-        bitD->bitContainer = *(const BYTE*)(bitD->start);
-        switch(srcSize)
-        {
-        case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
-                ZSTD_FALLTHROUGH;
-
-        case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
-                ZSTD_FALLTHROUGH;
-
-        case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
-                ZSTD_FALLTHROUGH;
-
-        case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
-                ZSTD_FALLTHROUGH;
-
-        case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
-                ZSTD_FALLTHROUGH;
-
-        case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) <<  8;
-                ZSTD_FALLTHROUGH;
-
-        default: break;
-        }
-        {   BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
-            bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
-            if (lastByte == 0) return ERROR(corruption_detected);  /* endMark not present */
-        }
-        bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
-    }
-
-    return srcSize;
-}
-
-MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
-{
-    return bitContainer >> start;
-}
-
-MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
-{
-    U32 const regMask = sizeof(bitContainer)*8 - 1;
-    /* if start > regMask, bitstream is corrupted, and result is undefined */
-    assert(nbBits < BIT_MASK_SIZE);
-    return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
-}
-
-MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
-{
-    assert(nbBits < BIT_MASK_SIZE);
-    return bitContainer & BIT_mask[nbBits];
-}
-
-/*! BIT_lookBits() :
- *  Provides next n bits from local register.
- *  local register is not modified.
- *  On 32-bits, maxNbBits==24.
- *  On 64-bits, maxNbBits==56.
- * @return : value extracted */
-MEM_STATIC  FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t*  bitD, U32 nbBits)
-{
-    /* arbitrate between double-shift and shift+mask */
-#if 1
-    /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,
-     * bitstream is likely corrupted, and result is undefined */
-    return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
-#else
-    /* this code path is slower on my os-x laptop */
-    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
-    return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
-#endif
-}
-
-/*! BIT_lookBitsFast() :
- *  unsafe version; only works if nbBits >= 1 */
-MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
-{
-    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
-    assert(nbBits >= 1);
-    return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
-}
-
-MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
-{
-    bitD->bitsConsumed += nbBits;
-}
-
-/*! BIT_readBits() :
- *  Read (consume) next n bits from local register and update.
- *  Pay attention to not read more than nbBits contained into local register.
- * @return : extracted value. */
-MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
-{
-    size_t const value = BIT_lookBits(bitD, nbBits);
-    BIT_skipBits(bitD, nbBits);
-    return value;
-}
-
-/*! BIT_readBitsFast() :
- *  unsafe version; only works only if nbBits >= 1 */
-MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
-{
-    size_t const value = BIT_lookBitsFast(bitD, nbBits);
-    assert(nbBits >= 1);
-    BIT_skipBits(bitD, nbBits);
-    return value;
-}
-
-/*! BIT_reloadDStreamFast() :
- *  Similar to BIT_reloadDStream(), but with two differences:
- *  1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
- *  2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this
- *     point you must use BIT_reloadDStream() to reload.
- */
-MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
-{
-    if (UNLIKELY(bitD->ptr < bitD->limitPtr))
-        return BIT_DStream_overflow;
-    assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
-    bitD->ptr -= bitD->bitsConsumed >> 3;
-    bitD->bitsConsumed &= 7;
-    bitD->bitContainer = MEM_readLEST(bitD->ptr);
-    return BIT_DStream_unfinished;
-}
-
-/*! BIT_reloadDStream() :
- *  Refill `bitD` from buffer previously set in BIT_initDStream() .
- *  This function is safe, it guarantees it will not read beyond src buffer.
- * @return : status of `BIT_DStream_t` internal register.
- *           when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
-MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
-{
-    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* overflow detected, like end of stream */
-        return BIT_DStream_overflow;
-
-    if (bitD->ptr >= bitD->limitPtr) {
-        return BIT_reloadDStreamFast(bitD);
-    }
-    if (bitD->ptr == bitD->start) {
-        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
-        return BIT_DStream_completed;
-    }
-    /* start < ptr < limitPtr */
-    {   U32 nbBytes = bitD->bitsConsumed >> 3;
-        BIT_DStream_status result = BIT_DStream_unfinished;
-        if (bitD->ptr - nbBytes < bitD->start) {
-            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */
-            result = BIT_DStream_endOfBuffer;
-        }
-        bitD->ptr -= nbBytes;
-        bitD->bitsConsumed -= nbBytes*8;
-        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
-        return result;
-    }
-}
-
-/*! BIT_endOfDStream() :
- * @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
- */
-MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
-{
-    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
-}
-
-
-#endif /* BITSTREAM_H_MODULE */
diff --git a/lib/zstd/common/compiler.h b/lib/zstd/common/compiler.h
deleted file mode 100644
index f5a9c70a228a..000000000000
--- a/lib/zstd/common/compiler.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-#ifndef ZSTD_COMPILER_H
-#define ZSTD_COMPILER_H
-
-/*-*******************************************************
-*  Compiler specifics
-*********************************************************/
-/* force inlining */
-
-#if !defined(ZSTD_NO_INLINE)
-#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
-#  define INLINE_KEYWORD inline
-#else
-#  define INLINE_KEYWORD
-#endif
-
-#define FORCE_INLINE_ATTR __attribute__((always_inline))
-
-#else
-
-#define INLINE_KEYWORD
-#define FORCE_INLINE_ATTR
-
-#endif
-
-/*
-  On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
-  This explictly marks such functions as __cdecl so that the code will still compile
-  if a CC other than __cdecl has been made the default.
-*/
-#define WIN_CDECL
-
-/*
- * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
- * parameters. They must be inlined for the compiler to eliminate the constant
- * branches.
- */
-#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
-/*
- * HINT_INLINE is used to help the compiler generate better code. It is *not*
- * used for "templates", so it can be tweaked based on the compilers
- * performance.
- *
- * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the
- * always_inline attribute.
- *
- * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline
- * attribute.
- */
-#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
-#  define HINT_INLINE static INLINE_KEYWORD
-#else
-#  define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR
-#endif
-
-/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */
-#define UNUSED_ATTR __attribute__((unused))
-
-/* force no inlining */
-#define FORCE_NOINLINE static __attribute__((__noinline__))
-
-
-/* target attribute */
-#ifndef __has_attribute
-  #define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */
-#endif
-#define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
-
-/* Enable runtime BMI2 dispatch based on the CPU.
- * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
- */
-#ifndef DYNAMIC_BMI2
-  #if ((defined(__clang__) && __has_attribute(__target__)) \
-      || (defined(__GNUC__) \
-          && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
-      && (defined(__x86_64__) || defined(_M_X86)) \
-      && !defined(__BMI2__)
-  #  define DYNAMIC_BMI2 1
-  #else
-  #  define DYNAMIC_BMI2 0
-  #endif
-#endif
-
-/* prefetch
- * can be disabled, by declaring NO_PREFETCH build macro */
-#if ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
-#  define PREFETCH_L1(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
-#  define PREFETCH_L2(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
-#elif defined(__aarch64__)
-#  define PREFETCH_L1(ptr)  __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
-#  define PREFETCH_L2(ptr)  __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
-#else
-#  define PREFETCH_L1(ptr) (void)(ptr)  /* disabled */
-#  define PREFETCH_L2(ptr) (void)(ptr)  /* disabled */
-#endif  /* NO_PREFETCH */
-
-#define CACHELINE_SIZE 64
-
-#define PREFETCH_AREA(p, s)  {            \
-    const char* const _ptr = (const char*)(p);  \
-    size_t const _size = (size_t)(s);     \
-    size_t _pos;                          \
-    for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) {  \
-        PREFETCH_L2(_ptr + _pos);         \
-    }                                     \
-}
-
-/* vectorization
- * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */
-#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__)
-#  if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)
-#    define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
-#  else
-#    define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")")
-#  endif
-#else
-#  define DONT_VECTORIZE
-#endif
-
-/* Tell the compiler that a branch is likely or unlikely.
- * Only use these macros if it causes the compiler to generate better code.
- * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc
- * and clang, please do.
- */
-#define LIKELY(x) (__builtin_expect((x), 1))
-#define UNLIKELY(x) (__builtin_expect((x), 0))
-
-/* disable warnings */
-
-/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/
-
-
-/* compat. with non-clang compilers */
-#ifndef __has_builtin
-#  define __has_builtin(x) 0
-#endif
-
-/* compat. with non-clang compilers */
-#ifndef __has_feature
-#  define __has_feature(x) 0
-#endif
-
-/* C-language Attributes are added in C23. */
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
-# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
-#else
-# define ZSTD_HAS_C_ATTRIBUTE(x) 0
-#endif
-
-/* Only use C++ attributes in C++. Some compilers report support for C++
- * attributes when compiling with C.
- */
-#define ZSTD_HAS_CPP_ATTRIBUTE(x) 0
-
-/* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute.
- * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough
- * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough
- * - Else: __attribute__((__fallthrough__))
- */
-#define ZSTD_FALLTHROUGH fallthrough
-
-/* detects whether we are being compiled under msan */
-
-
-/* detects whether we are being compiled under asan */
-
-
-#endif /* ZSTD_COMPILER_H */
diff --git a/lib/zstd/common/cpu.h b/lib/zstd/common/cpu.h
deleted file mode 100644
index 0db7b42407ee..000000000000
--- a/lib/zstd/common/cpu.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-#ifndef ZSTD_COMMON_CPU_H
-#define ZSTD_COMMON_CPU_H
-
-/*
- * Implementation taken from folly/CpuId.h
- * https://github.com/facebook/folly/blob/master/folly/CpuId.h
- */
-
-#include "mem.h"
-
-
-typedef struct {
-    U32 f1c;
-    U32 f1d;
-    U32 f7b;
-    U32 f7c;
-} ZSTD_cpuid_t;
-
-MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
-    U32 f1c = 0;
-    U32 f1d = 0;
-    U32 f7b = 0;
-    U32 f7c = 0;
-#if defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
-    /* The following block like the normal cpuid branch below, but gcc
-     * reserves ebx for use of its pic register so we must specially
-     * handle the save and restore to avoid clobbering the register
-     */
-    U32 n;
-    __asm__(
-        "pushl %%ebx\n\t"
-        "cpuid\n\t"
-        "popl %%ebx\n\t"
-        : "=a"(n)
-        : "a"(0)
-        : "ecx", "edx");
-    if (n >= 1) {
-      U32 f1a;
-      __asm__(
-          "pushl %%ebx\n\t"
-          "cpuid\n\t"
-          "popl %%ebx\n\t"
-          : "=a"(f1a), "=c"(f1c), "=d"(f1d)
-          : "a"(1));
-    }
-    if (n >= 7) {
-      __asm__(
-          "pushl %%ebx\n\t"
-          "cpuid\n\t"
-          "movl %%ebx, %%eax\n\t"
-          "popl %%ebx"
-          : "=a"(f7b), "=c"(f7c)
-          : "a"(7), "c"(0)
-          : "edx");
-    }
-#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
-    U32 n;
-    __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
-    if (n >= 1) {
-      U32 f1a;
-      __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
-    }
-    if (n >= 7) {
-      U32 f7a;
-      __asm__("cpuid"
-              : "=a"(f7a), "=b"(f7b), "=c"(f7c)
-              : "a"(7), "c"(0)
-              : "edx");
-    }
-#endif
-    {
-        ZSTD_cpuid_t cpuid;
-        cpuid.f1c = f1c;
-        cpuid.f1d = f1d;
-        cpuid.f7b = f7b;
-        cpuid.f7c = f7c;
-        return cpuid;
-    }
-}
-
-#define X(name, r, bit)                                                        \
-  MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) {                 \
-    return ((cpuid.r) & (1U << bit)) != 0;                                     \
-  }
-
-/* cpuid(1): Processor Info and Feature Bits. */
-#define C(name, bit) X(name, f1c, bit)
-  C(sse3, 0)
-  C(pclmuldq, 1)
-  C(dtes64, 2)
-  C(monitor, 3)
-  C(dscpl, 4)
-  C(vmx, 5)
-  C(smx, 6)
-  C(eist, 7)
-  C(tm2, 8)
-  C(ssse3, 9)
-  C(cnxtid, 10)
-  C(fma, 12)
-  C(cx16, 13)
-  C(xtpr, 14)
-  C(pdcm, 15)
-  C(pcid, 17)
-  C(dca, 18)
-  C(sse41, 19)
-  C(sse42, 20)
-  C(x2apic, 21)
-  C(movbe, 22)
-  C(popcnt, 23)
-  C(tscdeadline, 24)
-  C(aes, 25)
-  C(xsave, 26)
-  C(osxsave, 27)
-  C(avx, 28)
-  C(f16c, 29)
-  C(rdrand, 30)
-#undef C
-#define D(name, bit) X(name, f1d, bit)
-  D(fpu, 0)
-  D(vme, 1)
-  D(de, 2)
-  D(pse, 3)
-  D(tsc, 4)
-  D(msr, 5)
-  D(pae, 6)
-  D(mce, 7)
-  D(cx8, 8)
-  D(apic, 9)
-  D(sep, 11)
-  D(mtrr, 12)
-  D(pge, 13)
-  D(mca, 14)
-  D(cmov, 15)
-  D(pat, 16)
-  D(pse36, 17)
-  D(psn, 18)
-  D(clfsh, 19)
-  D(ds, 21)
-  D(acpi, 22)
-  D(mmx, 23)
-  D(fxsr, 24)
-  D(sse, 25)
-  D(sse2, 26)
-  D(ss, 27)
-  D(htt, 28)
-  D(tm, 29)
-  D(pbe, 31)
-#undef D
-
-/* cpuid(7): Extended Features. */
-#define B(name, bit) X(name, f7b, bit)
-  B(bmi1, 3)
-  B(hle, 4)
-  B(avx2, 5)
-  B(smep, 7)
-  B(bmi2, 8)
-  B(erms, 9)
-  B(invpcid, 10)
-  B(rtm, 11)
-  B(mpx, 14)
-  B(avx512f, 16)
-  B(avx512dq, 17)
-  B(rdseed, 18)
-  B(adx, 19)
-  B(smap, 20)
-  B(avx512ifma, 21)
-  B(pcommit, 22)
-  B(clflushopt, 23)
-  B(clwb, 24)
-  B(avx512pf, 26)
-  B(avx512er, 27)
-  B(avx512cd, 28)
-  B(sha, 29)
-  B(avx512bw, 30)
-  B(avx512vl, 31)
-#undef B
-#define C(name, bit) X(name, f7c, bit)
-  C(prefetchwt1, 0)
-  C(avx512vbmi, 1)
-#undef C
-
-#undef X
-
-#endif /* ZSTD_COMMON_CPU_H */
diff --git a/lib/zstd/common/debug.c b/lib/zstd/common/debug.c
deleted file mode 100644
index bb863c9ea616..000000000000
--- a/lib/zstd/common/debug.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ******************************************************************
- * debug
- * Part of FSE library
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-
-
-/*
- * This module only hosts one global variable
- * which can be used to dynamically influence the verbosity of traces,
- * such as DEBUGLOG and RAWLOG
- */
-
-#include "debug.h"
-
-int g_debuglevel = DEBUGLEVEL;
diff --git a/lib/zstd/common/debug.h b/lib/zstd/common/debug.h
deleted file mode 100644
index 6dd88d1fbd02..000000000000
--- a/lib/zstd/common/debug.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/* ******************************************************************
- * debug
- * Part of FSE library
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-
-
-/*
- * The purpose of this header is to enable debug functions.
- * They regroup assert(), DEBUGLOG() and RAWLOG() for run-time,
- * and DEBUG_STATIC_ASSERT() for compile-time.
- *
- * By default, DEBUGLEVEL==0, which means run-time debug is disabled.
- *
- * Level 1 enables assert() only.
- * Starting level 2, traces can be generated and pushed to stderr.
- * The higher the level, the more verbose the traces.
- *
- * It's possible to dynamically adjust level using variable g_debug_level,
- * which is only declared if DEBUGLEVEL>=2,
- * and is a global variable, not multi-thread protected (use with care)
- */
-
-#ifndef DEBUG_H_12987983217
-#define DEBUG_H_12987983217
-
-
-
-/* static assert is triggered at compile time, leaving no runtime artefact.
- * static assert only works with compile-time constants.
- * Also, this variant can only be used inside a function. */
-#define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1])
-
-
-/* DEBUGLEVEL is expected to be defined externally,
- * typically through compiler command line.
- * Value must be a number. */
-#ifndef DEBUGLEVEL
-#  define DEBUGLEVEL 0
-#endif
-
-
-/* recommended values for DEBUGLEVEL :
- * 0 : release mode, no debug, all run-time checks disabled
- * 1 : enables assert() only, no display
- * 2 : reserved, for currently active debug path
- * 3 : events once per object lifetime (CCtx, CDict, etc.)
- * 4 : events once per frame
- * 5 : events once per block
- * 6 : events once per sequence (verbose)
- * 7+: events at every position (*very* verbose)
- *
- * It's generally inconvenient to output traces > 5.
- * In which case, it's possible to selectively trigger high verbosity levels
- * by modifying g_debug_level.
- */
-
-#if (DEBUGLEVEL>=1)
-#  define ZSTD_DEPS_NEED_ASSERT
-#  include "zstd_deps.h"
-#else
-#  ifndef assert   /* assert may be already defined, due to prior #include <assert.h> */
-#    define assert(condition) ((void)0)   /* disable assert (default) */
-#  endif
-#endif
-
-#if (DEBUGLEVEL>=2)
-#  define ZSTD_DEPS_NEED_IO
-#  include "zstd_deps.h"
-extern int g_debuglevel; /* the variable is only declared,
-                            it actually lives in debug.c,
-                            and is shared by the whole process.
-                            It's not thread-safe.
-                            It's useful when enabling very verbose levels
-                            on selective conditions (such as position in src) */
-
-#  define RAWLOG(l, ...) {                                       \
-                if (l<=g_debuglevel) {                           \
-                    ZSTD_DEBUG_PRINT(__VA_ARGS__);               \
-            }   }
-#  define DEBUGLOG(l, ...) {                                     \
-                if (l<=g_debuglevel) {                           \
-                    ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \
-                    ZSTD_DEBUG_PRINT(" \n");                     \
-            }   }
-#else
-#  define RAWLOG(l, ...)      {}    /* disabled */
-#  define DEBUGLOG(l, ...)    {}    /* disabled */
-#endif
-
-
-
-#endif /* DEBUG_H_12987983217 */
diff --git a/lib/zstd/common/entropy_common.c b/lib/zstd/common/entropy_common.c
deleted file mode 100644
index 53b47a2b52ff..000000000000
--- a/lib/zstd/common/entropy_common.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* ******************************************************************
- * Common functions of New Generation Entropy library
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- *  You can contact the author at :
- *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *  - Public forum : https://groups.google.com/forum/#!forum/lz4c
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-
-/* *************************************
-*  Dependencies
-***************************************/
-#include "mem.h"
-#include "error_private.h"       /* ERR_*, ERROR */
-#define FSE_STATIC_LINKING_ONLY  /* FSE_MIN_TABLELOG */
-#include "fse.h"
-#define HUF_STATIC_LINKING_ONLY  /* HUF_TABLELOG_ABSOLUTEMAX */
-#include "huf.h"
-
-
-/*===   Version   ===*/
-unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
-
-
-/*===   Error Management   ===*/
-unsigned FSE_isError(size_t code) { return ERR_isError(code); }
-const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }
-
-unsigned HUF_isError(size_t code) { return ERR_isError(code); }
-const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }
-
-
-/*-**************************************************************
-*  FSE NCount encoding-decoding
-****************************************************************/
-static U32 FSE_ctz(U32 val)
-{
-    assert(val != 0);
-    {
-#   if (__GNUC__ >= 3)   /* GCC Intrinsic */
-        return __builtin_ctz(val);
-#   else   /* Software version */
-        U32 count = 0;
-        while ((val & 1) == 0) {
-            val >>= 1;
-            ++count;
-        }
-        return count;
-#   endif
-    }
-}
-
-FORCE_INLINE_TEMPLATE
-size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
-                           const void* headerBuffer, size_t hbSize)
-{
-    const BYTE* const istart = (const BYTE*) headerBuffer;
-    const BYTE* const iend = istart + hbSize;
-    const BYTE* ip = istart;
-    int nbBits;
-    int remaining;
-    int threshold;
-    U32 bitStream;
-    int bitCount;
-    unsigned charnum = 0;
-    unsigned const maxSV1 = *maxSVPtr + 1;
-    int previous0 = 0;
-
-    if (hbSize < 8) {
-        /* This function only works when hbSize >= 8 */
-        char buffer[8] = {0};
-        ZSTD_memcpy(buffer, headerBuffer, hbSize);
-        {   size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,
-                                                    buffer, sizeof(buffer));
-            if (FSE_isError(countSize)) return countSize;
-            if (countSize > hbSize) return ERROR(corruption_detected);
-            return countSize;
-    }   }
-    assert(hbSize >= 8);
-
-    /* init */
-    ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0]));   /* all symbols not present in NCount have a frequency of 0 */
-    bitStream = MEM_readLE32(ip);
-    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */
-    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
-    bitStream >>= 4;
-    bitCount = 4;
-    *tableLogPtr = nbBits;
-    remaining = (1<<nbBits)+1;
-    threshold = 1<<nbBits;
-    nbBits++;
-
-    for (;;) {
-        if (previous0) {
-            /* Count the number of repeats. Each time the
-             * 2-bit repeat code is 0b11 there is another
-             * repeat.
-             * Avoid UB by setting the high bit to 1.
-             */
-            int repeats = FSE_ctz(~bitStream | 0x80000000) >> 1;
-            while (repeats >= 12) {
-                charnum += 3 * 12;
-                if (LIKELY(ip <= iend-7)) {
-                    ip += 3;
-                } else {
-                    bitCount -= (int)(8 * (iend - 7 - ip));
-                    bitCount &= 31;
-                    ip = iend - 4;
-                }
-                bitStream = MEM_readLE32(ip) >> bitCount;
-                repeats = FSE_ctz(~bitStream | 0x80000000) >> 1;
-            }
-            charnum += 3 * repeats;
-            bitStream >>= 2 * repeats;
-            bitCount += 2 * repeats;
-
-            /* Add the final repeat which isn't 0b11. */
-            assert((bitStream & 3) < 3);
-            charnum += bitStream & 3;
-            bitCount += 2;
-
-            /* This is an error, but break and return an error
-             * at the end, because returning out of a loop makes
-             * it harder for the compiler to optimize.
-             */
-            if (charnum >= maxSV1) break;
-
-            /* We don't need to set the normalized count to 0
-             * because we already memset the whole buffer to 0.
-             */
-
-            if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
-                assert((bitCount >> 3) <= 3); /* For first condition to work */
-                ip += bitCount>>3;
-                bitCount &= 7;
-            } else {
-                bitCount -= (int)(8 * (iend - 4 - ip));
-                bitCount &= 31;
-                ip = iend - 4;
-            }
-            bitStream = MEM_readLE32(ip) >> bitCount;
-        }
-        {
-            int const max = (2*threshold-1) - remaining;
-            int count;
-
-            if ((bitStream & (threshold-1)) < (U32)max) {
-                count = bitStream & (threshold-1);
-                bitCount += nbBits-1;
-            } else {
-                count = bitStream & (2*threshold-1);
-                if (count >= threshold) count -= max;
-                bitCount += nbBits;
-            }
-
-            count--;   /* extra accuracy */
-            /* When it matters (small blocks), this is a
-             * predictable branch, because we don't use -1.
-             */
-            if (count >= 0) {
-                remaining -= count;
-            } else {
-                assert(count == -1);
-                remaining += count;
-            }
-            normalizedCounter[charnum++] = (short)count;
-            previous0 = !count;
-
-            assert(threshold > 1);
-            if (remaining < threshold) {
-                /* This branch can be folded into the
-                 * threshold update condition because we
-                 * know that threshold > 1.
-                 */
-                if (remaining <= 1) break;
-                nbBits = BIT_highbit32(remaining) + 1;
-                threshold = 1 << (nbBits - 1);
-            }
-            if (charnum >= maxSV1) break;
-
-            if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
-                ip += bitCount>>3;
-                bitCount &= 7;
-            } else {
-                bitCount -= (int)(8 * (iend - 4 - ip));
-                bitCount &= 31;
-                ip = iend - 4;
-            }
-            bitStream = MEM_readLE32(ip) >> bitCount;
-    }   }
-    if (remaining != 1) return ERROR(corruption_detected);
-    /* Only possible when there are too many zeros. */
-    if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall);
-    if (bitCount > 32) return ERROR(corruption_detected);
-    *maxSVPtr = charnum-1;
-
-    ip += (bitCount+7)>>3;
-    return ip-istart;
-}
-
-/* Avoids the FORCE_INLINE of the _body() function. */
-static size_t FSE_readNCount_body_default(
-        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
-        const void* headerBuffer, size_t hbSize)
-{
-    return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
-}
-
-#if DYNAMIC_BMI2
-TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2(
-        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
-        const void* headerBuffer, size_t hbSize)
-{
-    return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
-}
-#endif
-
-size_t FSE_readNCount_bmi2(
-        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
-        const void* headerBuffer, size_t hbSize, int bmi2)
-{
-#if DYNAMIC_BMI2
-    if (bmi2) {
-        return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
-    }
-#endif
-    (void)bmi2;
-    return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
-}
-
-size_t FSE_readNCount(
-        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
-        const void* headerBuffer, size_t hbSize)
-{
-    return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0);
-}
-
-
-/*! HUF_readStats() :
-    Read compact Huffman tree, saved by HUF_writeCTable().
-    `huffWeight` is destination buffer.
-    `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
-    @return : size read from `src` , or an error Code .
-    Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
-*/
-size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
-                     U32* nbSymbolsPtr, U32* tableLogPtr,
-                     const void* src, size_t srcSize)
-{
-    U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
-    return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0);
-}
-
-FORCE_INLINE_TEMPLATE size_t
-HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,
-                   U32* nbSymbolsPtr, U32* tableLogPtr,
-                   const void* src, size_t srcSize,
-                   void* workSpace, size_t wkspSize,
-                   int bmi2)
-{
-    U32 weightTotal;
-    const BYTE* ip = (const BYTE*) src;
-    size_t iSize;
-    size_t oSize;
-
-    if (!srcSize) return ERROR(srcSize_wrong);
-    iSize = ip[0];
-    /* ZSTD_memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */
-
-    if (iSize >= 128) {  /* special header */
-        oSize = iSize - 127;
-        iSize = ((oSize+1)/2);
-        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
-        if (oSize >= hwSize) return ERROR(corruption_detected);
-        ip += 1;
-        {   U32 n;
-            for (n=0; n<oSize; n+=2) {
-                huffWeight[n]   = ip[n/2] >> 4;
-                huffWeight[n+1] = ip[n/2] & 15;
-    }   }   }
-    else  {   /* header compressed with FSE (normal case) */
-        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
-        /* max (hwSize-1) values decoded, as last one is implied */
-        oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2);
-        if (FSE_isError(oSize)) return oSize;
-    }
-
-    /* collect weight stats */
-    ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
-    weightTotal = 0;
-    {   U32 n; for (n=0; n<oSize; n++) {
-            if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected);
-            rankStats[huffWeight[n]]++;
-            weightTotal += (1 << huffWeight[n]) >> 1;
-    }   }
-    if (weightTotal == 0) return ERROR(corruption_detected);
-
-    /* get last non-null symbol weight (implied, total must be 2^n) */
-    {   U32 const tableLog = BIT_highbit32(weightTotal) + 1;
-        if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
-        *tableLogPtr = tableLog;
-        /* determine last weight */
-        {   U32 const total = 1 << tableLog;
-            U32 const rest = total - weightTotal;
-            U32 const verif = 1 << BIT_highbit32(rest);
-            U32 const lastWeight = BIT_highbit32(rest) + 1;
-            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */
-            huffWeight[oSize] = (BYTE)lastWeight;
-            rankStats[lastWeight]++;
-    }   }
-
-    /* check tree construction validity */
-    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */
-
-    /* results */
-    *nbSymbolsPtr = (U32)(oSize+1);
-    return iSize+1;
-}
-
-/* Avoids the FORCE_INLINE of the _body() function. */
-static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats,
-                     U32* nbSymbolsPtr, U32* tableLogPtr,
-                     const void* src, size_t srcSize,
-                     void* workSpace, size_t wkspSize)
-{
-    return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0);
-}
-
-#if DYNAMIC_BMI2
-static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
-                     U32* nbSymbolsPtr, U32* tableLogPtr,
-                     const void* src, size_t srcSize,
-                     void* workSpace, size_t wkspSize)
-{
-    return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1);
-}
-#endif
-
-size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,
-                     U32* nbSymbolsPtr, U32* tableLogPtr,
-                     const void* src, size_t srcSize,
-                     void* workSpace, size_t wkspSize,
-                     int bmi2)
-{
-#if DYNAMIC_BMI2
-    if (bmi2) {
-        return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
-    }
-#endif
-    (void)bmi2;
-    return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
-}
diff --git a/lib/zstd/common/error_private.c b/lib/zstd/common/error_private.c
deleted file mode 100644
index 6d1135f8c373..000000000000
--- a/lib/zstd/common/error_private.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-/* The purpose of this file is to have a single list of error strings embedded in binary */
-
-#include "error_private.h"
-
-const char* ERR_getErrorString(ERR_enum code)
-{
-#ifdef ZSTD_STRIP_ERROR_STRINGS
-    (void)code;
-    return "Error strings stripped";
-#else
-    static const char* const notErrorCode = "Unspecified error code";
-    switch( code )
-    {
-    case PREFIX(no_error): return "No error detected";
-    case PREFIX(GENERIC):  return "Error (generic)";
-    case PREFIX(prefix_unknown): return "Unknown frame descriptor";
-    case PREFIX(version_unsupported): return "Version not supported";
-    case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
-    case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding";
-    case PREFIX(corruption_detected): return "Corrupted block detected";
-    case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
-    case PREFIX(parameter_unsupported): return "Unsupported parameter";
-    case PREFIX(parameter_outOfBound): return "Parameter is out of bound";
-    case PREFIX(init_missing): return "Context should be init first";
-    case PREFIX(memory_allocation): return "Allocation error : not enough memory";
-    case PREFIX(workSpace_tooSmall): return "workSpace buffer is not large enough";
-    case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
-    case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
-    case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
-    case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
-    case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
-    case PREFIX(dictionary_wrong): return "Dictionary mismatch";
-    case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples";
-    case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
-    case PREFIX(srcSize_wrong): return "Src size is incorrect";
-    case PREFIX(dstBuffer_null): return "Operation on NULL destination buffer";
-        /* following error codes are not stable and may be removed or changed in a future version */
-    case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
-    case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
-    case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
-    case PREFIX(srcBuffer_wrong): return "Source buffer is wrong";
-    case PREFIX(maxCode):
-    default: return notErrorCode;
-    }
-#endif
-}
diff --git a/lib/zstd/common/error_private.h b/lib/zstd/common/error_private.h
deleted file mode 100644
index bb60835cac30..000000000000
--- a/lib/zstd/common/error_private.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-/* Note : this module is expected to remain private, do not expose it */
-
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-#ifdef __PBL__
-#define ZSTD_STRIP_ERROR_STRINGS
-#endif
-
-
-/* ****************************************
-*  Dependencies
-******************************************/
-#include "zstd_deps.h"    /* size_t */
-#include <linux/zstd_errors.h>  /* enum list */
-
-
-/* ****************************************
-*  Compiler-specific
-******************************************/
-#define ERR_STATIC static __attribute__((unused))
-
-
-/*-****************************************
-*  Customization (error_public.h)
-******************************************/
-typedef ZSTD_ErrorCode ERR_enum;
-#define PREFIX(name) ZSTD_error_##name
-
-
-/*-****************************************
-*  Error codes handling
-******************************************/
-#undef ERROR   /* already defined on Visual Studio */
-#define ERROR(name) ZSTD_ERROR(name)
-#define ZSTD_ERROR(name) ((size_t)-PREFIX(name))
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
-
-/* check and forward error code */
-#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
-#define CHECK_F(f)   { CHECK_V_F(_var_err__, f); }
-
-
-/*-****************************************
-*  Error Strings
-******************************************/
-
-const char* ERR_getErrorString(ERR_enum code);   /* error_private.c */
-
-ERR_STATIC const char* ERR_getErrorName(size_t code)
-{
-    return ERR_getErrorString(ERR_getErrorCode(code));
-}
-
-
-#endif /* ERROR_H_MODULE */
diff --git a/lib/zstd/common/fse.h b/lib/zstd/common/fse.h
deleted file mode 100644
index 0bb174c2c367..000000000000
--- a/lib/zstd/common/fse.h
+++ /dev/null
@@ -1,710 +0,0 @@
-/* ******************************************************************
- * FSE : Finite State Entropy codec
- * Public Prototypes declaration
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-
-
-#ifndef FSE_H
-#define FSE_H
-
-
-/*-*****************************************
-*  Dependencies
-******************************************/
-#include "zstd_deps.h"    /* size_t, ptrdiff_t */
-
-
-/*-*****************************************
-*  FSE_PUBLIC_API : control library symbols visibility
-******************************************/
-#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
-#  define FSE_PUBLIC_API __attribute__ ((visibility ("default")))
-#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1)   /* Visual expected */
-#  define FSE_PUBLIC_API __declspec(dllexport)
-#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
-#  define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
-#else
-#  define FSE_PUBLIC_API
-#endif
-
-/*------   Version   ------*/
-#define FSE_VERSION_MAJOR    0
-#define FSE_VERSION_MINOR    9
-#define FSE_VERSION_RELEASE  0
-
-#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
-#define FSE_QUOTE(str) #str
-#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
-#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
-
-#define FSE_VERSION_NUMBER  (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)
-FSE_PUBLIC_API unsigned FSE_versionNumber(void);   /*< library version number; to be used when checking dll version */
-
-
-/*-****************************************
-*  FSE simple functions
-******************************************/
-/*! FSE_compress() :
-    Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
-    'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize).
-    @return : size of compressed data (<= dstCapacity).
-    Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
-                     if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.
-                     if FSE_isError(return), compression failed (more details using FSE_getErrorName())
-*/
-FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity,
-                             const void* src, size_t srcSize);
-
-/*! FSE_decompress():
-    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
-    into already allocated destination buffer 'dst', of size 'dstCapacity'.
-    @return : size of regenerated data (<= maxDstSize),
-              or an error code, which can be tested using FSE_isError() .
-
-    ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!!
-    Why ? : making this distinction requires a header.
-    Header management is intentionally delegated to the user layer, which can better manage special cases.
-*/
-FSE_PUBLIC_API size_t FSE_decompress(void* dst,  size_t dstCapacity,
-                               const void* cSrc, size_t cSrcSize);
-
-
-/*-*****************************************
-*  Tool functions
-******************************************/
-FSE_PUBLIC_API size_t FSE_compressBound(size_t size);       /* maximum compressed size */
-
-/* Error Management */
-FSE_PUBLIC_API unsigned    FSE_isError(size_t code);        /* tells if a return value is an error code */
-FSE_PUBLIC_API const char* FSE_getErrorName(size_t code);   /* provides error code string (useful for debugging) */
-
-
-/*-*****************************************
-*  FSE advanced functions
-******************************************/
-/*! FSE_compress2() :
-    Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'
-    Both parameters can be defined as '0' to mean : use default value
-    @return : size of compressed data
-    Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!
-                     if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
-                     if FSE_isError(return), it's an error code.
-*/
-FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
-
-
-/*-*****************************************
-*  FSE detailed API
-******************************************/
-/*!
-FSE_compress() does the following:
-1. count symbol occurrence from source[] into table count[] (see hist.h)
-2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
-3. save normalized counters to memory buffer using writeNCount()
-4. build encoding table 'CTable' from normalized counters
-5. encode the data stream using encoding table 'CTable'
-
-FSE_decompress() does the following:
-1. read normalized counters with readNCount()
-2. build decoding table 'DTable' from normalized counters
-3. decode the data stream using decoding table 'DTable'
-
-The following API allows targeting specific sub-functions for advanced tasks.
-For example, it's possible to compress several blocks using the same 'CTable',
-or to save and provide normalized distribution using external method.
-*/
-
-/* *** COMPRESSION *** */
-
-/*! FSE_optimalTableLog():
-    dynamically downsize 'tableLog' when conditions are met.
-    It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
-    @return : recommended tableLog (necessarily <= 'maxTableLog') */
-FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
-
-/*! FSE_normalizeCount():
-    normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
-    'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
-    useLowProbCount is a boolean parameter which trades off compressed size for
-    faster header decoding. When it is set to 1, the compressed data will be slightly
-    smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be
-    faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0
-    is a good default, since header deserialization makes a big speed difference.
-    Otherwise, useLowProbCount=1 is a good default, since the speed difference is small.
-    @return : tableLog,
-              or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,
-                    const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);
-
-/*! FSE_NCountWriteBound():
-    Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
-    Typically useful for allocation purpose. */
-FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
-
-/*! FSE_writeNCount():
-    Compactly save 'normalizedCounter' into 'buffer'.
-    @return : size of the compressed table,
-              or an errorCode, which can be tested using FSE_isError(). */
-FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,
-                                 const short* normalizedCounter,
-                                 unsigned maxSymbolValue, unsigned tableLog);
-
-/*! Constructor and Destructor of FSE_CTable.
-    Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
-typedef unsigned FSE_CTable;   /* don't allocate that. It's only meant to be more restrictive than void* */
-FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog);
-FSE_PUBLIC_API void        FSE_freeCTable (FSE_CTable* ct);
-
-/*! FSE_buildCTable():
-    Builds `ct`, which must be already allocated, using FSE_createCTable().
-    @return : 0, or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
-
-/*! FSE_compress_usingCTable():
-    Compress `src` using `ct` into `dst` which must be already allocated.
-    @return : size of compressed data (<= `dstCapacity`),
-              or 0 if compressed data could not fit into `dst`,
-              or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);
-
-/*!
-Tutorial :
-----------
-The first step is to count all symbols. FSE_count() does this job very fast.
-Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
-'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
-maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
-FSE_count() will return the number of occurrence of the most frequent symbol.
-This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
-If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
-
-The next step is to normalize the frequencies.
-FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
-It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
-You can use 'tableLog'==0 to mean "use default tableLog value".
-If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
-which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
-
-The result of FSE_normalizeCount() will be saved into a table,
-called 'normalizedCounter', which is a table of signed short.
-'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
-The return value is tableLog if everything proceeded as expected.
-It is 0 if there is a single symbol within distribution.
-If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
-
-'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
-'buffer' must be already allocated.
-For guaranteed success, buffer size must be at least FSE_headerBound().
-The result of the function is the number of bytes written into 'buffer'.
-If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
-
-'normalizedCounter' can then be used to create the compression table 'CTable'.
-The space required by 'CTable' must be already allocated, using FSE_createCTable().
-You can then use FSE_buildCTable() to fill 'CTable'.
-If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
-
-'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
-Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
-The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
-If it returns '0', compressed data could not fit into 'dst'.
-If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
-*/
-
-
-/* *** DECOMPRESSION *** */
-
-/*! FSE_readNCount():
-    Read compactly saved 'normalizedCounter' from 'rBuffer'.
-    @return : size read from 'rBuffer',
-              or an errorCode, which can be tested using FSE_isError().
-              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
-FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,
-                           unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
-                           const void* rBuffer, size_t rBuffSize);
-
-/*! FSE_readNCount_bmi2():
- * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise.
- */
-FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,
-                           unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
-                           const void* rBuffer, size_t rBuffSize, int bmi2);
-
-/*! Constructor and Destructor of FSE_DTable.
-    Note that its size depends on 'tableLog' */
-typedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */
-FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog);
-FSE_PUBLIC_API void        FSE_freeDTable(FSE_DTable* dt);
-
-/*! FSE_buildDTable():
-    Builds 'dt', which must be already allocated, using FSE_createDTable().
-    return : 0, or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
-
-/*! FSE_decompress_usingDTable():
-    Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
-    into `dst` which must be already allocated.
-    @return : size of regenerated data (necessarily <= `dstCapacity`),
-              or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);
-
-/*!
-Tutorial :
-----------
-(Note : these functions only decompress FSE-compressed blocks.
- If block is uncompressed, use memcpy() instead
- If block is a single repeated byte, use memset() instead )
-
-The first step is to obtain the normalized frequencies of symbols.
-This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
-'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
-In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
-or size the table to handle worst case situations (typically 256).
-FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
-The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
-Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
-If there is an error, the function will return an error code, which can be tested using FSE_isError().
-
-The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
-This is performed by the function FSE_buildDTable().
-The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
-If there is an error, the function will return an error code, which can be tested using FSE_isError().
-
-`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().
-`cSrcSize` must be strictly correct, otherwise decompression will fail.
-FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
-If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
-*/
-
-#endif  /* FSE_H */
-
-#if !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
-#define FSE_H_FSE_STATIC_LINKING_ONLY
-
-/* *** Dependency *** */
-#include "bitstream.h"
-
-
-/* *****************************************
-*  Static allocation
-*******************************************/
-/* FSE buffer bounds */
-#define FSE_NCOUNTBOUND 512
-#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)
-#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */
-
-/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
-#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))
-#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<(maxTableLog)))
-
-/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */
-#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue)   (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))
-#define FSE_DTABLE_SIZE(maxTableLog)                   (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))
-
-
-/* *****************************************
- *  FSE advanced API
- ***************************************** */
-
-unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
-/*< same as FSE_optimalTableLog(), which used `minus==2` */
-
-/* FSE_compress_wksp() :
- * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
- * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
- */
-#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue)   ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
-size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
-
-size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
-/*< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
-
-size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
-/*< build a fake FSE_CTable, designed to compress always the same symbolValue */
-
-/* FSE_buildCTable_wksp() :
- * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
- * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.
- */
-#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (maxSymbolValue + 2 + (1ull << (tableLog - 2)))
-#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))
-size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
-
-#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)
-#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))
-FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
-/*< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */
-
-size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
-/*< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
-
-size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
-/*< build a fake FSE_DTable, designed to always generate the same symbolValue */
-
-#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)
-#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
-size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize);
-/*< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */
-
-size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);
-/*< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */
-
-typedef enum {
-   FSE_repeat_none,  /*< Cannot use the previous table */
-   FSE_repeat_check, /*< Can use the previous table but it must be checked */
-   FSE_repeat_valid  /*< Can use the previous table and it is assumed to be valid */
- } FSE_repeat;
-
-/* *****************************************
-*  FSE symbol compression API
-*******************************************/
-/*!
-   This API consists of small unitary functions, which highly benefit from being inlined.
-   Hence their body are included in next section.
-*/
-typedef struct {
-    ptrdiff_t   value;
-    const void* stateTable;
-    const void* symbolTT;
-    unsigned    stateLog;
-} FSE_CState_t;
-
-static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);
-
-static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);
-
-static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);
-
-/*<
-These functions are inner components of FSE_compress_usingCTable().
-They allow the creation of custom streams, mixing multiple tables and bit sources.
-
-A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
-So the first symbol you will encode is the last you will decode, like a LIFO stack.
-
-You will need a few variables to track your CStream. They are :
-
-FSE_CTable    ct;         // Provided by FSE_buildCTable()
-BIT_CStream_t bitStream;  // bitStream tracking structure
-FSE_CState_t  state;      // State tracking structure (can have several)
-
-
-The first thing to do is to init bitStream and state.
-    size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
-    FSE_initCState(&state, ct);
-
-Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
-You can then encode your input data, byte after byte.
-FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
-Remember decoding will be done in reverse direction.
-    FSE_encodeByte(&bitStream, &state, symbol);
-
-At any time, you can also add any bit sequence.
-Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
-    BIT_addBits(&bitStream, bitField, nbBits);
-
-The above methods don't commit data to memory, they just store it into local register, for speed.
-Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
-Writing data to memory is a manual operation, performed by the flushBits function.
-    BIT_flushBits(&bitStream);
-
-Your last FSE encoding operation shall be to flush your last state value(s).
-    FSE_flushState(&bitStream, &state);
-
-Finally, you must close the bitStream.
-The function returns the size of CStream in bytes.
-If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
-If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
-    size_t size = BIT_closeCStream(&bitStream);
-*/
-
-
-/* *****************************************
-*  FSE symbol decompression API
-*******************************************/
-typedef struct {
-    size_t      state;
-    const void* table;   /* precise table may vary, depending on U16 */
-} FSE_DState_t;
-
-
-static void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);
-
-static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
-
-static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
-
-/*<
-Let's now decompose FSE_decompress_usingDTable() into its unitary components.
-You will decode FSE-encoded symbols from the bitStream,
-and also any other bitFields you put in, **in reverse order**.
-
-You will need a few variables to track your bitStream. They are :
-
-BIT_DStream_t DStream;    // Stream context
-FSE_DState_t  DState;     // State context. Multiple ones are possible
-FSE_DTable*   DTablePtr;  // Decoding table, provided by FSE_buildDTable()
-
-The first thing to do is to init the bitStream.
-    errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
-
-You should then retrieve your initial state(s)
-(in reverse flushing order if you have several ones) :
-    errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
-
-You can then decode your data, symbol after symbol.
-For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
-Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
-    unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
-
-You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
-Note : maximum allowed nbBits is 25, for 32-bits compatibility
-    size_t bitField = BIT_readBits(&DStream, nbBits);
-
-All above operations only read from local register (which size depends on size_t).
-Refueling the register from memory is manually performed by the reload method.
-    endSignal = FSE_reloadDStream(&DStream);
-
-BIT_reloadDStream() result tells if there is still some more data to read from DStream.
-BIT_DStream_unfinished : there is still some data left into the DStream.
-BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
-BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
-BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
-
-When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
-to properly detect the exact end of stream.
-After each decoded symbol, check if DStream is fully consumed using this simple test :
-    BIT_reloadDStream(&DStream) >= BIT_DStream_completed
-
-When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
-Checking if DStream has reached its end is performed by :
-    BIT_endOfDStream(&DStream);
-Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
-    FSE_endOfDState(&DState);
-*/
-
-
-/* *****************************************
-*  FSE unsafe API
-*******************************************/
-static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
-/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
-
-
-/* *****************************************
-*  Implementation of inlined functions
-*******************************************/
-typedef struct {
-    int deltaFindState;
-    U32 deltaNbBits;
-} FSE_symbolCompressionTransform; /* total 8 bytes */
-
-MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)
-{
-    const void* ptr = ct;
-    const U16* u16ptr = (const U16*) ptr;
-    const U32 tableLog = MEM_read16(ptr);
-    statePtr->value = (ptrdiff_t)1<<tableLog;
-    statePtr->stateTable = u16ptr+2;
-    statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);
-    statePtr->stateLog = tableLog;
-}
-
-
-/*! FSE_initCState2() :
-*   Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
-*   uses the smallest state value possible, saving the cost of this symbol */
-MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)
-{
-    FSE_initCState(statePtr, ct);
-    {   const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
-        const U16* stateTable = (const U16*)(statePtr->stateTable);
-        U32 nbBitsOut  = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);
-        statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
-        statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
-    }
-}
-
-MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)
-{
-    FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
-    const U16* const stateTable = (const U16*)(statePtr->stateTable);
-    U32 const nbBitsOut  = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
-    BIT_addBits(bitC, statePtr->value, nbBitsOut);
-    statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
-}
-
-MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)
-{
-    BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
-    BIT_flushBits(bitC);
-}
-
-
-/* FSE_getMaxNbBits() :
- * Approximate maximum cost of a symbol, in bits.
- * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)
- * note 1 : assume symbolValue is valid (<= maxSymbolValue)
- * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
-MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)
-{
-    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
-    return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;
-}
-
-/* FSE_bitCost() :
- * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)
- * note 1 : assume symbolValue is valid (<= maxSymbolValue)
- * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
-MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)
-{
-    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
-    U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;
-    U32 const threshold = (minNbBits+1) << 16;
-    assert(tableLog < 16);
-    assert(accuracyLog < 31-tableLog);  /* ensure enough room for renormalization double shift */
-    {   U32 const tableSize = 1 << tableLog;
-        U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);
-        U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog;   /* linear interpolation (very approximate) */
-        U32 const bitMultiplier = 1 << accuracyLog;
-        assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);
-        assert(normalizedDeltaFromThreshold <= bitMultiplier);
-        return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;
-    }
-}
-
-
-/* ======    Decompression    ====== */
-
-typedef struct {
-    U16 tableLog;
-    U16 fastMode;
-} FSE_DTableHeader;   /* sizeof U32 */
-
-typedef struct
-{
-    unsigned short newState;
-    unsigned char  symbol;
-    unsigned char  nbBits;
-} FSE_decode_t;   /* size == U32 */
-
-MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)
-{
-    const void* ptr = dt;
-    const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;
-    DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
-    BIT_reloadDStream(bitD);
-    DStatePtr->table = dt + 1;
-}
-
-MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)
-{
-    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
-    return DInfo.symbol;
-}
-
-MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
-{
-    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
-    U32 const nbBits = DInfo.nbBits;
-    size_t const lowBits = BIT_readBits(bitD, nbBits);
-    DStatePtr->state = DInfo.newState + lowBits;
-}
-
-MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
-{
-    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
-    U32 const nbBits = DInfo.nbBits;
-    BYTE const symbol = DInfo.symbol;
-    size_t const lowBits = BIT_readBits(bitD, nbBits);
-
-    DStatePtr->state = DInfo.newState + lowBits;
-    return symbol;
-}
-
-/*! FSE_decodeSymbolFast() :
-    unsafe, only works if no symbol has a probability > 50% */
-MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
-{
-    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
-    U32 const nbBits = DInfo.nbBits;
-    BYTE const symbol = DInfo.symbol;
-    size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
-
-    DStatePtr->state = DInfo.newState + lowBits;
-    return symbol;
-}
-
-MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
-{
-    return DStatePtr->state == 0;
-}
-
-
-
-#ifndef FSE_COMMONDEFS_ONLY
-
-/* **************************************************************
-*  Tuning parameters
-****************************************************************/
-/*!MEMORY_USAGE :
-*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
-*  Increasing memory usage improves compression ratio
-*  Reduced memory usage can improve speed, due to cache effect
-*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
-#ifndef FSE_MAX_MEMORY_USAGE
-#  define FSE_MAX_MEMORY_USAGE 14
-#endif
-#ifndef FSE_DEFAULT_MEMORY_USAGE
-#  define FSE_DEFAULT_MEMORY_USAGE 13
-#endif
-#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)
-#  error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE"
-#endif
-
-/*!FSE_MAX_SYMBOL_VALUE :
-*  Maximum symbol value authorized.
-*  Required for proper stack allocation */
-#ifndef FSE_MAX_SYMBOL_VALUE
-#  define FSE_MAX_SYMBOL_VALUE 255
-#endif
-
-/* **************************************************************
-*  template functions type & suffix
-****************************************************************/
-#define FSE_FUNCTION_TYPE BYTE
-#define FSE_FUNCTION_EXTENSION
-#define FSE_DECODE_TYPE FSE_decode_t
-
-
-#endif   /* !FSE_COMMONDEFS_ONLY */
-
-
-/* ***************************************************************
-*  Constants
-*****************************************************************/
-#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)
-#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
-#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
-#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
-#define FSE_MIN_TABLELOG 5
-
-#define FSE_TABLELOG_ABSOLUTE_MAX 15
-#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
-#  error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
-#endif
-
-#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
-
-
-#endif /* FSE_STATIC_LINKING_ONLY */
-
-
diff --git a/lib/zstd/common/fse_decompress.c b/lib/zstd/common/fse_decompress.c
deleted file mode 100644
index 2c8bbe3e4c14..000000000000
--- a/lib/zstd/common/fse_decompress.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/* ******************************************************************
- * FSE : Finite State Entropy decoder
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- *  You can contact the author at :
- *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *  - Public forum : https://groups.google.com/forum/#!forum/lz4c
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-
-
-/* **************************************************************
-*  Includes
-****************************************************************/
-#include "debug.h"      /* assert */
-#include "bitstream.h"
-#include "compiler.h"
-#define FSE_STATIC_LINKING_ONLY
-#include "fse.h"
-#include "error_private.h"
-#define ZSTD_DEPS_NEED_MALLOC
-#include "zstd_deps.h"
-
-
-/* **************************************************************
-*  Error Management
-****************************************************************/
-#define FSE_isError ERR_isError
-#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)   /* use only *after* variable declarations */
-
-
-/* **************************************************************
-*  Templates
-****************************************************************/
-/*
-  designed to be included
-  for type-specific functions (template emulation in C)
-  Objective is to write these functions only once, for improved maintenance
-*/
-
-/* safety checks */
-#ifndef FSE_FUNCTION_EXTENSION
-#  error "FSE_FUNCTION_EXTENSION must be defined"
-#endif
-#ifndef FSE_FUNCTION_TYPE
-#  error "FSE_FUNCTION_TYPE must be defined"
-#endif
-
-/* Function names */
-#define FSE_CAT(X,Y) X##Y
-#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
-#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
-
-
-/* Function templates */
-FSE_DTable* FSE_createDTable (unsigned tableLog)
-{
-    if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
-    return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
-}
-
-void FSE_freeDTable (FSE_DTable* dt)
-{
-    ZSTD_free(dt);
-}
-
-static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
-{
-    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */
-    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);
-    U16* symbolNext = (U16*)workSpace;
-    BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1);
-
-    U32 const maxSV1 = maxSymbolValue + 1;
-    U32 const tableSize = 1 << tableLog;
-    U32 highThreshold = tableSize-1;
-
-    /* Sanity Checks */
-    if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge);
-    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
-    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
-
-    /* Init, lay down lowprob symbols */
-    {   FSE_DTableHeader DTableH;
-        DTableH.tableLog = (U16)tableLog;
-        DTableH.fastMode = 1;
-        {   S16 const largeLimit= (S16)(1 << (tableLog-1));
-            U32 s;
-            for (s=0; s<maxSV1; s++) {
-                if (normalizedCounter[s]==-1) {
-                    tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
-                    symbolNext[s] = 1;
-                } else {
-                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
-                    symbolNext[s] = normalizedCounter[s];
-        }   }   }
-        ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
-    }
-
-    /* Spread symbols */
-    if (highThreshold == tableSize - 1) {
-        size_t const tableMask = tableSize-1;
-        size_t const step = FSE_TABLESTEP(tableSize);
-        /* First lay down the symbols in order.
-         * We use a uint64_t to lay down 8 bytes at a time. This reduces branch
-         * misses since small blocks generally have small table logs, so nearly
-         * all symbols have counts <= 8. We ensure we have 8 bytes at the end of
-         * our buffer to handle the over-write.
-         */
-        {
-            U64 const add = 0x0101010101010101ull;
-            size_t pos = 0;
-            U64 sv = 0;
-            U32 s;
-            for (s=0; s<maxSV1; ++s, sv += add) {
-                int i;
-                int const n = normalizedCounter[s];
-                MEM_write64(spread + pos, sv);
-                for (i = 8; i < n; i += 8) {
-                    MEM_write64(spread + pos + i, sv);
-                }
-                pos += n;
-            }
-        }
-        /* Now we spread those positions across the table.
-         * The benefit of doing it in two stages is that we avoid the the
-         * variable size inner loop, which caused lots of branch misses.
-         * Now we can run through all the positions without any branch misses.
-         * We unroll the loop twice, since that is what emperically worked best.
-         */
-        {
-            size_t position = 0;
-            size_t s;
-            size_t const unroll = 2;
-            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
-            for (s = 0; s < (size_t)tableSize; s += unroll) {
-                size_t u;
-                for (u = 0; u < unroll; ++u) {
-                    size_t const uPosition = (position + (u * step)) & tableMask;
-                    tableDecode[uPosition].symbol = spread[s + u];
-                }
-                position = (position + (unroll * step)) & tableMask;
-            }
-            assert(position == 0);
-        }
-    } else {
-        U32 const tableMask = tableSize-1;
-        U32 const step = FSE_TABLESTEP(tableSize);
-        U32 s, position = 0;
-        for (s=0; s<maxSV1; s++) {
-            int i;
-            for (i=0; i<normalizedCounter[s]; i++) {
-                tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
-                position = (position + step) & tableMask;
-                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */
-        }   }
-        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */
-    }
-
-    /* Build Decoding table */
-    {   U32 u;
-        for (u=0; u<tableSize; u++) {
-            FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
-            U32 const nextState = symbolNext[symbol]++;
-            tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
-            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
-    }   }
-
-    return 0;
-}
-
-size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
-{
-    return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize);
-}
-
-
-#ifndef FSE_COMMONDEFS_ONLY
-
-/*-*******************************************************
-*  Decompression (Byte symbols)
-*********************************************************/
-size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
-{
-    void* ptr = dt;
-    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
-    void* dPtr = dt + 1;
-    FSE_decode_t* const cell = (FSE_decode_t*)dPtr;
-
-    DTableH->tableLog = 0;
-    DTableH->fastMode = 0;
-
-    cell->newState = 0;
-    cell->symbol = symbolValue;
-    cell->nbBits = 0;
-
-    return 0;
-}
-
-
-size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
-{
-    void* ptr = dt;
-    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
-    void* dPtr = dt + 1;
-    FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;
-    const unsigned tableSize = 1 << nbBits;
-    const unsigned tableMask = tableSize - 1;
-    const unsigned maxSV1 = tableMask+1;
-    unsigned s;
-
-    /* Sanity checks */
-    if (nbBits < 1) return ERROR(GENERIC);         /* min size */
-
-    /* Build Decoding Table */
-    DTableH->tableLog = (U16)nbBits;
-    DTableH->fastMode = 1;
-    for (s=0; s<maxSV1; s++) {
-        dinfo[s].newState = 0;
-        dinfo[s].symbol = (BYTE)s;
-        dinfo[s].nbBits = (BYTE)nbBits;
-    }
-
-    return 0;
-}
-
-FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(
-          void* dst, size_t maxDstSize,
-    const void* cSrc, size_t cSrcSize,
-    const FSE_DTable* dt, const unsigned fast)
-{
-    BYTE* const ostart = (BYTE*) dst;
-    BYTE* op = ostart;
-    BYTE* const omax = op + maxDstSize;
-    BYTE* const olimit = omax-3;
-
-    BIT_DStream_t bitD;
-    FSE_DState_t state1;
-    FSE_DState_t state2;
-
-    /* Init */
-    CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));
-
-    FSE_initDState(&state1, &bitD, dt);
-    FSE_initDState(&state2, &bitD, dt);
-
-#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
-
-    /* 4 symbols per loop */
-    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) {
-        op[0] = FSE_GETSYMBOL(&state1);
-
-        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
-            BIT_reloadDStream(&bitD);
-
-        op[1] = FSE_GETSYMBOL(&state2);
-
-        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
-            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }
-
-        op[2] = FSE_GETSYMBOL(&state1);
-
-        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */
-            BIT_reloadDStream(&bitD);
-
-        op[3] = FSE_GETSYMBOL(&state2);
-    }
-
-    /* tail */
-    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
-    while (1) {
-        if (op>(omax-2)) return ERROR(dstSize_tooSmall);
-        *op++ = FSE_GETSYMBOL(&state1);
-        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
-            *op++ = FSE_GETSYMBOL(&state2);
-            break;
-        }
-
-        if (op>(omax-2)) return ERROR(dstSize_tooSmall);
-        *op++ = FSE_GETSYMBOL(&state2);
-        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
-            *op++ = FSE_GETSYMBOL(&state1);
-            break;
-    }   }
-
-    return op-ostart;
-}
-
-
-size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
-                            const void* cSrc, size_t cSrcSize,
-                            const FSE_DTable* dt)
-{
-    const void* ptr = dt;
-    const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
-    const U32 fastMode = DTableH->fastMode;
-
-    /* select fast mode (static) */
-    if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
-    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
-}
-
-
-size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
-{
-    return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0);
-}
-
-typedef struct {
-    short ncount[FSE_MAX_SYMBOL_VALUE + 1];
-    FSE_DTable dtable[1]; /* Dynamically sized */
-} FSE_DecompressWksp;
-
-
-FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
-        void* dst, size_t dstCapacity,
-        const void* cSrc, size_t cSrcSize,
-        unsigned maxLog, void* workSpace, size_t wkspSize,
-        int bmi2)
-{
-    const BYTE* const istart = (const BYTE*)cSrc;
-    const BYTE* ip = istart;
-    unsigned tableLog;
-    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
-    FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;
-
-    DEBUG_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);
-    if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);
-
-    /* normal FSE decoding mode */
-    {
-        size_t const NCountLength = FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
-        if (FSE_isError(NCountLength)) return NCountLength;
-        if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
-        assert(NCountLength <= cSrcSize);
-        ip += NCountLength;
-        cSrcSize -= NCountLength;
-    }
-
-    if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);
-    workSpace = wksp->dtable + FSE_DTABLE_SIZE_U32(tableLog);
-    wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
-
-    CHECK_F( FSE_buildDTable_internal(wksp->dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );
-
-    {
-        const void* ptr = wksp->dtable;
-        const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
-        const U32 fastMode = DTableH->fastMode;
-
-        /* select fast mode (static) */
-        if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 1);
-        return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 0);
-    }
-}
-
-/* Avoids the FORCE_INLINE of the _body() function. */
-static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
-{
-    return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0);
-}
-
-#if DYNAMIC_BMI2
-TARGET_ATTRIBUTE("bmi2") static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
-{
-    return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);
-}
-#endif
-
-size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2)
-{
-#if DYNAMIC_BMI2
-    if (bmi2) {
-        return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
-    }
-#endif
-    (void)bmi2;
-    return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
-}
-
-
-typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
-
-
-
-#endif   /* FSE_COMMONDEFS_ONLY */
diff --git a/lib/zstd/common/huf.h b/lib/zstd/common/huf.h
deleted file mode 100644
index 88c5586646aa..000000000000
--- a/lib/zstd/common/huf.h
+++ /dev/null
@@ -1,356 +0,0 @@
-/* ******************************************************************
- * huff0 huffman codec,
- * part of Finite State Entropy library
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-
-
-#ifndef HUF_H_298734234
-#define HUF_H_298734234
-
-/* *** Dependencies *** */
-#include "zstd_deps.h"    /* size_t */
-
-
-/* *** library symbols visibility *** */
-/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual,
- *        HUF symbols remain "private" (internal symbols for library only).
- *        Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */
-#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
-#  define HUF_PUBLIC_API __attribute__ ((visibility ("default")))
-#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1)   /* Visual expected */
-#  define HUF_PUBLIC_API __declspec(dllexport)
-#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
-#  define HUF_PUBLIC_API __declspec(dllimport)  /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */
-#else
-#  define HUF_PUBLIC_API
-#endif
-
-
-/* ========================== */
-/* ***  simple functions  *** */
-/* ========================== */
-
-/* HUF_compress() :
- *  Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.
- * 'dst' buffer must be already allocated.
- *  Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize).
- * `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB.
- * @return : size of compressed data (<= `dstCapacity`).
- *  Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
- *                   if HUF_isError(return), compression failed (more details using HUF_getErrorName())
- */
-HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,
-                             const void* src, size_t srcSize);
-
-/* HUF_decompress() :
- *  Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
- *  into already allocated buffer 'dst', of minimum size 'dstSize'.
- * `originalSize` : **must** be the ***exact*** size of original (uncompressed) data.
- *  Note : in contrast with FSE, HUF_decompress can regenerate
- *         RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
- *         because it knows size to regenerate (originalSize).
- * @return : size of regenerated data (== originalSize),
- *           or an error code, which can be tested using HUF_isError()
- */
-HUF_PUBLIC_API size_t HUF_decompress(void* dst,  size_t originalSize,
-                               const void* cSrc, size_t cSrcSize);
-
-
-/* ***   Tool functions *** */
-#define HUF_BLOCKSIZE_MAX (128 * 1024)                  /*< maximum input size for a single block compressed with HUF_compress */
-HUF_PUBLIC_API size_t HUF_compressBound(size_t size);   /*< maximum compressed size (worst case) */
-
-/* Error Management */
-HUF_PUBLIC_API unsigned    HUF_isError(size_t code);       /*< tells if a return value is an error code */
-HUF_PUBLIC_API const char* HUF_getErrorName(size_t code);  /*< provides error code string (useful for debugging) */
-
-
-/* ***   Advanced function   *** */
-
-/* HUF_compress2() :
- *  Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`.
- * `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX .
- * `tableLog` must be `<= HUF_TABLELOG_MAX` . */
-HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity,
-                               const void* src, size_t srcSize,
-                               unsigned maxSymbolValue, unsigned tableLog);
-
-/* HUF_compress4X_wksp() :
- *  Same as HUF_compress2(), but uses externally allocated `workSpace`.
- * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */
-#define HUF_WORKSPACE_SIZE ((6 << 10) + 256)
-#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))
-HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
-                                     const void* src, size_t srcSize,
-                                     unsigned maxSymbolValue, unsigned tableLog,
-                                     void* workSpace, size_t wkspSize);
-
-#endif   /* HUF_H_298734234 */
-
-/* ******************************************************************
- *  WARNING !!
- *  The following section contains advanced and experimental definitions
- *  which shall never be used in the context of a dynamic library,
- *  because they are not guaranteed to remain stable in the future.
- *  Only consider them in association with static linking.
- * *****************************************************************/
-#if !defined(HUF_H_HUF_STATIC_LINKING_ONLY)
-#define HUF_H_HUF_STATIC_LINKING_ONLY
-
-/* *** Dependencies *** */
-#include "mem.h"   /* U32 */
-#define FSE_STATIC_LINKING_ONLY
-#include "fse.h"
-
-
-/* *** Constants *** */
-#define HUF_TABLELOG_MAX      12      /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
-#define HUF_TABLELOG_DEFAULT  11      /* default tableLog value when none specified */
-#define HUF_SYMBOLVALUE_MAX  255
-
-#define HUF_TABLELOG_ABSOLUTEMAX  15  /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
-#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
-#  error "HUF_TABLELOG_MAX is too large !"
-#endif
-
-
-/* ****************************************
-*  Static allocation
-******************************************/
-/* HUF buffer bounds */
-#define HUF_CTABLEBOUND 129
-#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true when incompressible is pre-filtered with fast heuristic */
-#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */
-
-/* static allocation of HUF's Compression Table */
-/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */
-struct HUF_CElt_s {
-  U16  val;
-  BYTE nbBits;
-};   /* typedef'd to HUF_CElt */
-typedef struct HUF_CElt_s HUF_CElt;   /* consider it an incomplete type */
-#define HUF_CTABLE_SIZE_U32(maxSymbolValue)   ((maxSymbolValue)+1)   /* Use tables of U32, for proper alignment */
-#define HUF_CTABLE_SIZE(maxSymbolValue)       (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32))
-#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
-    HUF_CElt name[HUF_CTABLE_SIZE_U32(maxSymbolValue)] /* no final ; */
-
-/* static allocation of HUF's DTable */
-typedef U32 HUF_DTable;
-#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<(maxTableLog)))
-#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \
-        HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) }
-#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
-        HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }
-
-
-/* ****************************************
-*  Advanced decompression functions
-******************************************/
-size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /*< single-symbol decoder */
-#ifndef HUF_FORCE_DECOMPRESS_X1
-size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /*< double-symbols decoder */
-#endif
-
-size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /*< decodes RLE and uncompressed */
-size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< considers RLE and uncompressed as errors */
-size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /*< considers RLE and uncompressed as errors */
-size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /*< single-symbol decoder */
-size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /*< single-symbol decoder */
-#ifndef HUF_FORCE_DECOMPRESS_X1
-size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /*< double-symbols decoder */
-size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /*< double-symbols decoder */
-#endif
-
-
-/* ****************************************
- *  HUF detailed API
- * ****************************************/
-
-/*! HUF_compress() does the following:
- *  1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h")
- *  2. (optional) refine tableLog using HUF_optimalTableLog()
- *  3. build Huffman table from count using HUF_buildCTable()
- *  4. save Huffman table to memory buffer using HUF_writeCTable()
- *  5. encode the data stream using HUF_compress4X_usingCTable()
- *
- *  The following API allows targeting specific sub-functions for advanced tasks.
- *  For example, it's possible to compress several blocks using the same 'CTable',
- *  or to save and regenerate 'CTable' using external methods.
- */
-unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
-size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits);   /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
-size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
-size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);
-size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
-size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
-int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
-
-typedef enum {
-   HUF_repeat_none,  /*< Cannot use the previous table */
-   HUF_repeat_check, /*< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */
-   HUF_repeat_valid  /*< Can use the previous table and it is assumed to be valid */
- } HUF_repeat;
-/* HUF_compress4X_repeat() :
- *  Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
- *  If it uses hufTable it does not modify hufTable or repeat.
- *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
- *  If preferRepeat then the old table will always be used if valid. */
-size_t HUF_compress4X_repeat(void* dst, size_t dstSize,
-                       const void* src, size_t srcSize,
-                       unsigned maxSymbolValue, unsigned tableLog,
-                       void* workSpace, size_t wkspSize,    /*< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
-                       HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);
-
-/* HUF_buildCTable_wksp() :
- *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.
- * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.
- */
-#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1)
-#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))
-size_t HUF_buildCTable_wksp (HUF_CElt* tree,
-                       const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,
-                             void* workSpace, size_t wkspSize);
-
-/*! HUF_readStats() :
- *  Read compact Huffman tree, saved by HUF_writeCTable().
- * `huffWeight` is destination buffer.
- * @return : size read from `src` , or an error Code .
- *  Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
-size_t HUF_readStats(BYTE* huffWeight, size_t hwSize,
-                     U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
-                     const void* src, size_t srcSize);
-
-/*! HUF_readStats_wksp() :
- * Same as HUF_readStats() but takes an external workspace which must be
- * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE.
- * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
- */
-#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1)
-#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned))
-size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,
-                          U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
-                          const void* src, size_t srcSize,
-                          void* workspace, size_t wkspSize,
-                          int bmi2);
-
-/* HUF_readCTable() :
- *  Loading a CTable saved with HUF_writeCTable() */
-size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);
-
-/* HUF_getNbBits() :
- *  Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX
- *  Note 1 : is not inlined, as HUF_CElt definition is private
- *  Note 2 : const void* used, so that it can provide a statically allocated table as argument (which uses type U32) */
-U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue);
-
-/*
- * HUF_decompress() does the following:
- * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics
- * 2. build Huffman table from save, using HUF_readDTableX?()
- * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()
- */
-
-/* HUF_selectDecoder() :
- *  Tells which decoder is likely to decode faster,
- *  based on a set of pre-computed metrics.
- * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
- *  Assumption : 0 < dstSize <= 128 KB */
-U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
-
-/*
- *  The minimum workspace size for the `workSpace` used in
- *  HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp().
- *
- *  The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when
- *  HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.
- *  Buffer overflow errors may potentially occur if code modifications result in
- *  a required workspace size greater than that specified in the following
- *  macro.
- */
-#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))
-#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
-
-#ifndef HUF_FORCE_DECOMPRESS_X2
-size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize);
-size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
-#endif
-#ifndef HUF_FORCE_DECOMPRESS_X1
-size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize);
-size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
-#endif
-
-size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
-#ifndef HUF_FORCE_DECOMPRESS_X2
-size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
-#endif
-#ifndef HUF_FORCE_DECOMPRESS_X1
-size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
-#endif
-
-
-/* ====================== */
-/* single stream variants */
-/* ====================== */
-
-size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
-size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);  /*< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
-size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
-/* HUF_compress1X_repeat() :
- *  Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
- *  If it uses hufTable it does not modify hufTable or repeat.
- *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
- *  If preferRepeat then the old table will always be used if valid. */
-size_t HUF_compress1X_repeat(void* dst, size_t dstSize,
-                       const void* src, size_t srcSize,
-                       unsigned maxSymbolValue, unsigned tableLog,
-                       void* workSpace, size_t wkspSize,   /*< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
-                       HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);
-
-size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */
-#ifndef HUF_FORCE_DECOMPRESS_X1
-size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */
-#endif
-
-size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
-size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);
-#ifndef HUF_FORCE_DECOMPRESS_X2
-size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /*< single-symbol decoder */
-size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /*< single-symbol decoder */
-#endif
-#ifndef HUF_FORCE_DECOMPRESS_X1
-size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /*< double-symbols decoder */
-size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /*< double-symbols decoder */
-#endif
-
-size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);   /*< automatic selection of sing or double symbol decoder, based on DTable */
-#ifndef HUF_FORCE_DECOMPRESS_X2
-size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
-#endif
-#ifndef HUF_FORCE_DECOMPRESS_X1
-size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
-#endif
-
-/* BMI2 variants.
- * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
- */
-size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
-#ifndef HUF_FORCE_DECOMPRESS_X2
-size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
-#endif
-size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
-size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
-#ifndef HUF_FORCE_DECOMPRESS_X2
-size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
-#endif
-
-#endif /* HUF_STATIC_LINKING_ONLY */
-
diff --git a/lib/zstd/common/mem.h b/lib/zstd/common/mem.h
deleted file mode 100644
index dcdd586a9fd9..000000000000
--- a/lib/zstd/common/mem.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-#ifndef MEM_H_MODULE
-#define MEM_H_MODULE
-
-/*-****************************************
-*  Dependencies
-******************************************/
-#include <asm/unaligned.h>  /* get_unaligned, put_unaligned* */
-#include <linux/compiler.h>  /* inline */
-#include <linux/swab.h>  /* swab32, swab64 */
-#include <linux/types.h>  /* size_t, ptrdiff_t */
-#include "debug.h"  /* DEBUG_STATIC_ASSERT */
-
-/*-****************************************
-*  Compiler specifics
-******************************************/
-#define MEM_STATIC static inline
-
-/*-**************************************************************
-*  Basic Types
-*****************************************************************/
-typedef uint8_t  BYTE;
-typedef uint16_t U16;
-typedef int16_t  S16;
-typedef uint32_t U32;
-typedef int32_t  S32;
-typedef uint64_t U64;
-typedef int64_t  S64;
-
-/*-**************************************************************
-*  Memory I/O API
-*****************************************************************/
-/*=== Static platform detection ===*/
-MEM_STATIC unsigned MEM_32bits(void);
-MEM_STATIC unsigned MEM_64bits(void);
-MEM_STATIC unsigned MEM_isLittleEndian(void);
-
-/*=== Native unaligned read/write ===*/
-MEM_STATIC U16 MEM_read16(const void* memPtr);
-MEM_STATIC U32 MEM_read32(const void* memPtr);
-MEM_STATIC U64 MEM_read64(const void* memPtr);
-MEM_STATIC size_t MEM_readST(const void* memPtr);
-
-MEM_STATIC void MEM_write16(void* memPtr, U16 value);
-MEM_STATIC void MEM_write32(void* memPtr, U32 value);
-MEM_STATIC void MEM_write64(void* memPtr, U64 value);
-
-/*=== Little endian unaligned read/write ===*/
-MEM_STATIC U16 MEM_readLE16(const void* memPtr);
-MEM_STATIC U32 MEM_readLE24(const void* memPtr);
-MEM_STATIC U32 MEM_readLE32(const void* memPtr);
-MEM_STATIC U64 MEM_readLE64(const void* memPtr);
-MEM_STATIC size_t MEM_readLEST(const void* memPtr);
-
-MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);
-MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);
-MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);
-MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);
-MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);
-
-/*=== Big endian unaligned read/write ===*/
-MEM_STATIC U32 MEM_readBE32(const void* memPtr);
-MEM_STATIC U64 MEM_readBE64(const void* memPtr);
-MEM_STATIC size_t MEM_readBEST(const void* memPtr);
-
-MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);
-MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);
-MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);
-
-/*=== Byteswap ===*/
-MEM_STATIC U32 MEM_swap32(U32 in);
-MEM_STATIC U64 MEM_swap64(U64 in);
-MEM_STATIC size_t MEM_swapST(size_t in);
-
-/*-**************************************************************
-*  Memory I/O Implementation
-*****************************************************************/
-MEM_STATIC unsigned MEM_32bits(void)
-{
-    return sizeof(size_t) == 4;
-}
-
-MEM_STATIC unsigned MEM_64bits(void)
-{
-    return sizeof(size_t) == 8;
-}
-
-#if defined(__LITTLE_ENDIAN)
-#define MEM_LITTLE_ENDIAN 1
-#else
-#define MEM_LITTLE_ENDIAN 0
-#endif
-
-MEM_STATIC unsigned MEM_isLittleEndian(void)
-{
-    return MEM_LITTLE_ENDIAN;
-}
-
-MEM_STATIC U16 MEM_read16(const void *memPtr)
-{
-    return get_unaligned((const U16 *)memPtr);
-}
-
-MEM_STATIC U32 MEM_read32(const void *memPtr)
-{
-    return get_unaligned((const U32 *)memPtr);
-}
-
-MEM_STATIC U64 MEM_read64(const void *memPtr)
-{
-    return get_unaligned((const U64 *)memPtr);
-}
-
-MEM_STATIC size_t MEM_readST(const void *memPtr)
-{
-    return get_unaligned((const size_t *)memPtr);
-}
-
-MEM_STATIC void MEM_write16(void *memPtr, U16 value)
-{
-    put_unaligned(value, (U16 *)memPtr);
-}
-
-MEM_STATIC void MEM_write32(void *memPtr, U32 value)
-{
-    put_unaligned(value, (U32 *)memPtr);
-}
-
-MEM_STATIC void MEM_write64(void *memPtr, U64 value)
-{
-    put_unaligned(value, (U64 *)memPtr);
-}
-
-/*=== Little endian r/w ===*/
-
-MEM_STATIC U16 MEM_readLE16(const void *memPtr)
-{
-    return get_unaligned_le16(memPtr);
-}
-
-MEM_STATIC void MEM_writeLE16(void *memPtr, U16 val)
-{
-    put_unaligned_le16(val, memPtr);
-}
-
-MEM_STATIC U32 MEM_readLE24(const void *memPtr)
-{
-    return MEM_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16);
-}
-
-MEM_STATIC void MEM_writeLE24(void *memPtr, U32 val)
-{
-	MEM_writeLE16(memPtr, (U16)val);
-	((BYTE *)memPtr)[2] = (BYTE)(val >> 16);
-}
-
-MEM_STATIC U32 MEM_readLE32(const void *memPtr)
-{
-    return get_unaligned_le32(memPtr);
-}
-
-MEM_STATIC void MEM_writeLE32(void *memPtr, U32 val32)
-{
-    put_unaligned_le32(val32, memPtr);
-}
-
-MEM_STATIC U64 MEM_readLE64(const void *memPtr)
-{
-    return get_unaligned_le64(memPtr);
-}
-
-MEM_STATIC void MEM_writeLE64(void *memPtr, U64 val64)
-{
-    put_unaligned_le64(val64, memPtr);
-}
-
-MEM_STATIC size_t MEM_readLEST(const void *memPtr)
-{
-	if (MEM_32bits())
-		return (size_t)MEM_readLE32(memPtr);
-	else
-		return (size_t)MEM_readLE64(memPtr);
-}
-
-MEM_STATIC void MEM_writeLEST(void *memPtr, size_t val)
-{
-	if (MEM_32bits())
-		MEM_writeLE32(memPtr, (U32)val);
-	else
-		MEM_writeLE64(memPtr, (U64)val);
-}
-
-/*=== Big endian r/w ===*/
-
-MEM_STATIC U32 MEM_readBE32(const void *memPtr)
-{
-    return get_unaligned_be32(memPtr);
-}
-
-MEM_STATIC void MEM_writeBE32(void *memPtr, U32 val32)
-{
-    put_unaligned_be32(val32, memPtr);
-}
-
-MEM_STATIC U64 MEM_readBE64(const void *memPtr)
-{
-    return get_unaligned_be64(memPtr);
-}
-
-MEM_STATIC void MEM_writeBE64(void *memPtr, U64 val64)
-{
-    put_unaligned_be64(val64, memPtr);
-}
-
-MEM_STATIC size_t MEM_readBEST(const void *memPtr)
-{
-	if (MEM_32bits())
-		return (size_t)MEM_readBE32(memPtr);
-	else
-		return (size_t)MEM_readBE64(memPtr);
-}
-
-MEM_STATIC void MEM_writeBEST(void *memPtr, size_t val)
-{
-	if (MEM_32bits())
-		MEM_writeBE32(memPtr, (U32)val);
-	else
-		MEM_writeBE64(memPtr, (U64)val);
-}
-
-MEM_STATIC U32 MEM_swap32(U32 in)
-{
-    return swab32(in);
-}
-
-MEM_STATIC U64 MEM_swap64(U64 in)
-{
-    return swab64(in);
-}
-
-MEM_STATIC size_t MEM_swapST(size_t in)
-{
-    if (MEM_32bits())
-        return (size_t)MEM_swap32((U32)in);
-    else
-        return (size_t)MEM_swap64((U64)in);
-}
-
-#endif /* MEM_H_MODULE */
diff --git a/lib/zstd/common/zstd_common.c b/lib/zstd/common/zstd_common.c
deleted file mode 100644
index 3d7e35b309b5..000000000000
--- a/lib/zstd/common/zstd_common.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-
-
-/*-*************************************
-*  Dependencies
-***************************************/
-#define ZSTD_DEPS_NEED_MALLOC
-#include "zstd_deps.h"   /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */
-#include "error_private.h"
-#include "zstd_internal.h"
-
-
-/*-****************************************
-*  Version
-******************************************/
-unsigned ZSTD_versionNumber(void) { return ZSTD_VERSION_NUMBER; }
-
-const char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; }
-
-
-/*-****************************************
-*  ZSTD Error Management
-******************************************/
-#undef ZSTD_isError   /* defined within zstd_internal.h */
-/*! ZSTD_isError() :
- *  tells if a return value is an error code
- *  symbol is required for external callers */
-unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
-
-/*! ZSTD_getErrorName() :
- *  provides error code string from function result (useful for debugging) */
-const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }
-
-/*! ZSTD_getError() :
- *  convert a `size_t` function result into a proper ZSTD_errorCode enum */
-ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
-
-/*! ZSTD_getErrorString() :
- *  provides error code string from enum */
-const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); }
-
-
-
-/*=**************************************************************
-*  Custom allocator
-****************************************************************/
-void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem)
-{
-    if (customMem.customAlloc)
-        return customMem.customAlloc(customMem.opaque, size);
-    return ZSTD_malloc(size);
-}
-
-void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem)
-{
-    if (customMem.customAlloc) {
-        /* calloc implemented as malloc+memset;
-         * not as efficient as calloc, but next best guess for custom malloc */
-        void* const ptr = customMem.customAlloc(customMem.opaque, size);
-        ZSTD_memset(ptr, 0, size);
-        return ptr;
-    }
-    return ZSTD_calloc(1, size);
-}
-
-void ZSTD_customFree(void* ptr, ZSTD_customMem customMem)
-{
-    if (ptr!=NULL) {
-        if (customMem.customFree)
-            customMem.customFree(customMem.opaque, ptr);
-        else
-            ZSTD_free(ptr);
-    }
-}
diff --git a/lib/zstd/common/zstd_deps.h b/lib/zstd/common/zstd_deps.h
deleted file mode 100644
index 7a5bf44839c9..000000000000
--- a/lib/zstd/common/zstd_deps.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
-/*
- * Copyright (c) Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-/*
- * This file provides common libc dependencies that zstd requires.
- * The purpose is to allow replacing this file with a custom implementation
- * to compile zstd without libc support.
- */
-
-/* Need:
- * NULL
- * INT_MAX
- * UINT_MAX
- * ZSTD_memcpy()
- * ZSTD_memset()
- * ZSTD_memmove()
- */
-#ifndef ZSTD_DEPS_COMMON
-#define ZSTD_DEPS_COMMON
-
-#include <linux/limits.h>
-#include <linux/stddef.h>
-
-#define ZSTD_memcpy(d,s,n) __builtin_memcpy((d),(s),(n))
-#define ZSTD_memmove(d,s,n) __builtin_memmove((d),(s),(n))
-#define ZSTD_memset(d,s,n) __builtin_memset((d),(s),(n))
-
-#endif /* ZSTD_DEPS_COMMON */
-
-/*
- * Define malloc as always failing. That means the user must
- * either use ZSTD_customMem or statically allocate memory.
- * Need:
- * ZSTD_malloc()
- * ZSTD_free()
- * ZSTD_calloc()
- */
-#ifdef ZSTD_DEPS_NEED_MALLOC
-#ifndef ZSTD_DEPS_MALLOC
-#define ZSTD_DEPS_MALLOC
-
-#define ZSTD_malloc(s) ({ (void)(s); NULL; })
-#define ZSTD_free(p) ((void)(p))
-#define ZSTD_calloc(n,s) ({ (void)(n); (void)(s); NULL; })
-
-#endif /* ZSTD_DEPS_MALLOC */
-#endif /* ZSTD_DEPS_NEED_MALLOC */
-
-/*
- * Provides 64-bit math support.
- * Need:
- * U64 ZSTD_div64(U64 dividend, U32 divisor)
- */
-#ifdef ZSTD_DEPS_NEED_MATH64
-#ifndef ZSTD_DEPS_MATH64
-#define ZSTD_DEPS_MATH64
-
-#include <linux/math64.h>
-
-static uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) {
-  return div_u64(dividend, divisor);
-}
-
-#endif /* ZSTD_DEPS_MATH64 */
-#endif /* ZSTD_DEPS_NEED_MATH64 */
-
-/*
- * This is only requested when DEBUGLEVEL >= 1, meaning
- * it is disabled in production.
- * Need:
- * assert()
- */
-#ifdef ZSTD_DEPS_NEED_ASSERT
-#ifndef ZSTD_DEPS_ASSERT
-#define ZSTD_DEPS_ASSERT
-
-#include <linux/kernel.h>
-
-#define assert(x) WARN_ON((x))
-
-#endif /* ZSTD_DEPS_ASSERT */
-#endif /* ZSTD_DEPS_NEED_ASSERT */
-
-/*
- * This is only requested when DEBUGLEVEL >= 2, meaning
- * it is disabled in production.
- * Need:
- * ZSTD_DEBUG_PRINT()
- */
-#ifdef ZSTD_DEPS_NEED_IO
-#ifndef ZSTD_DEPS_IO
-#define ZSTD_DEPS_IO
-
-#include <linux/printk.h>
-
-#define ZSTD_DEBUG_PRINT(...) pr_debug(__VA_ARGS__)
-
-#endif /* ZSTD_DEPS_IO */
-#endif /* ZSTD_DEPS_NEED_IO */
-
-/*
- * Only requested when MSAN is enabled.
- * Need:
- * intptr_t
- */
-#ifdef ZSTD_DEPS_NEED_STDINT
-#ifndef ZSTD_DEPS_STDINT
-#define ZSTD_DEPS_STDINT
-
-/*
- * The Linux Kernel doesn't provide intptr_t, only uintptr_t, which
- * is an unsigned long.
- */
-typedef long intptr_t;
-
-#endif /* ZSTD_DEPS_STDINT */
-#endif /* ZSTD_DEPS_NEED_STDINT */
diff --git a/lib/zstd/common/zstd_internal.h b/lib/zstd/common/zstd_internal.h
deleted file mode 100644
index fc6f3a9b40c0..000000000000
--- a/lib/zstd/common/zstd_internal.h
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-#ifndef ZSTD_CCOMMON_H_MODULE
-#define ZSTD_CCOMMON_H_MODULE
-
-/* this module contains definitions which must be identical
- * across compression, decompression and dictBuilder.
- * It also contains a few functions useful to at least 2 of them
- * and which benefit from being inlined */
-
-/*-*************************************
-*  Dependencies
-***************************************/
-#include "compiler.h"
-#include "mem.h"
-#include "debug.h"                 /* assert, DEBUGLOG, RAWLOG, g_debuglevel */
-#include "error_private.h"
-#define ZSTD_STATIC_LINKING_ONLY
-#include <linux/zstd.h>
-#define FSE_STATIC_LINKING_ONLY
-#include "fse.h"
-#define HUF_STATIC_LINKING_ONLY
-#include "huf.h"
-#include <linux/xxhash.h>                /* XXH_reset, update, digest */
-#define ZSTD_TRACE 0
-
-
-/* ---- static assert (debug) --- */
-#define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)
-#define ZSTD_isError ERR_isError   /* for inlining */
-#define FSE_isError  ERR_isError
-#define HUF_isError  ERR_isError
-
-
-/*-*************************************
-*  shared macros
-***************************************/
-#undef MIN
-#undef MAX
-#define MIN(a,b) ((a)<(b) ? (a) : (b))
-#define MAX(a,b) ((a)>(b) ? (a) : (b))
-
-/*
- * Ignore: this is an internal helper.
- *
- * This is a helper function to help force C99-correctness during compilation.
- * Under strict compilation modes, variadic macro arguments can't be empty.
- * However, variadic function arguments can be. Using a function therefore lets
- * us statically check that at least one (string) argument was passed,
- * independent of the compilation flags.
- */
-static INLINE_KEYWORD UNUSED_ATTR
-void _force_has_format_string(const char *format, ...) {
-  (void)format;
-}
-
-/*
- * Ignore: this is an internal helper.
- *
- * We want to force this function invocation to be syntactically correct, but
- * we don't want to force runtime evaluation of its arguments.
- */
-#define _FORCE_HAS_FORMAT_STRING(...) \
-  if (0) { \
-    _force_has_format_string(__VA_ARGS__); \
-  }
-
-/*
- * Return the specified error if the condition evaluates to true.
- *
- * In debug modes, prints additional information.
- * In order to do that (particularly, printing the conditional that failed),
- * this can't just wrap RETURN_ERROR().
- */
-#define RETURN_ERROR_IF(cond, err, ...) \
-  if (cond) { \
-    RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
-           __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \
-    _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
-    RAWLOG(3, ": " __VA_ARGS__); \
-    RAWLOG(3, "\n"); \
-    return ERROR(err); \
-  }
-
-/*
- * Unconditionally return the specified error.
- *
- * In debug modes, prints additional information.
- */
-#define RETURN_ERROR(err, ...) \
-  do { \
-    RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
-           __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \
-    _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
-    RAWLOG(3, ": " __VA_ARGS__); \
-    RAWLOG(3, "\n"); \
-    return ERROR(err); \
-  } while(0);
-
-/*
- * If the provided expression evaluates to an error code, returns that error code.
- *
- * In debug modes, prints additional information.
- */
-#define FORWARD_IF_ERROR(err, ...) \
-  do { \
-    size_t const err_code = (err); \
-    if (ERR_isError(err_code)) { \
-      RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
-             __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \
-      _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
-      RAWLOG(3, ": " __VA_ARGS__); \
-      RAWLOG(3, "\n"); \
-      return err_code; \
-    } \
-  } while(0);
-
-
-/*-*************************************
-*  Common constants
-***************************************/
-#define ZSTD_OPT_NUM    (1<<12)
-
-#define ZSTD_REP_NUM      3                 /* number of repcodes */
-#define ZSTD_REP_MOVE     (ZSTD_REP_NUM-1)
-static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
-
-#define KB *(1 <<10)
-#define MB *(1 <<20)
-#define GB *(1U<<30)
-
-#define BIT7 128
-#define BIT6  64
-#define BIT5  32
-#define BIT4  16
-#define BIT1   2
-#define BIT0   1
-
-#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
-static UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
-static UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
-
-#define ZSTD_FRAMEIDSIZE 4   /* magic number size */
-
-#define ZSTD_BLOCKHEADERSIZE 3   /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
-static UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
-typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
-
-#define ZSTD_FRAMECHECKSUMSIZE 4
-
-#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
-#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */
-
-#define HufLog 12
-typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e;
-
-#define LONGNBSEQ 0x7F00
-
-#define MINMATCH 3
-
-#define Litbits  8
-#define MaxLit ((1<<Litbits) - 1)
-#define MaxML   52
-#define MaxLL   35
-#define DefaultMaxOff 28
-#define MaxOff  31
-#define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */
-#define MLFSELog    9
-#define LLFSELog    9
-#define OffFSELog   8
-#define MaxFSELog  MAX(MAX(MLFSELog, LLFSELog), OffFSELog)
-
-#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */
-/* Each table cannot take more than #symbols * FSELog bits */
-#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)
-
-static UNUSED_ATTR const U32 LL_bits[MaxLL+1] = {
-     0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0,
-     1, 1, 1, 1, 2, 2, 3, 3,
-     4, 6, 7, 8, 9,10,11,12,
-    13,14,15,16
-};
-static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {
-     4, 3, 2, 2, 2, 2, 2, 2,
-     2, 2, 2, 2, 2, 1, 1, 1,
-     2, 2, 2, 2, 2, 2, 2, 2,
-     2, 3, 2, 1, 1, 1, 1, 1,
-    -1,-1,-1,-1
-};
-#define LL_DEFAULTNORMLOG 6  /* for static allocation */
-static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
-
-static UNUSED_ATTR const U32 ML_bits[MaxML+1] = {
-     0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0,
-     1, 1, 1, 1, 2, 2, 3, 3,
-     4, 4, 5, 7, 8, 9,10,11,
-    12,13,14,15,16
-};
-static UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = {
-     1, 4, 3, 2, 2, 2, 2, 2,
-     2, 1, 1, 1, 1, 1, 1, 1,
-     1, 1, 1, 1, 1, 1, 1, 1,
-     1, 1, 1, 1, 1, 1, 1, 1,
-     1, 1, 1, 1, 1, 1, 1, 1,
-     1, 1, 1, 1, 1, 1,-1,-1,
-    -1,-1,-1,-1,-1
-};
-#define ML_DEFAULTNORMLOG 6  /* for static allocation */
-static UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
-
-static UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = {
-     1, 1, 1, 1, 1, 1, 2, 2,
-     2, 1, 1, 1, 1, 1, 1, 1,
-     1, 1, 1, 1, 1, 1, 1, 1,
-    -1,-1,-1,-1,-1
-};
-#define OF_DEFAULTNORMLOG 5  /* for static allocation */
-static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
-
-
-/*-*******************************************
-*  Shared functions to include for inlining
-*********************************************/
-static void ZSTD_copy8(void* dst, const void* src) {
-    ZSTD_memcpy(dst, src, 8);
-}
-
-#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
-static void ZSTD_copy16(void* dst, const void* src) {
-    ZSTD_memcpy(dst, src, 16);
-}
-#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; }
-
-#define WILDCOPY_OVERLENGTH 32
-#define WILDCOPY_VECLEN 16
-
-typedef enum {
-    ZSTD_no_overlap,
-    ZSTD_overlap_src_before_dst
-    /*  ZSTD_overlap_dst_before_src, */
-} ZSTD_overlap_e;
-
-/*! ZSTD_wildcopy() :
- *  Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0)
- *  @param ovtype controls the overlap detection
- *         - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.
- *         - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart.
- *           The src buffer must be before the dst buffer.
- */
-MEM_STATIC FORCE_INLINE_ATTR
-void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype)
-{
-    ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;
-    const BYTE* ip = (const BYTE*)src;
-    BYTE* op = (BYTE*)dst;
-    BYTE* const oend = op + length;
-
-    assert(diff >= 8 || (ovtype == ZSTD_no_overlap && diff <= -WILDCOPY_VECLEN));
-
-    if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {
-        /* Handle short offset copies. */
-        do {
-            COPY8(op, ip)
-        } while (op < oend);
-    } else {
-        assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN);
-        /* Separate out the first COPY16() call because the copy length is
-         * almost certain to be short, so the branches have different
-         * probabilities. Since it is almost certain to be short, only do
-         * one COPY16() in the first call. Then, do two calls per loop since
-         * at that point it is more likely to have a high trip count.
-         */
-#ifdef __aarch64__
-        do {
-            COPY16(op, ip);
-        }
-        while (op < oend);
-#else
-        ZSTD_copy16(op, ip);
-        if (16 >= length) return;
-        op += 16;
-        ip += 16;
-        do {
-            COPY16(op, ip);
-            COPY16(op, ip);
-        }
-        while (op < oend);
-#endif
-    }
-}
-
-MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
-{
-    size_t const length = MIN(dstCapacity, srcSize);
-    if (length > 0) {
-        ZSTD_memcpy(dst, src, length);
-    }
-    return length;
-}
-
-/* define "workspace is too large" as this number of times larger than needed */
-#define ZSTD_WORKSPACETOOLARGE_FACTOR 3
-
-/* when workspace is continuously too large
- * during at least this number of times,
- * context's memory usage is considered wasteful,
- * because it's sized to handle a worst case scenario which rarely happens.
- * In which case, resize it down to free some memory */
-#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128
-
-/* Controls whether the input/output buffer is buffered or stable. */
-typedef enum {
-    ZSTD_bm_buffered = 0,  /* Buffer the input/output */
-    ZSTD_bm_stable = 1     /* ZSTD_inBuffer/ZSTD_outBuffer is stable */
-} ZSTD_bufferMode_e;
-
-
-/*-*******************************************
-*  Private declarations
-*********************************************/
-typedef struct seqDef_s {
-    U32 offset;         /* Offset code of the sequence */
-    U16 litLength;
-    U16 matchLength;
-} seqDef;
-
-typedef struct {
-    seqDef* sequencesStart;
-    seqDef* sequences;      /* ptr to end of sequences */
-    BYTE* litStart;
-    BYTE* lit;              /* ptr to end of literals */
-    BYTE* llCode;
-    BYTE* mlCode;
-    BYTE* ofCode;
-    size_t maxNbSeq;
-    size_t maxNbLit;
-
-    /* longLengthPos and longLengthID to allow us to represent either a single litLength or matchLength
-     * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment
-     * the existing value of the litLength or matchLength by 0x10000.
-     */
-    U32   longLengthID;   /* 0 == no longLength; 1 == Represent the long literal; 2 == Represent the long match; */
-    U32   longLengthPos;  /* Index of the sequence to apply long length modification to */
-} seqStore_t;
-
-typedef struct {
-    U32 litLength;
-    U32 matchLength;
-} ZSTD_sequenceLength;
-
-/*
- * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences
- * indicated by longLengthPos and longLengthID, and adds MINMATCH back to matchLength.
- */
-MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq)
-{
-    ZSTD_sequenceLength seqLen;
-    seqLen.litLength = seq->litLength;
-    seqLen.matchLength = seq->matchLength + MINMATCH;
-    if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {
-        if (seqStore->longLengthID == 1) {
-            seqLen.litLength += 0xFFFF;
-        }
-        if (seqStore->longLengthID == 2) {
-            seqLen.matchLength += 0xFFFF;
-        }
-    }
-    return seqLen;
-}
-
-/*
- * Contains the compressed frame size and an upper-bound for the decompressed frame size.
- * Note: before using `compressedSize`, check for errors using ZSTD_isError().
- *       similarly, before using `decompressedBound`, check for errors using:
- *          `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
- */
-typedef struct {
-    size_t compressedSize;
-    unsigned long long decompressedBound;
-} ZSTD_frameSizeInfo;   /* decompress & legacy */
-
-const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);   /* compress & dictBuilder */
-void ZSTD_seqToCodes(const seqStore_t* seqStorePtr);   /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
-
-/* custom memory allocation functions */
-void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem);
-void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem);
-void ZSTD_customFree(void* ptr, ZSTD_customMem customMem);
-
-
-MEM_STATIC U32 ZSTD_highbit32(U32 val)   /* compress, dictBuilder, decodeCorpus */
-{
-    assert(val != 0);
-    {
-#   if (__GNUC__ >= 3)   /* GCC Intrinsic */
-        return __builtin_clz (val) ^ 31;
-#   else   /* Software version */
-        static const U32 DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
-        U32 v = val;
-        v |= v >> 1;
-        v |= v >> 2;
-        v |= v >> 4;
-        v |= v >> 8;
-        v |= v >> 16;
-        return DeBruijnClz[(v * 0x07C4ACDDU) >> 27];
-#   endif
-    }
-}
-
-
-/* ZSTD_invalidateRepCodes() :
- * ensures next compression will not use repcodes from previous block.
- * Note : only works with regular variant;
- *        do not use with extDict variant ! */
-void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);   /* zstdmt, adaptive_compression (shouldn't get this definition from here) */
-
-
-typedef struct {
-    blockType_e blockType;
-    U32 lastBlock;
-    U32 origSize;
-} blockProperties_t;   /* declared here for decompress and fullbench */
-
-/*! ZSTD_getcBlockSize() :
- *  Provides the size of compressed block from block header `src` */
-/* Used by: decompress, fullbench (does not get its definition from here) */
-size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
-                          blockProperties_t* bpPtr);
-
-/*! ZSTD_decodeSeqHeaders() :
- *  decode sequence header from src */
-/* Used by: decompress, fullbench (does not get its definition from here) */
-size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
-                       const void* src, size_t srcSize);
-
-
-
-#endif   /* ZSTD_CCOMMON_H_MODULE */
diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c
new file mode 100644
index 000000000000..19bf71288111
--- /dev/null
+++ b/lib/zstd/decompress.c
@@ -0,0 +1,2528 @@
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd.
+ * An additional grant of patent rights can be found in the PATENTS file in the
+ * same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ */
+
+/* ***************************************************************
+*  Tuning parameters
+*****************************************************************/
+/*!
+*  MAXWINDOWSIZE_DEFAULT :
+*  maximum window size accepted by DStream, by default.
+*  Frames requiring more memory will be rejected.
+*/
+#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
+#define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */
+#endif
+
+/*-*******************************************************
+*  Dependencies
+*********************************************************/
+#include "fse.h"
+#include "huf.h"
+#include "mem.h" /* low level memory routines */
+#include "zstd_internal.h"
+#include <linux/kernel.h>
+#include <module.h>
+#include <linux/string.h> /* memcpy, memmove, memset */
+
+#define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
+
+/*-*************************************
+*  Macros
+***************************************/
+#define ZSTD_isError ERR_isError /* for inlining */
+#define FSE_isError ERR_isError
+#define HUF_isError ERR_isError
+
+/*_*******************************************************
+*  Memory operations
+**********************************************************/
+static void ZSTD_copy4(void *dst, const void *src) { memcpy(dst, src, 4); }
+
+/*-*************************************************************
+*   Context management
+***************************************************************/
+typedef enum {
+	ZSTDds_getFrameHeaderSize,
+	ZSTDds_decodeFrameHeader,
+	ZSTDds_decodeBlockHeader,
+	ZSTDds_decompressBlock,
+	ZSTDds_decompressLastBlock,
+	ZSTDds_checkChecksum,
+	ZSTDds_decodeSkippableHeader,
+	ZSTDds_skipFrame
+} ZSTD_dStage;
+
+typedef struct {
+	FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
+	FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
+	FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
+	HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
+	U64 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32 / 2];
+	U32 rep[ZSTD_REP_NUM];
+} ZSTD_entropyTables_t;
+
+struct ZSTD_DCtx_s {
+	const FSE_DTable *LLTptr;
+	const FSE_DTable *MLTptr;
+	const FSE_DTable *OFTptr;
+	const HUF_DTable *HUFptr;
+	ZSTD_entropyTables_t entropy;
+	const void *previousDstEnd; /* detect continuity */
+	const void *base;	   /* start of curr segment */
+	const void *vBase;	  /* virtual start of previous segment if it was just before curr one */
+	const void *dictEnd;	/* end of previous segment */
+	size_t expected;
+	ZSTD_frameParams fParams;
+	blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
+	ZSTD_dStage stage;
+	U32 litEntropy;
+	U32 fseEntropy;
+	struct xxh64_state xxhState;
+	size_t headerSize;
+	U32 dictID;
+	const BYTE *litPtr;
+	ZSTD_customMem customMem;
+	size_t litSize;
+	size_t rleSize;
+	BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
+	BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
+}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
+
+size_t ZSTD_DCtxWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DCtx)); }
+
+size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx)
+{
+	dctx->expected = ZSTD_frameHeaderSize_prefix;
+	dctx->stage = ZSTDds_getFrameHeaderSize;
+	dctx->previousDstEnd = NULL;
+	dctx->base = NULL;
+	dctx->vBase = NULL;
+	dctx->dictEnd = NULL;
+	dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+	dctx->litEntropy = dctx->fseEntropy = 0;
+	dctx->dictID = 0;
+	ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
+	memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
+	dctx->LLTptr = dctx->entropy.LLTable;
+	dctx->MLTptr = dctx->entropy.MLTable;
+	dctx->OFTptr = dctx->entropy.OFTable;
+	dctx->HUFptr = dctx->entropy.hufTable;
+	return 0;
+}
+
+static ZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
+{
+	ZSTD_DCtx *dctx;
+
+	if (!customMem.customAlloc || !customMem.customFree)
+		return NULL;
+
+	dctx = (ZSTD_DCtx *)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem);
+	if (!dctx)
+		return NULL;
+	memcpy(&dctx->customMem, &customMem, sizeof(customMem));
+	ZSTD_decompressBegin(dctx);
+	return dctx;
+}
+
+ZSTD_DCtx *ZSTD_initDCtx(void *workspace, size_t workspaceSize)
+{
+	ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
+	return ZSTD_createDCtx_advanced(stackMem);
+}
+
+size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx)
+{
+	if (dctx == NULL)
+		return 0; /* support free on NULL */
+	ZSTD_free(dctx, dctx->customMem);
+	return 0; /* reserved as a potential error code in the future */
+}
+
+void ZSTD_copyDCtx(ZSTD_DCtx *dstDCtx, const ZSTD_DCtx *srcDCtx)
+{
+	size_t const workSpaceSize = (ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH) + ZSTD_frameHeaderSize_max;
+	memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
+}
+
+static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict);
+
+/*-*************************************************************
+*   Decompression section
+***************************************************************/
+
+/*! ZSTD_isFrame() :
+ *  Tells if the content of `buffer` starts with a valid Frame Identifier.
+ *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
+ *  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
+ *  Note 3 : Skippable Frame Identifiers are considered valid. */
+unsigned ZSTD_isFrame(const void *buffer, size_t size)
+{
+	if (size < 4)
+		return 0;
+	{
+		U32 const magic = ZSTD_readLE32(buffer);
+		if (magic == ZSTD_MAGICNUMBER)
+			return 1;
+		if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START)
+			return 1;
+	}
+	return 0;
+}
+
+/** ZSTD_frameHeaderSize() :
+*   srcSize must be >= ZSTD_frameHeaderSize_prefix.
+*   @return : size of the Frame Header */
+static size_t ZSTD_frameHeaderSize(const void *src, size_t srcSize)
+{
+	if (srcSize < ZSTD_frameHeaderSize_prefix)
+		return ERROR(srcSize_wrong);
+	{
+		BYTE const fhd = ((const BYTE *)src)[4];
+		U32 const dictID = fhd & 3;
+		U32 const singleSegment = (fhd >> 5) & 1;
+		U32 const fcsId = fhd >> 6;
+		return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] + (singleSegment && !fcsId);
+	}
+}
+
+/** ZSTD_getFrameParams() :
+*   decode Frame Header, or require larger `srcSize`.
+*   @return : 0, `fparamsPtr` is correctly filled,
+*            >0, `srcSize` is too small, result is expected `srcSize`,
+*             or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src, size_t srcSize)
+{
+	const BYTE *ip = (const BYTE *)src;
+
+	if (srcSize < ZSTD_frameHeaderSize_prefix)
+		return ZSTD_frameHeaderSize_prefix;
+	if (ZSTD_readLE32(src) != ZSTD_MAGICNUMBER) {
+		if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+			if (srcSize < ZSTD_skippableHeaderSize)
+				return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */
+			memset(fparamsPtr, 0, sizeof(*fparamsPtr));
+			fparamsPtr->frameContentSize = ZSTD_readLE32((const char *)src + 4);
+			fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
+			return 0;
+		}
+		return ERROR(prefix_unknown);
+	}
+
+	/* ensure there is enough `srcSize` to fully read/decode frame header */
+	{
+		size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize);
+		if (srcSize < fhsize)
+			return fhsize;
+	}
+
+	{
+		BYTE const fhdByte = ip[4];
+		size_t pos = 5;
+		U32 const dictIDSizeCode = fhdByte & 3;
+		U32 const checksumFlag = (fhdByte >> 2) & 1;
+		U32 const singleSegment = (fhdByte >> 5) & 1;
+		U32 const fcsID = fhdByte >> 6;
+		U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;
+		U32 windowSize = 0;
+		U32 dictID = 0;
+		U64 frameContentSize = 0;
+		if ((fhdByte & 0x08) != 0)
+			return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */
+		if (!singleSegment) {
+			BYTE const wlByte = ip[pos++];
+			U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
+			if (windowLog > ZSTD_WINDOWLOG_MAX)
+				return ERROR(frameParameter_windowTooLarge); /* avoids issue with 1 << windowLog */
+			windowSize = (1U << windowLog);
+			windowSize += (windowSize >> 3) * (wlByte & 7);
+		}
+
+		switch (dictIDSizeCode) {
+		default: /* impossible */
+		case 0: break;
+		case 1:
+			dictID = ip[pos];
+			pos++;
+			break;
+		case 2:
+			dictID = ZSTD_readLE16(ip + pos);
+			pos += 2;
+			break;
+		case 3:
+			dictID = ZSTD_readLE32(ip + pos);
+			pos += 4;
+			break;
+		}
+		switch (fcsID) {
+		default: /* impossible */
+		case 0:
+			if (singleSegment)
+				frameContentSize = ip[pos];
+			break;
+		case 1: frameContentSize = ZSTD_readLE16(ip + pos) + 256; break;
+		case 2: frameContentSize = ZSTD_readLE32(ip + pos); break;
+		case 3: frameContentSize = ZSTD_readLE64(ip + pos); break;
+		}
+		if (!windowSize)
+			windowSize = (U32)frameContentSize;
+		if (windowSize > windowSizeMax)
+			return ERROR(frameParameter_windowTooLarge);
+		fparamsPtr->frameContentSize = frameContentSize;
+		fparamsPtr->windowSize = windowSize;
+		fparamsPtr->dictID = dictID;
+		fparamsPtr->checksumFlag = checksumFlag;
+	}
+	return 0;
+}
+
+/** ZSTD_getFrameContentSize() :
+*   compatible with legacy mode
+*   @return : decompressed size of the single frame pointed to be `src` if known, otherwise
+*             - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
+*             - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
+unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
+{
+	{
+		ZSTD_frameParams fParams;
+		if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0)
+			return ZSTD_CONTENTSIZE_ERROR;
+		if (fParams.windowSize == 0) {
+			/* Either skippable or empty frame, size == 0 either way */
+			return 0;
+		} else if (fParams.frameContentSize != 0) {
+			return fParams.frameContentSize;
+		} else {
+			return ZSTD_CONTENTSIZE_UNKNOWN;
+		}
+	}
+}
+
+/** ZSTD_findDecompressedSize() :
+ *  compatible with legacy mode
+ *  `srcSize` must be the exact length of some number of ZSTD compressed and/or
+ *      skippable frames
+ *  @return : decompressed size of the frames contained */
+unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize)
+{
+	{
+		unsigned long long totalDstSize = 0;
+		while (srcSize >= ZSTD_frameHeaderSize_prefix) {
+			const U32 magicNumber = ZSTD_readLE32(src);
+
+			if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+				size_t skippableSize;
+				if (srcSize < ZSTD_skippableHeaderSize)
+					return ERROR(srcSize_wrong);
+				skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize;
+				if (srcSize < skippableSize) {
+					return ZSTD_CONTENTSIZE_ERROR;
+				}
+
+				src = (const BYTE *)src + skippableSize;
+				srcSize -= skippableSize;
+				continue;
+			}
+
+			{
+				unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
+				if (ret >= ZSTD_CONTENTSIZE_ERROR)
+					return ret;
+
+				/* check for overflow */
+				if (totalDstSize + ret < totalDstSize)
+					return ZSTD_CONTENTSIZE_ERROR;
+				totalDstSize += ret;
+			}
+			{
+				size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
+				if (ZSTD_isError(frameSrcSize)) {
+					return ZSTD_CONTENTSIZE_ERROR;
+				}
+
+				src = (const BYTE *)src + frameSrcSize;
+				srcSize -= frameSrcSize;
+			}
+		}
+
+		if (srcSize) {
+			return ZSTD_CONTENTSIZE_ERROR;
+		}
+
+		return totalDstSize;
+	}
+}
+
+/** ZSTD_decodeFrameHeader() :
+*   `headerSize` must be the size provided by ZSTD_frameHeaderSize().
+*   @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
+static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx *dctx, const void *src, size_t headerSize)
+{
+	size_t const result = ZSTD_getFrameParams(&(dctx->fParams), src, headerSize);
+	if (ZSTD_isError(result))
+		return result; /* invalid header */
+	if (result > 0)
+		return ERROR(srcSize_wrong); /* headerSize too small */
+	if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
+		return ERROR(dictionary_wrong);
+	if (dctx->fParams.checksumFlag)
+		xxh64_reset(&dctx->xxhState, 0);
+	return 0;
+}
+
+typedef struct {
+	blockType_e blockType;
+	U32 lastBlock;
+	U32 origSize;
+} blockProperties_t;
+
+/*! ZSTD_getcBlockSize() :
+*   Provides the size of compressed block from block header `src` */
+static size_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr)
+{
+	if (srcSize < ZSTD_blockHeaderSize)
+		return ERROR(srcSize_wrong);
+	{
+		U32 const cBlockHeader = ZSTD_readLE24(src);
+		U32 const cSize = cBlockHeader >> 3;
+		bpPtr->lastBlock = cBlockHeader & 1;
+		bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
+		bpPtr->origSize = cSize; /* only useful for RLE */
+		if (bpPtr->blockType == bt_rle)
+			return 1;
+		if (bpPtr->blockType == bt_reserved)
+			return ERROR(corruption_detected);
+		return cSize;
+	}
+}
+
+static size_t ZSTD_copyRawBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+	if (srcSize > dstCapacity)
+		return ERROR(dstSize_tooSmall);
+	memcpy(dst, src, srcSize);
+	return srcSize;
+}
+
+static size_t ZSTD_setRleBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize, size_t regenSize)
+{
+	if (srcSize != 1)
+		return ERROR(srcSize_wrong);
+	if (regenSize > dstCapacity)
+		return ERROR(dstSize_tooSmall);
+	memset(dst, *(const BYTE *)src, regenSize);
+	return regenSize;
+}
+
+/*! ZSTD_decodeLiteralsBlock() :
+	@return : nb of bytes read from src (< srcSize ) */
+static size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
+{
+	if (srcSize < MIN_CBLOCK_SIZE)
+		return ERROR(corruption_detected);
+
+	{
+		const BYTE *const istart = (const BYTE *)src;
+		symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
+
+		switch (litEncType) {
+		case set_repeat:
+			if (dctx->litEntropy == 0)
+				return ERROR(dictionary_corrupted);
+		/* fall-through */
+		case set_compressed:
+			if (srcSize < 5)
+				return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
+			{
+				size_t lhSize, litSize, litCSize;
+				U32 singleStream = 0;
+				U32 const lhlCode = (istart[0] >> 2) & 3;
+				U32 const lhc = ZSTD_readLE32(istart);
+				switch (lhlCode) {
+				case 0:
+				case 1:
+				default: /* note : default is impossible, since lhlCode into [0..3] */
+					/* 2 - 2 - 10 - 10 */
+					singleStream = !lhlCode;
+					lhSize = 3;
+					litSize = (lhc >> 4) & 0x3FF;
+					litCSize = (lhc >> 14) & 0x3FF;
+					break;
+				case 2:
+					/* 2 - 2 - 14 - 14 */
+					lhSize = 4;
+					litSize = (lhc >> 4) & 0x3FFF;
+					litCSize = lhc >> 18;
+					break;
+				case 3:
+					/* 2 - 2 - 18 - 18 */
+					lhSize = 5;
+					litSize = (lhc >> 4) & 0x3FFFF;
+					litCSize = (lhc >> 22) + (istart[4] << 10);
+					break;
+				}
+				if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX)
+					return ERROR(corruption_detected);
+				if (litCSize + lhSize > srcSize)
+					return ERROR(corruption_detected);
+
+				if (HUF_isError(
+					(litEncType == set_repeat)
+					    ? (singleStream ? HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr)
+							    : HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr))
+					    : (singleStream
+						   ? HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize,
+										 dctx->entropy.workspace, sizeof(dctx->entropy.workspace))
+						   : HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize,
+										   dctx->entropy.workspace, sizeof(dctx->entropy.workspace)))))
+					return ERROR(corruption_detected);
+
+				dctx->litPtr = dctx->litBuffer;
+				dctx->litSize = litSize;
+				dctx->litEntropy = 1;
+				if (litEncType == set_compressed)
+					dctx->HUFptr = dctx->entropy.hufTable;
+				memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+				return litCSize + lhSize;
+			}
+
+		case set_basic: {
+			size_t litSize, lhSize;
+			U32 const lhlCode = ((istart[0]) >> 2) & 3;
+			switch (lhlCode) {
+			case 0:
+			case 2:
+			default: /* note : default is impossible, since lhlCode into [0..3] */
+				lhSize = 1;
+				litSize = istart[0] >> 3;
+				break;
+			case 1:
+				lhSize = 2;
+				litSize = ZSTD_readLE16(istart) >> 4;
+				break;
+			case 3:
+				lhSize = 3;
+				litSize = ZSTD_readLE24(istart) >> 4;
+				break;
+			}
+
+			if (lhSize + litSize + WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
+				if (litSize + lhSize > srcSize)
+					return ERROR(corruption_detected);
+				memcpy(dctx->litBuffer, istart + lhSize, litSize);
+				dctx->litPtr = dctx->litBuffer;
+				dctx->litSize = litSize;
+				memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
+				return lhSize + litSize;
+			}
+			/* direct reference into compressed stream */
+			dctx->litPtr = istart + lhSize;
+			dctx->litSize = litSize;
+			return lhSize + litSize;
+		}
+
+		case set_rle: {
+			U32 const lhlCode = ((istart[0]) >> 2) & 3;
+			size_t litSize, lhSize;
+			switch (lhlCode) {
+			case 0:
+			case 2:
+			default: /* note : default is impossible, since lhlCode into [0..3] */
+				lhSize = 1;
+				litSize = istart[0] >> 3;
+				break;
+			case 1:
+				lhSize = 2;
+				litSize = ZSTD_readLE16(istart) >> 4;
+				break;
+			case 3:
+				lhSize = 3;
+				litSize = ZSTD_readLE24(istart) >> 4;
+				if (srcSize < 4)
+					return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
+				break;
+			}
+			if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX)
+				return ERROR(corruption_detected);
+			memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
+			dctx->litPtr = dctx->litBuffer;
+			dctx->litSize = litSize;
+			return lhSize + 1;
+		}
+		default:
+			return ERROR(corruption_detected); /* impossible */
+		}
+	}
+}
+
+typedef union {
+	FSE_decode_t realData;
+	U32 alignedBy4;
+} FSE_decode_t4;
+
+static const FSE_decode_t4 LL_defaultDTable[(1 << LL_DEFAULTNORMLOG) + 1] = {
+    {{LL_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
+    {{0, 0, 4}},		 /* 0 : base, symbol, bits */
+    {{16, 0, 4}},
+    {{32, 1, 5}},
+    {{0, 3, 5}},
+    {{0, 4, 5}},
+    {{0, 6, 5}},
+    {{0, 7, 5}},
+    {{0, 9, 5}},
+    {{0, 10, 5}},
+    {{0, 12, 5}},
+    {{0, 14, 6}},
+    {{0, 16, 5}},
+    {{0, 18, 5}},
+    {{0, 19, 5}},
+    {{0, 21, 5}},
+    {{0, 22, 5}},
+    {{0, 24, 5}},
+    {{32, 25, 5}},
+    {{0, 26, 5}},
+    {{0, 27, 6}},
+    {{0, 29, 6}},
+    {{0, 31, 6}},
+    {{32, 0, 4}},
+    {{0, 1, 4}},
+    {{0, 2, 5}},
+    {{32, 4, 5}},
+    {{0, 5, 5}},
+    {{32, 7, 5}},
+    {{0, 8, 5}},
+    {{32, 10, 5}},
+    {{0, 11, 5}},
+    {{0, 13, 6}},
+    {{32, 16, 5}},
+    {{0, 17, 5}},
+    {{32, 19, 5}},
+    {{0, 20, 5}},
+    {{32, 22, 5}},
+    {{0, 23, 5}},
+    {{0, 25, 4}},
+    {{16, 25, 4}},
+    {{32, 26, 5}},
+    {{0, 28, 6}},
+    {{0, 30, 6}},
+    {{48, 0, 4}},
+    {{16, 1, 4}},
+    {{32, 2, 5}},
+    {{32, 3, 5}},
+    {{32, 5, 5}},
+    {{32, 6, 5}},
+    {{32, 8, 5}},
+    {{32, 9, 5}},
+    {{32, 11, 5}},
+    {{32, 12, 5}},
+    {{0, 15, 6}},
+    {{32, 17, 5}},
+    {{32, 18, 5}},
+    {{32, 20, 5}},
+    {{32, 21, 5}},
+    {{32, 23, 5}},
+    {{32, 24, 5}},
+    {{0, 35, 6}},
+    {{0, 34, 6}},
+    {{0, 33, 6}},
+    {{0, 32, 6}},
+}; /* LL_defaultDTable */
+
+static const FSE_decode_t4 ML_defaultDTable[(1 << ML_DEFAULTNORMLOG) + 1] = {
+    {{ML_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
+    {{0, 0, 6}},		 /* 0 : base, symbol, bits */
+    {{0, 1, 4}},
+    {{32, 2, 5}},
+    {{0, 3, 5}},
+    {{0, 5, 5}},
+    {{0, 6, 5}},
+    {{0, 8, 5}},
+    {{0, 10, 6}},
+    {{0, 13, 6}},
+    {{0, 16, 6}},
+    {{0, 19, 6}},
+    {{0, 22, 6}},
+    {{0, 25, 6}},
+    {{0, 28, 6}},
+    {{0, 31, 6}},
+    {{0, 33, 6}},
+    {{0, 35, 6}},
+    {{0, 37, 6}},
+    {{0, 39, 6}},
+    {{0, 41, 6}},
+    {{0, 43, 6}},
+    {{0, 45, 6}},
+    {{16, 1, 4}},
+    {{0, 2, 4}},
+    {{32, 3, 5}},
+    {{0, 4, 5}},
+    {{32, 6, 5}},
+    {{0, 7, 5}},
+    {{0, 9, 6}},
+    {{0, 12, 6}},
+    {{0, 15, 6}},
+    {{0, 18, 6}},
+    {{0, 21, 6}},
+    {{0, 24, 6}},
+    {{0, 27, 6}},
+    {{0, 30, 6}},
+    {{0, 32, 6}},
+    {{0, 34, 6}},
+    {{0, 36, 6}},
+    {{0, 38, 6}},
+    {{0, 40, 6}},
+    {{0, 42, 6}},
+    {{0, 44, 6}},
+    {{32, 1, 4}},
+    {{48, 1, 4}},
+    {{16, 2, 4}},
+    {{32, 4, 5}},
+    {{32, 5, 5}},
+    {{32, 7, 5}},
+    {{32, 8, 5}},
+    {{0, 11, 6}},
+    {{0, 14, 6}},
+    {{0, 17, 6}},
+    {{0, 20, 6}},
+    {{0, 23, 6}},
+    {{0, 26, 6}},
+    {{0, 29, 6}},
+    {{0, 52, 6}},
+    {{0, 51, 6}},
+    {{0, 50, 6}},
+    {{0, 49, 6}},
+    {{0, 48, 6}},
+    {{0, 47, 6}},
+    {{0, 46, 6}},
+}; /* ML_defaultDTable */
+
+static const FSE_decode_t4 OF_defaultDTable[(1 << OF_DEFAULTNORMLOG) + 1] = {
+    {{OF_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
+    {{0, 0, 5}},		 /* 0 : base, symbol, bits */
+    {{0, 6, 4}},
+    {{0, 9, 5}},
+    {{0, 15, 5}},
+    {{0, 21, 5}},
+    {{0, 3, 5}},
+    {{0, 7, 4}},
+    {{0, 12, 5}},
+    {{0, 18, 5}},
+    {{0, 23, 5}},
+    {{0, 5, 5}},
+    {{0, 8, 4}},
+    {{0, 14, 5}},
+    {{0, 20, 5}},
+    {{0, 2, 5}},
+    {{16, 7, 4}},
+    {{0, 11, 5}},
+    {{0, 17, 5}},
+    {{0, 22, 5}},
+    {{0, 4, 5}},
+    {{16, 8, 4}},
+    {{0, 13, 5}},
+    {{0, 19, 5}},
+    {{0, 1, 5}},
+    {{16, 6, 4}},
+    {{0, 10, 5}},
+    {{0, 16, 5}},
+    {{0, 28, 5}},
+    {{0, 27, 5}},
+    {{0, 26, 5}},
+    {{0, 25, 5}},
+    {{0, 24, 5}},
+}; /* OF_defaultDTable */
+
+/*! ZSTD_buildSeqTable() :
+	@return : nb bytes read from src,
+			  or an error code if it fails, testable with ZSTD_isError()
+*/
+static size_t ZSTD_buildSeqTable(FSE_DTable *DTableSpace, const FSE_DTable **DTablePtr, symbolEncodingType_e type, U32 max, U32 maxLog, const void *src,
+				 size_t srcSize, const FSE_decode_t4 *defaultTable, U32 flagRepeatTable, void *workspace, size_t workspaceSize)
+{
+	const void *const tmpPtr = defaultTable; /* bypass strict aliasing */
+	switch (type) {
+	case set_rle:
+		if (!srcSize)
+			return ERROR(srcSize_wrong);
+		if ((*(const BYTE *)src) > max)
+			return ERROR(corruption_detected);
+		FSE_buildDTable_rle(DTableSpace, *(const BYTE *)src);
+		*DTablePtr = DTableSpace;
+		return 1;
+	case set_basic: *DTablePtr = (const FSE_DTable *)tmpPtr; return 0;
+	case set_repeat:
+		if (!flagRepeatTable)
+			return ERROR(corruption_detected);
+		return 0;
+	default: /* impossible */
+	case set_compressed: {
+		U32 tableLog;
+		S16 *norm = (S16 *)workspace;
+		size_t const spaceUsed32 = ALIGN(sizeof(S16) * (MaxSeq + 1), sizeof(U32)) >> 2;
+
+		if ((spaceUsed32 << 2) > workspaceSize)
+			return ERROR(GENERIC);
+		workspace = (U32 *)workspace + spaceUsed32;
+		workspaceSize -= (spaceUsed32 << 2);
+		{
+			size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
+			if (FSE_isError(headerSize))
+				return ERROR(corruption_detected);
+			if (tableLog > maxLog)
+				return ERROR(corruption_detected);
+			FSE_buildDTable_wksp(DTableSpace, norm, max, tableLog, workspace, workspaceSize);
+			*DTablePtr = DTableSpace;
+			return headerSize;
+		}
+	}
+	}
+}
+
+static size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx *dctx, int *nbSeqPtr, const void *src, size_t srcSize)
+{
+	const BYTE *const istart = (const BYTE *const)src;
+	const BYTE *const iend = istart + srcSize;
+	const BYTE *ip = istart;
+
+	/* check */
+	if (srcSize < MIN_SEQUENCES_SIZE)
+		return ERROR(srcSize_wrong);
+
+	/* SeqHead */
+	{
+		int nbSeq = *ip++;
+		if (!nbSeq) {
+			*nbSeqPtr = 0;
+			return 1;
+		}
+		if (nbSeq > 0x7F) {
+			if (nbSeq == 0xFF) {
+				if (ip + 2 > iend)
+					return ERROR(srcSize_wrong);
+				nbSeq = ZSTD_readLE16(ip) + LONGNBSEQ, ip += 2;
+			} else {
+				if (ip >= iend)
+					return ERROR(srcSize_wrong);
+				nbSeq = ((nbSeq - 0x80) << 8) + *ip++;
+			}
+		}
+		*nbSeqPtr = nbSeq;
+	}
+
+	/* FSE table descriptors */
+	if (ip + 4 > iend)
+		return ERROR(srcSize_wrong); /* minimum possible size */
+	{
+		symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
+		symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
+		symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
+		ip++;
+
+		/* Build DTables */
+		{
+			size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, LLtype, MaxLL, LLFSELog, ip, iend - ip,
+								  LL_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
+			if (ZSTD_isError(llhSize))
+				return ERROR(corruption_detected);
+			ip += llhSize;
+		}
+		{
+			size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, OFtype, MaxOff, OffFSELog, ip, iend - ip,
+								  OF_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
+			if (ZSTD_isError(ofhSize))
+				return ERROR(corruption_detected);
+			ip += ofhSize;
+		}
+		{
+			size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, MLtype, MaxML, MLFSELog, ip, iend - ip,
+								  ML_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
+			if (ZSTD_isError(mlhSize))
+				return ERROR(corruption_detected);
+			ip += mlhSize;
+		}
+	}
+
+	return ip - istart;
+}
+
+typedef struct {
+	size_t litLength;
+	size_t matchLength;
+	size_t offset;
+	const BYTE *match;
+} seq_t;
+
+typedef struct {
+	BIT_DStream_t DStream;
+	FSE_DState_t stateLL;
+	FSE_DState_t stateOffb;
+	FSE_DState_t stateML;
+	size_t prevOffset[ZSTD_REP_NUM];
+	const BYTE *base;
+	size_t pos;
+	uPtrDiff gotoDict;
+} seqState_t;
+
+FORCE_NOINLINE
+size_t ZSTD_execSequenceLast7(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
+			      const BYTE *const vBase, const BYTE *const dictEnd)
+{
+	BYTE *const oLitEnd = op + sequence.litLength;
+	size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+	BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+	BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
+	const BYTE *const iLitEnd = *litPtr + sequence.litLength;
+	const BYTE *match = oLitEnd - sequence.offset;
+
+	/* check */
+	if (oMatchEnd > oend)
+		return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
+	if (iLitEnd > litLimit)
+		return ERROR(corruption_detected); /* over-read beyond lit buffer */
+	if (oLitEnd <= oend_w)
+		return ERROR(GENERIC); /* Precondition */
+
+	/* copy literals */
+	if (op < oend_w) {
+		ZSTD_wildcopy(op, *litPtr, oend_w - op);
+		*litPtr += oend_w - op;
+		op = oend_w;
+	}
+	while (op < oLitEnd)
+		*op++ = *(*litPtr)++;
+
+	/* copy Match */
+	if (sequence.offset > (size_t)(oLitEnd - base)) {
+		/* offset beyond prefix */
+		if (sequence.offset > (size_t)(oLitEnd - vBase))
+			return ERROR(corruption_detected);
+		match = dictEnd - (base - match);
+		if (match + sequence.matchLength <= dictEnd) {
+			memmove(oLitEnd, match, sequence.matchLength);
+			return sequenceLength;
+		}
+		/* span extDict & currPrefixSegment */
+		{
+			size_t const length1 = dictEnd - match;
+			memmove(oLitEnd, match, length1);
+			op = oLitEnd + length1;
+			sequence.matchLength -= length1;
+			match = base;
+		}
+	}
+	while (op < oMatchEnd)
+		*op++ = *match++;
+	return sequenceLength;
+}
+
+static seq_t ZSTD_decodeSequence(seqState_t *seqState)
+{
+	seq_t seq;
+
+	U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
+	U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
+	U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
+
+	U32 const llBits = LL_bits[llCode];
+	U32 const mlBits = ML_bits[mlCode];
+	U32 const ofBits = ofCode;
+	U32 const totalBits = llBits + mlBits + ofBits;
+
+	static const U32 LL_base[MaxLL + 1] = {0,  1,  2,  3,  4,  5,  6,  7,  8,    9,     10,    11,    12,    13,     14,     15,     16,     18,
+					       20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000};
+
+	static const U32 ML_base[MaxML + 1] = {3,  4,  5,  6,  7,  8,  9,  10,   11,    12,    13,    14,    15,     16,     17,     18,     19,     20,
+					       21, 22, 23, 24, 25, 26, 27, 28,   29,    30,    31,    32,    33,     34,     35,     37,     39,     41,
+					       43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003};
+
+	static const U32 OF_base[MaxOff + 1] = {0,       1,	1,	5,	0xD,      0x1D,      0x3D,      0x7D,      0xFD,     0x1FD,
+						0x3FD,   0x7FD,    0xFFD,    0x1FFD,   0x3FFD,   0x7FFD,    0xFFFD,    0x1FFFD,   0x3FFFD,  0x7FFFD,
+						0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD};
+
+	/* sequence */
+	{
+		size_t offset;
+		if (!ofCode)
+			offset = 0;
+		else {
+			offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <=  (ZSTD_WINDOWLOG_MAX-1) bits */
+			if (ZSTD_32bits())
+				BIT_reloadDStream(&seqState->DStream);
+		}
+
+		if (ofCode <= 1) {
+			offset += (llCode == 0);
+			if (offset) {
+				size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+				temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+				if (offset != 1)
+					seqState->prevOffset[2] = seqState->prevOffset[1];
+				seqState->prevOffset[1] = seqState->prevOffset[0];
+				seqState->prevOffset[0] = offset = temp;
+			} else {
+				offset = seqState->prevOffset[0];
+			}
+		} else {
+			seqState->prevOffset[2] = seqState->prevOffset[1];
+			seqState->prevOffset[1] = seqState->prevOffset[0];
+			seqState->prevOffset[0] = offset;
+		}
+		seq.offset = offset;
+	}
+
+	seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <=  16 bits */
+	if (ZSTD_32bits() && (mlBits + llBits > 24))
+		BIT_reloadDStream(&seqState->DStream);
+
+	seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <=  16 bits */
+	if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog)))
+		BIT_reloadDStream(&seqState->DStream);
+
+	/* ANS state update */
+	FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <=  9 bits */
+	FSE_updateState(&seqState->stateML, &seqState->DStream); /* <=  9 bits */
+	if (ZSTD_32bits())
+		BIT_reloadDStream(&seqState->DStream);		   /* <= 18 bits */
+	FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <=  8 bits */
+
+	seq.match = NULL;
+
+	return seq;
+}
+
+FORCE_INLINE
+size_t ZSTD_execSequence(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
+			 const BYTE *const vBase, const BYTE *const dictEnd)
+{
+	BYTE *const oLitEnd = op + sequence.litLength;
+	size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+	BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+	BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
+	const BYTE *const iLitEnd = *litPtr + sequence.litLength;
+	const BYTE *match = oLitEnd - sequence.offset;
+
+	/* check */
+	if (oMatchEnd > oend)
+		return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
+	if (iLitEnd > litLimit)
+		return ERROR(corruption_detected); /* over-read beyond lit buffer */
+	if (oLitEnd > oend_w)
+		return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
+
+	/* copy Literals */
+	ZSTD_copy8(op, *litPtr);
+	if (sequence.litLength > 8)
+		ZSTD_wildcopy(op + 8, (*litPtr) + 8,
+			      sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
+	op = oLitEnd;
+	*litPtr = iLitEnd; /* update for next sequence */
+
+	/* copy Match */
+	if (sequence.offset > (size_t)(oLitEnd - base)) {
+		/* offset beyond prefix */
+		if (sequence.offset > (size_t)(oLitEnd - vBase))
+			return ERROR(corruption_detected);
+		match = dictEnd + (match - base);
+		if (match + sequence.matchLength <= dictEnd) {
+			memmove(oLitEnd, match, sequence.matchLength);
+			return sequenceLength;
+		}
+		/* span extDict & currPrefixSegment */
+		{
+			size_t const length1 = dictEnd - match;
+			memmove(oLitEnd, match, length1);
+			op = oLitEnd + length1;
+			sequence.matchLength -= length1;
+			match = base;
+			if (op > oend_w || sequence.matchLength < MINMATCH) {
+				U32 i;
+				for (i = 0; i < sequence.matchLength; ++i)
+					op[i] = match[i];
+				return sequenceLength;
+			}
+		}
+	}
+	/* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
+
+	/* match within prefix */
+	if (sequence.offset < 8) {
+		/* close range match, overlap */
+		static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */
+		static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */
+		int const sub2 = dec64table[sequence.offset];
+		op[0] = match[0];
+		op[1] = match[1];
+		op[2] = match[2];
+		op[3] = match[3];
+		match += dec32table[sequence.offset];
+		ZSTD_copy4(op + 4, match);
+		match -= sub2;
+	} else {
+		ZSTD_copy8(op, match);
+	}
+	op += 8;
+	match += 8;
+
+	if (oMatchEnd > oend - (16 - MINMATCH)) {
+		if (op < oend_w) {
+			ZSTD_wildcopy(op, match, oend_w - op);
+			match += oend_w - op;
+			op = oend_w;
+		}
+		while (op < oMatchEnd)
+			*op++ = *match++;
+	} else {
+		ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */
+	}
+	return sequenceLength;
+}
+
+static size_t ZSTD_decompressSequences(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize)
+{
+	const BYTE *ip = (const BYTE *)seqStart;
+	const BYTE *const iend = ip + seqSize;
+	BYTE *const ostart = (BYTE * const)dst;
+	BYTE *const oend = ostart + maxDstSize;
+	BYTE *op = ostart;
+	const BYTE *litPtr = dctx->litPtr;
+	const BYTE *const litEnd = litPtr + dctx->litSize;
+	const BYTE *const base = (const BYTE *)(dctx->base);
+	const BYTE *const vBase = (const BYTE *)(dctx->vBase);
+	const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd);
+	int nbSeq;
+
+	/* Build Decoding Tables */
+	{
+		size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
+		if (ZSTD_isError(seqHSize))
+			return seqHSize;
+		ip += seqHSize;
+	}
+
+	/* Regen sequences */
+	if (nbSeq) {
+		seqState_t seqState;
+		dctx->fseEntropy = 1;
+		{
+			U32 i;
+			for (i = 0; i < ZSTD_REP_NUM; i++)
+				seqState.prevOffset[i] = dctx->entropy.rep[i];
+		}
+		CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected);
+		FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+		FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+		FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+
+		for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq;) {
+			nbSeq--;
+			{
+				seq_t const sequence = ZSTD_decodeSequence(&seqState);
+				size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
+				if (ZSTD_isError(oneSeqSize))
+					return oneSeqSize;
+				op += oneSeqSize;
+			}
+		}
+
+		/* check if reached exact end */
+		if (nbSeq)
+			return ERROR(corruption_detected);
+		/* save reps for next block */
+		{
+			U32 i;
+			for (i = 0; i < ZSTD_REP_NUM; i++)
+				dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]);
+		}
+	}
+
+	/* last literal segment */
+	{
+		size_t const lastLLSize = litEnd - litPtr;
+		if (lastLLSize > (size_t)(oend - op))
+			return ERROR(dstSize_tooSmall);
+		memcpy(op, litPtr, lastLLSize);
+		op += lastLLSize;
+	}
+
+	return op - ostart;
+}
+
+FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t *seqState, int const longOffsets)
+{
+	seq_t seq;
+
+	U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
+	U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
+	U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
+
+	U32 const llBits = LL_bits[llCode];
+	U32 const mlBits = ML_bits[mlCode];
+	U32 const ofBits = ofCode;
+	U32 const totalBits = llBits + mlBits + ofBits;
+
+	static const U32 LL_base[MaxLL + 1] = {0,  1,  2,  3,  4,  5,  6,  7,  8,    9,     10,    11,    12,    13,     14,     15,     16,     18,
+					       20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000};
+
+	static const U32 ML_base[MaxML + 1] = {3,  4,  5,  6,  7,  8,  9,  10,   11,    12,    13,    14,    15,     16,     17,     18,     19,     20,
+					       21, 22, 23, 24, 25, 26, 27, 28,   29,    30,    31,    32,    33,     34,     35,     37,     39,     41,
+					       43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003};
+
+	static const U32 OF_base[MaxOff + 1] = {0,       1,	1,	5,	0xD,      0x1D,      0x3D,      0x7D,      0xFD,     0x1FD,
+						0x3FD,   0x7FD,    0xFFD,    0x1FFD,   0x3FFD,   0x7FFD,    0xFFFD,    0x1FFFD,   0x3FFFD,  0x7FFFD,
+						0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD};
+
+	/* sequence */
+	{
+		size_t offset;
+		if (!ofCode)
+			offset = 0;
+		else {
+			if (longOffsets) {
+				int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN);
+				offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+				if (ZSTD_32bits() || extraBits)
+					BIT_reloadDStream(&seqState->DStream);
+				if (extraBits)
+					offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+			} else {
+				offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <=  (ZSTD_WINDOWLOG_MAX-1) bits */
+				if (ZSTD_32bits())
+					BIT_reloadDStream(&seqState->DStream);
+			}
+		}
+
+		if (ofCode <= 1) {
+			offset += (llCode == 0);
+			if (offset) {
+				size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+				temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+				if (offset != 1)
+					seqState->prevOffset[2] = seqState->prevOffset[1];
+				seqState->prevOffset[1] = seqState->prevOffset[0];
+				seqState->prevOffset[0] = offset = temp;
+			} else {
+				offset = seqState->prevOffset[0];
+			}
+		} else {
+			seqState->prevOffset[2] = seqState->prevOffset[1];
+			seqState->prevOffset[1] = seqState->prevOffset[0];
+			seqState->prevOffset[0] = offset;
+		}
+		seq.offset = offset;
+	}
+
+	seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <=  16 bits */
+	if (ZSTD_32bits() && (mlBits + llBits > 24))
+		BIT_reloadDStream(&seqState->DStream);
+
+	seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <=  16 bits */
+	if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog)))
+		BIT_reloadDStream(&seqState->DStream);
+
+	{
+		size_t const pos = seqState->pos + seq.litLength;
+		seq.match = seqState->base + pos - seq.offset; /* single memory segment */
+		if (seq.offset > pos)
+			seq.match += seqState->gotoDict; /* separate memory segment */
+		seqState->pos = pos + seq.matchLength;
+	}
+
+	/* ANS state update */
+	FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <=  9 bits */
+	FSE_updateState(&seqState->stateML, &seqState->DStream); /* <=  9 bits */
+	if (ZSTD_32bits())
+		BIT_reloadDStream(&seqState->DStream);		   /* <= 18 bits */
+	FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <=  8 bits */
+
+	return seq;
+}
+
+static seq_t ZSTD_decodeSequenceLong(seqState_t *seqState, unsigned const windowSize)
+{
+	if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) {
+		return ZSTD_decodeSequenceLong_generic(seqState, 1);
+	} else {
+		return ZSTD_decodeSequenceLong_generic(seqState, 0);
+	}
+}
+
+FORCE_INLINE
+size_t ZSTD_execSequenceLong(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
+			     const BYTE *const vBase, const BYTE *const dictEnd)
+{
+	BYTE *const oLitEnd = op + sequence.litLength;
+	size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+	BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+	BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
+	const BYTE *const iLitEnd = *litPtr + sequence.litLength;
+	const BYTE *match = sequence.match;
+
+	/* check */
+	if (oMatchEnd > oend)
+		return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
+	if (iLitEnd > litLimit)
+		return ERROR(corruption_detected); /* over-read beyond lit buffer */
+	if (oLitEnd > oend_w)
+		return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
+
+	/* copy Literals */
+	ZSTD_copy8(op, *litPtr);
+	if (sequence.litLength > 8)
+		ZSTD_wildcopy(op + 8, (*litPtr) + 8,
+			      sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
+	op = oLitEnd;
+	*litPtr = iLitEnd; /* update for next sequence */
+
+	/* copy Match */
+	if (sequence.offset > (size_t)(oLitEnd - base)) {
+		/* offset beyond prefix */
+		if (sequence.offset > (size_t)(oLitEnd - vBase))
+			return ERROR(corruption_detected);
+		if (match + sequence.matchLength <= dictEnd) {
+			memmove(oLitEnd, match, sequence.matchLength);
+			return sequenceLength;
+		}
+		/* span extDict & currPrefixSegment */
+		{
+			size_t const length1 = dictEnd - match;
+			memmove(oLitEnd, match, length1);
+			op = oLitEnd + length1;
+			sequence.matchLength -= length1;
+			match = base;
+			if (op > oend_w || sequence.matchLength < MINMATCH) {
+				U32 i;
+				for (i = 0; i < sequence.matchLength; ++i)
+					op[i] = match[i];
+				return sequenceLength;
+			}
+		}
+	}
+	/* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
+
+	/* match within prefix */
+	if (sequence.offset < 8) {
+		/* close range match, overlap */
+		static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */
+		static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */
+		int const sub2 = dec64table[sequence.offset];
+		op[0] = match[0];
+		op[1] = match[1];
+		op[2] = match[2];
+		op[3] = match[3];
+		match += dec32table[sequence.offset];
+		ZSTD_copy4(op + 4, match);
+		match -= sub2;
+	} else {
+		ZSTD_copy8(op, match);
+	}
+	op += 8;
+	match += 8;
+
+	if (oMatchEnd > oend - (16 - MINMATCH)) {
+		if (op < oend_w) {
+			ZSTD_wildcopy(op, match, oend_w - op);
+			match += oend_w - op;
+			op = oend_w;
+		}
+		while (op < oMatchEnd)
+			*op++ = *match++;
+	} else {
+		ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */
+	}
+	return sequenceLength;
+}
+
+static size_t ZSTD_decompressSequencesLong(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize)
+{
+	const BYTE *ip = (const BYTE *)seqStart;
+	const BYTE *const iend = ip + seqSize;
+	BYTE *const ostart = (BYTE * const)dst;
+	BYTE *const oend = ostart + maxDstSize;
+	BYTE *op = ostart;
+	const BYTE *litPtr = dctx->litPtr;
+	const BYTE *const litEnd = litPtr + dctx->litSize;
+	const BYTE *const base = (const BYTE *)(dctx->base);
+	const BYTE *const vBase = (const BYTE *)(dctx->vBase);
+	const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd);
+	unsigned const windowSize = dctx->fParams.windowSize;
+	int nbSeq;
+
+	/* Build Decoding Tables */
+	{
+		size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
+		if (ZSTD_isError(seqHSize))
+			return seqHSize;
+		ip += seqHSize;
+	}
+
+	/* Regen sequences */
+	if (nbSeq) {
+#define STORED_SEQS 4
+#define STOSEQ_MASK (STORED_SEQS - 1)
+#define ADVANCED_SEQS 4
+		seq_t *sequences = (seq_t *)dctx->entropy.workspace;
+		int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
+		seqState_t seqState;
+		int seqNb;
+		ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.workspace) >= sizeof(seq_t) * STORED_SEQS);
+		dctx->fseEntropy = 1;
+		{
+			U32 i;
+			for (i = 0; i < ZSTD_REP_NUM; i++)
+				seqState.prevOffset[i] = dctx->entropy.rep[i];
+		}
+		seqState.base = base;
+		seqState.pos = (size_t)(op - base);
+		seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */
+		CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected);
+		FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+		FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+		FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+
+		/* prepare in advance */
+		for (seqNb = 0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb < seqAdvance; seqNb++) {
+			sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize);
+		}
+		if (seqNb < seqAdvance)
+			return ERROR(corruption_detected);
+
+		/* decode and decompress */
+		for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb < nbSeq; seqNb++) {
+			seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize);
+			size_t const oneSeqSize =
+			    ZSTD_execSequenceLong(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
+			if (ZSTD_isError(oneSeqSize))
+				return oneSeqSize;
+			ZSTD_PREFETCH(sequence.match);
+			sequences[seqNb & STOSEQ_MASK] = sequence;
+			op += oneSeqSize;
+		}
+		if (seqNb < nbSeq)
+			return ERROR(corruption_detected);
+
+		/* finish queue */
+		seqNb -= seqAdvance;
+		for (; seqNb < nbSeq; seqNb++) {
+			size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
+			if (ZSTD_isError(oneSeqSize))
+				return oneSeqSize;
+			op += oneSeqSize;
+		}
+
+		/* save reps for next block */
+		{
+			U32 i;
+			for (i = 0; i < ZSTD_REP_NUM; i++)
+				dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]);
+		}
+	}
+
+	/* last literal segment */
+	{
+		size_t const lastLLSize = litEnd - litPtr;
+		if (lastLLSize > (size_t)(oend - op))
+			return ERROR(dstSize_tooSmall);
+		memcpy(op, litPtr, lastLLSize);
+		op += lastLLSize;
+	}
+
+	return op - ostart;
+}
+
+static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{ /* blockType == blockCompressed */
+	const BYTE *ip = (const BYTE *)src;
+
+	if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX)
+		return ERROR(srcSize_wrong);
+
+	/* Decode literals section */
+	{
+		size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
+		if (ZSTD_isError(litCSize))
+			return litCSize;
+		ip += litCSize;
+		srcSize -= litCSize;
+	}
+	if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */
+				/* likely because of register pressure */
+				/* if that's the correct cause, then 32-bits ARM should be affected differently */
+				/* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */
+		if (dctx->fParams.windowSize > (1 << 23))
+			return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
+	return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
+}
+
+static void ZSTD_checkContinuity(ZSTD_DCtx *dctx, const void *dst)
+{
+	if (dst != dctx->previousDstEnd) { /* not contiguous */
+		dctx->dictEnd = dctx->previousDstEnd;
+		dctx->vBase = (const char *)dst - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base));
+		dctx->base = dst;
+		dctx->previousDstEnd = dst;
+	}
+}
+
+size_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+	size_t dSize;
+	ZSTD_checkContinuity(dctx, dst);
+	dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
+	dctx->previousDstEnd = (char *)dst + dSize;
+	return dSize;
+}
+
+/** ZSTD_insertBlock() :
+	insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
+size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSize)
+{
+	ZSTD_checkContinuity(dctx, blockStart);
+	dctx->previousDstEnd = (const char *)blockStart + blockSize;
+	return blockSize;
+}
+
+static size_t ZSTD_generateNxBytes(void *dst, size_t dstCapacity, BYTE byte, size_t length)
+{
+	if (length > dstCapacity)
+		return ERROR(dstSize_tooSmall);
+	memset(dst, byte, length);
+	return length;
+}
+
+/** ZSTD_findFrameCompressedSize() :
+ *  compatible with legacy mode
+ *  `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
+ *  `srcSize` must be at least as large as the frame contained
+ *  @return : the compressed size of the frame starting at `src` */
+size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
+{
+	if (srcSize >= ZSTD_skippableHeaderSize && (ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+		return ZSTD_skippableHeaderSize + ZSTD_readLE32((const BYTE *)src + 4);
+	} else {
+		const BYTE *ip = (const BYTE *)src;
+		const BYTE *const ipstart = ip;
+		size_t remainingSize = srcSize;
+		ZSTD_frameParams fParams;
+
+		size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize);
+		if (ZSTD_isError(headerSize))
+			return headerSize;
+
+		/* Frame Header */
+		{
+			size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize);
+			if (ZSTD_isError(ret))
+				return ret;
+			if (ret > 0)
+				return ERROR(srcSize_wrong);
+		}
+
+		ip += headerSize;
+		remainingSize -= headerSize;
+
+		/* Loop on each block */
+		while (1) {
+			blockProperties_t blockProperties;
+			size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
+			if (ZSTD_isError(cBlockSize))
+				return cBlockSize;
+
+			if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
+				return ERROR(srcSize_wrong);
+
+			ip += ZSTD_blockHeaderSize + cBlockSize;
+			remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
+
+			if (blockProperties.lastBlock)
+				break;
+		}
+
+		if (fParams.checksumFlag) { /* Frame content checksum */
+			if (remainingSize < 4)
+				return ERROR(srcSize_wrong);
+			ip += 4;
+			remainingSize -= 4;
+		}
+
+		return ip - ipstart;
+	}
+}
+
+/*! ZSTD_decompressFrame() :
+*   @dctx must be properly initialized */
+static size_t ZSTD_decompressFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void **srcPtr, size_t *srcSizePtr)
+{
+	const BYTE *ip = (const BYTE *)(*srcPtr);
+	BYTE *const ostart = (BYTE * const)dst;
+	BYTE *const oend = ostart + dstCapacity;
+	BYTE *op = ostart;
+	size_t remainingSize = *srcSizePtr;
+
+	/* check */
+	if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize)
+		return ERROR(srcSize_wrong);
+
+	/* Frame Header */
+	{
+		size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
+		if (ZSTD_isError(frameHeaderSize))
+			return frameHeaderSize;
+		if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize)
+			return ERROR(srcSize_wrong);
+		CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
+		ip += frameHeaderSize;
+		remainingSize -= frameHeaderSize;
+	}
+
+	/* Loop on each block */
+	while (1) {
+		size_t decodedSize;
+		blockProperties_t blockProperties;
+		size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
+		if (ZSTD_isError(cBlockSize))
+			return cBlockSize;
+
+		ip += ZSTD_blockHeaderSize;
+		remainingSize -= ZSTD_blockHeaderSize;
+		if (cBlockSize > remainingSize)
+			return ERROR(srcSize_wrong);
+
+		switch (blockProperties.blockType) {
+		case bt_compressed: decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend - op, ip, cBlockSize); break;
+		case bt_raw: decodedSize = ZSTD_copyRawBlock(op, oend - op, ip, cBlockSize); break;
+		case bt_rle: decodedSize = ZSTD_generateNxBytes(op, oend - op, *ip, blockProperties.origSize); break;
+		case bt_reserved:
+		default: return ERROR(corruption_detected);
+		}
+
+		if (ZSTD_isError(decodedSize))
+			return decodedSize;
+		if (dctx->fParams.checksumFlag)
+			xxh64_update(&dctx->xxhState, op, decodedSize);
+		op += decodedSize;
+		ip += cBlockSize;
+		remainingSize -= cBlockSize;
+		if (blockProperties.lastBlock)
+			break;
+	}
+
+	if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
+		U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState);
+		U32 checkRead;
+		if (remainingSize < 4)
+			return ERROR(checksum_wrong);
+		checkRead = ZSTD_readLE32(ip);
+		if (checkRead != checkCalc)
+			return ERROR(checksum_wrong);
+		ip += 4;
+		remainingSize -= 4;
+	}
+
+	/* Allow caller to get size read */
+	*srcPtr = ip;
+	*srcSizePtr = remainingSize;
+	return op - ostart;
+}
+
+static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict);
+static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict);
+
+static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize,
+					const ZSTD_DDict *ddict)
+{
+	void *const dststart = dst;
+
+	if (ddict) {
+		if (dict) {
+			/* programmer error, these two cases should be mutually exclusive */
+			return ERROR(GENERIC);
+		}
+
+		dict = ZSTD_DDictDictContent(ddict);
+		dictSize = ZSTD_DDictDictSize(ddict);
+	}
+
+	while (srcSize >= ZSTD_frameHeaderSize_prefix) {
+		U32 magicNumber;
+
+		magicNumber = ZSTD_readLE32(src);
+		if (magicNumber != ZSTD_MAGICNUMBER) {
+			if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
+				size_t skippableSize;
+				if (srcSize < ZSTD_skippableHeaderSize)
+					return ERROR(srcSize_wrong);
+				skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize;
+				if (srcSize < skippableSize) {
+					return ERROR(srcSize_wrong);
+				}
+
+				src = (const BYTE *)src + skippableSize;
+				srcSize -= skippableSize;
+				continue;
+			} else {
+				return ERROR(prefix_unknown);
+			}
+		}
+
+		if (ddict) {
+			/* we were called from ZSTD_decompress_usingDDict */
+			ZSTD_refDDict(dctx, ddict);
+		} else {
+			/* this will initialize correctly with no dict if dict == NULL, so
+			 * use this in all cases but ddict */
+			CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
+		}
+		ZSTD_checkContinuity(dctx, dst);
+
+		{
+			const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, &src, &srcSize);
+			if (ZSTD_isError(res))
+				return res;
+			/* don't need to bounds check this, ZSTD_decompressFrame will have
+			 * already */
+			dst = (BYTE *)dst + res;
+			dstCapacity -= res;
+		}
+	}
+
+	if (srcSize)
+		return ERROR(srcSize_wrong); /* input not entirely consumed */
+
+	return (BYTE *)dst - (BYTE *)dststart;
+}
+
+size_t ZSTD_decompress_usingDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize)
+{
+	return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
+}
+
+size_t ZSTD_decompressDCtx(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+	return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
+}
+
+/*-**************************************
+*   Advanced Streaming Decompression API
+*   Bufferless and synchronous
+****************************************/
+size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx) { return dctx->expected; }
+
+ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx)
+{
+	switch (dctx->stage) {
+	default: /* should not happen */
+	case ZSTDds_getFrameHeaderSize:
+	case ZSTDds_decodeFrameHeader: return ZSTDnit_frameHeader;
+	case ZSTDds_decodeBlockHeader: return ZSTDnit_blockHeader;
+	case ZSTDds_decompressBlock: return ZSTDnit_block;
+	case ZSTDds_decompressLastBlock: return ZSTDnit_lastBlock;
+	case ZSTDds_checkChecksum: return ZSTDnit_checksum;
+	case ZSTDds_decodeSkippableHeader:
+	case ZSTDds_skipFrame: return ZSTDnit_skippableFrame;
+	}
+}
+
+int ZSTD_isSkipFrame(ZSTD_DCtx *dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */
+
+/** ZSTD_decompressContinue() :
+*   @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
+*             or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+	/* Sanity check */
+	if (srcSize != dctx->expected)
+		return ERROR(srcSize_wrong);
+	if (dstCapacity)
+		ZSTD_checkContinuity(dctx, dst);
+
+	switch (dctx->stage) {
+	case ZSTDds_getFrameHeaderSize:
+		if (srcSize != ZSTD_frameHeaderSize_prefix)
+			return ERROR(srcSize_wrong);					/* impossible */
+		if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+			memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
+			dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */
+			dctx->stage = ZSTDds_decodeSkippableHeader;
+			return 0;
+		}
+		dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
+		if (ZSTD_isError(dctx->headerSize))
+			return dctx->headerSize;
+		memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
+		if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) {
+			dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix;
+			dctx->stage = ZSTDds_decodeFrameHeader;
+			return 0;
+		}
+		dctx->expected = 0; /* not necessary to copy more */
+
+	case ZSTDds_decodeFrameHeader:
+		memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
+		CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
+		dctx->expected = ZSTD_blockHeaderSize;
+		dctx->stage = ZSTDds_decodeBlockHeader;
+		return 0;
+
+	case ZSTDds_decodeBlockHeader: {
+		blockProperties_t bp;
+		size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
+		if (ZSTD_isError(cBlockSize))
+			return cBlockSize;
+		dctx->expected = cBlockSize;
+		dctx->bType = bp.blockType;
+		dctx->rleSize = bp.origSize;
+		if (cBlockSize) {
+			dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;
+			return 0;
+		}
+		/* empty block */
+		if (bp.lastBlock) {
+			if (dctx->fParams.checksumFlag) {
+				dctx->expected = 4;
+				dctx->stage = ZSTDds_checkChecksum;
+			} else {
+				dctx->expected = 0; /* end of frame */
+				dctx->stage = ZSTDds_getFrameHeaderSize;
+			}
+		} else {
+			dctx->expected = 3; /* go directly to next header */
+			dctx->stage = ZSTDds_decodeBlockHeader;
+		}
+		return 0;
+	}
+	case ZSTDds_decompressLastBlock:
+	case ZSTDds_decompressBlock: {
+		size_t rSize;
+		switch (dctx->bType) {
+		case bt_compressed: rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize); break;
+		case bt_raw: rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); break;
+		case bt_rle: rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize); break;
+		case bt_reserved: /* should never happen */
+		default: return ERROR(corruption_detected);
+		}
+		if (ZSTD_isError(rSize))
+			return rSize;
+		if (dctx->fParams.checksumFlag)
+			xxh64_update(&dctx->xxhState, dst, rSize);
+
+		if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
+			if (dctx->fParams.checksumFlag) {	/* another round for frame checksum */
+				dctx->expected = 4;
+				dctx->stage = ZSTDds_checkChecksum;
+			} else {
+				dctx->expected = 0; /* ends here */
+				dctx->stage = ZSTDds_getFrameHeaderSize;
+			}
+		} else {
+			dctx->stage = ZSTDds_decodeBlockHeader;
+			dctx->expected = ZSTD_blockHeaderSize;
+			dctx->previousDstEnd = (char *)dst + rSize;
+		}
+		return rSize;
+	}
+	case ZSTDds_checkChecksum: {
+		U32 const h32 = (U32)xxh64_digest(&dctx->xxhState);
+		U32 const check32 = ZSTD_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */
+		if (check32 != h32)
+			return ERROR(checksum_wrong);
+		dctx->expected = 0;
+		dctx->stage = ZSTDds_getFrameHeaderSize;
+		return 0;
+	}
+	case ZSTDds_decodeSkippableHeader: {
+		memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
+		dctx->expected = ZSTD_readLE32(dctx->headerBuffer + 4);
+		dctx->stage = ZSTDds_skipFrame;
+		return 0;
+	}
+	case ZSTDds_skipFrame: {
+		dctx->expected = 0;
+		dctx->stage = ZSTDds_getFrameHeaderSize;
+		return 0;
+	}
+	default:
+		return ERROR(GENERIC); /* impossible */
+	}
+}
+
+static size_t ZSTD_refDictContent(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
+{
+	dctx->dictEnd = dctx->previousDstEnd;
+	dctx->vBase = (const char *)dict - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base));
+	dctx->base = dict;
+	dctx->previousDstEnd = (const char *)dict + dictSize;
+	return 0;
+}
+
+/* ZSTD_loadEntropy() :
+ * dict : must point at beginning of a valid zstd dictionary
+ * @return : size of entropy tables read */
+static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t *entropy, const void *const dict, size_t const dictSize)
+{
+	const BYTE *dictPtr = (const BYTE *)dict;
+	const BYTE *const dictEnd = dictPtr + dictSize;
+
+	if (dictSize <= 8)
+		return ERROR(dictionary_corrupted);
+	dictPtr += 8; /* skip header = magic + dictID */
+
+	{
+		size_t const hSize = HUF_readDTableX4_wksp(entropy->hufTable, dictPtr, dictEnd - dictPtr, entropy->workspace, sizeof(entropy->workspace));
+		if (HUF_isError(hSize))
+			return ERROR(dictionary_corrupted);
+		dictPtr += hSize;
+	}
+
+	{
+		short offcodeNCount[MaxOff + 1];
+		U32 offcodeMaxValue = MaxOff, offcodeLog;
+		size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd - dictPtr);
+		if (FSE_isError(offcodeHeaderSize))
+			return ERROR(dictionary_corrupted);
+		if (offcodeLog > OffFSELog)
+			return ERROR(dictionary_corrupted);
+		CHECK_E(FSE_buildDTable_wksp(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
+		dictPtr += offcodeHeaderSize;
+	}
+
+	{
+		short matchlengthNCount[MaxML + 1];
+		unsigned matchlengthMaxValue = MaxML, matchlengthLog;
+		size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd - dictPtr);
+		if (FSE_isError(matchlengthHeaderSize))
+			return ERROR(dictionary_corrupted);
+		if (matchlengthLog > MLFSELog)
+			return ERROR(dictionary_corrupted);
+		CHECK_E(FSE_buildDTable_wksp(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
+		dictPtr += matchlengthHeaderSize;
+	}
+
+	{
+		short litlengthNCount[MaxLL + 1];
+		unsigned litlengthMaxValue = MaxLL, litlengthLog;
+		size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd - dictPtr);
+		if (FSE_isError(litlengthHeaderSize))
+			return ERROR(dictionary_corrupted);
+		if (litlengthLog > LLFSELog)
+			return ERROR(dictionary_corrupted);
+		CHECK_E(FSE_buildDTable_wksp(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
+		dictPtr += litlengthHeaderSize;
+	}
+
+	if (dictPtr + 12 > dictEnd)
+		return ERROR(dictionary_corrupted);
+	{
+		int i;
+		size_t const dictContentSize = (size_t)(dictEnd - (dictPtr + 12));
+		for (i = 0; i < 3; i++) {
+			U32 const rep = ZSTD_readLE32(dictPtr);
+			dictPtr += 4;
+			if (rep == 0 || rep >= dictContentSize)
+				return ERROR(dictionary_corrupted);
+			entropy->rep[i] = rep;
+		}
+	}
+
+	return dictPtr - (const BYTE *)dict;
+}
+
+static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
+{
+	if (dictSize < 8)
+		return ZSTD_refDictContent(dctx, dict, dictSize);
+	{
+		U32 const magic = ZSTD_readLE32(dict);
+		if (magic != ZSTD_DICT_MAGIC) {
+			return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
+		}
+	}
+	dctx->dictID = ZSTD_readLE32((const char *)dict + 4);
+
+	/* load entropy tables */
+	{
+		size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
+		if (ZSTD_isError(eSize))
+			return ERROR(dictionary_corrupted);
+		dict = (const char *)dict + eSize;
+		dictSize -= eSize;
+	}
+	dctx->litEntropy = dctx->fseEntropy = 1;
+
+	/* reference dictionary content */
+	return ZSTD_refDictContent(dctx, dict, dictSize);
+}
+
+size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
+{
+	CHECK_F(ZSTD_decompressBegin(dctx));
+	if (dict && dictSize)
+		CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
+	return 0;
+}
+
+/* ======   ZSTD_DDict   ====== */
+
+struct ZSTD_DDict_s {
+	void *dictBuffer;
+	const void *dictContent;
+	size_t dictSize;
+	ZSTD_entropyTables_t entropy;
+	U32 dictID;
+	U32 entropyPresent;
+	ZSTD_customMem cMem;
+}; /* typedef'd to ZSTD_DDict within "zstd.h" */
+
+size_t ZSTD_DDictWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DDict)); }
+
+static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict) { return ddict->dictContent; }
+
+static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict) { return ddict->dictSize; }
+
+static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict)
+{
+	ZSTD_decompressBegin(dstDCtx); /* init */
+	if (ddict) {		       /* support refDDict on NULL */
+		dstDCtx->dictID = ddict->dictID;
+		dstDCtx->base = ddict->dictContent;
+		dstDCtx->vBase = ddict->dictContent;
+		dstDCtx->dictEnd = (const BYTE *)ddict->dictContent + ddict->dictSize;
+		dstDCtx->previousDstEnd = dstDCtx->dictEnd;
+		if (ddict->entropyPresent) {
+			dstDCtx->litEntropy = 1;
+			dstDCtx->fseEntropy = 1;
+			dstDCtx->LLTptr = ddict->entropy.LLTable;
+			dstDCtx->MLTptr = ddict->entropy.MLTable;
+			dstDCtx->OFTptr = ddict->entropy.OFTable;
+			dstDCtx->HUFptr = ddict->entropy.hufTable;
+			dstDCtx->entropy.rep[0] = ddict->entropy.rep[0];
+			dstDCtx->entropy.rep[1] = ddict->entropy.rep[1];
+			dstDCtx->entropy.rep[2] = ddict->entropy.rep[2];
+		} else {
+			dstDCtx->litEntropy = 0;
+			dstDCtx->fseEntropy = 0;
+		}
+	}
+}
+
+static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict *ddict)
+{
+	ddict->dictID = 0;
+	ddict->entropyPresent = 0;
+	if (ddict->dictSize < 8)
+		return 0;
+	{
+		U32 const magic = ZSTD_readLE32(ddict->dictContent);
+		if (magic != ZSTD_DICT_MAGIC)
+			return 0; /* pure content mode */
+	}
+	ddict->dictID = ZSTD_readLE32((const char *)ddict->dictContent + 4);
+
+	/* load entropy tables */
+	CHECK_E(ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted);
+	ddict->entropyPresent = 1;
+	return 0;
+}
+
+static ZSTD_DDict *ZSTD_createDDict_advanced(const void *dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
+{
+	if (!customMem.customAlloc || !customMem.customFree)
+		return NULL;
+
+	{
+		ZSTD_DDict *const ddict = (ZSTD_DDict *)ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
+		if (!ddict)
+			return NULL;
+		ddict->cMem = customMem;
+
+		if ((byReference) || (!dict) || (!dictSize)) {
+			ddict->dictBuffer = NULL;
+			ddict->dictContent = dict;
+		} else {
+			void *const internalBuffer = ZSTD_malloc(dictSize, customMem);
+			if (!internalBuffer) {
+				ZSTD_freeDDict(ddict);
+				return NULL;
+			}
+			memcpy(internalBuffer, dict, dictSize);
+			ddict->dictBuffer = internalBuffer;
+			ddict->dictContent = internalBuffer;
+		}
+		ddict->dictSize = dictSize;
+		ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+		/* parse dictionary content */
+		{
+			size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict);
+			if (ZSTD_isError(errorCode)) {
+				ZSTD_freeDDict(ddict);
+				return NULL;
+			}
+		}
+
+		return ddict;
+	}
+}
+
+/*! ZSTD_initDDict() :
+*   Create a digested dictionary, to start decompression without startup delay.
+*   `dict` content is copied inside DDict.
+*   Consequently, `dict` can be released after `ZSTD_DDict` creation */
+ZSTD_DDict *ZSTD_initDDict(const void *dict, size_t dictSize, void *workspace, size_t workspaceSize)
+{
+	ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
+	return ZSTD_createDDict_advanced(dict, dictSize, 1, stackMem);
+}
+
+size_t ZSTD_freeDDict(ZSTD_DDict *ddict)
+{
+	if (ddict == NULL)
+		return 0; /* support free on NULL */
+	{
+		ZSTD_customMem const cMem = ddict->cMem;
+		ZSTD_free(ddict->dictBuffer, cMem);
+		ZSTD_free(ddict, cMem);
+		return 0;
+	}
+}
+
+/*! ZSTD_getDictID_fromDict() :
+ *  Provides the dictID stored within dictionary.
+ *  if @return == 0, the dictionary is not conformant with Zstandard specification.
+ *  It can still be loaded, but as a content-only dictionary. */
+unsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize)
+{
+	if (dictSize < 8)
+		return 0;
+	if (ZSTD_readLE32(dict) != ZSTD_DICT_MAGIC)
+		return 0;
+	return ZSTD_readLE32((const char *)dict + 4);
+}
+
+/*! ZSTD_getDictID_fromDDict() :
+ *  Provides the dictID of the dictionary loaded into `ddict`.
+ *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict)
+{
+	if (ddict == NULL)
+		return 0;
+	return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
+}
+
+/*! ZSTD_getDictID_fromFrame() :
+ *  Provides the dictID required to decompressed the frame stored within `src`.
+ *  If @return == 0, the dictID could not be decoded.
+ *  This could for one of the following reasons :
+ *  - The frame does not require a dictionary to be decoded (most common case).
+ *  - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
+ *    Note : this use case also happens when using a non-conformant dictionary.
+ *  - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
+ *  - This is not a Zstandard frame.
+ *  When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
+unsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize)
+{
+	ZSTD_frameParams zfp = {0, 0, 0, 0};
+	size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize);
+	if (ZSTD_isError(hError))
+		return 0;
+	return zfp.dictID;
+}
+
+/*! ZSTD_decompress_usingDDict() :
+*   Decompression using a pre-digested Dictionary
+*   Use dictionary without significant overhead. */
+size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const ZSTD_DDict *ddict)
+{
+	/* pass content and size in case legacy frames are encountered */
+	return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, NULL, 0, ddict);
+}
+
+/*=====================================
+*   Streaming decompression
+*====================================*/
+
+typedef enum { zdss_init, zdss_loadHeader, zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
+
+/* *** Resource management *** */
+struct ZSTD_DStream_s {
+	ZSTD_DCtx *dctx;
+	ZSTD_DDict *ddictLocal;
+	const ZSTD_DDict *ddict;
+	ZSTD_frameParams fParams;
+	ZSTD_dStreamStage stage;
+	char *inBuff;
+	size_t inBuffSize;
+	size_t inPos;
+	size_t maxWindowSize;
+	char *outBuff;
+	size_t outBuffSize;
+	size_t outStart;
+	size_t outEnd;
+	size_t blockSize;
+	BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
+	size_t lhSize;
+	ZSTD_customMem customMem;
+	void *legacyContext;
+	U32 previousLegacyVersion;
+	U32 legacyVersion;
+	U32 hostageByte;
+}; /* typedef'd to ZSTD_DStream within "zstd.h" */
+
+size_t ZSTD_DStreamWorkspaceBound(size_t maxWindowSize)
+{
+	size_t const blockSize = MIN(maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+	size_t const inBuffSize = blockSize;
+	size_t const outBuffSize = maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+	return ZSTD_DCtxWorkspaceBound() + ZSTD_ALIGN(sizeof(ZSTD_DStream)) + ZSTD_ALIGN(inBuffSize) + ZSTD_ALIGN(outBuffSize);
+}
+
+static ZSTD_DStream *ZSTD_createDStream_advanced(ZSTD_customMem customMem)
+{
+	ZSTD_DStream *zds;
+
+	if (!customMem.customAlloc || !customMem.customFree)
+		return NULL;
+
+	zds = (ZSTD_DStream *)ZSTD_malloc(sizeof(ZSTD_DStream), customMem);
+	if (zds == NULL)
+		return NULL;
+	memset(zds, 0, sizeof(ZSTD_DStream));
+	memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem));
+	zds->dctx = ZSTD_createDCtx_advanced(customMem);
+	if (zds->dctx == NULL) {
+		ZSTD_freeDStream(zds);
+		return NULL;
+	}
+	zds->stage = zdss_init;
+	zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
+	return zds;
+}
+
+ZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace, size_t workspaceSize)
+{
+	ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
+	ZSTD_DStream *zds = ZSTD_createDStream_advanced(stackMem);
+	if (!zds) {
+		return NULL;
+	}
+
+	zds->maxWindowSize = maxWindowSize;
+	zds->stage = zdss_loadHeader;
+	zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+	ZSTD_freeDDict(zds->ddictLocal);
+	zds->ddictLocal = NULL;
+	zds->ddict = zds->ddictLocal;
+	zds->legacyVersion = 0;
+	zds->hostageByte = 0;
+
+	{
+		size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+		size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+
+		zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
+		zds->inBuffSize = blockSize;
+		zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
+		zds->outBuffSize = neededOutSize;
+		if (zds->inBuff == NULL || zds->outBuff == NULL) {
+			ZSTD_freeDStream(zds);
+			return NULL;
+		}
+	}
+	return zds;
+}
+
+ZSTD_DStream *ZSTD_initDStream_usingDDict(size_t maxWindowSize, const ZSTD_DDict *ddict, void *workspace, size_t workspaceSize)
+{
+	ZSTD_DStream *zds = ZSTD_initDStream(maxWindowSize, workspace, workspaceSize);
+	if (zds) {
+		zds->ddict = ddict;
+	}
+	return zds;
+}
+
+size_t ZSTD_freeDStream(ZSTD_DStream *zds)
+{
+	if (zds == NULL)
+		return 0; /* support free on null */
+	{
+		ZSTD_customMem const cMem = zds->customMem;
+		ZSTD_freeDCtx(zds->dctx);
+		zds->dctx = NULL;
+		ZSTD_freeDDict(zds->ddictLocal);
+		zds->ddictLocal = NULL;
+		ZSTD_free(zds->inBuff, cMem);
+		zds->inBuff = NULL;
+		ZSTD_free(zds->outBuff, cMem);
+		zds->outBuff = NULL;
+		ZSTD_free(zds, cMem);
+		return 0;
+	}
+}
+
+/* *** Initialization *** */
+
+size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; }
+size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
+
+size_t ZSTD_resetDStream(ZSTD_DStream *zds)
+{
+	zds->stage = zdss_loadHeader;
+	zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+	zds->legacyVersion = 0;
+	zds->hostageByte = 0;
+	return ZSTD_frameHeaderSize_prefix;
+}
+
+/* *****   Decompression   ***** */
+
+ZSTD_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
+{
+	size_t const length = MIN(dstCapacity, srcSize);
+	memcpy(dst, src, length);
+	return length;
+}
+
+size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
+{
+	const char *const istart = (const char *)(input->src) + input->pos;
+	const char *const iend = (const char *)(input->src) + input->size;
+	const char *ip = istart;
+	char *const ostart = (char *)(output->dst) + output->pos;
+	char *const oend = (char *)(output->dst) + output->size;
+	char *op = ostart;
+	U32 someMoreWork = 1;
+
+	while (someMoreWork) {
+		switch (zds->stage) {
+		case zdss_init:
+			ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
+						/* fall-through */
+
+		case zdss_loadHeader: {
+			size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize);
+			if (ZSTD_isError(hSize))
+				return hSize;
+			if (hSize != 0) {				   /* need more input */
+				size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
+				if (toLoad > (size_t)(iend - ip)) {	/* not enough input to load full header */
+					memcpy(zds->headerBuffer + zds->lhSize, ip, iend - ip);
+					zds->lhSize += iend - ip;
+					input->pos = input->size;
+					return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) +
+					       ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
+				}
+				memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad);
+				zds->lhSize = hSize;
+				ip += toLoad;
+				break;
+			}
+
+			/* check for single-pass mode opportunity */
+			if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
+			    && (U64)(size_t)(oend - op) >= zds->fParams.frameContentSize) {
+				size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend - istart);
+				if (cSize <= (size_t)(iend - istart)) {
+					size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend - op, istart, cSize, zds->ddict);
+					if (ZSTD_isError(decompressedSize))
+						return decompressedSize;
+					ip = istart + cSize;
+					op += decompressedSize;
+					zds->dctx->expected = 0;
+					zds->stage = zdss_init;
+					someMoreWork = 0;
+					break;
+				}
+			}
+
+			/* Consume header */
+			ZSTD_refDDict(zds->dctx, zds->ddict);
+			{
+				size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
+				CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
+				{
+					size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+					CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer + h1Size, h2Size));
+				}
+			}
+
+			zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
+			if (zds->fParams.windowSize > zds->maxWindowSize)
+				return ERROR(frameParameter_windowTooLarge);
+
+			/* Buffers are preallocated, but double check */
+			{
+				size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+				size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+				if (zds->inBuffSize < blockSize) {
+					return ERROR(GENERIC);
+				}
+				if (zds->outBuffSize < neededOutSize) {
+					return ERROR(GENERIC);
+				}
+				zds->blockSize = blockSize;
+			}
+			zds->stage = zdss_read;
+		}
+		/* pass-through */
+
+		case zdss_read: {
+			size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+			if (neededInSize == 0) { /* end of frame */
+				zds->stage = zdss_init;
+				someMoreWork = 0;
+				break;
+			}
+			if ((size_t)(iend - ip) >= neededInSize) { /* decode directly from src */
+				const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
+				size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart,
+										   (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), ip, neededInSize);
+				if (ZSTD_isError(decodedSize))
+					return decodedSize;
+				ip += neededInSize;
+				if (!decodedSize && !isSkipFrame)
+					break; /* this was just a header */
+				zds->outEnd = zds->outStart + decodedSize;
+				zds->stage = zdss_flush;
+				break;
+			}
+			if (ip == iend) {
+				someMoreWork = 0;
+				break;
+			} /* no more input */
+			zds->stage = zdss_load;
+			/* pass-through */
+		}
+
+		case zdss_load: {
+			size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+			size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */
+			size_t loadedSize;
+			if (toLoad > zds->inBuffSize - zds->inPos)
+				return ERROR(corruption_detected); /* should never happen */
+			loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend - ip);
+			ip += loadedSize;
+			zds->inPos += loadedSize;
+			if (loadedSize < toLoad) {
+				someMoreWork = 0;
+				break;
+			} /* not enough input, wait for more */
+
+			/* decode loaded input */
+			{
+				const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
+				size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
+										   zds->inBuff, neededInSize);
+				if (ZSTD_isError(decodedSize))
+					return decodedSize;
+				zds->inPos = 0; /* input is consumed */
+				if (!decodedSize && !isSkipFrame) {
+					zds->stage = zdss_read;
+					break;
+				} /* this was just a header */
+				zds->outEnd = zds->outStart + decodedSize;
+				zds->stage = zdss_flush;
+				/* pass-through */
+			}
+		}
+
+		case zdss_flush: {
+			size_t const toFlushSize = zds->outEnd - zds->outStart;
+			size_t const flushedSize = ZSTD_limitCopy(op, oend - op, zds->outBuff + zds->outStart, toFlushSize);
+			op += flushedSize;
+			zds->outStart += flushedSize;
+			if (flushedSize == toFlushSize) { /* flush completed */
+				zds->stage = zdss_read;
+				if (zds->outStart + zds->blockSize > zds->outBuffSize)
+					zds->outStart = zds->outEnd = 0;
+				break;
+			}
+			/* cannot complete flush */
+			someMoreWork = 0;
+			break;
+		}
+		default:
+			return ERROR(GENERIC); /* impossible */
+		}
+	}
+
+	/* result */
+	input->pos += (size_t)(ip - istart);
+	output->pos += (size_t)(op - ostart);
+	{
+		size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx);
+		if (!nextSrcSizeHint) {			    /* frame fully decoded */
+			if (zds->outEnd == zds->outStart) { /* output fully flushed */
+				if (zds->hostageByte) {
+					if (input->pos >= input->size) {
+						zds->stage = zdss_read;
+						return 1;
+					}	     /* can't release hostage (not present) */
+					input->pos++; /* release hostage */
+				}
+				return 0;
+			}
+			if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
+				input->pos--;    /* note : pos > 0, otherwise, impossible to finish reading last block */
+				zds->hostageByte = 1;
+			}
+			return 1;
+		}
+		nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */
+		if (zds->inPos > nextSrcSizeHint)
+			return ERROR(GENERIC); /* should never happen */
+		nextSrcSizeHint -= zds->inPos; /* already loaded*/
+		return nextSrcSizeHint;
+	}
+}
+
+EXPORT_SYMBOL(ZSTD_DCtxWorkspaceBound);
+EXPORT_SYMBOL(ZSTD_initDCtx);
+EXPORT_SYMBOL(ZSTD_decompressDCtx);
+EXPORT_SYMBOL(ZSTD_decompress_usingDict);
+
+EXPORT_SYMBOL(ZSTD_DDictWorkspaceBound);
+EXPORT_SYMBOL(ZSTD_initDDict);
+EXPORT_SYMBOL(ZSTD_decompress_usingDDict);
+
+EXPORT_SYMBOL(ZSTD_DStreamWorkspaceBound);
+EXPORT_SYMBOL(ZSTD_initDStream);
+EXPORT_SYMBOL(ZSTD_initDStream_usingDDict);
+EXPORT_SYMBOL(ZSTD_resetDStream);
+EXPORT_SYMBOL(ZSTD_decompressStream);
+EXPORT_SYMBOL(ZSTD_DStreamInSize);
+EXPORT_SYMBOL(ZSTD_DStreamOutSize);
+
+EXPORT_SYMBOL(ZSTD_findFrameCompressedSize);
+EXPORT_SYMBOL(ZSTD_getFrameContentSize);
+EXPORT_SYMBOL(ZSTD_findDecompressedSize);
+
+EXPORT_SYMBOL(ZSTD_isFrame);
+EXPORT_SYMBOL(ZSTD_getDictID_fromDict);
+EXPORT_SYMBOL(ZSTD_getDictID_fromDDict);
+EXPORT_SYMBOL(ZSTD_getDictID_fromFrame);
+
+EXPORT_SYMBOL(ZSTD_getFrameParams);
+EXPORT_SYMBOL(ZSTD_decompressBegin);
+EXPORT_SYMBOL(ZSTD_decompressBegin_usingDict);
+EXPORT_SYMBOL(ZSTD_copyDCtx);
+EXPORT_SYMBOL(ZSTD_nextSrcSizeToDecompress);
+EXPORT_SYMBOL(ZSTD_decompressContinue);
+EXPORT_SYMBOL(ZSTD_nextInputType);
+
+EXPORT_SYMBOL(ZSTD_decompressBlock);
+EXPORT_SYMBOL(ZSTD_insertBlock);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Zstd Decompressor");
diff --git a/lib/zstd/decompress/huf_decompress.c b/lib/zstd/decompress/huf_decompress.c
deleted file mode 100644
index 5105e59ac04a..000000000000
--- a/lib/zstd/decompress/huf_decompress.c
+++ /dev/null
@@ -1,1206 +0,0 @@
-/* ******************************************************************
- * huff0 huffman decoder,
- * part of Finite State Entropy library
- * Copyright (c) Yann Collet, Facebook, Inc.
- *
- *  You can contact the author at :
- *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
-****************************************************************** */
-
-/* **************************************************************
-*  Dependencies
-****************************************************************/
-#include "../common/zstd_deps.h"  /* ZSTD_memcpy, ZSTD_memset */
-#include "../common/compiler.h"
-#include "../common/bitstream.h"  /* BIT_* */
-#include "../common/fse.h"        /* to compress headers */
-#define HUF_STATIC_LINKING_ONLY
-#include "../common/huf.h"
-#include "../common/error_private.h"
-
-/* **************************************************************
-*  Macros
-****************************************************************/
-
-/* These two optional macros force the use one way or another of the two
- * Huffman decompression implementations. You can't force in both directions
- * at the same time.
- */
-#if defined(HUF_FORCE_DECOMPRESS_X1) && \
-    defined(HUF_FORCE_DECOMPRESS_X2)
-#error "Cannot force the use of the X1 and X2 decoders at the same time!"
-#endif
-
-
-/* **************************************************************
-*  Error Management
-****************************************************************/
-#define HUF_isError ERR_isError
-
-
-/* **************************************************************
-*  Byte alignment for workSpace management
-****************************************************************/
-#define HUF_ALIGN(x, a)         HUF_ALIGN_MASK((x), (a) - 1)
-#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
-
-
-/* **************************************************************
-*  BMI2 Variant Wrappers
-****************************************************************/
-#if DYNAMIC_BMI2
-
-#define HUF_DGEN(fn)                                                        \
-                                                                            \
-    static size_t fn##_default(                                             \
-                  void* dst,  size_t dstSize,                               \
-            const void* cSrc, size_t cSrcSize,                              \
-            const HUF_DTable* DTable)                                       \
-    {                                                                       \
-        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
-    }                                                                       \
-                                                                            \
-    static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2(                       \
-                  void* dst,  size_t dstSize,                               \
-            const void* cSrc, size_t cSrcSize,                              \
-            const HUF_DTable* DTable)                                       \
-    {                                                                       \
-        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
-    }                                                                       \
-                                                                            \
-    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \
-                     size_t cSrcSize, HUF_DTable const* DTable, int bmi2)   \
-    {                                                                       \
-        if (bmi2) {                                                         \
-            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \
-        }                                                                   \
-        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \
-    }
-
-#else
-
-#define HUF_DGEN(fn)                                                        \
-    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \
-                     size_t cSrcSize, HUF_DTable const* DTable, int bmi2)   \
-    {                                                                       \
-        (void)bmi2;                                                         \
-        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \
-    }
-
-#endif
-
-
-/*-***************************/
-/*  generic DTableDesc       */
-/*-***************************/
-typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
-
-static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
-{
-    DTableDesc dtd;
-    ZSTD_memcpy(&dtd, table, sizeof(dtd));
-    return dtd;
-}
-
-
-#ifndef HUF_FORCE_DECOMPRESS_X2
-
-/*-***************************/
-/*  single-symbol decoding   */
-/*-***************************/
-typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1;   /* single-symbol decoding */
-
-/*
- * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at
- * a time.
- */
-static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {
-    U64 D4;
-    if (MEM_isLittleEndian()) {
-        D4 = symbol + (nbBits << 8);
-    } else {
-        D4 = (symbol << 8) + nbBits;
-    }
-    D4 *= 0x0001000100010001ULL;
-    return D4;
-}
-
-typedef struct {
-        U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];
-        U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1];
-        U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
-        BYTE symbols[HUF_SYMBOLVALUE_MAX + 1];
-        BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
-} HUF_ReadDTableX1_Workspace;
-
-
-size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
-{
-    return HUF_readDTableX1_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0);
-}
-
-size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2)
-{
-    U32 tableLog = 0;
-    U32 nbSymbols = 0;
-    size_t iSize;
-    void* const dtPtr = DTable + 1;
-    HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;
-    HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace;
-
-    DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp));
-    if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge);
-
-    DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
-    /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */
-
-    iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), bmi2);
-    if (HUF_isError(iSize)) return iSize;
-
-    /* Table header */
-    {   DTableDesc dtd = HUF_getDTableDesc(DTable);
-        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, Huffman tree cannot fit in */
-        dtd.tableType = 0;
-        dtd.tableLog = (BYTE)tableLog;
-        ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
-    }
-
-    /* Compute symbols and rankStart given rankVal:
-     *
-     * rankVal already contains the number of values of each weight.
-     *
-     * symbols contains the symbols ordered by weight. First are the rankVal[0]
-     * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on.
-     * symbols[0] is filled (but unused) to avoid a branch.
-     *
-     * rankStart contains the offset where each rank belongs in the DTable.
-     * rankStart[0] is not filled because there are no entries in the table for
-     * weight 0.
-     */
-    {
-        int n;
-        int nextRankStart = 0;
-        int const unroll = 4;
-        int const nLimit = (int)nbSymbols - unroll + 1;
-        for (n=0; n<(int)tableLog+1; n++) {
-            U32 const curr = nextRankStart;
-            nextRankStart += wksp->rankVal[n];
-            wksp->rankStart[n] = curr;
-        }
-        for (n=0; n < nLimit; n += unroll) {
-            int u;
-            for (u=0; u < unroll; ++u) {
-                size_t const w = wksp->huffWeight[n+u];
-                wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u);
-            }
-        }
-        for (; n < (int)nbSymbols; ++n) {
-            size_t const w = wksp->huffWeight[n];
-            wksp->symbols[wksp->rankStart[w]++] = (BYTE)n;
-        }
-    }
-
-    /* fill DTable
-     * We fill all entries of each weight in order.
-     * That way length is a constant for each iteration of the outter loop.
-     * We can switch based on the length to a different inner loop which is
-     * optimized for that particular case.
-     */
-    {
-        U32 w;
-        int symbol=wksp->rankVal[0];
-        int rankStart=0;
-        for (w=1; w<tableLog+1; ++w) {
-            int const symbolCount = wksp->rankVal[w];
-            int const length = (1 << w) >> 1;
-            int uStart = rankStart;
-            BYTE const nbBits = (BYTE)(tableLog + 1 - w);
-            int s;
-            int u;
-            switch (length) {
-            case 1:
-                for (s=0; s<symbolCount; ++s) {
-                    HUF_DEltX1 D;
-                    D.byte = wksp->symbols[symbol + s];
-                    D.nbBits = nbBits;
-                    dt[uStart] = D;
-                    uStart += 1;
-                }
-                break;
-            case 2:
-                for (s=0; s<symbolCount; ++s) {
-                    HUF_DEltX1 D;
-                    D.byte = wksp->symbols[symbol + s];
-                    D.nbBits = nbBits;
-                    dt[uStart+0] = D;
-                    dt[uStart+1] = D;
-                    uStart += 2;
-                }
-                break;
-            case 4:
-                for (s=0; s<symbolCount; ++s) {
-                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
-                    MEM_write64(dt + uStart, D4);
-                    uStart += 4;
-                }
-                break;
-            case 8:
-                for (s=0; s<symbolCount; ++s) {
-                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
-                    MEM_write64(dt + uStart, D4);
-                    MEM_write64(dt + uStart + 4, D4);
-                    uStart += 8;
-                }
-                break;
-            default:
-                for (s=0; s<symbolCount; ++s) {
-                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
-                    for (u=0; u < length; u += 16) {
-                        MEM_write64(dt + uStart + u + 0, D4);
-                        MEM_write64(dt + uStart + u + 4, D4);
-                        MEM_write64(dt + uStart + u + 8, D4);
-                        MEM_write64(dt + uStart + u + 12, D4);
-                    }
-                    assert(u == length);
-                    uStart += length;
-                }
-                break;
-            }
-            symbol += symbolCount;
-            rankStart += symbolCount * length;
-        }
-    }
-    return iSize;
-}
-
-FORCE_INLINE_TEMPLATE BYTE
-HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)
-{
-    size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
-    BYTE const c = dt[val].byte;
-    BIT_skipBits(Dstream, dt[val].nbBits);
-    return c;
-}
-
-#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \
-    *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr)  \
-    if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
-        HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
-
-#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \
-    if (MEM_64bits()) \
-        HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
-
-HINT_INLINE size_t
-HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)
-{
-    BYTE* const pStart = p;
-
-    /* up to 4 symbols at a time */
-    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
-        HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
-        HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
-        HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
-        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
-    }
-
-    /* [0-3] symbols remaining */
-    if (MEM_32bits())
-        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))
-            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
-
-    /* no more data to retrieve from bitstream, no need to reload */
-    while (p < pEnd)
-        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
-
-    return pEnd-pStart;
-}
-
-FORCE_INLINE_TEMPLATE size_t
-HUF_decompress1X1_usingDTable_internal_body(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    BYTE* op = (BYTE*)dst;
-    BYTE* const oend = op + dstSize;
-    const void* dtPtr = DTable + 1;
-    const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
-    BIT_DStream_t bitD;
-    DTableDesc const dtd = HUF_getDTableDesc(DTable);
-    U32 const dtLog = dtd.tableLog;
-
-    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
-
-    HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);
-
-    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
-
-    return dstSize;
-}
-
-FORCE_INLINE_TEMPLATE size_t
-HUF_decompress4X1_usingDTable_internal_body(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    /* Check */
-    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */
-
-    {   const BYTE* const istart = (const BYTE*) cSrc;
-        BYTE* const ostart = (BYTE*) dst;
-        BYTE* const oend = ostart + dstSize;
-        BYTE* const olimit = oend - 3;
-        const void* const dtPtr = DTable + 1;
-        const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
-
-        /* Init */
-        BIT_DStream_t bitD1;
-        BIT_DStream_t bitD2;
-        BIT_DStream_t bitD3;
-        BIT_DStream_t bitD4;
-        size_t const length1 = MEM_readLE16(istart);
-        size_t const length2 = MEM_readLE16(istart+2);
-        size_t const length3 = MEM_readLE16(istart+4);
-        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
-        const BYTE* const istart1 = istart + 6;  /* jumpTable */
-        const BYTE* const istart2 = istart1 + length1;
-        const BYTE* const istart3 = istart2 + length2;
-        const BYTE* const istart4 = istart3 + length3;
-        const size_t segmentSize = (dstSize+3) / 4;
-        BYTE* const opStart2 = ostart + segmentSize;
-        BYTE* const opStart3 = opStart2 + segmentSize;
-        BYTE* const opStart4 = opStart3 + segmentSize;
-        BYTE* op1 = ostart;
-        BYTE* op2 = opStart2;
-        BYTE* op3 = opStart3;
-        BYTE* op4 = opStart4;
-        DTableDesc const dtd = HUF_getDTableDesc(DTable);
-        U32 const dtLog = dtd.tableLog;
-        U32 endSignal = 1;
-
-        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
-        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
-        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
-        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
-        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
-
-        /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
-        for ( ; (endSignal) & (op4 < olimit) ; ) {
-            HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
-            HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
-            HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
-            HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
-            HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
-            HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
-            HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
-            HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
-            HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
-            HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
-            HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
-            HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
-            HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
-            HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
-            HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
-            HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
-            endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
-            endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
-            endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
-            endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
-        }
-
-        /* check corruption */
-        /* note : should not be necessary : op# advance in lock step, and we control op4.
-         *        but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */
-        if (op1 > opStart2) return ERROR(corruption_detected);
-        if (op2 > opStart3) return ERROR(corruption_detected);
-        if (op3 > opStart4) return ERROR(corruption_detected);
-        /* note : op4 supposed already verified within main loop */
-
-        /* finish bitStreams one by one */
-        HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);
-        HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);
-        HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);
-        HUF_decodeStreamX1(op4, &bitD4, oend,     dt, dtLog);
-
-        /* check */
-        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
-          if (!endCheck) return ERROR(corruption_detected); }
-
-        /* decoded size */
-        return dstSize;
-    }
-}
-
-
-typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
-                                               const void *cSrc,
-                                               size_t cSrcSize,
-                                               const HUF_DTable *DTable);
-
-HUF_DGEN(HUF_decompress1X1_usingDTable_internal)
-HUF_DGEN(HUF_decompress4X1_usingDTable_internal)
-
-
-
-size_t HUF_decompress1X1_usingDTable(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    DTableDesc dtd = HUF_getDTableDesc(DTable);
-    if (dtd.tableType != 0) return ERROR(GENERIC);
-    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-}
-
-size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
-                                   const void* cSrc, size_t cSrcSize,
-                                   void* workSpace, size_t wkspSize)
-{
-    const BYTE* ip = (const BYTE*) cSrc;
-
-    size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
-    if (HUF_isError(hSize)) return hSize;
-    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
-    ip += hSize; cSrcSize -= hSize;
-
-    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
-}
-
-
-size_t HUF_decompress4X1_usingDTable(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    DTableDesc dtd = HUF_getDTableDesc(DTable);
-    if (dtd.tableType != 0) return ERROR(GENERIC);
-    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-}
-
-static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
-                                   const void* cSrc, size_t cSrcSize,
-                                   void* workSpace, size_t wkspSize, int bmi2)
-{
-    const BYTE* ip = (const BYTE*) cSrc;
-
-    size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
-    if (HUF_isError(hSize)) return hSize;
-    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
-    ip += hSize; cSrcSize -= hSize;
-
-    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
-}
-
-size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
-                                   const void* cSrc, size_t cSrcSize,
-                                   void* workSpace, size_t wkspSize)
-{
-    return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);
-}
-
-
-#endif /* HUF_FORCE_DECOMPRESS_X2 */
-
-
-#ifndef HUF_FORCE_DECOMPRESS_X1
-
-/* *************************/
-/* double-symbols decoding */
-/* *************************/
-
-typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2;  /* double-symbols decoding */
-typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
-typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
-typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
-
-
-/* HUF_fillDTableX2Level2() :
- * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
-static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,
-                           const U32* rankValOrigin, const int minWeight,
-                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
-                           U32 nbBitsBaseline, U16 baseSeq, U32* wksp, size_t wkspSize)
-{
-    HUF_DEltX2 DElt;
-    U32* rankVal = wksp;
-
-    assert(wkspSize >= HUF_TABLELOG_MAX + 1);
-    (void)wkspSize;
-    /* get pre-calculated rankVal */
-    ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
-
-    /* fill skipped values */
-    if (minWeight>1) {
-        U32 i, skipSize = rankVal[minWeight];
-        MEM_writeLE16(&(DElt.sequence), baseSeq);
-        DElt.nbBits   = (BYTE)(consumed);
-        DElt.length   = 1;
-        for (i = 0; i < skipSize; i++)
-            DTable[i] = DElt;
-    }
-
-    /* fill DTable */
-    {   U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */
-            const U32 symbol = sortedSymbols[s].symbol;
-            const U32 weight = sortedSymbols[s].weight;
-            const U32 nbBits = nbBitsBaseline - weight;
-            const U32 length = 1 << (sizeLog-nbBits);
-            const U32 start = rankVal[weight];
-            U32 i = start;
-            const U32 end = start + length;
-
-            MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
-            DElt.nbBits = (BYTE)(nbBits + consumed);
-            DElt.length = 2;
-            do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */
-
-            rankVal[weight] += length;
-    }   }
-}
-
-
-static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
-                           const sortedSymbol_t* sortedList, const U32 sortedListSize,
-                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
-                           const U32 nbBitsBaseline, U32* wksp, size_t wkspSize)
-{
-    U32* rankVal = wksp;
-    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */
-    const U32 minBits  = nbBitsBaseline - maxWeight;
-    U32 s;
-
-    assert(wkspSize >= HUF_TABLELOG_MAX + 1);
-    wksp += HUF_TABLELOG_MAX + 1;
-    wkspSize -= HUF_TABLELOG_MAX + 1;
-
-    ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
-
-    /* fill DTable */
-    for (s=0; s<sortedListSize; s++) {
-        const U16 symbol = sortedList[s].symbol;
-        const U32 weight = sortedList[s].weight;
-        const U32 nbBits = nbBitsBaseline - weight;
-        const U32 start = rankVal[weight];
-        const U32 length = 1 << (targetLog-nbBits);
-
-        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */
-            U32 sortedRank;
-            int minWeight = nbBits + scaleLog;
-            if (minWeight < 1) minWeight = 1;
-            sortedRank = rankStart[minWeight];
-            HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,
-                           rankValOrigin[nbBits], minWeight,
-                           sortedList+sortedRank, sortedListSize-sortedRank,
-                           nbBitsBaseline, symbol, wksp, wkspSize);
-        } else {
-            HUF_DEltX2 DElt;
-            MEM_writeLE16(&(DElt.sequence), symbol);
-            DElt.nbBits = (BYTE)(nbBits);
-            DElt.length = 1;
-            {   U32 const end = start + length;
-                U32 u;
-                for (u = start; u < end; u++) DTable[u] = DElt;
-        }   }
-        rankVal[weight] += length;
-    }
-}
-
-typedef struct {
-    rankValCol_t rankVal[HUF_TABLELOG_MAX];
-    U32 rankStats[HUF_TABLELOG_MAX + 1];
-    U32 rankStart0[HUF_TABLELOG_MAX + 2];
-    sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];
-    BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];
-    U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
-} HUF_ReadDTableX2_Workspace;
-
-size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
-                       const void* src, size_t srcSize,
-                             void* workSpace, size_t wkspSize)
-{
-    U32 tableLog, maxW, sizeOfSort, nbSymbols;
-    DTableDesc dtd = HUF_getDTableDesc(DTable);
-    U32 const maxTableLog = dtd.maxTableLog;
-    size_t iSize;
-    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */
-    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
-    U32 *rankStart;
-
-    HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;
-
-    if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);
-
-    rankStart = wksp->rankStart0 + 1;
-    ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));
-    ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));
-
-    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable));   /* if compiler fails here, assertion is wrong */
-    if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
-    /* ZSTD_memset(weightList, 0, sizeof(weightList)); */  /* is not necessary, even though some analyzer complain ... */
-
-    iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), /* bmi2 */ 0);
-    if (HUF_isError(iSize)) return iSize;
-
-    /* check result */
-    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */
-
-    /* find maxWeight */
-    for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */
-
-    /* Get start index of each weight */
-    {   U32 w, nextRankStart = 0;
-        for (w=1; w<maxW+1; w++) {
-            U32 curr = nextRankStart;
-            nextRankStart += wksp->rankStats[w];
-            rankStart[w] = curr;
-        }
-        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/
-        sizeOfSort = nextRankStart;
-    }
-
-    /* sort symbols by weight */
-    {   U32 s;
-        for (s=0; s<nbSymbols; s++) {
-            U32 const w = wksp->weightList[s];
-            U32 const r = rankStart[w]++;
-            wksp->sortedSymbol[r].symbol = (BYTE)s;
-            wksp->sortedSymbol[r].weight = (BYTE)w;
-        }
-        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */
-    }
-
-    /* Build rankVal */
-    {   U32* const rankVal0 = wksp->rankVal[0];
-        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */
-            U32 nextRankVal = 0;
-            U32 w;
-            for (w=1; w<maxW+1; w++) {
-                U32 curr = nextRankVal;
-                nextRankVal += wksp->rankStats[w] << (w+rescale);
-                rankVal0[w] = curr;
-        }   }
-        {   U32 const minBits = tableLog+1 - maxW;
-            U32 consumed;
-            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
-                U32* const rankValPtr = wksp->rankVal[consumed];
-                U32 w;
-                for (w = 1; w < maxW+1; w++) {
-                    rankValPtr[w] = rankVal0[w] >> consumed;
-    }   }   }   }
-
-    HUF_fillDTableX2(dt, maxTableLog,
-                   wksp->sortedSymbol, sizeOfSort,
-                   wksp->rankStart0, wksp->rankVal, maxW,
-                   tableLog+1,
-                   wksp->calleeWksp, sizeof(wksp->calleeWksp) / sizeof(U32));
-
-    dtd.tableLog = (BYTE)maxTableLog;
-    dtd.tableType = 1;
-    ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
-    return iSize;
-}
-
-
-FORCE_INLINE_TEMPLATE U32
-HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
-{
-    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
-    ZSTD_memcpy(op, dt+val, 2);
-    BIT_skipBits(DStream, dt[val].nbBits);
-    return dt[val].length;
-}
-
-FORCE_INLINE_TEMPLATE U32
-HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
-{
-    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */
-    ZSTD_memcpy(op, dt+val, 1);
-    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
-    else {
-        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
-            BIT_skipBits(DStream, dt[val].nbBits);
-            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
-                /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
-                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
-    }   }
-    return 1;
-}
-
-#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
-    ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
-    if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
-        ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
-    if (MEM_64bits()) \
-        ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
-
-HINT_INLINE size_t
-HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
-                const HUF_DEltX2* const dt, const U32 dtLog)
-{
-    BYTE* const pStart = p;
-
-    /* up to 8 symbols at a time */
-    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
-        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
-        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
-        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
-        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
-    }
-
-    /* closer to end : up to 2 symbols at a time */
-    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
-        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
-
-    while (p <= pEnd-2)
-        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */
-
-    if (p < pEnd)
-        p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);
-
-    return p-pStart;
-}
-
-FORCE_INLINE_TEMPLATE size_t
-HUF_decompress1X2_usingDTable_internal_body(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    BIT_DStream_t bitD;
-
-    /* Init */
-    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
-
-    /* decode */
-    {   BYTE* const ostart = (BYTE*) dst;
-        BYTE* const oend = ostart + dstSize;
-        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */
-        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
-        DTableDesc const dtd = HUF_getDTableDesc(DTable);
-        HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);
-    }
-
-    /* check */
-    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
-
-    /* decoded size */
-    return dstSize;
-}
-
-FORCE_INLINE_TEMPLATE size_t
-HUF_decompress4X2_usingDTable_internal_body(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */
-
-    {   const BYTE* const istart = (const BYTE*) cSrc;
-        BYTE* const ostart = (BYTE*) dst;
-        BYTE* const oend = ostart + dstSize;
-        BYTE* const olimit = oend - (sizeof(size_t)-1);
-        const void* const dtPtr = DTable+1;
-        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
-
-        /* Init */
-        BIT_DStream_t bitD1;
-        BIT_DStream_t bitD2;
-        BIT_DStream_t bitD3;
-        BIT_DStream_t bitD4;
-        size_t const length1 = MEM_readLE16(istart);
-        size_t const length2 = MEM_readLE16(istart+2);
-        size_t const length3 = MEM_readLE16(istart+4);
-        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
-        const BYTE* const istart1 = istart + 6;  /* jumpTable */
-        const BYTE* const istart2 = istart1 + length1;
-        const BYTE* const istart3 = istart2 + length2;
-        const BYTE* const istart4 = istart3 + length3;
-        size_t const segmentSize = (dstSize+3) / 4;
-        BYTE* const opStart2 = ostart + segmentSize;
-        BYTE* const opStart3 = opStart2 + segmentSize;
-        BYTE* const opStart4 = opStart3 + segmentSize;
-        BYTE* op1 = ostart;
-        BYTE* op2 = opStart2;
-        BYTE* op3 = opStart3;
-        BYTE* op4 = opStart4;
-        U32 endSignal = 1;
-        DTableDesc const dtd = HUF_getDTableDesc(DTable);
-        U32 const dtLog = dtd.tableLog;
-
-        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */
-        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
-        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
-        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
-        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
-
-        /* 16-32 symbols per loop (4-8 symbols per stream) */
-        for ( ; (endSignal) & (op4 < olimit); ) {
-#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
-            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
-            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
-            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
-            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
-            endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
-            endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
-            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
-            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
-            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
-            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
-            endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
-            endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
-#else
-            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
-            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
-            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
-            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
-            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
-            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
-            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
-            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
-            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
-            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
-            endSignal = (U32)LIKELY((U32)
-                        (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
-                      & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
-                      & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
-                      & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));
-#endif
-        }
-
-        /* check corruption */
-        if (op1 > opStart2) return ERROR(corruption_detected);
-        if (op2 > opStart3) return ERROR(corruption_detected);
-        if (op3 > opStart4) return ERROR(corruption_detected);
-        /* note : op4 already verified within main loop */
-
-        /* finish bitStreams one by one */
-        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
-        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
-        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
-        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);
-
-        /* check */
-        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
-          if (!endCheck) return ERROR(corruption_detected); }
-
-        /* decoded size */
-        return dstSize;
-    }
-}
-
-HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
-HUF_DGEN(HUF_decompress4X2_usingDTable_internal)
-
-size_t HUF_decompress1X2_usingDTable(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    DTableDesc dtd = HUF_getDTableDesc(DTable);
-    if (dtd.tableType != 1) return ERROR(GENERIC);
-    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-}
-
-size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
-                                   const void* cSrc, size_t cSrcSize,
-                                   void* workSpace, size_t wkspSize)
-{
-    const BYTE* ip = (const BYTE*) cSrc;
-
-    size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,
-                                               workSpace, wkspSize);
-    if (HUF_isError(hSize)) return hSize;
-    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
-    ip += hSize; cSrcSize -= hSize;
-
-    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
-}
-
-
-size_t HUF_decompress4X2_usingDTable(
-          void* dst,  size_t dstSize,
-    const void* cSrc, size_t cSrcSize,
-    const HUF_DTable* DTable)
-{
-    DTableDesc dtd = HUF_getDTableDesc(DTable);
-    if (dtd.tableType != 1) return ERROR(GENERIC);
-    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-}
-
-static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
-                                   const void* cSrc, size_t cSrcSize,
-                                   void* workSpace, size_t wkspSize, int bmi2)
-{
-    const BYTE* ip = (const BYTE*) cSrc;
-
-    size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,
-                                         workSpace, wkspSize);
-    if (HUF_isError(hSize)) return hSize;
-    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
-    ip += hSize; cSrcSize -= hSize;
-
-    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
-}
-
-size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
-                                   const void* cSrc, size_t cSrcSize,
-                                   void* workSpace, size_t wkspSize)
-{
-    return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);
-}
-
-
-#endif /* HUF_FORCE_DECOMPRESS_X1 */
-
-
-/* ***********************************/
-/* Universal decompression selectors */
-/* ***********************************/
-
-size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,
-                                    const void* cSrc, size_t cSrcSize,
-                                    const HUF_DTable* DTable)
-{
-    DTableDesc const dtd = HUF_getDTableDesc(DTable);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-    (void)dtd;
-    assert(dtd.tableType == 0);
-    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-    (void)dtd;
-    assert(dtd.tableType == 1);
-    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-#else
-    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
-                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-#endif
-}
-
-size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
-                                    const void* cSrc, size_t cSrcSize,
-                                    const HUF_DTable* DTable)
-{
-    DTableDesc const dtd = HUF_getDTableDesc(DTable);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-    (void)dtd;
-    assert(dtd.tableType == 0);
-    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-    (void)dtd;
-    assert(dtd.tableType == 1);
-    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-#else
-    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
-                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
-#endif
-}
-
-
-#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
-typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
-static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
-{
-    /* single, double, quad */
-    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */
-    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */
-    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */
-    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */
-    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */
-    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */
-    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */
-    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */
-    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */
-    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */
-    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */
-    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */
-    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */
-    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */
-    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */
-    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */
-};
-#endif
-
-/* HUF_selectDecoder() :
- *  Tells which decoder is likely to decode faster,
- *  based on a set of pre-computed metrics.
- * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
- *  Assumption : 0 < dstSize <= 128 KB */
-U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
-{
-    assert(dstSize > 0);
-    assert(dstSize <= 128*1024);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-    (void)dstSize;
-    (void)cSrcSize;
-    return 0;
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-    (void)dstSize;
-    (void)cSrcSize;
-    return 1;
-#else
-    /* decoder timing evaluation */
-    {   U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 */
-        U32 const D256 = (U32)(dstSize >> 8);
-        U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
-        U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
-        DTime1 += DTime1 >> 3;  /* advantage to algorithm using less memory, to reduce cache eviction */
-        return DTime1 < DTime0;
-    }
-#endif
-}
-
-
-size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst,
-                                     size_t dstSize, const void* cSrc,
-                                     size_t cSrcSize, void* workSpace,
-                                     size_t wkspSize)
-{
-    /* validation checks */
-    if (dstSize == 0) return ERROR(dstSize_tooSmall);
-    if (cSrcSize == 0) return ERROR(corruption_detected);
-
-    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-        (void)algoNb;
-        assert(algoNb == 0);
-        return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-        (void)algoNb;
-        assert(algoNb == 1);
-        return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
-#else
-        return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
-                            cSrcSize, workSpace, wkspSize):
-                        HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
-#endif
-    }
-}
-
-size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
-                                  const void* cSrc, size_t cSrcSize,
-                                  void* workSpace, size_t wkspSize)
-{
-    /* validation checks */
-    if (dstSize == 0) return ERROR(dstSize_tooSmall);
-    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */
-    if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */
-    if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */
-
-    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-        (void)algoNb;
-        assert(algoNb == 0);
-        return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
-                                cSrcSize, workSpace, wkspSize);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-        (void)algoNb;
-        assert(algoNb == 1);
-        return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
-                                cSrcSize, workSpace, wkspSize);
-#else
-        return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
-                                cSrcSize, workSpace, wkspSize):
-                        HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
-                                cSrcSize, workSpace, wkspSize);
-#endif
-    }
-}
-
-
-size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
-{
-    DTableDesc const dtd = HUF_getDTableDesc(DTable);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-    (void)dtd;
-    assert(dtd.tableType == 0);
-    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-    (void)dtd;
-    assert(dtd.tableType == 1);
-    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
-#else
-    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
-                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
-#endif
-}
-
-#ifndef HUF_FORCE_DECOMPRESS_X2
-size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
-{
-    const BYTE* ip = (const BYTE*) cSrc;
-
-    size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
-    if (HUF_isError(hSize)) return hSize;
-    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
-    ip += hSize; cSrcSize -= hSize;
-
-    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
-}
-#endif
-
-size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
-{
-    DTableDesc const dtd = HUF_getDTableDesc(DTable);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-    (void)dtd;
-    assert(dtd.tableType == 0);
-    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-    (void)dtd;
-    assert(dtd.tableType == 1);
-    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
-#else
-    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
-                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
-#endif
-}
-
-size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
-{
-    /* validation checks */
-    if (dstSize == 0) return ERROR(dstSize_tooSmall);
-    if (cSrcSize == 0) return ERROR(corruption_detected);
-
-    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
-#if defined(HUF_FORCE_DECOMPRESS_X1)
-        (void)algoNb;
-        assert(algoNb == 0);
-        return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
-#elif defined(HUF_FORCE_DECOMPRESS_X2)
-        (void)algoNb;
-        assert(algoNb == 1);
-        return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
-#else
-        return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :
-                        HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
-#endif
-    }
-}
-
diff --git a/lib/zstd/decompress/zstd_ddict.c b/lib/zstd/decompress/zstd_ddict.c
deleted file mode 100644
index dbbc7919de53..000000000000
--- a/lib/zstd/decompress/zstd_ddict.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-/* zstd_ddict.c :
- * concentrates all logic that needs to know the internals of ZSTD_DDict object */
-
-/*-*******************************************************
-*  Dependencies
-*********************************************************/
-#include "../common/zstd_deps.h"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
-#include "../common/cpu.h"         /* bmi2 */
-#include "../common/mem.h"         /* low level memory routines */
-#define FSE_STATIC_LINKING_ONLY
-#include "../common/fse.h"
-#define HUF_STATIC_LINKING_ONLY
-#include "../common/huf.h"
-#include "zstd_decompress_internal.h"
-#include "zstd_ddict.h"
-
-
-
-
-/*-*******************************************************
-*  Types
-*********************************************************/
-struct ZSTD_DDict_s {
-    void* dictBuffer;
-    const void* dictContent;
-    size_t dictSize;
-    ZSTD_entropyDTables_t entropy;
-    U32 dictID;
-    U32 entropyPresent;
-    ZSTD_customMem cMem;
-};  /* typedef'd to ZSTD_DDict within "zstd.h" */
-
-const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict)
-{
-    assert(ddict != NULL);
-    return ddict->dictContent;
-}
-
-size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict)
-{
-    assert(ddict != NULL);
-    return ddict->dictSize;
-}
-
-void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
-{
-    DEBUGLOG(4, "ZSTD_copyDDictParameters");
-    assert(dctx != NULL);
-    assert(ddict != NULL);
-    dctx->dictID = ddict->dictID;
-    dctx->prefixStart = ddict->dictContent;
-    dctx->virtualStart = ddict->dictContent;
-    dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
-    dctx->previousDstEnd = dctx->dictEnd;
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-    dctx->dictContentBeginForFuzzing = dctx->prefixStart;
-    dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
-#endif
-    if (ddict->entropyPresent) {
-        dctx->litEntropy = 1;
-        dctx->fseEntropy = 1;
-        dctx->LLTptr = ddict->entropy.LLTable;
-        dctx->MLTptr = ddict->entropy.MLTable;
-        dctx->OFTptr = ddict->entropy.OFTable;
-        dctx->HUFptr = ddict->entropy.hufTable;
-        dctx->entropy.rep[0] = ddict->entropy.rep[0];
-        dctx->entropy.rep[1] = ddict->entropy.rep[1];
-        dctx->entropy.rep[2] = ddict->entropy.rep[2];
-    } else {
-        dctx->litEntropy = 0;
-        dctx->fseEntropy = 0;
-    }
-}
-
-
-static size_t
-ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
-                           ZSTD_dictContentType_e dictContentType)
-{
-    ddict->dictID = 0;
-    ddict->entropyPresent = 0;
-    if (dictContentType == ZSTD_dct_rawContent) return 0;
-
-    if (ddict->dictSize < 8) {
-        if (dictContentType == ZSTD_dct_fullDict)
-            return ERROR(dictionary_corrupted);   /* only accept specified dictionaries */
-        return 0;   /* pure content mode */
-    }
-    {   U32 const magic = MEM_readLE32(ddict->dictContent);
-        if (magic != ZSTD_MAGIC_DICTIONARY) {
-            if (dictContentType == ZSTD_dct_fullDict)
-                return ERROR(dictionary_corrupted);   /* only accept specified dictionaries */
-            return 0;   /* pure content mode */
-        }
-    }
-    ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
-
-    /* load entropy tables */
-    RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
-            &ddict->entropy, ddict->dictContent, ddict->dictSize)),
-        dictionary_corrupted, "");
-    ddict->entropyPresent = 1;
-    return 0;
-}
-
-
-static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
-                                      const void* dict, size_t dictSize,
-                                      ZSTD_dictLoadMethod_e dictLoadMethod,
-                                      ZSTD_dictContentType_e dictContentType)
-{
-    if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
-        ddict->dictBuffer = NULL;
-        ddict->dictContent = dict;
-        if (!dict) dictSize = 0;
-    } else {
-        void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);
-        ddict->dictBuffer = internalBuffer;
-        ddict->dictContent = internalBuffer;
-        if (!internalBuffer) return ERROR(memory_allocation);
-        ZSTD_memcpy(internalBuffer, dict, dictSize);
-    }
-    ddict->dictSize = dictSize;
-    ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001);  /* cover both little and big endian */
-
-    /* parse dictionary content */
-    FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");
-
-    return 0;
-}
-
-ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
-                                      ZSTD_dictLoadMethod_e dictLoadMethod,
-                                      ZSTD_dictContentType_e dictContentType,
-                                      ZSTD_customMem customMem)
-{
-    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
-
-    {   ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);
-        if (ddict == NULL) return NULL;
-        ddict->cMem = customMem;
-        {   size_t const initResult = ZSTD_initDDict_internal(ddict,
-                                            dict, dictSize,
-                                            dictLoadMethod, dictContentType);
-            if (ZSTD_isError(initResult)) {
-                ZSTD_freeDDict(ddict);
-                return NULL;
-        }   }
-        return ddict;
-    }
-}
-
-/*! ZSTD_createDDict() :
-*   Create a digested dictionary, to start decompression without startup delay.
-*   `dict` content is copied inside DDict.
-*   Consequently, `dict` can be released after `ZSTD_DDict` creation */
-ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
-{
-    ZSTD_customMem const allocator = { NULL, NULL, NULL };
-    return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);
-}
-
-/*! ZSTD_createDDict_byReference() :
- *  Create a digested dictionary, to start decompression without startup delay.
- *  Dictionary content is simply referenced, it will be accessed during decompression.
- *  Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
-ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
-{
-    ZSTD_customMem const allocator = { NULL, NULL, NULL };
-    return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);
-}
-
-
-const ZSTD_DDict* ZSTD_initStaticDDict(
-                                void* sBuffer, size_t sBufferSize,
-                                const void* dict, size_t dictSize,
-                                ZSTD_dictLoadMethod_e dictLoadMethod,
-                                ZSTD_dictContentType_e dictContentType)
-{
-    size_t const neededSpace = sizeof(ZSTD_DDict)
-                             + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
-    ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer;
-    assert(sBuffer != NULL);
-    assert(dict != NULL);
-    if ((size_t)sBuffer & 7) return NULL;   /* 8-aligned */
-    if (sBufferSize < neededSpace) return NULL;
-    if (dictLoadMethod == ZSTD_dlm_byCopy) {
-        ZSTD_memcpy(ddict+1, dict, dictSize);  /* local copy */
-        dict = ddict+1;
-    }
-    if (ZSTD_isError( ZSTD_initDDict_internal(ddict,
-                                              dict, dictSize,
-                                              ZSTD_dlm_byRef, dictContentType) ))
-        return NULL;
-    return ddict;
-}
-
-
-size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
-{
-    if (ddict==NULL) return 0;   /* support free on NULL */
-    {   ZSTD_customMem const cMem = ddict->cMem;
-        ZSTD_customFree(ddict->dictBuffer, cMem);
-        ZSTD_customFree(ddict, cMem);
-        return 0;
-    }
-}
-
-/*! ZSTD_estimateDDictSize() :
- *  Estimate amount of memory that will be needed to create a dictionary for decompression.
- *  Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
-size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
-{
-    return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
-}
-
-size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
-{
-    if (ddict==NULL) return 0;   /* support sizeof on NULL */
-    return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
-}
-
-/*! ZSTD_getDictID_fromDDict() :
- *  Provides the dictID of the dictionary loaded into `ddict`.
- *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
- *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
-unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
-{
-    if (ddict==NULL) return 0;
-    return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
-}
diff --git a/lib/zstd/decompress/zstd_ddict.h b/lib/zstd/decompress/zstd_ddict.h
deleted file mode 100644
index 8c1a79d666f8..000000000000
--- a/lib/zstd/decompress/zstd_ddict.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-
-#ifndef ZSTD_DDICT_H
-#define ZSTD_DDICT_H
-
-/*-*******************************************************
- *  Dependencies
- *********************************************************/
-#include "../common/zstd_deps.h"   /* size_t */
-#include <linux/zstd.h>     /* ZSTD_DDict, and several public functions */
-
-
-/*-*******************************************************
- *  Interface
- *********************************************************/
-
-/* note: several prototypes are already published in `zstd.h` :
- * ZSTD_createDDict()
- * ZSTD_createDDict_byReference()
- * ZSTD_createDDict_advanced()
- * ZSTD_freeDDict()
- * ZSTD_initStaticDDict()
- * ZSTD_sizeof_DDict()
- * ZSTD_estimateDDictSize()
- * ZSTD_getDictID_fromDict()
- */
-
-const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict);
-size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict);
-
-void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
-
-
-
-#endif /* ZSTD_DDICT_H */
diff --git a/lib/zstd/decompress/zstd_decompress.c b/lib/zstd/decompress/zstd_decompress.c
deleted file mode 100644
index b4d81d84479a..000000000000
--- a/lib/zstd/decompress/zstd_decompress.c
+++ /dev/null
@@ -1,2085 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-
-/* ***************************************************************
-*  Tuning parameters
-*****************************************************************/
-/*!
- * HEAPMODE :
- * Select how default decompression function ZSTD_decompress() allocates its context,
- * on stack (0), or into heap (1, default; requires malloc()).
- * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.
- */
-#ifndef ZSTD_HEAPMODE
-#  define ZSTD_HEAPMODE 1
-#endif
-
-/*!
-*  LEGACY_SUPPORT :
-*  if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)
-*/
-
-/*!
- *  MAXWINDOWSIZE_DEFAULT :
- *  maximum window size accepted by DStream __by default__.
- *  Frames requiring more memory will be rejected.
- *  It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().
- */
-#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
-#  define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
-#endif
-
-/*!
- *  NO_FORWARD_PROGRESS_MAX :
- *  maximum allowed nb of calls to ZSTD_decompressStream()
- *  without any forward progress
- *  (defined as: no byte read from input, and no byte flushed to output)
- *  before triggering an error.
- */
-#ifndef ZSTD_NO_FORWARD_PROGRESS_MAX
-#  define ZSTD_NO_FORWARD_PROGRESS_MAX 16
-#endif
-
-
-/*-*******************************************************
-*  Dependencies
-*********************************************************/
-#include "../common/zstd_deps.h"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
-#include "../common/cpu.h"         /* bmi2 */
-#include "../common/mem.h"         /* low level memory routines */
-#define FSE_STATIC_LINKING_ONLY
-#include "../common/fse.h"
-#define HUF_STATIC_LINKING_ONLY
-#include "../common/huf.h"
-#include <linux/xxhash.h> /* xxh64_reset, xxh64_update, xxh64_digest, XXH64 */
-#include "../common/zstd_internal.h"  /* blockProperties_t */
-#include "zstd_decompress_internal.h"   /* ZSTD_DCtx */
-#include "zstd_ddict.h"  /* ZSTD_DDictDictContent */
-#include "zstd_decompress_block.h"   /* ZSTD_decompressBlock_internal */
-
-
-
-
-/* ***********************************
- * Multiple DDicts Hashset internals *
- *************************************/
-
-#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
-#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3   /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
-                                                     * Currently, that means a 0.75 load factor.
-                                                     * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
-                                                     * the load factor of the ddict hash set.
-                                                     */
-
-#define DDICT_HASHSET_TABLE_BASE_SIZE 64
-#define DDICT_HASHSET_RESIZE_FACTOR 2
-
-/* Hash function to determine starting position of dict insertion within the table
- * Returns an index between [0, hashSet->ddictPtrTableSize]
- */
-static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
-    const U64 hash = xxh64(&dictID, sizeof(U32), 0);
-    /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
-    return hash & (hashSet->ddictPtrTableSize - 1);
-}
-
-/* Adds DDict to a hashset without resizing it.
- * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
- * Returns 0 if successful, or a zstd error code if something went wrong.
- */
-static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
-    const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
-    size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
-    const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
-    RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
-    DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
-    while (hashSet->ddictPtrTable[idx] != NULL) {
-        /* Replace existing ddict if inserting ddict with same dictID */
-        if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
-            DEBUGLOG(4, "DictID already exists, replacing rather than adding");
-            hashSet->ddictPtrTable[idx] = ddict;
-            return 0;
-        }
-        idx &= idxRangeMask;
-        idx++;
-    }
-    DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
-    hashSet->ddictPtrTable[idx] = ddict;
-    hashSet->ddictPtrCount++;
-    return 0;
-}
-
-/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
- * rehashes all values, allocates new table, frees old table.
- * Returns 0 on success, otherwise a zstd error code.
- */
-static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
-    size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
-    const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
-    const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
-    size_t oldTableSize = hashSet->ddictPtrTableSize;
-    size_t i;
-
-    DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
-    RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
-    hashSet->ddictPtrTable = newTable;
-    hashSet->ddictPtrTableSize = newTableSize;
-    hashSet->ddictPtrCount = 0;
-    for (i = 0; i < oldTableSize; ++i) {
-        if (oldTable[i] != NULL) {
-            FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
-        }
-    }
-    ZSTD_customFree((void*)oldTable, customMem);
-    DEBUGLOG(4, "Finished re-hash");
-    return 0;
-}
-
-/* Fetches a DDict with the given dictID
- * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
- */
-static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
-    size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
-    const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
-    DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
-    for (;;) {
-        size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
-        if (currDictID == dictID || currDictID == 0) {
-            /* currDictID == 0 implies a NULL ddict entry */
-            break;
-        } else {
-            idx &= idxRangeMask;    /* Goes to start of table when we reach the end */
-            idx++;
-        }
-    }
-    DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
-    return hashSet->ddictPtrTable[idx];
-}
-
-/* Allocates space for and returns a ddict hash set
- * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
- * Returns NULL if allocation failed.
- */
-static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
-    ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
-    DEBUGLOG(4, "Allocating new hash set");
-    if (!ret)
-        return NULL;
-    ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
-    if (!ret->ddictPtrTable) {
-        ZSTD_customFree(ret, customMem);
-        return NULL;
-    }
-    ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
-    ret->ddictPtrCount = 0;
-    return ret;
-}
-
-/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
- * Note: The ZSTD_DDict* within the table are NOT freed.
- */
-static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
-    DEBUGLOG(4, "Freeing ddict hash set");
-    if (hashSet && hashSet->ddictPtrTable) {
-        ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
-    }
-    if (hashSet) {
-        ZSTD_customFree(hashSet, customMem);
-    }
-}
-
-/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
- * Returns 0 on success, or a ZSTD error.
- */
-static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
-    DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
-    if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
-        FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
-    }
-    FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
-    return 0;
-}
-
-/*-*************************************************************
-*   Context management
-***************************************************************/
-size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
-{
-    if (dctx==NULL) return 0;   /* support sizeof NULL */
-    return sizeof(*dctx)
-           + ZSTD_sizeof_DDict(dctx->ddictLocal)
-           + dctx->inBuffSize + dctx->outBuffSize;
-}
-
-size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
-
-
-static size_t ZSTD_startingInputLength(ZSTD_format_e format)
-{
-    size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
-    /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
-    assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
-    return startingInputLength;
-}
-
-static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
-{
-    assert(dctx->streamStage == zdss_init);
-    dctx->format = ZSTD_f_zstd1;
-    dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
-    dctx->outBufferMode = ZSTD_bm_buffered;
-    dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
-    dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
-}
-
-static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
-{
-    dctx->staticSize  = 0;
-    dctx->ddict       = NULL;
-    dctx->ddictLocal  = NULL;
-    dctx->dictEnd     = NULL;
-    dctx->ddictIsCold = 0;
-    dctx->dictUses = ZSTD_dont_use;
-    dctx->inBuff      = NULL;
-    dctx->inBuffSize  = 0;
-    dctx->outBuffSize = 0;
-    dctx->streamStage = zdss_init;
-    dctx->legacyContext = NULL;
-    dctx->previousLegacyVersion = 0;
-    dctx->noForwardProgress = 0;
-    dctx->oversizedDuration = 0;
-    dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
-    dctx->ddictSet = NULL;
-    ZSTD_DCtx_resetParameters(dctx);
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-    dctx->dictContentEndForFuzzing = NULL;
-#endif
-}
-
-ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
-{
-    ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
-
-    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */
-    if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL;  /* minimum size */
-
-    ZSTD_initDCtx_internal(dctx);
-    dctx->staticSize = workspaceSize;
-    dctx->inBuff = (char*)(dctx+1);
-    return dctx;
-}
-
-ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
-{
-    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
-
-    {   ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
-        if (!dctx) return NULL;
-        dctx->customMem = customMem;
-        ZSTD_initDCtx_internal(dctx);
-        return dctx;
-    }
-}
-
-ZSTD_DCtx* ZSTD_createDCtx(void)
-{
-    DEBUGLOG(3, "ZSTD_createDCtx");
-    return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
-}
-
-static void ZSTD_clearDict(ZSTD_DCtx* dctx)
-{
-    ZSTD_freeDDict(dctx->ddictLocal);
-    dctx->ddictLocal = NULL;
-    dctx->ddict = NULL;
-    dctx->dictUses = ZSTD_dont_use;
-}
-
-size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
-{
-    if (dctx==NULL) return 0;   /* support free on NULL */
-    RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
-    {   ZSTD_customMem const cMem = dctx->customMem;
-        ZSTD_clearDict(dctx);
-        ZSTD_customFree(dctx->inBuff, cMem);
-        dctx->inBuff = NULL;
-        if (dctx->ddictSet) {
-            ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
-            dctx->ddictSet = NULL;
-        }
-        ZSTD_customFree(dctx, cMem);
-        return 0;
-    }
-}
-
-/* no longer useful */
-void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
-{
-    size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
-    ZSTD_memcpy(dstDCtx, srcDCtx, toCopy);  /* no need to copy workspace */
-}
-
-/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
- * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
- * accordingly sets the ddict to be used to decompress the frame.
- *
- * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
- *
- * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
- */
-static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
-    assert(dctx->refMultipleDDicts && dctx->ddictSet);
-    DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
-    if (dctx->ddict) {
-        const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
-        if (frameDDict) {
-            DEBUGLOG(4, "DDict found!");
-            ZSTD_clearDict(dctx);
-            dctx->dictID = dctx->fParams.dictID;
-            dctx->ddict = frameDDict;
-            dctx->dictUses = ZSTD_use_indefinitely;
-        }
-    }
-}
-
-
-/*-*************************************************************
- *   Frame header decoding
- ***************************************************************/
-
-/*! ZSTD_isFrame() :
- *  Tells if the content of `buffer` starts with a valid Frame Identifier.
- *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
- *  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
- *  Note 3 : Skippable Frame Identifiers are considered valid. */
-unsigned ZSTD_isFrame(const void* buffer, size_t size)
-{
-    if (size < ZSTD_FRAMEIDSIZE) return 0;
-    {   U32 const magic = MEM_readLE32(buffer);
-        if (magic == ZSTD_MAGICNUMBER) return 1;
-        if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
-    }
-    return 0;
-}
-
-/* ZSTD_frameHeaderSize_internal() :
- *  srcSize must be large enough to reach header size fields.
- *  note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
- * @return : size of the Frame Header
- *           or an error code, which can be tested with ZSTD_isError() */
-static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
-{
-    size_t const minInputSize = ZSTD_startingInputLength(format);
-    RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
-
-    {   BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
-        U32 const dictID= fhd & 3;
-        U32 const singleSegment = (fhd >> 5) & 1;
-        U32 const fcsId = fhd >> 6;
-        return minInputSize + !singleSegment
-             + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
-             + (singleSegment && !fcsId);
-    }
-}
-
-/* ZSTD_frameHeaderSize() :
- *  srcSize must be >= ZSTD_frameHeaderSize_prefix.
- * @return : size of the Frame Header,
- *           or an error code (if srcSize is too small) */
-size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
-{
-    return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
-}
-
-
-/* ZSTD_getFrameHeader_advanced() :
- *  decode Frame Header, or require larger `srcSize`.
- *  note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
- * @return : 0, `zfhPtr` is correctly filled,
- *          >0, `srcSize` is too small, value is wanted `srcSize` amount,
- *           or an error code, which can be tested using ZSTD_isError() */
-size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
-{
-    const BYTE* ip = (const BYTE*)src;
-    size_t const minInputSize = ZSTD_startingInputLength(format);
-
-    ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));   /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
-    if (srcSize < minInputSize) return minInputSize;
-    RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
-
-    if ( (format != ZSTD_f_zstd1_magicless)
-      && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
-        if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
-            /* skippable frame */
-            if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
-                return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
-            ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
-            zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
-            zfhPtr->frameType = ZSTD_skippableFrame;
-            return 0;
-        }
-        RETURN_ERROR(prefix_unknown, "");
-    }
-
-    /* ensure there is enough `srcSize` to fully read/decode frame header */
-    {   size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
-        if (srcSize < fhsize) return fhsize;
-        zfhPtr->headerSize = (U32)fhsize;
-    }
-
-    {   BYTE const fhdByte = ip[minInputSize-1];
-        size_t pos = minInputSize;
-        U32 const dictIDSizeCode = fhdByte&3;
-        U32 const checksumFlag = (fhdByte>>2)&1;
-        U32 const singleSegment = (fhdByte>>5)&1;
-        U32 const fcsID = fhdByte>>6;
-        U64 windowSize = 0;
-        U32 dictID = 0;
-        U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
-        RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
-                        "reserved bits, must be zero");
-
-        if (!singleSegment) {
-            BYTE const wlByte = ip[pos++];
-            U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
-            RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
-            windowSize = (1ULL << windowLog);
-            windowSize += (windowSize >> 3) * (wlByte&7);
-        }
-        switch(dictIDSizeCode)
-        {
-            default:
-                assert(0);  /* impossible */
-                ZSTD_FALLTHROUGH;
-            case 0 : break;
-            case 1 : dictID = ip[pos]; pos++; break;
-            case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
-            case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;
-        }
-        switch(fcsID)
-        {
-            default:
-                assert(0);  /* impossible */
-                ZSTD_FALLTHROUGH;
-            case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
-            case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
-            case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
-            case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
-        }
-        if (singleSegment) windowSize = frameContentSize;
-
-        zfhPtr->frameType = ZSTD_frame;
-        zfhPtr->frameContentSize = frameContentSize;
-        zfhPtr->windowSize = windowSize;
-        zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
-        zfhPtr->dictID = dictID;
-        zfhPtr->checksumFlag = checksumFlag;
-    }
-    return 0;
-}
-
-/* ZSTD_getFrameHeader() :
- *  decode Frame Header, or require larger `srcSize`.
- *  note : this function does not consume input, it only reads it.
- * @return : 0, `zfhPtr` is correctly filled,
- *          >0, `srcSize` is too small, value is wanted `srcSize` amount,
- *           or an error code, which can be tested using ZSTD_isError() */
-size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
-{
-    return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
-}
-
-
-/* ZSTD_getFrameContentSize() :
- *  compatible with legacy mode
- * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
- *         - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
- *         - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
-unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
-{
-    {   ZSTD_frameHeader zfh;
-        if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)
-            return ZSTD_CONTENTSIZE_ERROR;
-        if (zfh.frameType == ZSTD_skippableFrame) {
-            return 0;
-        } else {
-            return zfh.frameContentSize;
-    }   }
-}
-
-static size_t readSkippableFrameSize(void const* src, size_t srcSize)
-{
-    size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
-    U32 sizeU32;
-
-    RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
-
-    sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
-    RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
-                    frameParameter_unsupported, "");
-    {
-        size_t const skippableSize = skippableHeaderSize + sizeU32;
-        RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
-        return skippableSize;
-    }
-}
-
-/* ZSTD_findDecompressedSize() :
- *  compatible with legacy mode
- *  `srcSize` must be the exact length of some number of ZSTD compressed and/or
- *      skippable frames
- *  @return : decompressed size of the frames contained */
-unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
-{
-    unsigned long long totalDstSize = 0;
-
-    while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
-        U32 const magicNumber = MEM_readLE32(src);
-
-        if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
-            size_t const skippableSize = readSkippableFrameSize(src, srcSize);
-            if (ZSTD_isError(skippableSize)) {
-                return ZSTD_CONTENTSIZE_ERROR;
-            }
-            assert(skippableSize <= srcSize);
-
-            src = (const BYTE *)src + skippableSize;
-            srcSize -= skippableSize;
-            continue;
-        }
-
-        {   unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
-            if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
-
-            /* check for overflow */
-            if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
-            totalDstSize += ret;
-        }
-        {   size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
-            if (ZSTD_isError(frameSrcSize)) {
-                return ZSTD_CONTENTSIZE_ERROR;
-            }
-
-            src = (const BYTE *)src + frameSrcSize;
-            srcSize -= frameSrcSize;
-        }
-    }  /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
-
-    if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
-
-    return totalDstSize;
-}
-
-/* ZSTD_getDecompressedSize() :
- *  compatible with legacy mode
- * @return : decompressed size if known, 0 otherwise
-             note : 0 can mean any of the following :
-                   - frame content is empty
-                   - decompressed size field is not present in frame header
-                   - frame header unknown / not supported
-                   - frame header not complete (`srcSize` too small) */
-unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
-{
-    unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
-    ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);
-    return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
-}
-
-
-/* ZSTD_decodeFrameHeader() :
- * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
- * If multiple DDict references are enabled, also will choose the correct DDict to use.
- * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
-static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
-{
-    size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
-    if (ZSTD_isError(result)) return result;    /* invalid header */
-    RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
-
-    /* Reference DDict requested by frame if dctx references multiple ddicts */
-    if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
-        ZSTD_DCtx_selectFrameDDict(dctx);
-    }
-
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-    /* Skip the dictID check in fuzzing mode, because it makes the search
-     * harder.
-     */
-    RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
-                    dictionary_wrong, "");
-#endif
-    dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
-    if (dctx->validateChecksum) xxh64_reset(&dctx->xxhState, 0);
-    dctx->processedCSize += headerSize;
-    return 0;
-}
-
-static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
-{
-    ZSTD_frameSizeInfo frameSizeInfo;
-    frameSizeInfo.compressedSize = ret;
-    frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
-    return frameSizeInfo;
-}
-
-static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
-{
-    ZSTD_frameSizeInfo frameSizeInfo;
-    ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
-
-
-    if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
-        && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
-        frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
-        assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
-               frameSizeInfo.compressedSize <= srcSize);
-        return frameSizeInfo;
-    } else {
-        const BYTE* ip = (const BYTE*)src;
-        const BYTE* const ipstart = ip;
-        size_t remainingSize = srcSize;
-        size_t nbBlocks = 0;
-        ZSTD_frameHeader zfh;
-
-        /* Extract Frame Header */
-        {   size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
-            if (ZSTD_isError(ret))
-                return ZSTD_errorFrameSizeInfo(ret);
-            if (ret > 0)
-                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
-        }
-
-        ip += zfh.headerSize;
-        remainingSize -= zfh.headerSize;
-
-        /* Iterate over each block */
-        while (1) {
-            blockProperties_t blockProperties;
-            size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
-            if (ZSTD_isError(cBlockSize))
-                return ZSTD_errorFrameSizeInfo(cBlockSize);
-
-            if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
-                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
-
-            ip += ZSTD_blockHeaderSize + cBlockSize;
-            remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
-            nbBlocks++;
-
-            if (blockProperties.lastBlock) break;
-        }
-
-        /* Final frame content checksum */
-        if (zfh.checksumFlag) {
-            if (remainingSize < 4)
-                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
-            ip += 4;
-        }
-
-        frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
-        frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
-                                        ? zfh.frameContentSize
-                                        : nbBlocks * zfh.blockSizeMax;
-        return frameSizeInfo;
-    }
-}
-
-/* ZSTD_findFrameCompressedSize() :
- *  compatible with legacy mode
- *  `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
- *  `srcSize` must be at least as large as the frame contained
- *  @return : the compressed size of the frame starting at `src` */
-size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
-{
-    ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
-    return frameSizeInfo.compressedSize;
-}
-
-/* ZSTD_decompressBound() :
- *  compatible with legacy mode
- *  `src` must point to the start of a ZSTD frame or a skippeable frame
- *  `srcSize` must be at least as large as the frame contained
- *  @return : the maximum decompressed size of the compressed source
- */
-unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
-{
-    unsigned long long bound = 0;
-    /* Iterate over each frame */
-    while (srcSize > 0) {
-        ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
-        size_t const compressedSize = frameSizeInfo.compressedSize;
-        unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
-        if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
-            return ZSTD_CONTENTSIZE_ERROR;
-        assert(srcSize >= compressedSize);
-        src = (const BYTE*)src + compressedSize;
-        srcSize -= compressedSize;
-        bound += decompressedBound;
-    }
-    return bound;
-}
-
-
-/*-*************************************************************
- *   Frame decoding
- ***************************************************************/
-
-/* ZSTD_insertBlock() :
- *  insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
-size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
-{
-    DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
-    ZSTD_checkContinuity(dctx, blockStart, blockSize);
-    dctx->previousDstEnd = (const char*)blockStart + blockSize;
-    return blockSize;
-}
-
-
-static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
-                          const void* src, size_t srcSize)
-{
-    DEBUGLOG(5, "ZSTD_copyRawBlock");
-    RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
-    if (dst == NULL) {
-        if (srcSize == 0) return 0;
-        RETURN_ERROR(dstBuffer_null, "");
-    }
-    ZSTD_memcpy(dst, src, srcSize);
-    return srcSize;
-}
-
-static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
-                               BYTE b,
-                               size_t regenSize)
-{
-    RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
-    if (dst == NULL) {
-        if (regenSize == 0) return 0;
-        RETURN_ERROR(dstBuffer_null, "");
-    }
-    ZSTD_memset(dst, b, regenSize);
-    return regenSize;
-}
-
-static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
-{
-    (void)dctx;
-    (void)uncompressedSize;
-    (void)compressedSize;
-    (void)streaming;
-}
-
-
-/*! ZSTD_decompressFrame() :
- * @dctx must be properly initialized
- *  will update *srcPtr and *srcSizePtr,
- *  to make *srcPtr progress by one frame. */
-static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
-                                   void* dst, size_t dstCapacity,
-                             const void** srcPtr, size_t *srcSizePtr)
-{
-    const BYTE* const istart = (const BYTE*)(*srcPtr);
-    const BYTE* ip = istart;
-    BYTE* const ostart = (BYTE*)dst;
-    BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
-    BYTE* op = ostart;
-    size_t remainingSrcSize = *srcSizePtr;
-
-    DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
-
-    /* check */
-    RETURN_ERROR_IF(
-        remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
-        srcSize_wrong, "");
-
-    /* Frame Header */
-    {   size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
-                ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
-        if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
-        RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
-                        srcSize_wrong, "");
-        FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
-        ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
-    }
-
-    /* Loop on each block */
-    while (1) {
-        size_t decodedSize;
-        blockProperties_t blockProperties;
-        size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
-        if (ZSTD_isError(cBlockSize)) return cBlockSize;
-
-        ip += ZSTD_blockHeaderSize;
-        remainingSrcSize -= ZSTD_blockHeaderSize;
-        RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
-
-        switch(blockProperties.blockType)
-        {
-        case bt_compressed:
-            decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1);
-            break;
-        case bt_raw :
-            decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
-            break;
-        case bt_rle :
-            decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
-            break;
-        case bt_reserved :
-        default:
-            RETURN_ERROR(corruption_detected, "invalid block type");
-        }
-
-        if (ZSTD_isError(decodedSize)) return decodedSize;
-        if (dctx->validateChecksum)
-            xxh64_update(&dctx->xxhState, op, decodedSize);
-        if (decodedSize != 0)
-            op += decodedSize;
-        assert(ip != NULL);
-        ip += cBlockSize;
-        remainingSrcSize -= cBlockSize;
-        if (blockProperties.lastBlock) break;
-    }
-
-    if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
-        RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
-                        corruption_detected, "");
-    }
-    if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
-        RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
-        if (!dctx->forceIgnoreChecksum) {
-            U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState);
-            U32 checkRead;
-            checkRead = MEM_readLE32(ip);
-            RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
-        }
-        ip += 4;
-        remainingSrcSize -= 4;
-    }
-    ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
-    /* Allow caller to get size read */
-    *srcPtr = ip;
-    *srcSizePtr = remainingSrcSize;
-    return (size_t)(op-ostart);
-}
-
-static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
-                                        void* dst, size_t dstCapacity,
-                                  const void* src, size_t srcSize,
-                                  const void* dict, size_t dictSize,
-                                  const ZSTD_DDict* ddict)
-{
-    void* const dststart = dst;
-    int moreThan1Frame = 0;
-
-    DEBUGLOG(5, "ZSTD_decompressMultiFrame");
-    assert(dict==NULL || ddict==NULL);  /* either dict or ddict set, not both */
-
-    if (ddict) {
-        dict = ZSTD_DDict_dictContent(ddict);
-        dictSize = ZSTD_DDict_dictSize(ddict);
-    }
-
-    while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
-
-
-        {   U32 const magicNumber = MEM_readLE32(src);
-            DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
-                        (unsigned)magicNumber, ZSTD_MAGICNUMBER);
-            if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
-                size_t const skippableSize = readSkippableFrameSize(src, srcSize);
-                FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
-                assert(skippableSize <= srcSize);
-
-                src = (const BYTE *)src + skippableSize;
-                srcSize -= skippableSize;
-                continue;
-        }   }
-
-        if (ddict) {
-            /* we were called from ZSTD_decompress_usingDDict */
-            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
-        } else {
-            /* this will initialize correctly with no dict if dict == NULL, so
-             * use this in all cases but ddict */
-            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
-        }
-        ZSTD_checkContinuity(dctx, dst, dstCapacity);
-
-        {   const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
-                                                    &src, &srcSize);
-            RETURN_ERROR_IF(
-                (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
-             && (moreThan1Frame==1),
-                srcSize_wrong,
-                "At least one frame successfully completed, "
-                "but following bytes are garbage: "
-                "it's more likely to be a srcSize error, "
-                "specifying more input bytes than size of frame(s). "
-                "Note: one could be unlucky, it might be a corruption error instead, "
-                "happening right at the place where we expect zstd magic bytes. "
-                "But this is _much_ less likely than a srcSize field error.");
-            if (ZSTD_isError(res)) return res;
-            assert(res <= dstCapacity);
-            if (res != 0)
-                dst = (BYTE*)dst + res;
-            dstCapacity -= res;
-        }
-        moreThan1Frame = 1;
-    }  /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
-
-    RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
-
-    return (size_t)((BYTE*)dst - (BYTE*)dststart);
-}
-
-size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
-                                 void* dst, size_t dstCapacity,
-                           const void* src, size_t srcSize,
-                           const void* dict, size_t dictSize)
-{
-    return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
-}
-
-
-static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
-{
-    switch (dctx->dictUses) {
-    default:
-        assert(0 /* Impossible */);
-        ZSTD_FALLTHROUGH;
-    case ZSTD_dont_use:
-        ZSTD_clearDict(dctx);
-        return NULL;
-    case ZSTD_use_indefinitely:
-        return dctx->ddict;
-    case ZSTD_use_once:
-        dctx->dictUses = ZSTD_dont_use;
-        return dctx->ddict;
-    }
-}
-
-size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
-{
-    return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
-}
-
-
-size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
-{
-#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
-    size_t regenSize;
-    ZSTD_DCtx* const dctx = ZSTD_createDCtx();
-    RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
-    regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
-    ZSTD_freeDCtx(dctx);
-    return regenSize;
-#else   /* stack mode */
-    ZSTD_DCtx dctx;
-    ZSTD_initDCtx_internal(&dctx);
-    return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
-#endif
-}
-
-
-/*-**************************************
-*   Advanced Streaming Decompression API
-*   Bufferless and synchronous
-****************************************/
-size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
-
-/*
- * Similar to ZSTD_nextSrcSizeToDecompress(), but when when a block input can be streamed,
- * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
- * be streamed.
- *
- * For blocks that can be streamed, this allows us to reduce the latency until we produce
- * output, and avoid copying the input.
- *
- * @param inputSize - The total amount of input that the caller currently has.
- */
-static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
-    if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
-        return dctx->expected;
-    if (dctx->bType != bt_raw)
-        return dctx->expected;
-    return MIN(MAX(inputSize, 1), dctx->expected);
-}
-
-ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
-    switch(dctx->stage)
-    {
-    default:   /* should not happen */
-        assert(0);
-        ZSTD_FALLTHROUGH;
-    case ZSTDds_getFrameHeaderSize:
-        ZSTD_FALLTHROUGH;
-    case ZSTDds_decodeFrameHeader:
-        return ZSTDnit_frameHeader;
-    case ZSTDds_decodeBlockHeader:
-        return ZSTDnit_blockHeader;
-    case ZSTDds_decompressBlock:
-        return ZSTDnit_block;
-    case ZSTDds_decompressLastBlock:
-        return ZSTDnit_lastBlock;
-    case ZSTDds_checkChecksum:
-        return ZSTDnit_checksum;
-    case ZSTDds_decodeSkippableHeader:
-        ZSTD_FALLTHROUGH;
-    case ZSTDds_skipFrame:
-        return ZSTDnit_skippableFrame;
-    }
-}
-
-static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
-
-/* ZSTD_decompressContinue() :
- *  srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
- *  @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
- *            or an error code, which can be tested using ZSTD_isError() */
-size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
-{
-    DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
-    /* Sanity check */
-    RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
-    ZSTD_checkContinuity(dctx, dst, dstCapacity);
-
-    dctx->processedCSize += srcSize;
-
-    switch (dctx->stage)
-    {
-    case ZSTDds_getFrameHeaderSize :
-        assert(src != NULL);
-        if (dctx->format == ZSTD_f_zstd1) {  /* allows header */
-            assert(srcSize >= ZSTD_FRAMEIDSIZE);  /* to read skippable magic number */
-            if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {        /* skippable frame */
-                ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
-                dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize;  /* remaining to load to get full skippable frame header */
-                dctx->stage = ZSTDds_decodeSkippableHeader;
-                return 0;
-        }   }
-        dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
-        if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
-        ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
-        dctx->expected = dctx->headerSize - srcSize;
-        dctx->stage = ZSTDds_decodeFrameHeader;
-        return 0;
-
-    case ZSTDds_decodeFrameHeader:
-        assert(src != NULL);
-        ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
-        FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
-        dctx->expected = ZSTD_blockHeaderSize;
-        dctx->stage = ZSTDds_decodeBlockHeader;
-        return 0;
-
-    case ZSTDds_decodeBlockHeader:
-        {   blockProperties_t bp;
-            size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
-            if (ZSTD_isError(cBlockSize)) return cBlockSize;
-            RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
-            dctx->expected = cBlockSize;
-            dctx->bType = bp.blockType;
-            dctx->rleSize = bp.origSize;
-            if (cBlockSize) {
-                dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;
-                return 0;
-            }
-            /* empty block */
-            if (bp.lastBlock) {
-                if (dctx->fParams.checksumFlag) {
-                    dctx->expected = 4;
-                    dctx->stage = ZSTDds_checkChecksum;
-                } else {
-                    dctx->expected = 0; /* end of frame */
-                    dctx->stage = ZSTDds_getFrameHeaderSize;
-                }
-            } else {
-                dctx->expected = ZSTD_blockHeaderSize;  /* jump to next header */
-                dctx->stage = ZSTDds_decodeBlockHeader;
-            }
-            return 0;
-        }
-
-    case ZSTDds_decompressLastBlock:
-    case ZSTDds_decompressBlock:
-        DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
-        {   size_t rSize;
-            switch(dctx->bType)
-            {
-            case bt_compressed:
-                DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
-                rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
-                dctx->expected = 0;  /* Streaming not supported */
-                break;
-            case bt_raw :
-                assert(srcSize <= dctx->expected);
-                rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
-                FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
-                assert(rSize == srcSize);
-                dctx->expected -= rSize;
-                break;
-            case bt_rle :
-                rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
-                dctx->expected = 0;  /* Streaming not supported */
-                break;
-            case bt_reserved :   /* should never happen */
-            default:
-                RETURN_ERROR(corruption_detected, "invalid block type");
-            }
-            FORWARD_IF_ERROR(rSize, "");
-            RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
-            DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
-            dctx->decodedSize += rSize;
-            if (dctx->validateChecksum) xxh64_update(&dctx->xxhState, dst, rSize);
-            dctx->previousDstEnd = (char*)dst + rSize;
-
-            /* Stay on the same stage until we are finished streaming the block. */
-            if (dctx->expected > 0) {
-                return rSize;
-            }
-
-            if (dctx->stage == ZSTDds_decompressLastBlock) {   /* end of frame */
-                DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
-                RETURN_ERROR_IF(
-                    dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
-                 && dctx->decodedSize != dctx->fParams.frameContentSize,
-                    corruption_detected, "");
-                if (dctx->fParams.checksumFlag) {  /* another round for frame checksum */
-                    dctx->expected = 4;
-                    dctx->stage = ZSTDds_checkChecksum;
-                } else {
-                    ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
-                    dctx->expected = 0;   /* ends here */
-                    dctx->stage = ZSTDds_getFrameHeaderSize;
-                }
-            } else {
-                dctx->stage = ZSTDds_decodeBlockHeader;
-                dctx->expected = ZSTD_blockHeaderSize;
-            }
-            return rSize;
-        }
-
-    case ZSTDds_checkChecksum:
-        assert(srcSize == 4);  /* guaranteed by dctx->expected */
-        {
-            if (dctx->validateChecksum) {
-                U32 const h32 = (U32)xxh64_digest(&dctx->xxhState);
-                U32 const check32 = MEM_readLE32(src);
-                DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
-                RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
-            }
-            ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
-            dctx->expected = 0;
-            dctx->stage = ZSTDds_getFrameHeaderSize;
-            return 0;
-        }
-
-    case ZSTDds_decodeSkippableHeader:
-        assert(src != NULL);
-        assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
-        ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize);   /* complete skippable header */
-        dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE);   /* note : dctx->expected can grow seriously large, beyond local buffer size */
-        dctx->stage = ZSTDds_skipFrame;
-        return 0;
-
-    case ZSTDds_skipFrame:
-        dctx->expected = 0;
-        dctx->stage = ZSTDds_getFrameHeaderSize;
-        return 0;
-
-    default:
-        assert(0);   /* impossible */
-        RETURN_ERROR(GENERIC, "impossible to reach");   /* some compiler require default to do something */
-    }
-}
-
-
-static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
-{
-    dctx->dictEnd = dctx->previousDstEnd;
-    dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
-    dctx->prefixStart = dict;
-    dctx->previousDstEnd = (const char*)dict + dictSize;
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-    dctx->dictContentBeginForFuzzing = dctx->prefixStart;
-    dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
-#endif
-    return 0;
-}
-
-/*! ZSTD_loadDEntropy() :
- *  dict : must point at beginning of a valid zstd dictionary.
- * @return : size of entropy tables read */
-size_t
-ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
-                  const void* const dict, size_t const dictSize)
-{
-    const BYTE* dictPtr = (const BYTE*)dict;
-    const BYTE* const dictEnd = dictPtr + dictSize;
-
-    RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
-    assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY);   /* dict must be valid */
-    dictPtr += 8;   /* skip header = magic + dictID */
-
-    ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));
-    ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));
-    ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);
-    {   void* const workspace = &entropy->LLTable;   /* use fse tables as temporary workspace; implies fse tables are grouped together */
-        size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);
-#ifdef HUF_FORCE_DECOMPRESS_X1
-        /* in minimal huffman, we always use X1 variants */
-        size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
-                                                dictPtr, dictEnd - dictPtr,
-                                                workspace, workspaceSize);
-#else
-        size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
-                                                dictPtr, (size_t)(dictEnd - dictPtr),
-                                                workspace, workspaceSize);
-#endif
-        RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
-        dictPtr += hSize;
-    }
-
-    {   short offcodeNCount[MaxOff+1];
-        unsigned offcodeMaxValue = MaxOff, offcodeLog;
-        size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
-        RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
-        RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
-        RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
-        ZSTD_buildFSETable( entropy->OFTable,
-                            offcodeNCount, offcodeMaxValue,
-                            OF_base, OF_bits,
-                            offcodeLog,
-                            entropy->workspace, sizeof(entropy->workspace),
-                            /* bmi2 */0);
-        dictPtr += offcodeHeaderSize;
-    }
-
-    {   short matchlengthNCount[MaxML+1];
-        unsigned matchlengthMaxValue = MaxML, matchlengthLog;
-        size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
-        RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
-        RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
-        RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
-        ZSTD_buildFSETable( entropy->MLTable,
-                            matchlengthNCount, matchlengthMaxValue,
-                            ML_base, ML_bits,
-                            matchlengthLog,
-                            entropy->workspace, sizeof(entropy->workspace),
-                            /* bmi2 */ 0);
-        dictPtr += matchlengthHeaderSize;
-    }
-
-    {   short litlengthNCount[MaxLL+1];
-        unsigned litlengthMaxValue = MaxLL, litlengthLog;
-        size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
-        RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
-        RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
-        RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
-        ZSTD_buildFSETable( entropy->LLTable,
-                            litlengthNCount, litlengthMaxValue,
-                            LL_base, LL_bits,
-                            litlengthLog,
-                            entropy->workspace, sizeof(entropy->workspace),
-                            /* bmi2 */ 0);
-        dictPtr += litlengthHeaderSize;
-    }
-
-    RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
-    {   int i;
-        size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
-        for (i=0; i<3; i++) {
-            U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
-            RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
-                            dictionary_corrupted, "");
-            entropy->rep[i] = rep;
-    }   }
-
-    return (size_t)(dictPtr - (const BYTE*)dict);
-}
-
-static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
-{
-    if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);
-    {   U32 const magic = MEM_readLE32(dict);
-        if (magic != ZSTD_MAGIC_DICTIONARY) {
-            return ZSTD_refDictContent(dctx, dict, dictSize);   /* pure content mode */
-    }   }
-    dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
-
-    /* load entropy tables */
-    {   size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
-        RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
-        dict = (const char*)dict + eSize;
-        dictSize -= eSize;
-    }
-    dctx->litEntropy = dctx->fseEntropy = 1;
-
-    /* reference dictionary content */
-    return ZSTD_refDictContent(dctx, dict, dictSize);
-}
-
-size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
-{
-    assert(dctx != NULL);
-    dctx->expected = ZSTD_startingInputLength(dctx->format);  /* dctx->format must be properly set */
-    dctx->stage = ZSTDds_getFrameHeaderSize;
-    dctx->processedCSize = 0;
-    dctx->decodedSize = 0;
-    dctx->previousDstEnd = NULL;
-    dctx->prefixStart = NULL;
-    dctx->virtualStart = NULL;
-    dctx->dictEnd = NULL;
-    dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001);  /* cover both little and big endian */
-    dctx->litEntropy = dctx->fseEntropy = 0;
-    dctx->dictID = 0;
-    dctx->bType = bt_reserved;
-    ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
-    ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue));  /* initial repcodes */
-    dctx->LLTptr = dctx->entropy.LLTable;
-    dctx->MLTptr = dctx->entropy.MLTable;
-    dctx->OFTptr = dctx->entropy.OFTable;
-    dctx->HUFptr = dctx->entropy.hufTable;
-    return 0;
-}
-
-size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
-{
-    FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
-    if (dict && dictSize)
-        RETURN_ERROR_IF(
-            ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
-            dictionary_corrupted, "");
-    return 0;
-}
-
-
-/* ======   ZSTD_DDict   ====== */
-
-size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
-{
-    DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
-    assert(dctx != NULL);
-    if (ddict) {
-        const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);
-        size_t const dictSize = ZSTD_DDict_dictSize(ddict);
-        const void* const dictEnd = dictStart + dictSize;
-        dctx->ddictIsCold = (dctx->dictEnd != dictEnd);
-        DEBUGLOG(4, "DDict is %s",
-                    dctx->ddictIsCold ? "~cold~" : "hot!");
-    }
-    FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
-    if (ddict) {   /* NULL ddict is equivalent to no dictionary */
-        ZSTD_copyDDictParameters(dctx, ddict);
-    }
-    return 0;
-}
-
-/*! ZSTD_getDictID_fromDict() :
- *  Provides the dictID stored within dictionary.
- *  if @return == 0, the dictionary is not conformant with Zstandard specification.
- *  It can still be loaded, but as a content-only dictionary. */
-unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
-{
-    if (dictSize < 8) return 0;
-    if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
-    return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
-}
-
-/*! ZSTD_getDictID_fromFrame() :
- *  Provides the dictID required to decompress frame stored within `src`.
- *  If @return == 0, the dictID could not be decoded.
- *  This could for one of the following reasons :
- *  - The frame does not require a dictionary (most common case).
- *  - The frame was built with dictID intentionally removed.
- *    Needed dictionary is a hidden information.
- *    Note : this use case also happens when using a non-conformant dictionary.
- *  - `srcSize` is too small, and as a result, frame header could not be decoded.
- *    Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
- *  - This is not a Zstandard frame.
- *  When identifying the exact failure cause, it's possible to use
- *  ZSTD_getFrameHeader(), which will provide a more precise error code. */
-unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
-{
-    ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
-    size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
-    if (ZSTD_isError(hError)) return 0;
-    return zfp.dictID;
-}
-
-
-/*! ZSTD_decompress_usingDDict() :
-*   Decompression using a pre-digested Dictionary
-*   Use dictionary without significant overhead. */
-size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
-                                  void* dst, size_t dstCapacity,
-                            const void* src, size_t srcSize,
-                            const ZSTD_DDict* ddict)
-{
-    /* pass content and size in case legacy frames are encountered */
-    return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,
-                                     NULL, 0,
-                                     ddict);
-}
-
-
-/*=====================================
-*   Streaming decompression
-*====================================*/
-
-ZSTD_DStream* ZSTD_createDStream(void)
-{
-    DEBUGLOG(3, "ZSTD_createDStream");
-    return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
-}
-
-ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
-{
-    return ZSTD_initStaticDCtx(workspace, workspaceSize);
-}
-
-ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
-{
-    return ZSTD_createDCtx_advanced(customMem);
-}
-
-size_t ZSTD_freeDStream(ZSTD_DStream* zds)
-{
-    return ZSTD_freeDCtx(zds);
-}
-
-
-/* ***  Initialization  *** */
-
-size_t ZSTD_DStreamInSize(void)  { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
-size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
-
-size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
-                                   const void* dict, size_t dictSize,
-                                         ZSTD_dictLoadMethod_e dictLoadMethod,
-                                         ZSTD_dictContentType_e dictContentType)
-{
-    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
-    ZSTD_clearDict(dctx);
-    if (dict && dictSize != 0) {
-        dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
-        RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
-        dctx->ddict = dctx->ddictLocal;
-        dctx->dictUses = ZSTD_use_indefinitely;
-    }
-    return 0;
-}
-
-size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
-{
-    return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
-}
-
-size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
-{
-    return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
-}
-
-size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
-{
-    FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
-    dctx->dictUses = ZSTD_use_once;
-    return 0;
-}
-
-size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
-{
-    return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);
-}
-
-
-/* ZSTD_initDStream_usingDict() :
- * return : expected size, aka ZSTD_startingInputLength().
- * this function cannot fail */
-size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
-{
-    DEBUGLOG(4, "ZSTD_initDStream_usingDict");
-    FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
-    FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
-    return ZSTD_startingInputLength(zds->format);
-}
-
-/* note : this variant can't fail */
-size_t ZSTD_initDStream(ZSTD_DStream* zds)
-{
-    DEBUGLOG(4, "ZSTD_initDStream");
-    return ZSTD_initDStream_usingDDict(zds, NULL);
-}
-
-/* ZSTD_initDStream_usingDDict() :
- * ddict will just be referenced, and must outlive decompression session
- * this function cannot fail */
-size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
-{
-    FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
-    FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
-    return ZSTD_startingInputLength(dctx->format);
-}
-
-/* ZSTD_resetDStream() :
- * return : expected size, aka ZSTD_startingInputLength().
- * this function cannot fail */
-size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
-{
-    FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
-    return ZSTD_startingInputLength(dctx->format);
-}
-
-
-size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
-{
-    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
-    ZSTD_clearDict(dctx);
-    if (ddict) {
-        dctx->ddict = ddict;
-        dctx->dictUses = ZSTD_use_indefinitely;
-        if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
-            if (dctx->ddictSet == NULL) {
-                dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
-                if (!dctx->ddictSet) {
-                    RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
-                }
-            }
-            assert(!dctx->staticSize);  /* Impossible: ddictSet cannot have been allocated if static dctx */
-            FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
-        }
-    }
-    return 0;
-}
-
-/* ZSTD_DCtx_setMaxWindowSize() :
- * note : no direct equivalence in ZSTD_DCtx_setParameter,
- * since this version sets windowSize, and the other sets windowLog */
-size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
-{
-    ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
-    size_t const min = (size_t)1 << bounds.lowerBound;
-    size_t const max = (size_t)1 << bounds.upperBound;
-    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
-    RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
-    RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
-    dctx->maxWindowSize = maxWindowSize;
-    return 0;
-}
-
-size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
-{
-    return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
-}
-
-ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
-{
-    ZSTD_bounds bounds = { 0, 0, 0 };
-    switch(dParam) {
-        case ZSTD_d_windowLogMax:
-            bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;
-            bounds.upperBound = ZSTD_WINDOWLOG_MAX;
-            return bounds;
-        case ZSTD_d_format:
-            bounds.lowerBound = (int)ZSTD_f_zstd1;
-            bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
-            ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
-            return bounds;
-        case ZSTD_d_stableOutBuffer:
-            bounds.lowerBound = (int)ZSTD_bm_buffered;
-            bounds.upperBound = (int)ZSTD_bm_stable;
-            return bounds;
-        case ZSTD_d_forceIgnoreChecksum:
-            bounds.lowerBound = (int)ZSTD_d_validateChecksum;
-            bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
-            return bounds;
-        case ZSTD_d_refMultipleDDicts:
-            bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
-            bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
-            return bounds;
-        default:;
-    }
-    bounds.error = ERROR(parameter_unsupported);
-    return bounds;
-}
-
-/* ZSTD_dParam_withinBounds:
- * @return 1 if value is within dParam bounds,
- * 0 otherwise */
-static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
-{
-    ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);
-    if (ZSTD_isError(bounds.error)) return 0;
-    if (value < bounds.lowerBound) return 0;
-    if (value > bounds.upperBound) return 0;
-    return 1;
-}
-
-#define CHECK_DBOUNDS(p,v) {                \
-    RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
-}
-
-size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
-{
-    switch (param) {
-        case ZSTD_d_windowLogMax:
-            *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
-            return 0;
-        case ZSTD_d_format:
-            *value = (int)dctx->format;
-            return 0;
-        case ZSTD_d_stableOutBuffer:
-            *value = (int)dctx->outBufferMode;
-            return 0;
-        case ZSTD_d_forceIgnoreChecksum:
-            *value = (int)dctx->forceIgnoreChecksum;
-            return 0;
-        case ZSTD_d_refMultipleDDicts:
-            *value = (int)dctx->refMultipleDDicts;
-            return 0;
-        default:;
-    }
-    RETURN_ERROR(parameter_unsupported, "");
-}
-
-size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
-{
-    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
-    switch(dParam) {
-        case ZSTD_d_windowLogMax:
-            if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
-            CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
-            dctx->maxWindowSize = ((size_t)1) << value;
-            return 0;
-        case ZSTD_d_format:
-            CHECK_DBOUNDS(ZSTD_d_format, value);
-            dctx->format = (ZSTD_format_e)value;
-            return 0;
-        case ZSTD_d_stableOutBuffer:
-            CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
-            dctx->outBufferMode = (ZSTD_bufferMode_e)value;
-            return 0;
-        case ZSTD_d_forceIgnoreChecksum:
-            CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
-            dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
-            return 0;
-        case ZSTD_d_refMultipleDDicts:
-            CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
-            if (dctx->staticSize != 0) {
-                RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
-            }
-            dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
-            return 0;
-        default:;
-    }
-    RETURN_ERROR(parameter_unsupported, "");
-}
-
-size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
-{
-    if ( (reset == ZSTD_reset_session_only)
-      || (reset == ZSTD_reset_session_and_parameters) ) {
-        dctx->streamStage = zdss_init;
-        dctx->noForwardProgress = 0;
-    }
-    if ( (reset == ZSTD_reset_parameters)
-      || (reset == ZSTD_reset_session_and_parameters) ) {
-        RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
-        ZSTD_clearDict(dctx);
-        ZSTD_DCtx_resetParameters(dctx);
-    }
-    return 0;
-}
-
-
-size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
-{
-    return ZSTD_sizeof_DCtx(dctx);
-}
-
-size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
-{
-    size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
-    unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
-    unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
-    size_t const minRBSize = (size_t) neededSize;
-    RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
-                    frameParameter_windowTooLarge, "");
-    return minRBSize;
-}
-
-size_t ZSTD_estimateDStreamSize(size_t windowSize)
-{
-    size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
-    size_t const inBuffSize = blockSize;  /* no block can be larger */
-    size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);
-    return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
-}
-
-size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
-{
-    U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;   /* note : should be user-selectable, but requires an additional parameter (or a dctx) */
-    ZSTD_frameHeader zfh;
-    size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
-    if (ZSTD_isError(err)) return err;
-    RETURN_ERROR_IF(err>0, srcSize_wrong, "");
-    RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
-                    frameParameter_windowTooLarge, "");
-    return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
-}
-
-
-/* *****   Decompression   ***** */
-
-static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
-{
-    return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
-}
-
-static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
-{
-    if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
-        zds->oversizedDuration++;
-    else
-        zds->oversizedDuration = 0;
-}
-
-static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
-{
-    return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
-}
-
-/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
-static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
-{
-    ZSTD_outBuffer const expect = zds->expectedOutBuffer;
-    /* No requirement when ZSTD_obm_stable is not enabled. */
-    if (zds->outBufferMode != ZSTD_bm_stable)
-        return 0;
-    /* Any buffer is allowed in zdss_init, this must be the same for every other call until
-     * the context is reset.
-     */
-    if (zds->streamStage == zdss_init)
-        return 0;
-    /* The buffer must match our expectation exactly. */
-    if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
-        return 0;
-    RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
-}
-
-/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
- * and updates the stage and the output buffer state. This call is extracted so it can be
- * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
- * NOTE: You must break after calling this function since the streamStage is modified.
- */
-static size_t ZSTD_decompressContinueStream(
-            ZSTD_DStream* zds, char** op, char* oend,
-            void const* src, size_t srcSize) {
-    int const isSkipFrame = ZSTD_isSkipFrame(zds);
-    if (zds->outBufferMode == ZSTD_bm_buffered) {
-        size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
-        size_t const decodedSize = ZSTD_decompressContinue(zds,
-                zds->outBuff + zds->outStart, dstSize, src, srcSize);
-        FORWARD_IF_ERROR(decodedSize, "");
-        if (!decodedSize && !isSkipFrame) {
-            zds->streamStage = zdss_read;
-        } else {
-            zds->outEnd = zds->outStart + decodedSize;
-            zds->streamStage = zdss_flush;
-        }
-    } else {
-        /* Write directly into the output buffer */
-        size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
-        size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
-        FORWARD_IF_ERROR(decodedSize, "");
-        *op += decodedSize;
-        /* Flushing is not needed. */
-        zds->streamStage = zdss_read;
-        assert(*op <= oend);
-        assert(zds->outBufferMode == ZSTD_bm_stable);
-    }
-    return 0;
-}
-
-size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
-{
-    const char* const src = (const char*)input->src;
-    const char* const istart = input->pos != 0 ? src + input->pos : src;
-    const char* const iend = input->size != 0 ? src + input->size : src;
-    const char* ip = istart;
-    char* const dst = (char*)output->dst;
-    char* const ostart = output->pos != 0 ? dst + output->pos : dst;
-    char* const oend = output->size != 0 ? dst + output->size : dst;
-    char* op = ostart;
-    U32 someMoreWork = 1;
-
-    DEBUGLOG(5, "ZSTD_decompressStream");
-    RETURN_ERROR_IF(
-        input->pos > input->size,
-        srcSize_wrong,
-        "forbidden. in: pos: %u   vs size: %u",
-        (U32)input->pos, (U32)input->size);
-    RETURN_ERROR_IF(
-        output->pos > output->size,
-        dstSize_tooSmall,
-        "forbidden. out: pos: %u   vs size: %u",
-        (U32)output->pos, (U32)output->size);
-    DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
-    FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
-
-    while (someMoreWork) {
-        switch(zds->streamStage)
-        {
-        case zdss_init :
-            DEBUGLOG(5, "stage zdss_init => transparent reset ");
-            zds->streamStage = zdss_loadHeader;
-            zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
-            zds->legacyVersion = 0;
-            zds->hostageByte = 0;
-            zds->expectedOutBuffer = *output;
-            ZSTD_FALLTHROUGH;
-
-        case zdss_loadHeader :
-            DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
-            {   size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
-                if (zds->refMultipleDDicts && zds->ddictSet) {
-                    ZSTD_DCtx_selectFrameDDict(zds);
-                }
-                DEBUGLOG(5, "header size : %u", (U32)hSize);
-                if (ZSTD_isError(hSize)) {
-                    return hSize;   /* error */
-                }
-                if (hSize != 0) {   /* need more input */
-                    size_t const toLoad = hSize - zds->lhSize;   /* if hSize!=0, hSize > zds->lhSize */
-                    size_t const remainingInput = (size_t)(iend-ip);
-                    assert(iend >= ip);
-                    if (toLoad > remainingInput) {   /* not enough input to load full header */
-                        if (remainingInput > 0) {
-                            ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
-                            zds->lhSize += remainingInput;
-                        }
-                        input->pos = input->size;
-                        return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize;   /* remaining header bytes + next block header */
-                    }
-                    assert(ip != NULL);
-                    ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
-                    break;
-            }   }
-
-            /* check for single-pass mode opportunity */
-            if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
-                && zds->fParams.frameType != ZSTD_skippableFrame
-                && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
-                size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
-                if (cSize <= (size_t)(iend-istart)) {
-                    /* shortcut : using single-pass mode */
-                    size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
-                    if (ZSTD_isError(decompressedSize)) return decompressedSize;
-                    DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
-                    ip = istart + cSize;
-                    op += decompressedSize;
-                    zds->expected = 0;
-                    zds->streamStage = zdss_init;
-                    someMoreWork = 0;
-                    break;
-            }   }
-
-            /* Check output buffer is large enough for ZSTD_odm_stable. */
-            if (zds->outBufferMode == ZSTD_bm_stable
-                && zds->fParams.frameType != ZSTD_skippableFrame
-                && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
-                && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
-                RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
-            }
-
-            /* Consume header (see ZSTDds_decodeFrameHeader) */
-            DEBUGLOG(4, "Consume header");
-            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
-
-            if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {  /* skippable frame */
-                zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
-                zds->stage = ZSTDds_skipFrame;
-            } else {
-                FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
-                zds->expected = ZSTD_blockHeaderSize;
-                zds->stage = ZSTDds_decodeBlockHeader;
-            }
-
-            /* control buffer memory usage */
-            DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)",
-                        (U32)(zds->fParams.windowSize >>10),
-                        (U32)(zds->maxWindowSize >> 10) );
-            zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
-            RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
-                            frameParameter_windowTooLarge, "");
-
-            /* Adapt buffer sizes to frame header instructions */
-            {   size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
-                size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
-                        ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
-                        : 0;
-
-                ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
-
-                {   int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
-                    int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
-
-                    if (tooSmall || tooLarge) {
-                        size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
-                        DEBUGLOG(4, "inBuff  : from %u to %u",
-                                    (U32)zds->inBuffSize, (U32)neededInBuffSize);
-                        DEBUGLOG(4, "outBuff : from %u to %u",
-                                    (U32)zds->outBuffSize, (U32)neededOutBuffSize);
-                        if (zds->staticSize) {  /* static DCtx */
-                            DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
-                            assert(zds->staticSize >= sizeof(ZSTD_DCtx));  /* controlled at init */
-                            RETURN_ERROR_IF(
-                                bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
-                                memory_allocation, "");
-                        } else {
-                            ZSTD_customFree(zds->inBuff, zds->customMem);
-                            zds->inBuffSize = 0;
-                            zds->outBuffSize = 0;
-                            zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
-                            RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
-                        }
-                        zds->inBuffSize = neededInBuffSize;
-                        zds->outBuff = zds->inBuff + zds->inBuffSize;
-                        zds->outBuffSize = neededOutBuffSize;
-            }   }   }
-            zds->streamStage = zdss_read;
-            ZSTD_FALLTHROUGH;
-
-        case zdss_read:
-            DEBUGLOG(5, "stage zdss_read");
-            {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
-                DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
-                if (neededInSize==0) {  /* end of frame */
-                    zds->streamStage = zdss_init;
-                    someMoreWork = 0;
-                    break;
-                }
-                if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */
-                    FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
-                    ip += neededInSize;
-                    /* Function modifies the stage so we must break */
-                    break;
-            }   }
-            if (ip==iend) { someMoreWork = 0; break; }   /* no more input */
-            zds->streamStage = zdss_load;
-            ZSTD_FALLTHROUGH;
-
-        case zdss_load:
-            {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
-                size_t const toLoad = neededInSize - zds->inPos;
-                int const isSkipFrame = ZSTD_isSkipFrame(zds);
-                size_t loadedSize;
-                /* At this point we shouldn't be decompressing a block that we can stream. */
-                assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
-                if (isSkipFrame) {
-                    loadedSize = MIN(toLoad, (size_t)(iend-ip));
-                } else {
-                    RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
-                                    corruption_detected,
-                                    "should never happen");
-                    loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
-                }
-                ip += loadedSize;
-                zds->inPos += loadedSize;
-                if (loadedSize < toLoad) { someMoreWork = 0; break; }   /* not enough input, wait for more */
-
-                /* decode loaded input */
-                zds->inPos = 0;   /* input is consumed */
-                FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
-                /* Function modifies the stage so we must break */
-                break;
-            }
-        case zdss_flush:
-            {   size_t const toFlushSize = zds->outEnd - zds->outStart;
-                size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
-                op += flushedSize;
-                zds->outStart += flushedSize;
-                if (flushedSize == toFlushSize) {  /* flush completed */
-                    zds->streamStage = zdss_read;
-                    if ( (zds->outBuffSize < zds->fParams.frameContentSize)
-                      && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
-                        DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
-                                (int)(zds->outBuffSize - zds->outStart),
-                                (U32)zds->fParams.blockSizeMax);
-                        zds->outStart = zds->outEnd = 0;
-                    }
-                    break;
-            }   }
-            /* cannot complete flush */
-            someMoreWork = 0;
-            break;
-
-        default:
-            assert(0);    /* impossible */
-            RETURN_ERROR(GENERIC, "impossible to reach");   /* some compiler require default to do something */
-    }   }
-
-    /* result */
-    input->pos = (size_t)(ip - (const char*)(input->src));
-    output->pos = (size_t)(op - (char*)(output->dst));
-
-    /* Update the expected output buffer for ZSTD_obm_stable. */
-    zds->expectedOutBuffer = *output;
-
-    if ((ip==istart) && (op==ostart)) {  /* no forward progress */
-        zds->noForwardProgress ++;
-        if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
-            RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
-            RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
-            assert(0);
-        }
-    } else {
-        zds->noForwardProgress = 0;
-    }
-    {   size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
-        if (!nextSrcSizeHint) {   /* frame fully decoded */
-            if (zds->outEnd == zds->outStart) {  /* output fully flushed */
-                if (zds->hostageByte) {
-                    if (input->pos >= input->size) {
-                        /* can't release hostage (not present) */
-                        zds->streamStage = zdss_read;
-                        return 1;
-                    }
-                    input->pos++;  /* release hostage */
-                }   /* zds->hostageByte */
-                return 0;
-            }  /* zds->outEnd == zds->outStart */
-            if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
-                input->pos--;   /* note : pos > 0, otherwise, impossible to finish reading last block */
-                zds->hostageByte=1;
-            }
-            return 1;
-        }  /* nextSrcSizeHint==0 */
-        nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block);   /* preload header of next block */
-        assert(zds->inPos <= nextSrcSizeHint);
-        nextSrcSizeHint -= zds->inPos;   /* part already loaded*/
-        return nextSrcSizeHint;
-    }
-}
-
-size_t ZSTD_decompressStream_simpleArgs (
-                            ZSTD_DCtx* dctx,
-                            void* dst, size_t dstCapacity, size_t* dstPos,
-                      const void* src, size_t srcSize, size_t* srcPos)
-{
-    ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
-    ZSTD_inBuffer  input  = { src, srcSize, *srcPos };
-    /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
-    size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
-    *dstPos = output.pos;
-    *srcPos = input.pos;
-    return cErr;
-}
diff --git a/lib/zstd/decompress/zstd_decompress_block.c b/lib/zstd/decompress/zstd_decompress_block.c
deleted file mode 100644
index 2d101d9a842e..000000000000
--- a/lib/zstd/decompress/zstd_decompress_block.c
+++ /dev/null
@@ -1,1540 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-/* zstd_decompress_block :
- * this module takes care of decompressing _compressed_ block */
-
-/*-*******************************************************
-*  Dependencies
-*********************************************************/
-#include "../common/zstd_deps.h"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
-#include "../common/compiler.h"    /* prefetch */
-#include "../common/cpu.h"         /* bmi2 */
-#include "../common/mem.h"         /* low level memory routines */
-#define FSE_STATIC_LINKING_ONLY
-#include "../common/fse.h"
-#define HUF_STATIC_LINKING_ONLY
-#include "../common/huf.h"
-#include "../common/zstd_internal.h"
-#include "zstd_decompress_internal.h"   /* ZSTD_DCtx */
-#include "zstd_ddict.h"  /* ZSTD_DDictDictContent */
-#include "zstd_decompress_block.h"
-
-/*_*******************************************************
-*  Macros
-**********************************************************/
-
-/* These two optional macros force the use one way or another of the two
- * ZSTD_decompressSequences implementations. You can't force in both directions
- * at the same time.
- */
-#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
-    defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
-#error "Cannot force the use of the short and the long ZSTD_decompressSequences variants!"
-#endif
-
-
-/*_*******************************************************
-*  Memory operations
-**********************************************************/
-static void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); }
-
-
-/*-*************************************************************
- *   Block decoding
- ***************************************************************/
-
-/*! ZSTD_getcBlockSize() :
- *  Provides the size of compressed block from block header `src` */
-size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
-                          blockProperties_t* bpPtr)
-{
-    RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong, "");
-
-    {   U32 const cBlockHeader = MEM_readLE24(src);
-        U32 const cSize = cBlockHeader >> 3;
-        bpPtr->lastBlock = cBlockHeader & 1;
-        bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
-        bpPtr->origSize = cSize;   /* only useful for RLE */
-        if (bpPtr->blockType == bt_rle) return 1;
-        RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected, "");
-        return cSize;
-    }
-}
-
-
-/* Hidden declaration for fullbench */
-size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
-                          const void* src, size_t srcSize);
-/*! ZSTD_decodeLiteralsBlock() :
- * @return : nb of bytes read from src (< srcSize )
- *  note : symbol not declared but exposed for fullbench */
-size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
-                          const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */
-{
-    DEBUGLOG(5, "ZSTD_decodeLiteralsBlock");
-    RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, "");
-
-    {   const BYTE* const istart = (const BYTE*) src;
-        symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
-
-        switch(litEncType)
-        {
-        case set_repeat:
-            DEBUGLOG(5, "set_repeat flag : re-using stats from previous compressed literals block");
-            RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, "");
-            ZSTD_FALLTHROUGH;
-
-        case set_compressed:
-            RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3");
-            {   size_t lhSize, litSize, litCSize;
-                U32 singleStream=0;
-                U32 const lhlCode = (istart[0] >> 2) & 3;
-                U32 const lhc = MEM_readLE32(istart);
-                size_t hufSuccess;
-                switch(lhlCode)
-                {
-                case 0: case 1: default:   /* note : default is impossible, since lhlCode into [0..3] */
-                    /* 2 - 2 - 10 - 10 */
-                    singleStream = !lhlCode;
-                    lhSize = 3;
-                    litSize  = (lhc >> 4) & 0x3FF;
-                    litCSize = (lhc >> 14) & 0x3FF;
-                    break;
-                case 2:
-                    /* 2 - 2 - 14 - 14 */
-                    lhSize = 4;
-                    litSize  = (lhc >> 4) & 0x3FFF;
-                    litCSize = lhc >> 18;
-                    break;
-                case 3:
-                    /* 2 - 2 - 18 - 18 */
-                    lhSize = 5;
-                    litSize  = (lhc >> 4) & 0x3FFFF;
-                    litCSize = (lhc >> 22) + ((size_t)istart[4] << 10);
-                    break;
-                }
-                RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
-                RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, "");
-
-                /* prefetch huffman table if cold */
-                if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
-                    PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable));
-                }
-
-                if (litEncType==set_repeat) {
-                    if (singleStream) {
-                        hufSuccess = HUF_decompress1X_usingDTable_bmi2(
-                            dctx->litBuffer, litSize, istart+lhSize, litCSize,
-                            dctx->HUFptr, dctx->bmi2);
-                    } else {
-                        hufSuccess = HUF_decompress4X_usingDTable_bmi2(
-                            dctx->litBuffer, litSize, istart+lhSize, litCSize,
-                            dctx->HUFptr, dctx->bmi2);
-                    }
-                } else {
-                    if (singleStream) {
-#if defined(HUF_FORCE_DECOMPRESS_X2)
-                        hufSuccess = HUF_decompress1X_DCtx_wksp(
-                            dctx->entropy.hufTable, dctx->litBuffer, litSize,
-                            istart+lhSize, litCSize, dctx->workspace,
-                            sizeof(dctx->workspace));
-#else
-                        hufSuccess = HUF_decompress1X1_DCtx_wksp_bmi2(
-                            dctx->entropy.hufTable, dctx->litBuffer, litSize,
-                            istart+lhSize, litCSize, dctx->workspace,
-                            sizeof(dctx->workspace), dctx->bmi2);
-#endif
-                    } else {
-                        hufSuccess = HUF_decompress4X_hufOnly_wksp_bmi2(
-                            dctx->entropy.hufTable, dctx->litBuffer, litSize,
-                            istart+lhSize, litCSize, dctx->workspace,
-                            sizeof(dctx->workspace), dctx->bmi2);
-                    }
-                }
-
-                RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, "");
-
-                dctx->litPtr = dctx->litBuffer;
-                dctx->litSize = litSize;
-                dctx->litEntropy = 1;
-                if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
-                ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
-                return litCSize + lhSize;
-            }
-
-        case set_basic:
-            {   size_t litSize, lhSize;
-                U32 const lhlCode = ((istart[0]) >> 2) & 3;
-                switch(lhlCode)
-                {
-                case 0: case 2: default:   /* note : default is impossible, since lhlCode into [0..3] */
-                    lhSize = 1;
-                    litSize = istart[0] >> 3;
-                    break;
-                case 1:
-                    lhSize = 2;
-                    litSize = MEM_readLE16(istart) >> 4;
-                    break;
-                case 3:
-                    lhSize = 3;
-                    litSize = MEM_readLE24(istart) >> 4;
-                    break;
-                }
-
-                if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */
-                    RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, "");
-                    ZSTD_memcpy(dctx->litBuffer, istart+lhSize, litSize);
-                    dctx->litPtr = dctx->litBuffer;
-                    dctx->litSize = litSize;
-                    ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
-                    return lhSize+litSize;
-                }
-                /* direct reference into compressed stream */
-                dctx->litPtr = istart+lhSize;
-                dctx->litSize = litSize;
-                return lhSize+litSize;
-            }
-
-        case set_rle:
-            {   U32 const lhlCode = ((istart[0]) >> 2) & 3;
-                size_t litSize, lhSize;
-                switch(lhlCode)
-                {
-                case 0: case 2: default:   /* note : default is impossible, since lhlCode into [0..3] */
-                    lhSize = 1;
-                    litSize = istart[0] >> 3;
-                    break;
-                case 1:
-                    lhSize = 2;
-                    litSize = MEM_readLE16(istart) >> 4;
-                    break;
-                case 3:
-                    lhSize = 3;
-                    litSize = MEM_readLE24(istart) >> 4;
-                    RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4");
-                    break;
-                }
-                RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
-                ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
-                dctx->litPtr = dctx->litBuffer;
-                dctx->litSize = litSize;
-                return lhSize+1;
-            }
-        default:
-            RETURN_ERROR(corruption_detected, "impossible");
-        }
-    }
-}
-
-/* Default FSE distribution tables.
- * These are pre-calculated FSE decoding tables using default distributions as defined in specification :
- * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions
- * They were generated programmatically with following method :
- * - start from default distributions, present in /lib/common/zstd_internal.h
- * - generate tables normally, using ZSTD_buildFSETable()
- * - printout the content of tables
- * - pretify output, report below, test with fuzzer to ensure it's correct */
-
-/* Default FSE distribution table for Literal Lengths */
-static const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
-     {  1,  1,  1, LL_DEFAULTNORMLOG},  /* header : fastMode, tableLog */
-     /* nextState, nbAddBits, nbBits, baseVal */
-     {  0,  0,  4,    0},  { 16,  0,  4,    0},
-     { 32,  0,  5,    1},  {  0,  0,  5,    3},
-     {  0,  0,  5,    4},  {  0,  0,  5,    6},
-     {  0,  0,  5,    7},  {  0,  0,  5,    9},
-     {  0,  0,  5,   10},  {  0,  0,  5,   12},
-     {  0,  0,  6,   14},  {  0,  1,  5,   16},
-     {  0,  1,  5,   20},  {  0,  1,  5,   22},
-     {  0,  2,  5,   28},  {  0,  3,  5,   32},
-     {  0,  4,  5,   48},  { 32,  6,  5,   64},
-     {  0,  7,  5,  128},  {  0,  8,  6,  256},
-     {  0, 10,  6, 1024},  {  0, 12,  6, 4096},
-     { 32,  0,  4,    0},  {  0,  0,  4,    1},
-     {  0,  0,  5,    2},  { 32,  0,  5,    4},
-     {  0,  0,  5,    5},  { 32,  0,  5,    7},
-     {  0,  0,  5,    8},  { 32,  0,  5,   10},
-     {  0,  0,  5,   11},  {  0,  0,  6,   13},
-     { 32,  1,  5,   16},  {  0,  1,  5,   18},
-     { 32,  1,  5,   22},  {  0,  2,  5,   24},
-     { 32,  3,  5,   32},  {  0,  3,  5,   40},
-     {  0,  6,  4,   64},  { 16,  6,  4,   64},
-     { 32,  7,  5,  128},  {  0,  9,  6,  512},
-     {  0, 11,  6, 2048},  { 48,  0,  4,    0},
-     { 16,  0,  4,    1},  { 32,  0,  5,    2},
-     { 32,  0,  5,    3},  { 32,  0,  5,    5},
-     { 32,  0,  5,    6},  { 32,  0,  5,    8},
-     { 32,  0,  5,    9},  { 32,  0,  5,   11},
-     { 32,  0,  5,   12},  {  0,  0,  6,   15},
-     { 32,  1,  5,   18},  { 32,  1,  5,   20},
-     { 32,  2,  5,   24},  { 32,  2,  5,   28},
-     { 32,  3,  5,   40},  { 32,  4,  5,   48},
-     {  0, 16,  6,65536},  {  0, 15,  6,32768},
-     {  0, 14,  6,16384},  {  0, 13,  6, 8192},
-};   /* LL_defaultDTable */
-
-/* Default FSE distribution table for Offset Codes */
-static const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
-    {  1,  1,  1, OF_DEFAULTNORMLOG},  /* header : fastMode, tableLog */
-    /* nextState, nbAddBits, nbBits, baseVal */
-    {  0,  0,  5,    0},     {  0,  6,  4,   61},
-    {  0,  9,  5,  509},     {  0, 15,  5,32765},
-    {  0, 21,  5,2097149},   {  0,  3,  5,    5},
-    {  0,  7,  4,  125},     {  0, 12,  5, 4093},
-    {  0, 18,  5,262141},    {  0, 23,  5,8388605},
-    {  0,  5,  5,   29},     {  0,  8,  4,  253},
-    {  0, 14,  5,16381},     {  0, 20,  5,1048573},
-    {  0,  2,  5,    1},     { 16,  7,  4,  125},
-    {  0, 11,  5, 2045},     {  0, 17,  5,131069},
-    {  0, 22,  5,4194301},   {  0,  4,  5,   13},
-    { 16,  8,  4,  253},     {  0, 13,  5, 8189},
-    {  0, 19,  5,524285},    {  0,  1,  5,    1},
-    { 16,  6,  4,   61},     {  0, 10,  5, 1021},
-    {  0, 16,  5,65533},     {  0, 28,  5,268435453},
-    {  0, 27,  5,134217725}, {  0, 26,  5,67108861},
-    {  0, 25,  5,33554429},  {  0, 24,  5,16777213},
-};   /* OF_defaultDTable */
-
-
-/* Default FSE distribution table for Match Lengths */
-static const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
-    {  1,  1,  1, ML_DEFAULTNORMLOG},  /* header : fastMode, tableLog */
-    /* nextState, nbAddBits, nbBits, baseVal */
-    {  0,  0,  6,    3},  {  0,  0,  4,    4},
-    { 32,  0,  5,    5},  {  0,  0,  5,    6},
-    {  0,  0,  5,    8},  {  0,  0,  5,    9},
-    {  0,  0,  5,   11},  {  0,  0,  6,   13},
-    {  0,  0,  6,   16},  {  0,  0,  6,   19},
-    {  0,  0,  6,   22},  {  0,  0,  6,   25},
-    {  0,  0,  6,   28},  {  0,  0,  6,   31},
-    {  0,  0,  6,   34},  {  0,  1,  6,   37},
-    {  0,  1,  6,   41},  {  0,  2,  6,   47},
-    {  0,  3,  6,   59},  {  0,  4,  6,   83},
-    {  0,  7,  6,  131},  {  0,  9,  6,  515},
-    { 16,  0,  4,    4},  {  0,  0,  4,    5},
-    { 32,  0,  5,    6},  {  0,  0,  5,    7},
-    { 32,  0,  5,    9},  {  0,  0,  5,   10},
-    {  0,  0,  6,   12},  {  0,  0,  6,   15},
-    {  0,  0,  6,   18},  {  0,  0,  6,   21},
-    {  0,  0,  6,   24},  {  0,  0,  6,   27},
-    {  0,  0,  6,   30},  {  0,  0,  6,   33},
-    {  0,  1,  6,   35},  {  0,  1,  6,   39},
-    {  0,  2,  6,   43},  {  0,  3,  6,   51},
-    {  0,  4,  6,   67},  {  0,  5,  6,   99},
-    {  0,  8,  6,  259},  { 32,  0,  4,    4},
-    { 48,  0,  4,    4},  { 16,  0,  4,    5},
-    { 32,  0,  5,    7},  { 32,  0,  5,    8},
-    { 32,  0,  5,   10},  { 32,  0,  5,   11},
-    {  0,  0,  6,   14},  {  0,  0,  6,   17},
-    {  0,  0,  6,   20},  {  0,  0,  6,   23},
-    {  0,  0,  6,   26},  {  0,  0,  6,   29},
-    {  0,  0,  6,   32},  {  0, 16,  6,65539},
-    {  0, 15,  6,32771},  {  0, 14,  6,16387},
-    {  0, 13,  6, 8195},  {  0, 12,  6, 4099},
-    {  0, 11,  6, 2051},  {  0, 10,  6, 1027},
-};   /* ML_defaultDTable */
-
-
-static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddBits)
-{
-    void* ptr = dt;
-    ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;
-    ZSTD_seqSymbol* const cell = dt + 1;
-
-    DTableH->tableLog = 0;
-    DTableH->fastMode = 0;
-
-    cell->nbBits = 0;
-    cell->nextState = 0;
-    assert(nbAddBits < 255);
-    cell->nbAdditionalBits = (BYTE)nbAddBits;
-    cell->baseValue = baseValue;
-}
-
-
-/* ZSTD_buildFSETable() :
- * generate FSE decoding table for one symbol (ll, ml or off)
- * cannot fail if input is valid =>
- * all inputs are presumed validated at this stage */
-FORCE_INLINE_TEMPLATE
-void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,
-            const short* normalizedCounter, unsigned maxSymbolValue,
-            const U32* baseValue, const U32* nbAdditionalBits,
-            unsigned tableLog, void* wksp, size_t wkspSize)
-{
-    ZSTD_seqSymbol* const tableDecode = dt+1;
-    U32 const maxSV1 = maxSymbolValue + 1;
-    U32 const tableSize = 1 << tableLog;
-
-    U16* symbolNext = (U16*)wksp;
-    BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1);
-    U32 highThreshold = tableSize - 1;
-
-
-    /* Sanity Checks */
-    assert(maxSymbolValue <= MaxSeq);
-    assert(tableLog <= MaxFSELog);
-    assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE);
-    (void)wkspSize;
-    /* Init, lay down lowprob symbols */
-    {   ZSTD_seqSymbol_header DTableH;
-        DTableH.tableLog = tableLog;
-        DTableH.fastMode = 1;
-        {   S16 const largeLimit= (S16)(1 << (tableLog-1));
-            U32 s;
-            for (s=0; s<maxSV1; s++) {
-                if (normalizedCounter[s]==-1) {
-                    tableDecode[highThreshold--].baseValue = s;
-                    symbolNext[s] = 1;
-                } else {
-                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
-                    assert(normalizedCounter[s]>=0);
-                    symbolNext[s] = (U16)normalizedCounter[s];
-        }   }   }
-        ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
-    }
-
-    /* Spread symbols */
-    assert(tableSize <= 512);
-    /* Specialized symbol spreading for the case when there are
-     * no low probability (-1 count) symbols. When compressing
-     * small blocks we avoid low probability symbols to hit this
-     * case, since header decoding speed matters more.
-     */
-    if (highThreshold == tableSize - 1) {
-        size_t const tableMask = tableSize-1;
-        size_t const step = FSE_TABLESTEP(tableSize);
-        /* First lay down the symbols in order.
-         * We use a uint64_t to lay down 8 bytes at a time. This reduces branch
-         * misses since small blocks generally have small table logs, so nearly
-         * all symbols have counts <= 8. We ensure we have 8 bytes at the end of
-         * our buffer to handle the over-write.
-         */
-        {
-            U64 const add = 0x0101010101010101ull;
-            size_t pos = 0;
-            U64 sv = 0;
-            U32 s;
-            for (s=0; s<maxSV1; ++s, sv += add) {
-                int i;
-                int const n = normalizedCounter[s];
-                MEM_write64(spread + pos, sv);
-                for (i = 8; i < n; i += 8) {
-                    MEM_write64(spread + pos + i, sv);
-                }
-                pos += n;
-            }
-        }
-        /* Now we spread those positions across the table.
-         * The benefit of doing it in two stages is that we avoid the the
-         * variable size inner loop, which caused lots of branch misses.
-         * Now we can run through all the positions without any branch misses.
-         * We unroll the loop twice, since that is what emperically worked best.
-         */
-        {
-            size_t position = 0;
-            size_t s;
-            size_t const unroll = 2;
-            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
-            for (s = 0; s < (size_t)tableSize; s += unroll) {
-                size_t u;
-                for (u = 0; u < unroll; ++u) {
-                    size_t const uPosition = (position + (u * step)) & tableMask;
-                    tableDecode[uPosition].baseValue = spread[s + u];
-                }
-                position = (position + (unroll * step)) & tableMask;
-            }
-            assert(position == 0);
-        }
-    } else {
-        U32 const tableMask = tableSize-1;
-        U32 const step = FSE_TABLESTEP(tableSize);
-        U32 s, position = 0;
-        for (s=0; s<maxSV1; s++) {
-            int i;
-            int const n = normalizedCounter[s];
-            for (i=0; i<n; i++) {
-                tableDecode[position].baseValue = s;
-                position = (position + step) & tableMask;
-                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */
-        }   }
-        assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
-    }
-
-    /* Build Decoding table */
-    {
-        U32 u;
-        for (u=0; u<tableSize; u++) {
-            U32 const symbol = tableDecode[u].baseValue;
-            U32 const nextState = symbolNext[symbol]++;
-            tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
-            tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
-            assert(nbAdditionalBits[symbol] < 255);
-            tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol];
-            tableDecode[u].baseValue = baseValue[symbol];
-        }
-    }
-}
-
-/* Avoids the FORCE_INLINE of the _body() function. */
-static void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt,
-            const short* normalizedCounter, unsigned maxSymbolValue,
-            const U32* baseValue, const U32* nbAdditionalBits,
-            unsigned tableLog, void* wksp, size_t wkspSize)
-{
-    ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
-            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
-}
-
-#if DYNAMIC_BMI2
-TARGET_ATTRIBUTE("bmi2") static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt,
-            const short* normalizedCounter, unsigned maxSymbolValue,
-            const U32* baseValue, const U32* nbAdditionalBits,
-            unsigned tableLog, void* wksp, size_t wkspSize)
-{
-    ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
-            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
-}
-#endif
-
-void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
-            const short* normalizedCounter, unsigned maxSymbolValue,
-            const U32* baseValue, const U32* nbAdditionalBits,
-            unsigned tableLog, void* wksp, size_t wkspSize, int bmi2)
-{
-#if DYNAMIC_BMI2
-    if (bmi2) {
-        ZSTD_buildFSETable_body_bmi2(dt, normalizedCounter, maxSymbolValue,
-                baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
-        return;
-    }
-#endif
-    (void)bmi2;
-    ZSTD_buildFSETable_body_default(dt, normalizedCounter, maxSymbolValue,
-            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
-}
-
-
-/*! ZSTD_buildSeqTable() :
- * @return : nb bytes read from src,
- *           or an error code if it fails */
-static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,
-                                 symbolEncodingType_e type, unsigned max, U32 maxLog,
-                                 const void* src, size_t srcSize,
-                                 const U32* baseValue, const U32* nbAdditionalBits,
-                                 const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable,
-                                 int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize,
-                                 int bmi2)
-{
-    switch(type)
-    {
-    case set_rle :
-        RETURN_ERROR_IF(!srcSize, srcSize_wrong, "");
-        RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected, "");
-        {   U32 const symbol = *(const BYTE*)src;
-            U32 const baseline = baseValue[symbol];
-            U32 const nbBits = nbAdditionalBits[symbol];
-            ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);
-        }
-        *DTablePtr = DTableSpace;
-        return 1;
-    case set_basic :
-        *DTablePtr = defaultTable;
-        return 0;
-    case set_repeat:
-        RETURN_ERROR_IF(!flagRepeatTable, corruption_detected, "");
-        /* prefetch FSE table if used */
-        if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {
-            const void* const pStart = *DTablePtr;
-            size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog));
-            PREFETCH_AREA(pStart, pSize);
-        }
-        return 0;
-    case set_compressed :
-        {   unsigned tableLog;
-            S16 norm[MaxSeq+1];
-            size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
-            RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, "");
-            RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, "");
-            ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2);
-            *DTablePtr = DTableSpace;
-            return headerSize;
-        }
-    default :
-        assert(0);
-        RETURN_ERROR(GENERIC, "impossible");
-    }
-}
-
-size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
-                             const void* src, size_t srcSize)
-{
-    const BYTE* const istart = (const BYTE*)src;
-    const BYTE* const iend = istart + srcSize;
-    const BYTE* ip = istart;
-    int nbSeq;
-    DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
-
-    /* check */
-    RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong, "");
-
-    /* SeqHead */
-    nbSeq = *ip++;
-    if (!nbSeq) {
-        *nbSeqPtr=0;
-        RETURN_ERROR_IF(srcSize != 1, srcSize_wrong, "");
-        return 1;
-    }
-    if (nbSeq > 0x7F) {
-        if (nbSeq == 0xFF) {
-            RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, "");
-            nbSeq = MEM_readLE16(ip) + LONGNBSEQ;
-            ip+=2;
-        } else {
-            RETURN_ERROR_IF(ip >= iend, srcSize_wrong, "");
-            nbSeq = ((nbSeq-0x80)<<8) + *ip++;
-        }
-    }
-    *nbSeqPtr = nbSeq;
-
-    /* FSE table descriptors */
-    RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, ""); /* minimum possible size: 1 byte for symbol encoding types */
-    {   symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
-        symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
-        symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
-        ip++;
-
-        /* Build DTables */
-        {   size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
-                                                      LLtype, MaxLL, LLFSELog,
-                                                      ip, iend-ip,
-                                                      LL_base, LL_bits,
-                                                      LL_defaultDTable, dctx->fseEntropy,
-                                                      dctx->ddictIsCold, nbSeq,
-                                                      dctx->workspace, sizeof(dctx->workspace),
-                                                      dctx->bmi2);
-            RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed");
-            ip += llhSize;
-        }
-
-        {   size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
-                                                      OFtype, MaxOff, OffFSELog,
-                                                      ip, iend-ip,
-                                                      OF_base, OF_bits,
-                                                      OF_defaultDTable, dctx->fseEntropy,
-                                                      dctx->ddictIsCold, nbSeq,
-                                                      dctx->workspace, sizeof(dctx->workspace),
-                                                      dctx->bmi2);
-            RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed");
-            ip += ofhSize;
-        }
-
-        {   size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
-                                                      MLtype, MaxML, MLFSELog,
-                                                      ip, iend-ip,
-                                                      ML_base, ML_bits,
-                                                      ML_defaultDTable, dctx->fseEntropy,
-                                                      dctx->ddictIsCold, nbSeq,
-                                                      dctx->workspace, sizeof(dctx->workspace),
-                                                      dctx->bmi2);
-            RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed");
-            ip += mlhSize;
-        }
-    }
-
-    return ip-istart;
-}
-
-
-typedef struct {
-    size_t litLength;
-    size_t matchLength;
-    size_t offset;
-    const BYTE* match;
-} seq_t;
-
-typedef struct {
-    size_t state;
-    const ZSTD_seqSymbol* table;
-} ZSTD_fseState;
-
-typedef struct {
-    BIT_DStream_t DStream;
-    ZSTD_fseState stateLL;
-    ZSTD_fseState stateOffb;
-    ZSTD_fseState stateML;
-    size_t prevOffset[ZSTD_REP_NUM];
-    const BYTE* prefixStart;
-    const BYTE* dictEnd;
-    size_t pos;
-} seqState_t;
-
-/*! ZSTD_overlapCopy8() :
- *  Copies 8 bytes from ip to op and updates op and ip where ip <= op.
- *  If the offset is < 8 then the offset is spread to at least 8 bytes.
- *
- *  Precondition: *ip <= *op
- *  Postcondition: *op - *op >= 8
- */
-HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) {
-    assert(*ip <= *op);
-    if (offset < 8) {
-        /* close range match, overlap */
-        static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */
-        static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */
-        int const sub2 = dec64table[offset];
-        (*op)[0] = (*ip)[0];
-        (*op)[1] = (*ip)[1];
-        (*op)[2] = (*ip)[2];
-        (*op)[3] = (*ip)[3];
-        *ip += dec32table[offset];
-        ZSTD_copy4(*op+4, *ip);
-        *ip -= sub2;
-    } else {
-        ZSTD_copy8(*op, *ip);
-    }
-    *ip += 8;
-    *op += 8;
-    assert(*op - *ip >= 8);
-}
-
-/*! ZSTD_safecopy() :
- *  Specialized version of memcpy() that is allowed to READ up to WILDCOPY_OVERLENGTH past the input buffer
- *  and write up to 16 bytes past oend_w (op >= oend_w is allowed).
- *  This function is only called in the uncommon case where the sequence is near the end of the block. It
- *  should be fast for a single long sequence, but can be slow for several short sequences.
- *
- *  @param ovtype controls the overlap detection
- *         - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.
- *         - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart.
- *           The src buffer must be before the dst buffer.
- */
-static void ZSTD_safecopy(BYTE* op, BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) {
-    ptrdiff_t const diff = op - ip;
-    BYTE* const oend = op + length;
-
-    assert((ovtype == ZSTD_no_overlap && (diff <= -8 || diff >= 8 || op >= oend_w)) ||
-           (ovtype == ZSTD_overlap_src_before_dst && diff >= 0));
-
-    if (length < 8) {
-        /* Handle short lengths. */
-        while (op < oend) *op++ = *ip++;
-        return;
-    }
-    if (ovtype == ZSTD_overlap_src_before_dst) {
-        /* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */
-        assert(length >= 8);
-        ZSTD_overlapCopy8(&op, &ip, diff);
-        assert(op - ip >= 8);
-        assert(op <= oend);
-    }
-
-    if (oend <= oend_w) {
-        /* No risk of overwrite. */
-        ZSTD_wildcopy(op, ip, length, ovtype);
-        return;
-    }
-    if (op <= oend_w) {
-        /* Wildcopy until we get close to the end. */
-        assert(oend > oend_w);
-        ZSTD_wildcopy(op, ip, oend_w - op, ovtype);
-        ip += oend_w - op;
-        op = oend_w;
-    }
-    /* Handle the leftovers. */
-    while (op < oend) *op++ = *ip++;
-}
-
-/* ZSTD_execSequenceEnd():
- * This version handles cases that are near the end of the output buffer. It requires
- * more careful checks to make sure there is no overflow. By separating out these hard
- * and unlikely cases, we can speed up the common cases.
- *
- * NOTE: This function needs to be fast for a single long sequence, but doesn't need
- * to be optimized for many small sequences, since those fall into ZSTD_execSequence().
- */
-FORCE_NOINLINE
-size_t ZSTD_execSequenceEnd(BYTE* op,
-                            BYTE* const oend, seq_t sequence,
-                            const BYTE** litPtr, const BYTE* const litLimit,
-                            const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
-{
-    BYTE* const oLitEnd = op + sequence.litLength;
-    size_t const sequenceLength = sequence.litLength + sequence.matchLength;
-    const BYTE* const iLitEnd = *litPtr + sequence.litLength;
-    const BYTE* match = oLitEnd - sequence.offset;
-    BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
-
-    /* bounds checks : careful of address space overflow in 32-bit mode */
-    RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer");
-    RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer");
-    assert(op < op + sequenceLength);
-    assert(oLitEnd < op + sequenceLength);
-
-    /* copy literals */
-    ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, ZSTD_no_overlap);
-    op = oLitEnd;
-    *litPtr = iLitEnd;
-
-    /* copy Match */
-    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
-        /* offset beyond prefix */
-        RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, "");
-        match = dictEnd - (prefixStart-match);
-        if (match + sequence.matchLength <= dictEnd) {
-            ZSTD_memmove(oLitEnd, match, sequence.matchLength);
-            return sequenceLength;
-        }
-        /* span extDict & currentPrefixSegment */
-        {   size_t const length1 = dictEnd - match;
-            ZSTD_memmove(oLitEnd, match, length1);
-            op = oLitEnd + length1;
-            sequence.matchLength -= length1;
-            match = prefixStart;
-    }   }
-    ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);
-    return sequenceLength;
-}
-
-HINT_INLINE
-size_t ZSTD_execSequence(BYTE* op,
-                         BYTE* const oend, seq_t sequence,
-                         const BYTE** litPtr, const BYTE* const litLimit,
-                         const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
-{
-    BYTE* const oLitEnd = op + sequence.litLength;
-    size_t const sequenceLength = sequence.litLength + sequence.matchLength;
-    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */
-    BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;   /* risk : address space underflow on oend=NULL */
-    const BYTE* const iLitEnd = *litPtr + sequence.litLength;
-    const BYTE* match = oLitEnd - sequence.offset;
-
-    assert(op != NULL /* Precondition */);
-    assert(oend_w < oend /* No underflow */);
-    /* Handle edge cases in a slow path:
-     *   - Read beyond end of literals
-     *   - Match end is within WILDCOPY_OVERLIMIT of oend
-     *   - 32-bit mode and the match length overflows
-     */
-    if (UNLIKELY(
-            iLitEnd > litLimit ||
-            oMatchEnd > oend_w ||
-            (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))
-        return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
-
-    /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */
-    assert(op <= oLitEnd /* No overflow */);
-    assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);
-    assert(oMatchEnd <= oend /* No underflow */);
-    assert(iLitEnd <= litLimit /* Literal length is in bounds */);
-    assert(oLitEnd <= oend_w /* Can wildcopy literals */);
-    assert(oMatchEnd <= oend_w /* Can wildcopy matches */);
-
-    /* Copy Literals:
-     * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.
-     * We likely don't need the full 32-byte wildcopy.
-     */
-    assert(WILDCOPY_OVERLENGTH >= 16);
-    ZSTD_copy16(op, (*litPtr));
-    if (UNLIKELY(sequence.litLength > 16)) {
-        ZSTD_wildcopy(op+16, (*litPtr)+16, sequence.litLength-16, ZSTD_no_overlap);
-    }
-    op = oLitEnd;
-    *litPtr = iLitEnd;   /* update for next sequence */
-
-    /* Copy Match */
-    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
-        /* offset beyond prefix -> go into extDict */
-        RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, "");
-        match = dictEnd + (match - prefixStart);
-        if (match + sequence.matchLength <= dictEnd) {
-            ZSTD_memmove(oLitEnd, match, sequence.matchLength);
-            return sequenceLength;
-        }
-        /* span extDict & currentPrefixSegment */
-        {   size_t const length1 = dictEnd - match;
-            ZSTD_memmove(oLitEnd, match, length1);
-            op = oLitEnd + length1;
-            sequence.matchLength -= length1;
-            match = prefixStart;
-    }   }
-    /* Match within prefix of 1 or more bytes */
-    assert(op <= oMatchEnd);
-    assert(oMatchEnd <= oend_w);
-    assert(match >= prefixStart);
-    assert(sequence.matchLength >= 1);
-
-    /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy
-     * without overlap checking.
-     */
-    if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {
-        /* We bet on a full wildcopy for matches, since we expect matches to be
-         * longer than literals (in general). In silesia, ~10% of matches are longer
-         * than 16 bytes.
-         */
-        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);
-        return sequenceLength;
-    }
-    assert(sequence.offset < WILDCOPY_VECLEN);
-
-    /* Copy 8 bytes and spread the offset to be >= 8. */
-    ZSTD_overlapCopy8(&op, &match, sequence.offset);
-
-    /* If the match length is > 8 bytes, then continue with the wildcopy. */
-    if (sequence.matchLength > 8) {
-        assert(op < oMatchEnd);
-        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst);
-    }
-    return sequenceLength;
-}
-
-static void
-ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)
-{
-    const void* ptr = dt;
-    const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr;
-    DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
-    DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits",
-                (U32)DStatePtr->state, DTableH->tableLog);
-    BIT_reloadDStream(bitD);
-    DStatePtr->table = dt + 1;
-}
-
-FORCE_INLINE_TEMPLATE void
-ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
-{
-    ZSTD_seqSymbol const DInfo = DStatePtr->table[DStatePtr->state];
-    U32 const nbBits = DInfo.nbBits;
-    size_t const lowBits = BIT_readBits(bitD, nbBits);
-    DStatePtr->state = DInfo.nextState + lowBits;
-}
-
-FORCE_INLINE_TEMPLATE void
-ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD_seqSymbol const DInfo)
-{
-    U32 const nbBits = DInfo.nbBits;
-    size_t const lowBits = BIT_readBits(bitD, nbBits);
-    DStatePtr->state = DInfo.nextState + lowBits;
-}
-
-/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
- * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
- * bits before reloading. This value is the maximum number of bytes we read
- * after reloading when we are decoding long offsets.
- */
-#define LONG_OFFSETS_MAX_EXTRA_BITS_32                       \
-    (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32       \
-        ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32  \
-        : 0)
-
-typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
-typedef enum { ZSTD_p_noPrefetch=0, ZSTD_p_prefetch=1 } ZSTD_prefetch_e;
-
-FORCE_INLINE_TEMPLATE seq_t
-ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const ZSTD_prefetch_e prefetch)
-{
-    seq_t seq;
-    ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state];
-    ZSTD_seqSymbol const mlDInfo = seqState->stateML.table[seqState->stateML.state];
-    ZSTD_seqSymbol const ofDInfo = seqState->stateOffb.table[seqState->stateOffb.state];
-    U32 const llBase = llDInfo.baseValue;
-    U32 const mlBase = mlDInfo.baseValue;
-    U32 const ofBase = ofDInfo.baseValue;
-    BYTE const llBits = llDInfo.nbAdditionalBits;
-    BYTE const mlBits = mlDInfo.nbAdditionalBits;
-    BYTE const ofBits = ofDInfo.nbAdditionalBits;
-    BYTE const totalBits = llBits+mlBits+ofBits;
-
-    /* sequence */
-    {   size_t offset;
-        if (ofBits > 1) {
-            ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
-            ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
-            assert(ofBits <= MaxOff);
-            if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
-                U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
-                offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
-                BIT_reloadDStream(&seqState->DStream);
-                if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
-                assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32);   /* to avoid another reload */
-            } else {
-                offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/);   /* <=  (ZSTD_WINDOWLOG_MAX-1) bits */
-                if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
-            }
-            seqState->prevOffset[2] = seqState->prevOffset[1];
-            seqState->prevOffset[1] = seqState->prevOffset[0];
-            seqState->prevOffset[0] = offset;
-        } else {
-            U32 const ll0 = (llBase == 0);
-            if (LIKELY((ofBits == 0))) {
-                if (LIKELY(!ll0))
-                    offset = seqState->prevOffset[0];
-                else {
-                    offset = seqState->prevOffset[1];
-                    seqState->prevOffset[1] = seqState->prevOffset[0];
-                    seqState->prevOffset[0] = offset;
-                }
-            } else {
-                offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);
-                {   size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
-                    temp += !temp;   /* 0 is not valid; input is corrupted; force offset to 1 */
-                    if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
-                    seqState->prevOffset[1] = seqState->prevOffset[0];
-                    seqState->prevOffset[0] = offset = temp;
-        }   }   }
-        seq.offset = offset;
-    }
-
-    seq.matchLength = mlBase;
-    if (mlBits > 0)
-        seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);
-
-    if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
-        BIT_reloadDStream(&seqState->DStream);
-    if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
-        BIT_reloadDStream(&seqState->DStream);
-    /* Ensure there are enough bits to read the rest of data in 64-bit mode. */
-    ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
-
-    seq.litLength = llBase;
-    if (llBits > 0)
-        seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);
-
-    if (MEM_32bits())
-        BIT_reloadDStream(&seqState->DStream);
-
-    DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
-                (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
-
-    if (prefetch == ZSTD_p_prefetch) {
-        size_t const pos = seqState->pos + seq.litLength;
-        const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
-        seq.match = matchBase + pos - seq.offset;  /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
-                                                    * No consequence though : no memory access will occur, offset is only used for prefetching */
-        seqState->pos = pos + seq.matchLength;
-    }
-
-    /* ANS state update
-     * gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo().
-     * clang-9.2.0 does 7% worse with ZSTD_updateFseState().
-     * Naturally it seems like ZSTD_updateFseStateWithDInfo() should be the
-     * better option, so it is the default for other compilers. But, if you
-     * measure that it is worse, please put up a pull request.
-     */
-    {
-#if !defined(__clang__)
-        const int kUseUpdateFseState = 1;
-#else
-        const int kUseUpdateFseState = 0;
-#endif
-        if (kUseUpdateFseState) {
-            ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream);    /* <=  9 bits */
-            ZSTD_updateFseState(&seqState->stateML, &seqState->DStream);    /* <=  9 bits */
-            if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);    /* <= 18 bits */
-            ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream);  /* <=  8 bits */
-        } else {
-            ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llDInfo);    /* <=  9 bits */
-            ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlDInfo);    /* <=  9 bits */
-            if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);    /* <= 18 bits */
-            ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofDInfo);  /* <=  8 bits */
-        }
-    }
-
-    return seq;
-}
-
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-MEM_STATIC int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)
-{
-    size_t const windowSize = dctx->fParams.windowSize;
-    /* No dictionary used. */
-    if (dctx->dictContentEndForFuzzing == NULL) return 0;
-    /* Dictionary is our prefix. */
-    if (prefixStart == dctx->dictContentBeginForFuzzing) return 1;
-    /* Dictionary is not our ext-dict. */
-    if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0;
-    /* Dictionary is not within our window size. */
-    if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0;
-    /* Dictionary is active. */
-    return 1;
-}
-
-MEM_STATIC void ZSTD_assertValidSequence(
-        ZSTD_DCtx const* dctx,
-        BYTE const* op, BYTE const* oend,
-        seq_t const seq,
-        BYTE const* prefixStart, BYTE const* virtualStart)
-{
-#if DEBUGLEVEL >= 1
-    size_t const windowSize = dctx->fParams.windowSize;
-    size_t const sequenceSize = seq.litLength + seq.matchLength;
-    BYTE const* const oLitEnd = op + seq.litLength;
-    DEBUGLOG(6, "Checking sequence: litL=%u matchL=%u offset=%u",
-            (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
-    assert(op <= oend);
-    assert((size_t)(oend - op) >= sequenceSize);
-    assert(sequenceSize <= ZSTD_BLOCKSIZE_MAX);
-    if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) {
-        size_t const dictSize = (size_t)((char const*)dctx->dictContentEndForFuzzing - (char const*)dctx->dictContentBeginForFuzzing);
-        /* Offset must be within the dictionary. */
-        assert(seq.offset <= (size_t)(oLitEnd - virtualStart));
-        assert(seq.offset <= windowSize + dictSize);
-    } else {
-        /* Offset must be within our window. */
-        assert(seq.offset <= windowSize);
-    }
-#else
-    (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart;
-#endif
-}
-#endif
-
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
-FORCE_INLINE_TEMPLATE size_t
-DONT_VECTORIZE
-ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
-                               void* dst, size_t maxDstSize,
-                         const void* seqStart, size_t seqSize, int nbSeq,
-                         const ZSTD_longOffset_e isLongOffset,
-                         const int frame)
-{
-    const BYTE* ip = (const BYTE*)seqStart;
-    const BYTE* const iend = ip + seqSize;
-    BYTE* const ostart = (BYTE*)dst;
-    BYTE* const oend = ostart + maxDstSize;
-    BYTE* op = ostart;
-    const BYTE* litPtr = dctx->litPtr;
-    const BYTE* const litEnd = litPtr + dctx->litSize;
-    const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
-    const BYTE* const vBase = (const BYTE*) (dctx->virtualStart);
-    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
-    DEBUGLOG(5, "ZSTD_decompressSequences_body");
-    (void)frame;
-
-    /* Regen sequences */
-    if (nbSeq) {
-        seqState_t seqState;
-        size_t error = 0;
-        dctx->fseEntropy = 1;
-        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
-        RETURN_ERROR_IF(
-            ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
-            corruption_detected, "");
-        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
-        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
-        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
-        assert(dst != NULL);
-
-        ZSTD_STATIC_ASSERT(
-                BIT_DStream_unfinished < BIT_DStream_completed &&
-                BIT_DStream_endOfBuffer < BIT_DStream_completed &&
-                BIT_DStream_completed < BIT_DStream_overflow);
-
-#if defined(__x86_64__)
-        /* Align the decompression loop to 32 + 16 bytes.
-         *
-         * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression
-         * speed swings based on the alignment of the decompression loop. This
-         * performance swing is caused by parts of the decompression loop falling
-         * out of the DSB. The entire decompression loop should fit in the DSB,
-         * when it can't we get much worse performance. You can measure if you've
-         * hit the good case or the bad case with this perf command for some
-         * compressed file test.zst:
-         *
-         *   perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \
-         *             -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst
-         *
-         * If you see most cycles served out of the MITE you've hit the bad case.
-         * If you see most cycles served out of the DSB you've hit the good case.
-         * If it is pretty even then you may be in an okay case.
-         *
-         * I've been able to reproduce this issue on the following CPUs:
-         *   - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9
-         *               Use Instruments->Counters to get DSB/MITE cycles.
-         *               I never got performance swings, but I was able to
-         *               go from the good case of mostly DSB to half of the
-         *               cycles served from MITE.
-         *   - Coffeelake: Intel i9-9900k
-         *
-         * I haven't been able to reproduce the instability or DSB misses on any
-         * of the following CPUS:
-         *   - Haswell
-         *   - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH
-         *   - Skylake
-         *
-         * If you are seeing performance stability this script can help test.
-         * It tests on 4 commits in zstd where I saw performance change.
-         *
-         *   https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4
-         */
-        __asm__(".p2align 5");
-        __asm__("nop");
-        __asm__(".p2align 4");
-#endif
-        for ( ; ; ) {
-            seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch);
-            size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
-#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
-            assert(!ZSTD_isError(oneSeqSize));
-            if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
-#endif
-            DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
-            BIT_reloadDStream(&(seqState.DStream));
-            op += oneSeqSize;
-            /* gcc and clang both don't like early returns in this loop.
-             * Instead break and check for an error at the end of the loop.
-             */
-            if (UNLIKELY(ZSTD_isError(oneSeqSize))) {
-                error = oneSeqSize;
-                break;
-            }
-            if (UNLIKELY(!--nbSeq)) break;
-        }
-
-        /* check if reached exact end */
-        DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
-        if (ZSTD_isError(error)) return error;
-        RETURN_ERROR_IF(nbSeq, corruption_detected, "");
-        RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, "");
-        /* save reps for next block */
-        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
-    }
-
-    /* last literal segment */
-    {   size_t const lastLLSize = litEnd - litPtr;
-        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
-        if (op != NULL) {
-            ZSTD_memcpy(op, litPtr, lastLLSize);
-            op += lastLLSize;
-        }
-    }
-
-    return op-ostart;
-}
-
-static size_t
-ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
-                                 void* dst, size_t maxDstSize,
-                           const void* seqStart, size_t seqSize, int nbSeq,
-                           const ZSTD_longOffset_e isLongOffset,
-                           const int frame)
-{
-    return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-}
-#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
-
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
-FORCE_INLINE_TEMPLATE size_t
-ZSTD_decompressSequencesLong_body(
-                               ZSTD_DCtx* dctx,
-                               void* dst, size_t maxDstSize,
-                         const void* seqStart, size_t seqSize, int nbSeq,
-                         const ZSTD_longOffset_e isLongOffset,
-                         const int frame)
-{
-    const BYTE* ip = (const BYTE*)seqStart;
-    const BYTE* const iend = ip + seqSize;
-    BYTE* const ostart = (BYTE*)dst;
-    BYTE* const oend = ostart + maxDstSize;
-    BYTE* op = ostart;
-    const BYTE* litPtr = dctx->litPtr;
-    const BYTE* const litEnd = litPtr + dctx->litSize;
-    const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
-    const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart);
-    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
-    (void)frame;
-
-    /* Regen sequences */
-    if (nbSeq) {
-#define STORED_SEQS 4
-#define STORED_SEQS_MASK (STORED_SEQS-1)
-#define ADVANCED_SEQS 4
-        seq_t sequences[STORED_SEQS];
-        int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
-        seqState_t seqState;
-        int seqNb;
-        dctx->fseEntropy = 1;
-        { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
-        seqState.prefixStart = prefixStart;
-        seqState.pos = (size_t)(op-prefixStart);
-        seqState.dictEnd = dictEnd;
-        assert(dst != NULL);
-        assert(iend >= ip);
-        RETURN_ERROR_IF(
-            ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
-            corruption_detected, "");
-        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
-        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
-        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
-
-        /* prepare in advance */
-        for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
-            sequences[seqNb] = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
-            PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
-        }
-        RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, "");
-
-        /* decode and decompress */
-        for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
-            seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
-            size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
-#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
-            assert(!ZSTD_isError(oneSeqSize));
-            if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
-#endif
-            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
-            PREFETCH_L1(sequence.match); PREFETCH_L1(sequence.match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
-            sequences[seqNb & STORED_SEQS_MASK] = sequence;
-            op += oneSeqSize;
-        }
-        RETURN_ERROR_IF(seqNb<nbSeq, corruption_detected, "");
-
-        /* finish queue */
-        seqNb -= seqAdvance;
-        for ( ; seqNb<nbSeq ; seqNb++) {
-            size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[seqNb&STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
-#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
-            assert(!ZSTD_isError(oneSeqSize));
-            if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);
-#endif
-            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
-            op += oneSeqSize;
-        }
-
-        /* save reps for next block */
-        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
-    }
-
-    /* last literal segment */
-    {   size_t const lastLLSize = litEnd - litPtr;
-        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
-        if (op != NULL) {
-            ZSTD_memcpy(op, litPtr, lastLLSize);
-            op += lastLLSize;
-        }
-    }
-
-    return op-ostart;
-}
-
-static size_t
-ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
-                                 void* dst, size_t maxDstSize,
-                           const void* seqStart, size_t seqSize, int nbSeq,
-                           const ZSTD_longOffset_e isLongOffset,
-                           const int frame)
-{
-    return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-}
-#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
-
-
-
-#if DYNAMIC_BMI2
-
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
-static TARGET_ATTRIBUTE("bmi2") size_t
-DONT_VECTORIZE
-ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
-                                 void* dst, size_t maxDstSize,
-                           const void* seqStart, size_t seqSize, int nbSeq,
-                           const ZSTD_longOffset_e isLongOffset,
-                           const int frame)
-{
-    return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-}
-#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
-
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
-static TARGET_ATTRIBUTE("bmi2") size_t
-ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,
-                                 void* dst, size_t maxDstSize,
-                           const void* seqStart, size_t seqSize, int nbSeq,
-                           const ZSTD_longOffset_e isLongOffset,
-                           const int frame)
-{
-    return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-}
-#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
-
-#endif /* DYNAMIC_BMI2 */
-
-typedef size_t (*ZSTD_decompressSequences_t)(
-                            ZSTD_DCtx* dctx,
-                            void* dst, size_t maxDstSize,
-                            const void* seqStart, size_t seqSize, int nbSeq,
-                            const ZSTD_longOffset_e isLongOffset,
-                            const int frame);
-
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
-static size_t
-ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
-                   const void* seqStart, size_t seqSize, int nbSeq,
-                   const ZSTD_longOffset_e isLongOffset,
-                   const int frame)
-{
-    DEBUGLOG(5, "ZSTD_decompressSequences");
-#if DYNAMIC_BMI2
-    if (dctx->bmi2) {
-        return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-    }
-#endif
-  return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-}
-#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
-
-
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
-/* ZSTD_decompressSequencesLong() :
- * decompression function triggered when a minimum share of offsets is considered "long",
- * aka out of cache.
- * note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance".
- * This function will try to mitigate main memory latency through the use of prefetching */
-static size_t
-ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
-                             void* dst, size_t maxDstSize,
-                             const void* seqStart, size_t seqSize, int nbSeq,
-                             const ZSTD_longOffset_e isLongOffset,
-                             const int frame)
-{
-    DEBUGLOG(5, "ZSTD_decompressSequencesLong");
-#if DYNAMIC_BMI2
-    if (dctx->bmi2) {
-        return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-    }
-#endif
-  return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
-}
-#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
-
-
-
-#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
-    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
-/* ZSTD_getLongOffsetsShare() :
- * condition : offTable must be valid
- * @return : "share" of long offsets (arbitrarily defined as > (1<<23))
- *           compared to maximum possible of (1<<OffFSELog) */
-static unsigned
-ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable)
-{
-    const void* ptr = offTable;
-    U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;
-    const ZSTD_seqSymbol* table = offTable + 1;
-    U32 const max = 1 << tableLog;
-    U32 u, total = 0;
-    DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog);
-
-    assert(max <= (1 << OffFSELog));  /* max not too large */
-    for (u=0; u<max; u++) {
-        if (table[u].nbAdditionalBits > 22) total += 1;
-    }
-
-    assert(tableLog <= OffFSELog);
-    total <<= (OffFSELog - tableLog);  /* scale to OffFSELog */
-
-    return total;
-}
-#endif
-
-size_t
-ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
-                              void* dst, size_t dstCapacity,
-                        const void* src, size_t srcSize, const int frame)
-{   /* blockType == blockCompressed */
-    const BYTE* ip = (const BYTE*)src;
-    /* isLongOffset must be true if there are long offsets.
-     * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
-     * We don't expect that to be the case in 64-bit mode.
-     * In block mode, window size is not known, so we have to be conservative.
-     * (note: but it could be evaluated from current-lowLimit)
-     */
-    ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
-    DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
-
-    RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong, "");
-
-    /* Decode literals section */
-    {   size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
-        DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
-        if (ZSTD_isError(litCSize)) return litCSize;
-        ip += litCSize;
-        srcSize -= litCSize;
-    }
-
-    /* Build Decoding Tables */
-    {
-        /* These macros control at build-time which decompressor implementation
-         * we use. If neither is defined, we do some inspection and dispatch at
-         * runtime.
-         */
-#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
-    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
-        int usePrefetchDecoder = dctx->ddictIsCold;
-#endif
-        int nbSeq;
-        size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);
-        if (ZSTD_isError(seqHSize)) return seqHSize;
-        ip += seqHSize;
-        srcSize -= seqHSize;
-
-        RETURN_ERROR_IF(dst == NULL && nbSeq > 0, dstSize_tooSmall, "NULL not handled");
-
-#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
-    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
-        if ( !usePrefetchDecoder
-          && (!frame || (dctx->fParams.windowSize > (1<<24)))
-          && (nbSeq>ADVANCED_SEQS) ) {  /* could probably use a larger nbSeq limit */
-            U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr);
-            U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */
-            usePrefetchDecoder = (shareLongOffsets >= minShare);
-        }
-#endif
-
-        dctx->ddictIsCold = 0;
-
-#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
-    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
-        if (usePrefetchDecoder)
-#endif
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
-            return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
-#endif
-
-#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
-        /* else */
-        return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
-#endif
-    }
-}
-
-
-void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)
-{
-    if (dst != dctx->previousDstEnd && dstSize > 0) {   /* not contiguous */
-        dctx->dictEnd = dctx->previousDstEnd;
-        dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
-        dctx->prefixStart = dst;
-        dctx->previousDstEnd = dst;
-    }
-}
-
-
-size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
-                            void* dst, size_t dstCapacity,
-                      const void* src, size_t srcSize)
-{
-    size_t dSize;
-    ZSTD_checkContinuity(dctx, dst, dstCapacity);
-    dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
-    dctx->previousDstEnd = (char*)dst + dSize;
-    return dSize;
-}
diff --git a/lib/zstd/decompress/zstd_decompress_block.h b/lib/zstd/decompress/zstd_decompress_block.h
deleted file mode 100644
index e7f5f6689459..000000000000
--- a/lib/zstd/decompress/zstd_decompress_block.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-
-#ifndef ZSTD_DEC_BLOCK_H
-#define ZSTD_DEC_BLOCK_H
-
-/*-*******************************************************
- *  Dependencies
- *********************************************************/
-#include "../common/zstd_deps.h"   /* size_t */
-#include <linux/zstd.h>    /* DCtx, and some public functions */
-#include "../common/zstd_internal.h"  /* blockProperties_t, and some public functions */
-#include "zstd_decompress_internal.h"  /* ZSTD_seqSymbol */
-
-
-/* ===   Prototypes   === */
-
-/* note: prototypes already published within `zstd.h` :
- * ZSTD_decompressBlock()
- */
-
-/* note: prototypes already published within `zstd_internal.h` :
- * ZSTD_getcBlockSize()
- * ZSTD_decodeSeqHeaders()
- */
-
-
-/* ZSTD_decompressBlock_internal() :
- * decompress block, starting at `src`,
- * into destination buffer `dst`.
- * @return : decompressed block size,
- *           or an error code (which can be tested using ZSTD_isError())
- */
-size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
-                               void* dst, size_t dstCapacity,
-                         const void* src, size_t srcSize, const int frame);
-
-/* ZSTD_buildFSETable() :
- * generate FSE decoding table for one symbol (ll, ml or off)
- * this function must be called with valid parameters only
- * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.)
- * in which case it cannot fail.
- * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is
- * defined in zstd_decompress_internal.h.
- * Internal use only.
- */
-void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
-             const short* normalizedCounter, unsigned maxSymbolValue,
-             const U32* baseValue, const U32* nbAdditionalBits,
-                   unsigned tableLog, void* wksp, size_t wkspSize,
-                   int bmi2);
-
-
-#endif /* ZSTD_DEC_BLOCK_H */
diff --git a/lib/zstd/decompress/zstd_decompress_internal.h b/lib/zstd/decompress/zstd_decompress_internal.h
deleted file mode 100644
index 4b9052f68755..000000000000
--- a/lib/zstd/decompress/zstd_decompress_internal.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) Yann Collet, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-
-/* zstd_decompress_internal:
- * objects and definitions shared within lib/decompress modules */
-
- #ifndef ZSTD_DECOMPRESS_INTERNAL_H
- #define ZSTD_DECOMPRESS_INTERNAL_H
-
-
-/*-*******************************************************
- *  Dependencies
- *********************************************************/
-#include "../common/mem.h"             /* BYTE, U16, U32 */
-#include "../common/zstd_internal.h"   /* ZSTD_seqSymbol */
-
-
-
-/*-*******************************************************
- *  Constants
- *********************************************************/
-static UNUSED_ATTR const U32 LL_base[MaxLL+1] = {
-                 0,    1,    2,     3,     4,     5,     6,      7,
-                 8,    9,   10,    11,    12,    13,    14,     15,
-                16,   18,   20,    22,    24,    28,    32,     40,
-                48,   64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
-                0x2000, 0x4000, 0x8000, 0x10000 };
-
-static UNUSED_ATTR const U32 OF_base[MaxOff+1] = {
-                 0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,
-                 0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,
-                 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
-                 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
-
-static UNUSED_ATTR const U32 OF_bits[MaxOff+1] = {
-                     0,  1,  2,  3,  4,  5,  6,  7,
-                     8,  9, 10, 11, 12, 13, 14, 15,
-                    16, 17, 18, 19, 20, 21, 22, 23,
-                    24, 25, 26, 27, 28, 29, 30, 31 };
-
-static UNUSED_ATTR const U32 ML_base[MaxML+1] = {
-                     3,  4,  5,    6,     7,     8,     9,    10,
-                    11, 12, 13,   14,    15,    16,    17,    18,
-                    19, 20, 21,   22,    23,    24,    25,    26,
-                    27, 28, 29,   30,    31,    32,    33,    34,
-                    35, 37, 39,   41,    43,    47,    51,    59,
-                    67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
-                    0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
-
-
-/*-*******************************************************
- *  Decompression types
- *********************************************************/
- typedef struct {
-     U32 fastMode;
-     U32 tableLog;
- } ZSTD_seqSymbol_header;
-
- typedef struct {
-     U16  nextState;
-     BYTE nbAdditionalBits;
-     BYTE nbBits;
-     U32  baseValue;
- } ZSTD_seqSymbol;
-
- #define SEQSYMBOL_TABLE_SIZE(log)   (1 + (1 << (log)))
-
-#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64))
-#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32))
-
-typedef struct {
-    ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)];    /* Note : Space reserved for FSE Tables */
-    ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)];   /* is also used as temporary workspace while building hufTable during DDict creation */
-    ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)];    /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */
-    HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)];  /* can accommodate HUF_decompress4X */
-    U32 rep[ZSTD_REP_NUM];
-    U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32];
-} ZSTD_entropyDTables_t;
-
-typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
-               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,
-               ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
-               ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
-
-typedef enum { zdss_init=0, zdss_loadHeader,
-               zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
-
-typedef enum {
-    ZSTD_use_indefinitely = -1,  /* Use the dictionary indefinitely */
-    ZSTD_dont_use = 0,           /* Do not use the dictionary (if one exists free it) */
-    ZSTD_use_once = 1            /* Use the dictionary once and set to ZSTD_dont_use */
-} ZSTD_dictUses_e;
-
-/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */
-typedef struct {
-    const ZSTD_DDict** ddictPtrTable;
-    size_t ddictPtrTableSize;
-    size_t ddictPtrCount;
-} ZSTD_DDictHashSet;
-
-struct ZSTD_DCtx_s
-{
-    const ZSTD_seqSymbol* LLTptr;
-    const ZSTD_seqSymbol* MLTptr;
-    const ZSTD_seqSymbol* OFTptr;
-    const HUF_DTable* HUFptr;
-    ZSTD_entropyDTables_t entropy;
-    U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];   /* space needed when building huffman tables */
-    const void* previousDstEnd;   /* detect continuity */
-    const void* prefixStart;      /* start of current segment */
-    const void* virtualStart;     /* virtual start of previous segment if it was just before current one */
-    const void* dictEnd;          /* end of previous segment */
-    size_t expected;
-    ZSTD_frameHeader fParams;
-    U64 processedCSize;
-    U64 decodedSize;
-    blockType_e bType;            /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
-    ZSTD_dStage stage;
-    U32 litEntropy;
-    U32 fseEntropy;
-    struct xxh64_state xxhState;
-    size_t headerSize;
-    ZSTD_format_e format;
-    ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum;   /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */
-    U32 validateChecksum;         /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */
-    const BYTE* litPtr;
-    ZSTD_customMem customMem;
-    size_t litSize;
-    size_t rleSize;
-    size_t staticSize;
-    int bmi2;                     /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
-
-    /* dictionary */
-    ZSTD_DDict* ddictLocal;
-    const ZSTD_DDict* ddict;     /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
-    U32 dictID;
-    int ddictIsCold;             /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
-    ZSTD_dictUses_e dictUses;
-    ZSTD_DDictHashSet* ddictSet;                    /* Hash set for multiple ddicts */
-    ZSTD_refMultipleDDicts_e refMultipleDDicts;     /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */
-
-    /* streaming */
-    ZSTD_dStreamStage streamStage;
-    char*  inBuff;
-    size_t inBuffSize;
-    size_t inPos;
-    size_t maxWindowSize;
-    char*  outBuff;
-    size_t outBuffSize;
-    size_t outStart;
-    size_t outEnd;
-    size_t lhSize;
-    void* legacyContext;
-    U32 previousLegacyVersion;
-    U32 legacyVersion;
-    U32 hostageByte;
-    int noForwardProgress;
-    ZSTD_bufferMode_e outBufferMode;
-    ZSTD_outBuffer expectedOutBuffer;
-
-    /* workspace */
-    BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
-    BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
-
-    size_t oversizedDuration;
-
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-    void const* dictContentBeginForFuzzing;
-    void const* dictContentEndForFuzzing;
-#endif
-
-    /* Tracing */
-};  /* typedef'd to ZSTD_DCtx within "zstd.h" */
-
-
-/*-*******************************************************
- *  Shared internal functions
- *********************************************************/
-
-/*! ZSTD_loadDEntropy() :
- *  dict : must point at beginning of a valid zstd dictionary.
- * @return : size of dictionary header (size of magic number + dict ID + entropy tables) */
-size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
-                   const void* const dict, size_t const dictSize);
-
-/*! ZSTD_checkContinuity() :
- *  check if next `dst` follows previous position, where decompression ended.
- *  If yes, do nothing (continue on current segment).
- *  If not, classify previous segment as "external dictionary", and start a new segment.
- *  This function cannot fail. */
-void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize);
-
-
-#endif /* ZSTD_DECOMPRESS_INTERNAL_H */
diff --git a/lib/zstd/decompress_sources.h b/lib/zstd/decompress_sources.h
deleted file mode 100644
index 0fbec508f285..000000000000
--- a/lib/zstd/decompress_sources.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
-/*
- * Copyright (c) Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-/*
- * This file includes every .c file needed for decompression.
- * It is used by lib/decompress_unzstd.c to include the decompression
- * source into the translation-unit, so it can be used for kernel
- * decompression.
- */
-
-#include "common/debug.c"
-#include "common/entropy_common.c"
-#include "common/error_private.c"
-#include "common/fse_decompress.c"
-#include "common/zstd_common.c"
-#include "decompress/huf_decompress.c"
-#include "decompress/zstd_ddict.c"
-#include "decompress/zstd_decompress.c"
-#include "decompress/zstd_decompress_block.c"
-#include "zstd_decompress_module.c"
diff --git a/lib/zstd/entropy_common.c b/lib/zstd/entropy_common.c
new file mode 100644
index 000000000000..2b0a643c32c4
--- /dev/null
+++ b/lib/zstd/entropy_common.c
@@ -0,0 +1,243 @@
+/*
+ * Common functions of New Generation Entropy library
+ * Copyright (C) 2016, Yann Collet.
+ *
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+
+/* *************************************
+*  Dependencies
+***************************************/
+#include "error_private.h" /* ERR_*, ERROR */
+#include "fse.h"
+#include "huf.h"
+#include "mem.h"
+
+/*===   Version   ===*/
+unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
+
+/*===   Error Management   ===*/
+unsigned FSE_isError(size_t code) { return ERR_isError(code); }
+
+unsigned HUF_isError(size_t code) { return ERR_isError(code); }
+
+/*-**************************************************************
+*  FSE NCount encoding-decoding
+****************************************************************/
+size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSVPtr, unsigned *tableLogPtr, const void *headerBuffer, size_t hbSize)
+{
+	const BYTE *const istart = (const BYTE *)headerBuffer;
+	const BYTE *const iend = istart + hbSize;
+	const BYTE *ip = istart;
+	int nbBits;
+	int remaining;
+	int threshold;
+	U32 bitStream;
+	int bitCount;
+	unsigned charnum = 0;
+	int previous0 = 0;
+
+	if (hbSize < 4)
+		return ERROR(srcSize_wrong);
+	bitStream = ZSTD_readLE32(ip);
+	nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
+	if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX)
+		return ERROR(tableLog_tooLarge);
+	bitStream >>= 4;
+	bitCount = 4;
+	*tableLogPtr = nbBits;
+	remaining = (1 << nbBits) + 1;
+	threshold = 1 << nbBits;
+	nbBits++;
+
+	while ((remaining > 1) & (charnum <= *maxSVPtr)) {
+		if (previous0) {
+			unsigned n0 = charnum;
+			while ((bitStream & 0xFFFF) == 0xFFFF) {
+				n0 += 24;
+				if (ip < iend - 5) {
+					ip += 2;
+					bitStream = ZSTD_readLE32(ip) >> bitCount;
+				} else {
+					bitStream >>= 16;
+					bitCount += 16;
+				}
+			}
+			while ((bitStream & 3) == 3) {
+				n0 += 3;
+				bitStream >>= 2;
+				bitCount += 2;
+			}
+			n0 += bitStream & 3;
+			bitCount += 2;
+			if (n0 > *maxSVPtr)
+				return ERROR(maxSymbolValue_tooSmall);
+			while (charnum < n0)
+				normalizedCounter[charnum++] = 0;
+			if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
+				ip += bitCount >> 3;
+				bitCount &= 7;
+				bitStream = ZSTD_readLE32(ip) >> bitCount;
+			} else {
+				bitStream >>= 2;
+			}
+		}
+		{
+			int const max = (2 * threshold - 1) - remaining;
+			int count;
+
+			if ((bitStream & (threshold - 1)) < (U32)max) {
+				count = bitStream & (threshold - 1);
+				bitCount += nbBits - 1;
+			} else {
+				count = bitStream & (2 * threshold - 1);
+				if (count >= threshold)
+					count -= max;
+				bitCount += nbBits;
+			}
+
+			count--;				 /* extra accuracy */
+			remaining -= count < 0 ? -count : count; /* -1 means +1 */
+			normalizedCounter[charnum++] = (short)count;
+			previous0 = !count;
+			while (remaining < threshold) {
+				nbBits--;
+				threshold >>= 1;
+			}
+
+			if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
+				ip += bitCount >> 3;
+				bitCount &= 7;
+			} else {
+				bitCount -= (int)(8 * (iend - 4 - ip));
+				ip = iend - 4;
+			}
+			bitStream = ZSTD_readLE32(ip) >> (bitCount & 31);
+		}
+	} /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
+	if (remaining != 1)
+		return ERROR(corruption_detected);
+	if (bitCount > 32)
+		return ERROR(corruption_detected);
+	*maxSVPtr = charnum - 1;
+
+	ip += (bitCount + 7) >> 3;
+	return ip - istart;
+}
+
+/*! HUF_readStats() :
+	Read compact Huffman tree, saved by HUF_writeCTable().
+	`huffWeight` is destination buffer.
+	`rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
+	@return : size read from `src` , or an error Code .
+	Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
+*/
+size_t HUF_readStats_wksp(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
+{
+	U32 weightTotal;
+	const BYTE *ip = (const BYTE *)src;
+	size_t iSize;
+	size_t oSize;
+
+	if (!srcSize)
+		return ERROR(srcSize_wrong);
+	iSize = ip[0];
+	/* memset(huffWeight, 0, hwSize);   */ /* is not necessary, even though some analyzer complain ... */
+
+	if (iSize >= 128) { /* special header */
+		oSize = iSize - 127;
+		iSize = ((oSize + 1) / 2);
+		if (iSize + 1 > srcSize)
+			return ERROR(srcSize_wrong);
+		if (oSize >= hwSize)
+			return ERROR(corruption_detected);
+		ip += 1;
+		{
+			U32 n;
+			for (n = 0; n < oSize; n += 2) {
+				huffWeight[n] = ip[n / 2] >> 4;
+				huffWeight[n + 1] = ip[n / 2] & 15;
+			}
+		}
+	} else {						 /* header compressed with FSE (normal case) */
+		if (iSize + 1 > srcSize)
+			return ERROR(srcSize_wrong);
+		oSize = FSE_decompress_wksp(huffWeight, hwSize - 1, ip + 1, iSize, 6, workspace, workspaceSize); /* max (hwSize-1) values decoded, as last one is implied */
+		if (FSE_isError(oSize))
+			return oSize;
+	}
+
+	/* collect weight stats */
+	memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
+	weightTotal = 0;
+	{
+		U32 n;
+		for (n = 0; n < oSize; n++) {
+			if (huffWeight[n] >= HUF_TABLELOG_MAX)
+				return ERROR(corruption_detected);
+			rankStats[huffWeight[n]]++;
+			weightTotal += (1 << huffWeight[n]) >> 1;
+		}
+	}
+	if (weightTotal == 0)
+		return ERROR(corruption_detected);
+
+	/* get last non-null symbol weight (implied, total must be 2^n) */
+	{
+		U32 const tableLog = BIT_highbit32(weightTotal) + 1;
+		if (tableLog > HUF_TABLELOG_MAX)
+			return ERROR(corruption_detected);
+		*tableLogPtr = tableLog;
+		/* determine last weight */
+		{
+			U32 const total = 1 << tableLog;
+			U32 const rest = total - weightTotal;
+			U32 const verif = 1 << BIT_highbit32(rest);
+			U32 const lastWeight = BIT_highbit32(rest) + 1;
+			if (verif != rest)
+				return ERROR(corruption_detected); /* last value must be a clean power of 2 */
+			huffWeight[oSize] = (BYTE)lastWeight;
+			rankStats[lastWeight]++;
+		}
+	}
+
+	/* check tree construction validity */
+	if ((rankStats[1] < 2) || (rankStats[1] & 1))
+		return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
+
+	/* results */
+	*nbSymbolsPtr = (U32)(oSize + 1);
+	return iSize + 1;
+}
diff --git a/lib/zstd/error_private.h b/lib/zstd/error_private.h
new file mode 100644
index 000000000000..1a60b31f706c
--- /dev/null
+++ b/lib/zstd/error_private.h
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd.
+ * An additional grant of patent rights can be found in the PATENTS file in the
+ * same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ */
+
+/* Note : this module is expected to remain private, do not expose it */
+
+#ifndef ERROR_H_MODULE
+#define ERROR_H_MODULE
+
+/* ****************************************
+*  Dependencies
+******************************************/
+#include <linux/types.h> /* size_t */
+#include <linux/zstd.h>  /* enum list */
+
+/* ****************************************
+*  Compiler-specific
+******************************************/
+#define ERR_STATIC static __attribute__((unused))
+
+/*-****************************************
+*  Customization (error_public.h)
+******************************************/
+typedef ZSTD_ErrorCode ERR_enum;
+#define PREFIX(name) ZSTD_error_##name
+
+/*-****************************************
+*  Error codes handling
+******************************************/
+#define ERROR(name) ((size_t)-PREFIX(name))
+
+ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
+
+ERR_STATIC ERR_enum ERR_getErrorCode(size_t code)
+{
+	if (!ERR_isError(code))
+		return (ERR_enum)0;
+	return (ERR_enum)(0 - code);
+}
+
+#endif /* ERROR_H_MODULE */
diff --git a/lib/zstd/fse.h b/lib/zstd/fse.h
new file mode 100644
index 000000000000..7460ab04b191
--- /dev/null
+++ b/lib/zstd/fse.h
@@ -0,0 +1,575 @@
+/*
+ * FSE : Finite State Entropy codec
+ * Public Prototypes declaration
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+#ifndef FSE_H
+#define FSE_H
+
+/*-*****************************************
+*  Dependencies
+******************************************/
+#include <linux/types.h> /* size_t, ptrdiff_t */
+
+/*-*****************************************
+*  FSE_PUBLIC_API : control library symbols visibility
+******************************************/
+#define FSE_PUBLIC_API
+
+/*------   Version   ------*/
+#define FSE_VERSION_MAJOR 0
+#define FSE_VERSION_MINOR 9
+#define FSE_VERSION_RELEASE 0
+
+#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
+#define FSE_QUOTE(str) #str
+#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
+#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
+
+#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR * 100 * 100 + FSE_VERSION_MINOR * 100 + FSE_VERSION_RELEASE)
+FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
+
+/*-*****************************************
+*  Tool functions
+******************************************/
+FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
+
+/* Error Management */
+FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
+
+/*-*****************************************
+*  FSE detailed API
+******************************************/
+/*!
+FSE_compress() does the following:
+1. count symbol occurrence from source[] into table count[]
+2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
+3. save normalized counters to memory buffer using writeNCount()
+4. build encoding table 'CTable' from normalized counters
+5. encode the data stream using encoding table 'CTable'
+
+FSE_decompress() does the following:
+1. read normalized counters with readNCount()
+2. build decoding table 'DTable' from normalized counters
+3. decode the data stream using decoding table 'DTable'
+
+The following API allows targeting specific sub-functions for advanced tasks.
+For example, it's possible to compress several blocks using the same 'CTable',
+or to save and provide normalized distribution using external method.
+*/
+
+/* *** COMPRESSION *** */
+/*! FSE_optimalTableLog():
+	dynamically downsize 'tableLog' when conditions are met.
+	It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
+	@return : recommended tableLog (necessarily <= 'maxTableLog') */
+FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
+
+/*! FSE_normalizeCount():
+	normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
+	'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
+	@return : tableLog,
+			  or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_normalizeCount(short *normalizedCounter, unsigned tableLog, const unsigned *count, size_t srcSize, unsigned maxSymbolValue);
+
+/*! FSE_NCountWriteBound():
+	Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
+	Typically useful for allocation purpose. */
+FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
+
+/*! FSE_writeNCount():
+	Compactly save 'normalizedCounter' into 'buffer'.
+	@return : size of the compressed table,
+			  or an errorCode, which can be tested using FSE_isError(). */
+FSE_PUBLIC_API size_t FSE_writeNCount(void *buffer, size_t bufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
+
+/*! Constructor and Destructor of FSE_CTable.
+	Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
+typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
+
+/*! FSE_compress_usingCTable():
+	Compress `src` using `ct` into `dst` which must be already allocated.
+	@return : size of compressed data (<= `dstCapacity`),
+			  or 0 if compressed data could not fit into `dst`,
+			  or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_compress_usingCTable(void *dst, size_t dstCapacity, const void *src, size_t srcSize, const FSE_CTable *ct);
+
+/*!
+Tutorial :
+----------
+The first step is to count all symbols. FSE_count() does this job very fast.
+Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
+'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
+maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
+FSE_count() will return the number of occurrence of the most frequent symbol.
+This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
+
+The next step is to normalize the frequencies.
+FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
+It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
+You can use 'tableLog'==0 to mean "use default tableLog value".
+If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
+which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
+
+The result of FSE_normalizeCount() will be saved into a table,
+called 'normalizedCounter', which is a table of signed short.
+'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
+The return value is tableLog if everything proceeded as expected.
+It is 0 if there is a single symbol within distribution.
+If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
+
+'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
+'buffer' must be already allocated.
+For guaranteed success, buffer size must be at least FSE_headerBound().
+The result of the function is the number of bytes written into 'buffer'.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
+
+'normalizedCounter' can then be used to create the compression table 'CTable'.
+The space required by 'CTable' must be already allocated, using FSE_createCTable().
+You can then use FSE_buildCTable() to fill 'CTable'.
+If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
+
+'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
+Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
+The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
+If it returns '0', compressed data could not fit into 'dst'.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
+*/
+
+/* *** DECOMPRESSION *** */
+
+/*! FSE_readNCount():
+	Read compactly saved 'normalizedCounter' from 'rBuffer'.
+	@return : size read from 'rBuffer',
+			  or an errorCode, which can be tested using FSE_isError().
+			  maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
+FSE_PUBLIC_API size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSymbolValuePtr, unsigned *tableLogPtr, const void *rBuffer, size_t rBuffSize);
+
+/*! Constructor and Destructor of FSE_DTable.
+	Note that its size depends on 'tableLog' */
+typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
+
+/*! FSE_buildDTable():
+	Builds 'dt', which must be already allocated, using FSE_createDTable().
+	return : 0, or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize);
+
+/*! FSE_decompress_usingDTable():
+	Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
+	into `dst` which must be already allocated.
+	@return : size of regenerated data (necessarily <= `dstCapacity`),
+			  or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt);
+
+/*!
+Tutorial :
+----------
+(Note : these functions only decompress FSE-compressed blocks.
+ If block is uncompressed, use memcpy() instead
+ If block is a single repeated byte, use memset() instead )
+
+The first step is to obtain the normalized frequencies of symbols.
+This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
+'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
+In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
+or size the table to handle worst case situations (typically 256).
+FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
+The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
+Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
+If there is an error, the function will return an error code, which can be tested using FSE_isError().
+
+The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
+This is performed by the function FSE_buildDTable().
+The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
+If there is an error, the function will return an error code, which can be tested using FSE_isError().
+
+`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().
+`cSrcSize` must be strictly correct, otherwise decompression will fail.
+FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
+If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
+*/
+
+/* *** Dependency *** */
+#include "bitstream.h"
+
+/* *****************************************
+*  Static allocation
+*******************************************/
+/* FSE buffer bounds */
+#define FSE_NCOUNTBOUND 512
+#define FSE_BLOCKBOUND(size) (size + (size >> 7))
+#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
+
+/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
+#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1 << (maxTableLog - 1)) + ((maxSymbolValue + 1) * 2))
+#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1 << maxTableLog))
+
+/* *****************************************
+*  FSE advanced API
+*******************************************/
+/* FSE_count_wksp() :
+ * Same as FSE_count(), but using an externally provided scratch buffer.
+ * `workSpace` size must be table of >= `1024` unsigned
+ */
+size_t FSE_count_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *source, size_t sourceSize, unsigned *workSpace);
+
+/* FSE_countFast_wksp() :
+ * Same as FSE_countFast(), but using an externally provided scratch buffer.
+ * `workSpace` must be a table of minimum `1024` unsigned
+ */
+size_t FSE_countFast_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize, unsigned *workSpace);
+
+/*! FSE_count_simple
+ * Same as FSE_countFast(), but does not use any additional memory (not even on stack).
+ * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`).
+*/
+size_t FSE_count_simple(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize);
+
+unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
+/**< same as FSE_optimalTableLog(), which used `minus==2` */
+
+size_t FSE_buildCTable_raw(FSE_CTable *ct, unsigned nbBits);
+/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
+
+size_t FSE_buildCTable_rle(FSE_CTable *ct, unsigned char symbolValue);
+/**< build a fake FSE_CTable, designed to compress always the same symbolValue */
+
+/* FSE_buildCTable_wksp() :
+ * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
+ * `wkspSize` must be >= `(1<<tableLog)`.
+ */
+size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workSpace, size_t wkspSize);
+
+size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits);
+/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
+
+size_t FSE_buildDTable_rle(FSE_DTable *dt, unsigned char symbolValue);
+/**< build a fake FSE_DTable, designed to always generate the same symbolValue */
+
+size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workspace, size_t workspaceSize);
+/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */
+
+/* *****************************************
+*  FSE symbol compression API
+*******************************************/
+/*!
+   This API consists of small unitary functions, which highly benefit from being inlined.
+   Hence their body are included in next section.
+*/
+typedef struct {
+	ptrdiff_t value;
+	const void *stateTable;
+	const void *symbolTT;
+	unsigned stateLog;
+} FSE_CState_t;
+
+static void FSE_initCState(FSE_CState_t *CStatePtr, const FSE_CTable *ct);
+
+static void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *CStatePtr, unsigned symbol);
+
+static void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *CStatePtr);
+
+/**<
+These functions are inner components of FSE_compress_usingCTable().
+They allow the creation of custom streams, mixing multiple tables and bit sources.
+
+A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
+So the first symbol you will encode is the last you will decode, like a LIFO stack.
+
+You will need a few variables to track your CStream. They are :
+
+FSE_CTable    ct;         // Provided by FSE_buildCTable()
+BIT_CStream_t bitStream;  // bitStream tracking structure
+FSE_CState_t  state;      // State tracking structure (can have several)
+
+
+The first thing to do is to init bitStream and state.
+	size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
+	FSE_initCState(&state, ct);
+
+Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
+You can then encode your input data, byte after byte.
+FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
+Remember decoding will be done in reverse direction.
+	FSE_encodeByte(&bitStream, &state, symbol);
+
+At any time, you can also add any bit sequence.
+Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
+	BIT_addBits(&bitStream, bitField, nbBits);
+
+The above methods don't commit data to memory, they just store it into local register, for speed.
+Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
+Writing data to memory is a manual operation, performed by the flushBits function.
+	BIT_flushBits(&bitStream);
+
+Your last FSE encoding operation shall be to flush your last state value(s).
+	FSE_flushState(&bitStream, &state);
+
+Finally, you must close the bitStream.
+The function returns the size of CStream in bytes.
+If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
+If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
+	size_t size = BIT_closeCStream(&bitStream);
+*/
+
+/* *****************************************
+*  FSE symbol decompression API
+*******************************************/
+typedef struct {
+	size_t state;
+	const void *table; /* precise table may vary, depending on U16 */
+} FSE_DState_t;
+
+static void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt);
+
+static unsigned char FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
+
+static unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr);
+
+/**<
+Let's now decompose FSE_decompress_usingDTable() into its unitary components.
+You will decode FSE-encoded symbols from the bitStream,
+and also any other bitFields you put in, **in reverse order**.
+
+You will need a few variables to track your bitStream. They are :
+
+BIT_DStream_t DStream;    // Stream context
+FSE_DState_t  DState;     // State context. Multiple ones are possible
+FSE_DTable*   DTablePtr;  // Decoding table, provided by FSE_buildDTable()
+
+The first thing to do is to init the bitStream.
+	errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
+
+You should then retrieve your initial state(s)
+(in reverse flushing order if you have several ones) :
+	errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
+
+You can then decode your data, symbol after symbol.
+For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
+Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
+	unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
+
+You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
+Note : maximum allowed nbBits is 25, for 32-bits compatibility
+	size_t bitField = BIT_readBits(&DStream, nbBits);
+
+All above operations only read from local register (which size depends on size_t).
+Refueling the register from memory is manually performed by the reload method.
+	endSignal = FSE_reloadDStream(&DStream);
+
+BIT_reloadDStream() result tells if there is still some more data to read from DStream.
+BIT_DStream_unfinished : there is still some data left into the DStream.
+BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
+BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
+BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
+
+When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
+to properly detect the exact end of stream.
+After each decoded symbol, check if DStream is fully consumed using this simple test :
+	BIT_reloadDStream(&DStream) >= BIT_DStream_completed
+
+When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
+Checking if DStream has reached its end is performed by :
+	BIT_endOfDStream(&DStream);
+Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
+	FSE_endOfDState(&DState);
+*/
+
+/* *****************************************
+*  FSE unsafe API
+*******************************************/
+static unsigned char FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
+/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
+
+/* *****************************************
+*  Implementation of inlined functions
+*******************************************/
+typedef struct {
+	int deltaFindState;
+	U32 deltaNbBits;
+} FSE_symbolCompressionTransform; /* total 8 bytes */
+
+ZSTD_STATIC void FSE_initCState(FSE_CState_t *statePtr, const FSE_CTable *ct)
+{
+	const void *ptr = ct;
+	const U16 *u16ptr = (const U16 *)ptr;
+	const U32 tableLog = ZSTD_read16(ptr);
+	statePtr->value = (ptrdiff_t)1 << tableLog;
+	statePtr->stateTable = u16ptr + 2;
+	statePtr->symbolTT = ((const U32 *)ct + 1 + (tableLog ? (1 << (tableLog - 1)) : 1));
+	statePtr->stateLog = tableLog;
+}
+
+/*! FSE_initCState2() :
+*   Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
+*   uses the smallest state value possible, saving the cost of this symbol */
+ZSTD_STATIC void FSE_initCState2(FSE_CState_t *statePtr, const FSE_CTable *ct, U32 symbol)
+{
+	FSE_initCState(statePtr, ct);
+	{
+		const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
+		const U16 *stateTable = (const U16 *)(statePtr->stateTable);
+		U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1 << 15)) >> 16);
+		statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
+		statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
+	}
+}
+
+ZSTD_STATIC void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *statePtr, U32 symbol)
+{
+	const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
+	const U16 *const stateTable = (const U16 *)(statePtr->stateTable);
+	U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
+	BIT_addBits(bitC, statePtr->value, nbBitsOut);
+	statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
+}
+
+ZSTD_STATIC void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *statePtr)
+{
+	BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
+	BIT_flushBits(bitC);
+}
+
+/* ======    Decompression    ====== */
+
+typedef struct {
+	U16 tableLog;
+	U16 fastMode;
+} FSE_DTableHeader; /* sizeof U32 */
+
+typedef struct {
+	unsigned short newState;
+	unsigned char symbol;
+	unsigned char nbBits;
+} FSE_decode_t; /* size == U32 */
+
+ZSTD_STATIC void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt)
+{
+	const void *ptr = dt;
+	const FSE_DTableHeader *const DTableH = (const FSE_DTableHeader *)ptr;
+	DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
+	BIT_reloadDStream(bitD);
+	DStatePtr->table = dt + 1;
+}
+
+ZSTD_STATIC BYTE FSE_peekSymbol(const FSE_DState_t *DStatePtr)
+{
+	FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+	return DInfo.symbol;
+}
+
+ZSTD_STATIC void FSE_updateState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
+{
+	FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+	U32 const nbBits = DInfo.nbBits;
+	size_t const lowBits = BIT_readBits(bitD, nbBits);
+	DStatePtr->state = DInfo.newState + lowBits;
+}
+
+ZSTD_STATIC BYTE FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
+{
+	FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+	U32 const nbBits = DInfo.nbBits;
+	BYTE const symbol = DInfo.symbol;
+	size_t const lowBits = BIT_readBits(bitD, nbBits);
+
+	DStatePtr->state = DInfo.newState + lowBits;
+	return symbol;
+}
+
+/*! FSE_decodeSymbolFast() :
+	unsafe, only works if no symbol has a probability > 50% */
+ZSTD_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
+{
+	FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
+	U32 const nbBits = DInfo.nbBits;
+	BYTE const symbol = DInfo.symbol;
+	size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
+
+	DStatePtr->state = DInfo.newState + lowBits;
+	return symbol;
+}
+
+ZSTD_STATIC unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr) { return DStatePtr->state == 0; }
+
+/* **************************************************************
+*  Tuning parameters
+****************************************************************/
+/*!MEMORY_USAGE :
+*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+*  Increasing memory usage improves compression ratio
+*  Reduced memory usage can improve speed, due to cache effect
+*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
+#ifndef FSE_MAX_MEMORY_USAGE
+#define FSE_MAX_MEMORY_USAGE 14
+#endif
+#ifndef FSE_DEFAULT_MEMORY_USAGE
+#define FSE_DEFAULT_MEMORY_USAGE 13
+#endif
+
+/*!FSE_MAX_SYMBOL_VALUE :
+*  Maximum symbol value authorized.
+*  Required for proper stack allocation */
+#ifndef FSE_MAX_SYMBOL_VALUE
+#define FSE_MAX_SYMBOL_VALUE 255
+#endif
+
+/* **************************************************************
+*  template functions type & suffix
+****************************************************************/
+#define FSE_FUNCTION_TYPE BYTE
+#define FSE_FUNCTION_EXTENSION
+#define FSE_DECODE_TYPE FSE_decode_t
+
+/* ***************************************************************
+*  Constants
+*****************************************************************/
+#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE - 2)
+#define FSE_MAX_TABLESIZE (1U << FSE_MAX_TABLELOG)
+#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE - 1)
+#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE - 2)
+#define FSE_MIN_TABLELOG 5
+
+#define FSE_TABLELOG_ABSOLUTE_MAX 15
+#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
+#error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
+#endif
+
+#define FSE_TABLESTEP(tableSize) ((tableSize >> 1) + (tableSize >> 3) + 3)
+
+#endif /* FSE_H */
diff --git a/lib/zstd/fse_decompress.c b/lib/zstd/fse_decompress.c
new file mode 100644
index 000000000000..a84300e5a013
--- /dev/null
+++ b/lib/zstd/fse_decompress.c
@@ -0,0 +1,332 @@
+/*
+ * FSE : Finite State Entropy decoder
+ * Copyright (C) 2013-2015, Yann Collet.
+ *
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+
+/* **************************************************************
+*  Compiler specifics
+****************************************************************/
+#define FORCE_INLINE static __always_inline
+
+/* **************************************************************
+*  Includes
+****************************************************************/
+#include "bitstream.h"
+#include "fse.h"
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h> /* memcpy, memset */
+
+/* **************************************************************
+*  Error Management
+****************************************************************/
+#define FSE_isError ERR_isError
+#define FSE_STATIC_ASSERT(c)                                   \
+	{                                                      \
+		enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
+	} /* use only *after* variable declarations */
+
+/* check and forward error code */
+#define CHECK_F(f)                  \
+	{                           \
+		size_t const e = f; \
+		if (FSE_isError(e)) \
+			return e;   \
+	}
+
+/* **************************************************************
+*  Templates
+****************************************************************/
+/*
+  designed to be included
+  for type-specific functions (template emulation in C)
+  Objective is to write these functions only once, for improved maintenance
+*/
+
+/* safety checks */
+#ifndef FSE_FUNCTION_EXTENSION
+#error "FSE_FUNCTION_EXTENSION must be defined"
+#endif
+#ifndef FSE_FUNCTION_TYPE
+#error "FSE_FUNCTION_TYPE must be defined"
+#endif
+
+/* Function names */
+#define FSE_CAT(X, Y) X##Y
+#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y)
+#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y)
+
+/* Function templates */
+
+size_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize)
+{
+	void *const tdPtr = dt + 1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
+	FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)(tdPtr);
+	U16 *symbolNext = (U16 *)workspace;
+
+	U32 const maxSV1 = maxSymbolValue + 1;
+	U32 const tableSize = 1 << tableLog;
+	U32 highThreshold = tableSize - 1;
+
+	/* Sanity Checks */
+	if (workspaceSize < sizeof(U16) * (FSE_MAX_SYMBOL_VALUE + 1))
+		return ERROR(tableLog_tooLarge);
+	if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE)
+		return ERROR(maxSymbolValue_tooLarge);
+	if (tableLog > FSE_MAX_TABLELOG)
+		return ERROR(tableLog_tooLarge);
+
+	/* Init, lay down lowprob symbols */
+	{
+		FSE_DTableHeader DTableH;
+		DTableH.tableLog = (U16)tableLog;
+		DTableH.fastMode = 1;
+		{
+			S16 const largeLimit = (S16)(1 << (tableLog - 1));
+			U32 s;
+			for (s = 0; s < maxSV1; s++) {
+				if (normalizedCounter[s] == -1) {
+					tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
+					symbolNext[s] = 1;
+				} else {
+					if (normalizedCounter[s] >= largeLimit)
+						DTableH.fastMode = 0;
+					symbolNext[s] = normalizedCounter[s];
+				}
+			}
+		}
+		memcpy(dt, &DTableH, sizeof(DTableH));
+	}
+
+	/* Spread symbols */
+	{
+		U32 const tableMask = tableSize - 1;
+		U32 const step = FSE_TABLESTEP(tableSize);
+		U32 s, position = 0;
+		for (s = 0; s < maxSV1; s++) {
+			int i;
+			for (i = 0; i < normalizedCounter[s]; i++) {
+				tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
+				position = (position + step) & tableMask;
+				while (position > highThreshold)
+					position = (position + step) & tableMask; /* lowprob area */
+			}
+		}
+		if (position != 0)
+			return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
+	}
+
+	/* Build Decoding table */
+	{
+		U32 u;
+		for (u = 0; u < tableSize; u++) {
+			FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
+			U16 nextState = symbolNext[symbol]++;
+			tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32((U32)nextState));
+			tableDecode[u].newState = (U16)((nextState << tableDecode[u].nbBits) - tableSize);
+		}
+	}
+
+	return 0;
+}
+
+/*-*******************************************************
+*  Decompression (Byte symbols)
+*********************************************************/
+size_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue)
+{
+	void *ptr = dt;
+	FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
+	void *dPtr = dt + 1;
+	FSE_decode_t *const cell = (FSE_decode_t *)dPtr;
+
+	DTableH->tableLog = 0;
+	DTableH->fastMode = 0;
+
+	cell->newState = 0;
+	cell->symbol = symbolValue;
+	cell->nbBits = 0;
+
+	return 0;
+}
+
+size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits)
+{
+	void *ptr = dt;
+	FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
+	void *dPtr = dt + 1;
+	FSE_decode_t *const dinfo = (FSE_decode_t *)dPtr;
+	const unsigned tableSize = 1 << nbBits;
+	const unsigned tableMask = tableSize - 1;
+	const unsigned maxSV1 = tableMask + 1;
+	unsigned s;
+
+	/* Sanity checks */
+	if (nbBits < 1)
+		return ERROR(GENERIC); /* min size */
+
+	/* Build Decoding Table */
+	DTableH->tableLog = (U16)nbBits;
+	DTableH->fastMode = 1;
+	for (s = 0; s < maxSV1; s++) {
+		dinfo[s].newState = 0;
+		dinfo[s].symbol = (BYTE)s;
+		dinfo[s].nbBits = (BYTE)nbBits;
+	}
+
+	return 0;
+}
+
+FORCE_INLINE size_t FSE_decompress_usingDTable_generic(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt,
+						       const unsigned fast)
+{
+	BYTE *const ostart = (BYTE *)dst;
+	BYTE *op = ostart;
+	BYTE *const omax = op + maxDstSize;
+	BYTE *const olimit = omax - 3;
+
+	BIT_DStream_t bitD;
+	FSE_DState_t state1;
+	FSE_DState_t state2;
+
+	/* Init */
+	CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));
+
+	FSE_initDState(&state1, &bitD, dt);
+	FSE_initDState(&state2, &bitD, dt);
+
+#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
+
+	/* 4 symbols per loop */
+	for (; (BIT_reloadDStream(&bitD) == BIT_DStream_unfinished) & (op < olimit); op += 4) {
+		op[0] = FSE_GETSYMBOL(&state1);
+
+		if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
+			BIT_reloadDStream(&bitD);
+
+		op[1] = FSE_GETSYMBOL(&state2);
+
+		if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
+		{
+			if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) {
+				op += 2;
+				break;
+			}
+		}
+
+		op[2] = FSE_GETSYMBOL(&state1);
+
+		if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
+			BIT_reloadDStream(&bitD);
+
+		op[3] = FSE_GETSYMBOL(&state2);
+	}
+
+	/* tail */
+	/* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
+	while (1) {
+		if (op > (omax - 2))
+			return ERROR(dstSize_tooSmall);
+		*op++ = FSE_GETSYMBOL(&state1);
+		if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
+			*op++ = FSE_GETSYMBOL(&state2);
+			break;
+		}
+
+		if (op > (omax - 2))
+			return ERROR(dstSize_tooSmall);
+		*op++ = FSE_GETSYMBOL(&state2);
+		if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
+			*op++ = FSE_GETSYMBOL(&state1);
+			break;
+		}
+	}
+
+	return op - ostart;
+}
+
+size_t FSE_decompress_usingDTable(void *dst, size_t originalSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt)
+{
+	const void *ptr = dt;
+	const FSE_DTableHeader *DTableH = (const FSE_DTableHeader *)ptr;
+	const U32 fastMode = DTableH->fastMode;
+
+	/* select fast mode (static) */
+	if (fastMode)
+		return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
+	return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
+}
+
+size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workspace, size_t workspaceSize)
+{
+	const BYTE *const istart = (const BYTE *)cSrc;
+	const BYTE *ip = istart;
+	unsigned tableLog;
+	unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
+	size_t NCountLength;
+
+	FSE_DTable *dt;
+	short *counting;
+	size_t spaceUsed32 = 0;
+
+	FSE_STATIC_ASSERT(sizeof(FSE_DTable) == sizeof(U32));
+
+	dt = (FSE_DTable *)((U32 *)workspace + spaceUsed32);
+	spaceUsed32 += FSE_DTABLE_SIZE_U32(maxLog);
+	counting = (short *)((U32 *)workspace + spaceUsed32);
+	spaceUsed32 += ALIGN(sizeof(short) * (FSE_MAX_SYMBOL_VALUE + 1), sizeof(U32)) >> 2;
+
+	if ((spaceUsed32 << 2) > workspaceSize)
+		return ERROR(tableLog_tooLarge);
+	workspace = (U32 *)workspace + spaceUsed32;
+	workspaceSize -= (spaceUsed32 << 2);
+
+	/* normal FSE decoding mode */
+	NCountLength = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
+	if (FSE_isError(NCountLength))
+		return NCountLength;
+	// if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size; supposed to be already checked in NCountLength, only remaining
+	// case : NCountLength==cSrcSize */
+	if (tableLog > maxLog)
+		return ERROR(tableLog_tooLarge);
+	ip += NCountLength;
+	cSrcSize -= NCountLength;
+
+	CHECK_F(FSE_buildDTable_wksp(dt, counting, maxSymbolValue, tableLog, workspace, workspaceSize));
+
+	return FSE_decompress_usingDTable(dst, dstCapacity, ip, cSrcSize, dt); /* always return, even if it is an error code */
+}
diff --git a/lib/zstd/huf.h b/lib/zstd/huf.h
new file mode 100644
index 000000000000..2143da28d952
--- /dev/null
+++ b/lib/zstd/huf.h
@@ -0,0 +1,212 @@
+/*
+ * Huffman coder, part of New Generation Entropy library
+ * header file
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+#ifndef HUF_H_298734234
+#define HUF_H_298734234
+
+/* *** Dependencies *** */
+#include <linux/types.h> /* size_t */
+
+/* ***   Tool functions *** */
+#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
+size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
+
+/* Error Management */
+unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
+
+/* ***   Advanced function   *** */
+
+/** HUF_compress4X_wksp() :
+*   Same as HUF_compress2(), but uses externally allocated `workSpace`, which must be a table of >= 1024 unsigned */
+size_t HUF_compress4X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+			   size_t wkspSize); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+
+/* *** Dependencies *** */
+#include "mem.h" /* U32 */
+
+/* *** Constants *** */
+#define HUF_TABLELOG_MAX 12     /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
+#define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */
+#define HUF_SYMBOLVALUE_MAX 255
+
+#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
+#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
+#error "HUF_TABLELOG_MAX is too large !"
+#endif
+
+/* ****************************************
+*  Static allocation
+******************************************/
+/* HUF buffer bounds */
+#define HUF_CTABLEBOUND 129
+#define HUF_BLOCKBOUND(size) (size + (size >> 8) + 8)			 /* only true if incompressible pre-filtered with fast heuristic */
+#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
+
+/* static allocation of HUF's Compression Table */
+#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
+	U32 name##hb[maxSymbolValue + 1];              \
+	void *name##hv = &(name##hb);                  \
+	HUF_CElt *name = (HUF_CElt *)(name##hv) /* no final ; */
+
+/* static allocation of HUF's DTable */
+typedef U32 HUF_DTable;
+#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1 << (maxTableLog)))
+#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = {((U32)((maxTableLog)-1) * 0x01000001)}
+#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = {((U32)(maxTableLog)*0x01000001)}
+
+/* The workspace must have alignment at least 4 and be at least this large */
+#define HUF_COMPRESS_WORKSPACE_SIZE (6 << 10)
+#define HUF_COMPRESS_WORKSPACE_SIZE_U32 (HUF_COMPRESS_WORKSPACE_SIZE / sizeof(U32))
+
+/* The workspace must have alignment at least 4 and be at least this large */
+#define HUF_DECOMPRESS_WORKSPACE_SIZE (3 << 10)
+#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
+
+/* ****************************************
+*  Advanced decompression functions
+******************************************/
+size_t HUF_decompress4X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize); /**< decodes RLE and uncompressed */
+size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+				size_t workspaceSize);							       /**< considers RLE and uncompressed as errors */
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+				   size_t workspaceSize); /**< single-symbol decoder */
+size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+				   size_t workspaceSize); /**< double-symbols decoder */
+
+/* ****************************************
+*  HUF detailed API
+******************************************/
+/*!
+HUF_compress() does the following:
+1. count symbol occurrence from source[] into table count[] using FSE_count()
+2. (optional) refine tableLog using HUF_optimalTableLog()
+3. build Huffman table from count using HUF_buildCTable()
+4. save Huffman table to memory buffer using HUF_writeCTable_wksp()
+5. encode the data stream using HUF_compress4X_usingCTable()
+
+The following API allows targeting specific sub-functions for advanced tasks.
+For example, it's possible to compress several blocks using the same 'CTable',
+or to save and regenerate 'CTable' using external methods.
+*/
+/* FSE_count() : find it within "fse.h" */
+unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
+typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */
+size_t HUF_writeCTable_wksp(void *dst, size_t maxDstSize, const HUF_CElt *CTable, unsigned maxSymbolValue, unsigned huffLog, void *workspace, size_t workspaceSize);
+size_t HUF_compress4X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
+
+typedef enum {
+	HUF_repeat_none,  /**< Cannot use the previous table */
+	HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
+			     4}X_repeat */
+	HUF_repeat_valid  /**< Can use the previous table and it is asumed to be valid */
+} HUF_repeat;
+/** HUF_compress4X_repeat() :
+*   Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+*   If it uses hufTable it does not modify hufTable or repeat.
+*   If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+*   If preferRepeat then the old table will always be used if valid. */
+size_t HUF_compress4X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+			     size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
+			     int preferRepeat); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+
+/** HUF_buildCTable_wksp() :
+ *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.
+ *  `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
+ */
+size_t HUF_buildCTable_wksp(HUF_CElt *tree, const U32 *count, U32 maxSymbolValue, U32 maxNbBits, void *workSpace, size_t wkspSize);
+
+/*! HUF_readStats() :
+	Read compact Huffman tree, saved by HUF_writeCTable().
+	`huffWeight` is destination buffer.
+	@return : size read from `src` , or an error Code .
+	Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
+size_t HUF_readStats_wksp(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize,
+			  void *workspace, size_t workspaceSize);
+
+/** HUF_readCTable() :
+*   Loading a CTable saved with HUF_writeCTable() */
+size_t HUF_readCTable_wksp(HUF_CElt *CTable, unsigned maxSymbolValue, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
+
+/*
+HUF_decompress() does the following:
+1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
+2. build Huffman table from save, using HUF_readDTableXn()
+3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable
+*/
+
+/** HUF_selectDecoder() :
+*   Tells which decoder is likely to decode faster,
+*   based on a set of pre-determined metrics.
+*   @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+*   Assumption : 0 < cSrcSize < dstSize <= 128 KB */
+U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize);
+
+size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
+size_t HUF_readDTableX4_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
+
+size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+size_t HUF_decompress4X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+size_t HUF_decompress4X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+
+/* single stream variants */
+
+size_t HUF_compress1X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+			   size_t wkspSize); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
+/** HUF_compress1X_repeat() :
+*   Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+*   If it uses hufTable it does not modify hufTable or repeat.
+*   If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+*   If preferRepeat then the old table will always be used if valid. */
+size_t HUF_compress1X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
+			     size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
+			     int preferRepeat); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
+
+size_t HUF_decompress1X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize);
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+				   size_t workspaceSize); /**< single-symbol decoder */
+size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
+				   size_t workspaceSize); /**< double-symbols decoder */
+
+size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize,
+				    const HUF_DTable *DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */
+size_t HUF_decompress1X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+size_t HUF_decompress1X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
+
+#endif /* HUF_H_298734234 */
diff --git a/lib/zstd/huf_decompress.c b/lib/zstd/huf_decompress.c
new file mode 100644
index 000000000000..6526482047dc
--- /dev/null
+++ b/lib/zstd/huf_decompress.c
@@ -0,0 +1,960 @@
+/*
+ * Huffman decoder, part of New Generation Entropy library
+ * Copyright (C) 2013-2016, Yann Collet.
+ *
+ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ */
+
+/* **************************************************************
+*  Compiler specifics
+****************************************************************/
+#define FORCE_INLINE static __always_inline
+
+/* **************************************************************
+*  Dependencies
+****************************************************************/
+#include "bitstream.h" /* BIT_* */
+#include "fse.h"       /* header compression */
+#include "huf.h"
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/string.h> /* memcpy, memset */
+
+/* **************************************************************
+*  Error Management
+****************************************************************/
+#define HUF_STATIC_ASSERT(c)                                   \
+	{                                                      \
+		enum { HUF_static_assert = 1 / (int)(!!(c)) }; \
+	} /* use only *after* variable declarations */
+
+/*-***************************/
+/*  generic DTableDesc       */
+/*-***************************/
+
+typedef struct {
+	BYTE maxTableLog;
+	BYTE tableType;
+	BYTE tableLog;
+	BYTE reserved;
+} DTableDesc;
+
+static DTableDesc HUF_getDTableDesc(const HUF_DTable *table)
+{
+	DTableDesc dtd;
+	memcpy(&dtd, table, sizeof(dtd));
+	return dtd;
+}
+
+/*-***************************/
+/*  single-symbol decoding   */
+/*-***************************/
+
+typedef struct {
+	BYTE byte;
+	BYTE nbBits;
+} HUF_DEltX2; /* single-symbol decoding */
+
+size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
+{
+	U32 tableLog = 0;
+	U32 nbSymbols = 0;
+	size_t iSize;
+	void *const dtPtr = DTable + 1;
+	HUF_DEltX2 *const dt = (HUF_DEltX2 *)dtPtr;
+
+	U32 *rankVal;
+	BYTE *huffWeight;
+	size_t spaceUsed32 = 0;
+
+	rankVal = (U32 *)workspace + spaceUsed32;
+	spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1;
+	huffWeight = (BYTE *)((U32 *)workspace + spaceUsed32);
+	spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
+
+	if ((spaceUsed32 << 2) > workspaceSize)
+		return ERROR(tableLog_tooLarge);
+	workspace = (U32 *)workspace + spaceUsed32;
+	workspaceSize -= (spaceUsed32 << 2);
+
+	HUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
+	/* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
+
+	iSize = HUF_readStats_wksp(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
+	if (HUF_isError(iSize))
+		return iSize;
+
+	/* Table header */
+	{
+		DTableDesc dtd = HUF_getDTableDesc(DTable);
+		if (tableLog > (U32)(dtd.maxTableLog + 1))
+			return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */
+		dtd.tableType = 0;
+		dtd.tableLog = (BYTE)tableLog;
+		memcpy(DTable, &dtd, sizeof(dtd));
+	}
+
+	/* Calculate starting value for each rank */
+	{
+		U32 n, nextRankStart = 0;
+		for (n = 1; n < tableLog + 1; n++) {
+			U32 const curr = nextRankStart;
+			nextRankStart += (rankVal[n] << (n - 1));
+			rankVal[n] = curr;
+		}
+	}
+
+	/* fill DTable */
+	{
+		U32 n;
+		for (n = 0; n < nbSymbols; n++) {
+			U32 const w = huffWeight[n];
+			U32 const length = (1 << w) >> 1;
+			U32 u;
+			HUF_DEltX2 D;
+			D.byte = (BYTE)n;
+			D.nbBits = (BYTE)(tableLog + 1 - w);
+			for (u = rankVal[w]; u < rankVal[w] + length; u++)
+				dt[u] = D;
+			rankVal[w] += length;
+		}
+	}
+
+	return iSize;
+}
+
+static BYTE HUF_decodeSymbolX2(BIT_DStream_t *Dstream, const HUF_DEltX2 *dt, const U32 dtLog)
+{
+	size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
+	BYTE const c = dt[val].byte;
+	BIT_skipBits(Dstream, dt[val].nbBits);
+	return c;
+}
+
+#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr)         \
+	if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
+	HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
+
+#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
+	if (ZSTD_64bits())                     \
+	HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
+
+FORCE_INLINE size_t HUF_decodeStreamX2(BYTE *p, BIT_DStream_t *const bitDPtr, BYTE *const pEnd, const HUF_DEltX2 *const dt, const U32 dtLog)
+{
+	BYTE *const pStart = p;
+
+	/* up to 4 symbols at a time */
+	while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd - 4)) {
+		HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+		HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
+		HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+		HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+	}
+
+	/* closer to the end */
+	while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))
+		HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+
+	/* no more data to retrieve from bitstream, hence no need to reload */
+	while (p < pEnd)
+		HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+
+	return pEnd - pStart;
+}
+
+static size_t HUF_decompress1X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	BYTE *op = (BYTE *)dst;
+	BYTE *const oend = op + dstSize;
+	const void *dtPtr = DTable + 1;
+	const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
+	BIT_DStream_t bitD;
+	DTableDesc const dtd = HUF_getDTableDesc(DTable);
+	U32 const dtLog = dtd.tableLog;
+
+	{
+		size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
+		if (HUF_isError(errorCode))
+			return errorCode;
+	}
+
+	HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
+
+	/* check */
+	if (!BIT_endOfDStream(&bitD))
+		return ERROR(corruption_detected);
+
+	return dstSize;
+}
+
+size_t HUF_decompress1X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	DTableDesc dtd = HUF_getDTableDesc(DTable);
+	if (dtd.tableType != 0)
+		return ERROR(GENERIC);
+	return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+	const BYTE *ip = (const BYTE *)cSrc;
+
+	size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
+	if (HUF_isError(hSize))
+		return hSize;
+	if (hSize >= cSrcSize)
+		return ERROR(srcSize_wrong);
+	ip += hSize;
+	cSrcSize -= hSize;
+
+	return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
+}
+
+static size_t HUF_decompress4X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	/* Check */
+	if (cSrcSize < 10)
+		return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+	{
+		const BYTE *const istart = (const BYTE *)cSrc;
+		BYTE *const ostart = (BYTE *)dst;
+		BYTE *const oend = ostart + dstSize;
+		const void *const dtPtr = DTable + 1;
+		const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
+
+		/* Init */
+		BIT_DStream_t bitD1;
+		BIT_DStream_t bitD2;
+		BIT_DStream_t bitD3;
+		BIT_DStream_t bitD4;
+		size_t const length1 = ZSTD_readLE16(istart);
+		size_t const length2 = ZSTD_readLE16(istart + 2);
+		size_t const length3 = ZSTD_readLE16(istart + 4);
+		size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+		const BYTE *const istart1 = istart + 6; /* jumpTable */
+		const BYTE *const istart2 = istart1 + length1;
+		const BYTE *const istart3 = istart2 + length2;
+		const BYTE *const istart4 = istart3 + length3;
+		const size_t segmentSize = (dstSize + 3) / 4;
+		BYTE *const opStart2 = ostart + segmentSize;
+		BYTE *const opStart3 = opStart2 + segmentSize;
+		BYTE *const opStart4 = opStart3 + segmentSize;
+		BYTE *op1 = ostart;
+		BYTE *op2 = opStart2;
+		BYTE *op3 = opStart3;
+		BYTE *op4 = opStart4;
+		U32 endSignal;
+		DTableDesc const dtd = HUF_getDTableDesc(DTable);
+		U32 const dtLog = dtd.tableLog;
+
+		if (length4 > cSrcSize)
+			return ERROR(corruption_detected); /* overflow */
+		{
+			size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+		{
+			size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+		{
+			size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+		{
+			size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+
+		/* 16-32 symbols per loop (4-8 symbols per stream) */
+		endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+		for (; (endSignal == BIT_DStream_unfinished) && (op4 < (oend - 7));) {
+			HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+			HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+			HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+			HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+			HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
+			HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
+			HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
+			HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
+			HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+			HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+			HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+			HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+			HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
+			HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
+			HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
+			HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+			endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+		}
+
+		/* check corruption */
+		if (op1 > opStart2)
+			return ERROR(corruption_detected);
+		if (op2 > opStart3)
+			return ERROR(corruption_detected);
+		if (op3 > opStart4)
+			return ERROR(corruption_detected);
+		/* note : op4 supposed already verified within main loop */
+
+		/* finish bitStreams one by one */
+		HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
+		HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
+		HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
+		HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
+
+		/* check */
+		endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+		if (!endSignal)
+			return ERROR(corruption_detected);
+
+		/* decoded size */
+		return dstSize;
+	}
+}
+
+size_t HUF_decompress4X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	DTableDesc dtd = HUF_getDTableDesc(DTable);
+	if (dtd.tableType != 0)
+		return ERROR(GENERIC);
+	return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+	const BYTE *ip = (const BYTE *)cSrc;
+
+	size_t const hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
+	if (HUF_isError(hSize))
+		return hSize;
+	if (hSize >= cSrcSize)
+		return ERROR(srcSize_wrong);
+	ip += hSize;
+	cSrcSize -= hSize;
+
+	return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
+}
+
+/* *************************/
+/* double-symbols decoding */
+/* *************************/
+typedef struct {
+	U16 sequence;
+	BYTE nbBits;
+	BYTE length;
+} HUF_DEltX4; /* double-symbols decoding */
+
+typedef struct {
+	BYTE symbol;
+	BYTE weight;
+} sortedSymbol_t;
+
+/* HUF_fillDTableX4Level2() :
+ * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
+static void HUF_fillDTableX4Level2(HUF_DEltX4 *DTable, U32 sizeLog, const U32 consumed, const U32 *rankValOrigin, const int minWeight,
+				   const sortedSymbol_t *sortedSymbols, const U32 sortedListSize, U32 nbBitsBaseline, U16 baseSeq)
+{
+	HUF_DEltX4 DElt;
+	U32 rankVal[HUF_TABLELOG_MAX + 1];
+
+	/* get pre-calculated rankVal */
+	memcpy(rankVal, rankValOrigin, sizeof(rankVal));
+
+	/* fill skipped values */
+	if (minWeight > 1) {
+		U32 i, skipSize = rankVal[minWeight];
+		ZSTD_writeLE16(&(DElt.sequence), baseSeq);
+		DElt.nbBits = (BYTE)(consumed);
+		DElt.length = 1;
+		for (i = 0; i < skipSize; i++)
+			DTable[i] = DElt;
+	}
+
+	/* fill DTable */
+	{
+		U32 s;
+		for (s = 0; s < sortedListSize; s++) { /* note : sortedSymbols already skipped */
+			const U32 symbol = sortedSymbols[s].symbol;
+			const U32 weight = sortedSymbols[s].weight;
+			const U32 nbBits = nbBitsBaseline - weight;
+			const U32 length = 1 << (sizeLog - nbBits);
+			const U32 start = rankVal[weight];
+			U32 i = start;
+			const U32 end = start + length;
+
+			ZSTD_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
+			DElt.nbBits = (BYTE)(nbBits + consumed);
+			DElt.length = 2;
+			do {
+				DTable[i++] = DElt;
+			} while (i < end); /* since length >= 1 */
+
+			rankVal[weight] += length;
+		}
+	}
+}
+
+typedef U32 rankVal_t[HUF_TABLELOG_MAX][HUF_TABLELOG_MAX + 1];
+typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
+
+static void HUF_fillDTableX4(HUF_DEltX4 *DTable, const U32 targetLog, const sortedSymbol_t *sortedList, const U32 sortedListSize, const U32 *rankStart,
+			     rankVal_t rankValOrigin, const U32 maxWeight, const U32 nbBitsBaseline)
+{
+	U32 rankVal[HUF_TABLELOG_MAX + 1];
+	const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
+	const U32 minBits = nbBitsBaseline - maxWeight;
+	U32 s;
+
+	memcpy(rankVal, rankValOrigin, sizeof(rankVal));
+
+	/* fill DTable */
+	for (s = 0; s < sortedListSize; s++) {
+		const U16 symbol = sortedList[s].symbol;
+		const U32 weight = sortedList[s].weight;
+		const U32 nbBits = nbBitsBaseline - weight;
+		const U32 start = rankVal[weight];
+		const U32 length = 1 << (targetLog - nbBits);
+
+		if (targetLog - nbBits >= minBits) { /* enough room for a second symbol */
+			U32 sortedRank;
+			int minWeight = nbBits + scaleLog;
+			if (minWeight < 1)
+				minWeight = 1;
+			sortedRank = rankStart[minWeight];
+			HUF_fillDTableX4Level2(DTable + start, targetLog - nbBits, nbBits, rankValOrigin[nbBits], minWeight, sortedList + sortedRank,
+					       sortedListSize - sortedRank, nbBitsBaseline, symbol);
+		} else {
+			HUF_DEltX4 DElt;
+			ZSTD_writeLE16(&(DElt.sequence), symbol);
+			DElt.nbBits = (BYTE)(nbBits);
+			DElt.length = 1;
+			{
+				U32 const end = start + length;
+				U32 u;
+				for (u = start; u < end; u++)
+					DTable[u] = DElt;
+			}
+		}
+		rankVal[weight] += length;
+	}
+}
+
+size_t HUF_readDTableX4_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
+{
+	U32 tableLog, maxW, sizeOfSort, nbSymbols;
+	DTableDesc dtd = HUF_getDTableDesc(DTable);
+	U32 const maxTableLog = dtd.maxTableLog;
+	size_t iSize;
+	void *dtPtr = DTable + 1; /* force compiler to avoid strict-aliasing */
+	HUF_DEltX4 *const dt = (HUF_DEltX4 *)dtPtr;
+	U32 *rankStart;
+
+	rankValCol_t *rankVal;
+	U32 *rankStats;
+	U32 *rankStart0;
+	sortedSymbol_t *sortedSymbol;
+	BYTE *weightList;
+	size_t spaceUsed32 = 0;
+
+	HUF_STATIC_ASSERT((sizeof(rankValCol_t) & 3) == 0);
+
+	rankVal = (rankValCol_t *)((U32 *)workspace + spaceUsed32);
+	spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;
+	rankStats = (U32 *)workspace + spaceUsed32;
+	spaceUsed32 += HUF_TABLELOG_MAX + 1;
+	rankStart0 = (U32 *)workspace + spaceUsed32;
+	spaceUsed32 += HUF_TABLELOG_MAX + 2;
+	sortedSymbol = (sortedSymbol_t *)((U32 *)workspace + spaceUsed32);
+	spaceUsed32 += ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
+	weightList = (BYTE *)((U32 *)workspace + spaceUsed32);
+	spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
+
+	if ((spaceUsed32 << 2) > workspaceSize)
+		return ERROR(tableLog_tooLarge);
+	workspace = (U32 *)workspace + spaceUsed32;
+	workspaceSize -= (spaceUsed32 << 2);
+
+	rankStart = rankStart0 + 1;
+	memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
+
+	HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
+	if (maxTableLog > HUF_TABLELOG_MAX)
+		return ERROR(tableLog_tooLarge);
+	/* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
+
+	iSize = HUF_readStats_wksp(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
+	if (HUF_isError(iSize))
+		return iSize;
+
+	/* check result */
+	if (tableLog > maxTableLog)
+		return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
+
+	/* find maxWeight */
+	for (maxW = tableLog; rankStats[maxW] == 0; maxW--) {
+	} /* necessarily finds a solution before 0 */
+
+	/* Get start index of each weight */
+	{
+		U32 w, nextRankStart = 0;
+		for (w = 1; w < maxW + 1; w++) {
+			U32 curr = nextRankStart;
+			nextRankStart += rankStats[w];
+			rankStart[w] = curr;
+		}
+		rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
+		sizeOfSort = nextRankStart;
+	}
+
+	/* sort symbols by weight */
+	{
+		U32 s;
+		for (s = 0; s < nbSymbols; s++) {
+			U32 const w = weightList[s];
+			U32 const r = rankStart[w]++;
+			sortedSymbol[r].symbol = (BYTE)s;
+			sortedSymbol[r].weight = (BYTE)w;
+		}
+		rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
+	}
+
+	/* Build rankVal */
+	{
+		U32 *const rankVal0 = rankVal[0];
+		{
+			int const rescale = (maxTableLog - tableLog) - 1; /* tableLog <= maxTableLog */
+			U32 nextRankVal = 0;
+			U32 w;
+			for (w = 1; w < maxW + 1; w++) {
+				U32 curr = nextRankVal;
+				nextRankVal += rankStats[w] << (w + rescale);
+				rankVal0[w] = curr;
+			}
+		}
+		{
+			U32 const minBits = tableLog + 1 - maxW;
+			U32 consumed;
+			for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
+				U32 *const rankValPtr = rankVal[consumed];
+				U32 w;
+				for (w = 1; w < maxW + 1; w++) {
+					rankValPtr[w] = rankVal0[w] >> consumed;
+				}
+			}
+		}
+	}
+
+	HUF_fillDTableX4(dt, maxTableLog, sortedSymbol, sizeOfSort, rankStart0, rankVal, maxW, tableLog + 1);
+
+	dtd.tableLog = (BYTE)maxTableLog;
+	dtd.tableType = 1;
+	memcpy(DTable, &dtd, sizeof(dtd));
+	return iSize;
+}
+
+static U32 HUF_decodeSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
+{
+	size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+	memcpy(op, dt + val, 2);
+	BIT_skipBits(DStream, dt[val].nbBits);
+	return dt[val].length;
+}
+
+static U32 HUF_decodeLastSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
+{
+	size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+	memcpy(op, dt + val, 1);
+	if (dt[val].length == 1)
+		BIT_skipBits(DStream, dt[val].nbBits);
+	else {
+		if (DStream->bitsConsumed < (sizeof(DStream->bitContainer) * 8)) {
+			BIT_skipBits(DStream, dt[val].nbBits);
+			if (DStream->bitsConsumed > (sizeof(DStream->bitContainer) * 8))
+				/* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
+				DStream->bitsConsumed = (sizeof(DStream->bitContainer) * 8);
+		}
+	}
+	return 1;
+}
+
+#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr)         \
+	if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
+	ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
+	if (ZSTD_64bits())                     \
+	ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
+
+FORCE_INLINE size_t HUF_decodeStreamX4(BYTE *p, BIT_DStream_t *bitDPtr, BYTE *const pEnd, const HUF_DEltX4 *const dt, const U32 dtLog)
+{
+	BYTE *const pStart = p;
+
+	/* up to 8 symbols at a time */
+	while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd - (sizeof(bitDPtr->bitContainer) - 1))) {
+		HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
+		HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
+		HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
+		HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
+	}
+
+	/* closer to end : up to 2 symbols at a time */
+	while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd - 2))
+		HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
+
+	while (p <= pEnd - 2)
+		HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
+
+	if (p < pEnd)
+		p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
+
+	return p - pStart;
+}
+
+static size_t HUF_decompress1X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	BIT_DStream_t bitD;
+
+	/* Init */
+	{
+		size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
+		if (HUF_isError(errorCode))
+			return errorCode;
+	}
+
+	/* decode */
+	{
+		BYTE *const ostart = (BYTE *)dst;
+		BYTE *const oend = ostart + dstSize;
+		const void *const dtPtr = DTable + 1; /* force compiler to not use strict-aliasing */
+		const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
+		DTableDesc const dtd = HUF_getDTableDesc(DTable);
+		HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
+	}
+
+	/* check */
+	if (!BIT_endOfDStream(&bitD))
+		return ERROR(corruption_detected);
+
+	/* decoded size */
+	return dstSize;
+}
+
+size_t HUF_decompress1X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	DTableDesc dtd = HUF_getDTableDesc(DTable);
+	if (dtd.tableType != 1)
+		return ERROR(GENERIC);
+	return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+	const BYTE *ip = (const BYTE *)cSrc;
+
+	size_t const hSize = HUF_readDTableX4_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
+	if (HUF_isError(hSize))
+		return hSize;
+	if (hSize >= cSrcSize)
+		return ERROR(srcSize_wrong);
+	ip += hSize;
+	cSrcSize -= hSize;
+
+	return HUF_decompress1X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
+}
+
+static size_t HUF_decompress4X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	if (cSrcSize < 10)
+		return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+	{
+		const BYTE *const istart = (const BYTE *)cSrc;
+		BYTE *const ostart = (BYTE *)dst;
+		BYTE *const oend = ostart + dstSize;
+		const void *const dtPtr = DTable + 1;
+		const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
+
+		/* Init */
+		BIT_DStream_t bitD1;
+		BIT_DStream_t bitD2;
+		BIT_DStream_t bitD3;
+		BIT_DStream_t bitD4;
+		size_t const length1 = ZSTD_readLE16(istart);
+		size_t const length2 = ZSTD_readLE16(istart + 2);
+		size_t const length3 = ZSTD_readLE16(istart + 4);
+		size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+		const BYTE *const istart1 = istart + 6; /* jumpTable */
+		const BYTE *const istart2 = istart1 + length1;
+		const BYTE *const istart3 = istart2 + length2;
+		const BYTE *const istart4 = istart3 + length3;
+		size_t const segmentSize = (dstSize + 3) / 4;
+		BYTE *const opStart2 = ostart + segmentSize;
+		BYTE *const opStart3 = opStart2 + segmentSize;
+		BYTE *const opStart4 = opStart3 + segmentSize;
+		BYTE *op1 = ostart;
+		BYTE *op2 = opStart2;
+		BYTE *op3 = opStart3;
+		BYTE *op4 = opStart4;
+		U32 endSignal;
+		DTableDesc const dtd = HUF_getDTableDesc(DTable);
+		U32 const dtLog = dtd.tableLog;
+
+		if (length4 > cSrcSize)
+			return ERROR(corruption_detected); /* overflow */
+		{
+			size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+		{
+			size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+		{
+			size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+		{
+			size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
+			if (HUF_isError(errorCode))
+				return errorCode;
+		}
+
+		/* 16-32 symbols per loop (4-8 symbols per stream) */
+		endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+		for (; (endSignal == BIT_DStream_unfinished) & (op4 < (oend - (sizeof(bitD4.bitContainer) - 1)));) {
+			HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
+			HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
+			HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
+			HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
+			HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
+			HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
+			HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
+			HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
+			HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
+			HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
+			HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
+			HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
+			HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
+			HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
+			HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
+			HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
+
+			endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
+		}
+
+		/* check corruption */
+		if (op1 > opStart2)
+			return ERROR(corruption_detected);
+		if (op2 > opStart3)
+			return ERROR(corruption_detected);
+		if (op3 > opStart4)
+			return ERROR(corruption_detected);
+		/* note : op4 already verified within main loop */
+
+		/* finish bitStreams one by one */
+		HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
+		HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
+		HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
+		HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
+
+		/* check */
+		{
+			U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+			if (!endCheck)
+				return ERROR(corruption_detected);
+		}
+
+		/* decoded size */
+		return dstSize;
+	}
+}
+
+size_t HUF_decompress4X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	DTableDesc dtd = HUF_getDTableDesc(DTable);
+	if (dtd.tableType != 1)
+		return ERROR(GENERIC);
+	return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+	const BYTE *ip = (const BYTE *)cSrc;
+
+	size_t hSize = HUF_readDTableX4_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
+	if (HUF_isError(hSize))
+		return hSize;
+	if (hSize >= cSrcSize)
+		return ERROR(srcSize_wrong);
+	ip += hSize;
+	cSrcSize -= hSize;
+
+	return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
+}
+
+/* ********************************/
+/* Generic decompression selector */
+/* ********************************/
+
+size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	DTableDesc const dtd = HUF_getDTableDesc(DTable);
+	return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
+			     : HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
+}
+
+size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
+{
+	DTableDesc const dtd = HUF_getDTableDesc(DTable);
+	return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
+			     : HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
+}
+
+typedef struct {
+	U32 tableTime;
+	U32 decode256Time;
+} algo_time_t;
+static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = {
+    /* single, double, quad */
+    {{0, 0}, {1, 1}, {2, 2}},		     /* Q==0 : impossible */
+    {{0, 0}, {1, 1}, {2, 2}},		     /* Q==1 : impossible */
+    {{38, 130}, {1313, 74}, {2151, 38}},     /* Q == 2 : 12-18% */
+    {{448, 128}, {1353, 74}, {2238, 41}},    /* Q == 3 : 18-25% */
+    {{556, 128}, {1353, 74}, {2238, 47}},    /* Q == 4 : 25-32% */
+    {{714, 128}, {1418, 74}, {2436, 53}},    /* Q == 5 : 32-38% */
+    {{883, 128}, {1437, 74}, {2464, 61}},    /* Q == 6 : 38-44% */
+    {{897, 128}, {1515, 75}, {2622, 68}},    /* Q == 7 : 44-50% */
+    {{926, 128}, {1613, 75}, {2730, 75}},    /* Q == 8 : 50-56% */
+    {{947, 128}, {1729, 77}, {3359, 77}},    /* Q == 9 : 56-62% */
+    {{1107, 128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */
+    {{1177, 128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */
+    {{1242, 128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */
+    {{1349, 128}, {2644, 106}, {5260, 106}}, /* Q ==13 : 81-87% */
+    {{1455, 128}, {2422, 124}, {4174, 124}}, /* Q ==14 : 87-93% */
+    {{722, 128}, {1891, 145}, {1936, 146}},  /* Q ==15 : 93-99% */
+};
+
+/** HUF_selectDecoder() :
+*   Tells which decoder is likely to decode faster,
+*   based on a set of pre-determined metrics.
+*   @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
+*   Assumption : 0 < cSrcSize < dstSize <= 128 KB */
+U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize)
+{
+	/* decoder timing evaluation */
+	U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */
+	U32 const D256 = (U32)(dstSize >> 8);
+	U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
+	U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
+	DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */
+
+	return DTime1 < DTime0;
+}
+
+typedef size_t (*decompressionAlgo)(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize);
+
+size_t HUF_decompress4X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+	/* validation checks */
+	if (dstSize == 0)
+		return ERROR(dstSize_tooSmall);
+	if (cSrcSize > dstSize)
+		return ERROR(corruption_detected); /* invalid */
+	if (cSrcSize == dstSize) {
+		memcpy(dst, cSrc, dstSize);
+		return dstSize;
+	} /* not compressed */
+	if (cSrcSize == 1) {
+		memset(dst, *(const BYTE *)cSrc, dstSize);
+		return dstSize;
+	} /* RLE */
+
+	{
+		U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+		return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
+			      : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
+	}
+}
+
+size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+	/* validation checks */
+	if (dstSize == 0)
+		return ERROR(dstSize_tooSmall);
+	if ((cSrcSize >= dstSize) || (cSrcSize <= 1))
+		return ERROR(corruption_detected); /* invalid */
+
+	{
+		U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+		return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
+			      : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
+	}
+}
+
+size_t HUF_decompress1X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
+{
+	/* validation checks */
+	if (dstSize == 0)
+		return ERROR(dstSize_tooSmall);
+	if (cSrcSize > dstSize)
+		return ERROR(corruption_detected); /* invalid */
+	if (cSrcSize == dstSize) {
+		memcpy(dst, cSrc, dstSize);
+		return dstSize;
+	} /* not compressed */
+	if (cSrcSize == 1) {
+		memset(dst, *(const BYTE *)cSrc, dstSize);
+		return dstSize;
+	} /* RLE */
+
+	{
+		U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+		return algoNb ? HUF_decompress1X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
+			      : HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
+	}
+}
diff --git a/lib/zstd/mem.h b/lib/zstd/mem.h
new file mode 100644
index 000000000000..3a0f34c8706c
--- /dev/null
+++ b/lib/zstd/mem.h
@@ -0,0 +1,151 @@
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd.
+ * An additional grant of patent rights can be found in the PATENTS file in the
+ * same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ */
+
+#ifndef MEM_H_MODULE
+#define MEM_H_MODULE
+
+/*-****************************************
+*  Dependencies
+******************************************/
+#include <asm/unaligned.h>
+#include <linux/string.h> /* memcpy */
+#include <linux/types.h>  /* size_t, ptrdiff_t */
+
+/*-****************************************
+*  Compiler specifics
+******************************************/
+#define ZSTD_STATIC static __inline __attribute__((unused))
+
+/*-**************************************************************
+*  Basic Types
+*****************************************************************/
+typedef uint8_t BYTE;
+typedef uint16_t U16;
+typedef int16_t S16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+typedef int64_t S64;
+typedef ptrdiff_t iPtrDiff;
+typedef uintptr_t uPtrDiff;
+
+/*-**************************************************************
+*  Memory I/O
+*****************************************************************/
+ZSTD_STATIC unsigned ZSTD_32bits(void) { return sizeof(size_t) == 4; }
+ZSTD_STATIC unsigned ZSTD_64bits(void) { return sizeof(size_t) == 8; }
+
+#if defined(__LITTLE_ENDIAN)
+#define ZSTD_LITTLE_ENDIAN 1
+#else
+#define ZSTD_LITTLE_ENDIAN 0
+#endif
+
+ZSTD_STATIC unsigned ZSTD_isLittleEndian(void) { return ZSTD_LITTLE_ENDIAN; }
+
+ZSTD_STATIC U16 ZSTD_read16(const void *memPtr) { return get_unaligned((const U16 *)memPtr); }
+
+ZSTD_STATIC U32 ZSTD_read32(const void *memPtr) { return get_unaligned((const U32 *)memPtr); }
+
+ZSTD_STATIC U64 ZSTD_read64(const void *memPtr) { return get_unaligned((const U64 *)memPtr); }
+
+ZSTD_STATIC size_t ZSTD_readST(const void *memPtr) { return get_unaligned((const size_t *)memPtr); }
+
+ZSTD_STATIC void ZSTD_write16(void *memPtr, U16 value) { put_unaligned(value, (U16 *)memPtr); }
+
+ZSTD_STATIC void ZSTD_write32(void *memPtr, U32 value) { put_unaligned(value, (U32 *)memPtr); }
+
+ZSTD_STATIC void ZSTD_write64(void *memPtr, U64 value) { put_unaligned(value, (U64 *)memPtr); }
+
+/*=== Little endian r/w ===*/
+
+ZSTD_STATIC U16 ZSTD_readLE16(const void *memPtr) { return get_unaligned_le16(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeLE16(void *memPtr, U16 val) { put_unaligned_le16(val, memPtr); }
+
+ZSTD_STATIC U32 ZSTD_readLE24(const void *memPtr) { return ZSTD_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16); }
+
+ZSTD_STATIC void ZSTD_writeLE24(void *memPtr, U32 val)
+{
+	ZSTD_writeLE16(memPtr, (U16)val);
+	((BYTE *)memPtr)[2] = (BYTE)(val >> 16);
+}
+
+ZSTD_STATIC U32 ZSTD_readLE32(const void *memPtr) { return get_unaligned_le32(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeLE32(void *memPtr, U32 val32) { put_unaligned_le32(val32, memPtr); }
+
+ZSTD_STATIC U64 ZSTD_readLE64(const void *memPtr) { return get_unaligned_le64(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeLE64(void *memPtr, U64 val64) { put_unaligned_le64(val64, memPtr); }
+
+ZSTD_STATIC size_t ZSTD_readLEST(const void *memPtr)
+{
+	if (ZSTD_32bits())
+		return (size_t)ZSTD_readLE32(memPtr);
+	else
+		return (size_t)ZSTD_readLE64(memPtr);
+}
+
+ZSTD_STATIC void ZSTD_writeLEST(void *memPtr, size_t val)
+{
+	if (ZSTD_32bits())
+		ZSTD_writeLE32(memPtr, (U32)val);
+	else
+		ZSTD_writeLE64(memPtr, (U64)val);
+}
+
+/*=== Big endian r/w ===*/
+
+ZSTD_STATIC U32 ZSTD_readBE32(const void *memPtr) { return get_unaligned_be32(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeBE32(void *memPtr, U32 val32) { put_unaligned_be32(val32, memPtr); }
+
+ZSTD_STATIC U64 ZSTD_readBE64(const void *memPtr) { return get_unaligned_be64(memPtr); }
+
+ZSTD_STATIC void ZSTD_writeBE64(void *memPtr, U64 val64) { put_unaligned_be64(val64, memPtr); }
+
+ZSTD_STATIC size_t ZSTD_readBEST(const void *memPtr)
+{
+	if (ZSTD_32bits())
+		return (size_t)ZSTD_readBE32(memPtr);
+	else
+		return (size_t)ZSTD_readBE64(memPtr);
+}
+
+ZSTD_STATIC void ZSTD_writeBEST(void *memPtr, size_t val)
+{
+	if (ZSTD_32bits())
+		ZSTD_writeBE32(memPtr, (U32)val);
+	else
+		ZSTD_writeBE64(memPtr, (U64)val);
+}
+
+/* function safe only for comparisons */
+ZSTD_STATIC U32 ZSTD_readMINMATCH(const void *memPtr, U32 length)
+{
+	switch (length) {
+	default:
+	case 4: return ZSTD_read32(memPtr);
+	case 3:
+		if (ZSTD_isLittleEndian())
+			return ZSTD_read32(memPtr) << 8;
+		else
+			return ZSTD_read32(memPtr) >> 8;
+	}
+}
+
+#endif /* MEM_H_MODULE */
diff --git a/lib/zstd/zstd_common.c b/lib/zstd/zstd_common.c
new file mode 100644
index 000000000000..a282624ee155
--- /dev/null
+++ b/lib/zstd/zstd_common.c
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd.
+ * An additional grant of patent rights can be found in the PATENTS file in the
+ * same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ */
+
+/*-*************************************
+*  Dependencies
+***************************************/
+#include "error_private.h"
+#include "zstd_internal.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */
+#include <linux/kernel.h>
+
+/*=**************************************************************
+*  Custom allocator
+****************************************************************/
+
+#define stack_push(stack, size)                                 \
+	({                                                      \
+		void *const ptr = ZSTD_PTR_ALIGN((stack)->ptr); \
+		(stack)->ptr = (char *)ptr + (size);            \
+		(stack)->ptr <= (stack)->end ? ptr : NULL;      \
+	})
+
+ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize)
+{
+	ZSTD_customMem stackMem = {ZSTD_stackAlloc, ZSTD_stackFree, workspace};
+	ZSTD_stack *stack = (ZSTD_stack *)workspace;
+	/* Verify preconditions */
+	if (!workspace || workspaceSize < sizeof(ZSTD_stack) || workspace != ZSTD_PTR_ALIGN(workspace)) {
+		ZSTD_customMem error = {NULL, NULL, NULL};
+		return error;
+	}
+	/* Initialize the stack */
+	stack->ptr = workspace;
+	stack->end = (char *)workspace + workspaceSize;
+	stack_push(stack, sizeof(ZSTD_stack));
+	return stackMem;
+}
+
+void *ZSTD_stackAllocAll(void *opaque, size_t *size)
+{
+	ZSTD_stack *stack = (ZSTD_stack *)opaque;
+	*size = (BYTE const *)stack->end - (BYTE *)ZSTD_PTR_ALIGN(stack->ptr);
+	return stack_push(stack, *size);
+}
+
+void *ZSTD_stackAlloc(void *opaque, size_t size)
+{
+	ZSTD_stack *stack = (ZSTD_stack *)opaque;
+	return stack_push(stack, size);
+}
+void ZSTD_stackFree(void *opaque, void *address)
+{
+	(void)opaque;
+	(void)address;
+}
+
+void *ZSTD_malloc(size_t size, ZSTD_customMem customMem) { return customMem.customAlloc(customMem.opaque, size); }
+
+void ZSTD_free(void *ptr, ZSTD_customMem customMem)
+{
+	if (ptr != NULL)
+		customMem.customFree(customMem.opaque, ptr);
+}
diff --git a/lib/zstd/zstd_decompress_module.c b/lib/zstd/zstd_decompress_module.c
deleted file mode 100644
index 6fec1f178de7..000000000000
--- a/lib/zstd/zstd_decompress_module.c
+++ /dev/null
@@ -1,105 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
-/*
- * Copyright (c) Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under both the BSD-style license (found in the
- * LICENSE file in the root directory of this source tree) and the GPLv2 (found
- * in the COPYING file in the root directory of this source tree).
- * You may select, at your option, one of the above-listed licenses.
- */
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/string.h>
-#include <linux/zstd.h>
-
-#include "common/zstd_deps.h"
-
-/* Common symbols. zstd_compress must depend on zstd_decompress. */
-
-unsigned int zstd_is_error(size_t code)
-{
-	return ZSTD_isError(code);
-}
-EXPORT_SYMBOL(zstd_is_error);
-
-zstd_error_code zstd_get_error_code(size_t code)
-{
-	return ZSTD_getErrorCode(code);
-}
-EXPORT_SYMBOL(zstd_get_error_code);
-
-const char *zstd_get_error_name(size_t code)
-{
-	return ZSTD_getErrorName(code);
-}
-EXPORT_SYMBOL(zstd_get_error_name);
-
-/* Decompression symbols. */
-
-size_t zstd_dctx_workspace_bound(void)
-{
-	return ZSTD_estimateDCtxSize();
-}
-EXPORT_SYMBOL(zstd_dctx_workspace_bound);
-
-zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size)
-{
-	if (workspace == NULL)
-		return NULL;
-	return ZSTD_initStaticDCtx(workspace, workspace_size);
-}
-EXPORT_SYMBOL(zstd_init_dctx);
-
-size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
-	const void *src, size_t src_size)
-{
-	return ZSTD_decompressDCtx(dctx, dst, dst_capacity, src, src_size);
-}
-EXPORT_SYMBOL(zstd_decompress_dctx);
-
-size_t zstd_dstream_workspace_bound(size_t max_window_size)
-{
-	return ZSTD_estimateDStreamSize(max_window_size);
-}
-EXPORT_SYMBOL(zstd_dstream_workspace_bound);
-
-zstd_dstream *zstd_init_dstream(size_t max_window_size, void *workspace,
-	size_t workspace_size)
-{
-	if (workspace == NULL)
-		return NULL;
-	(void)max_window_size;
-	return ZSTD_initStaticDStream(workspace, workspace_size);
-}
-EXPORT_SYMBOL(zstd_init_dstream);
-
-size_t zstd_reset_dstream(zstd_dstream *dstream)
-{
-	return ZSTD_resetDStream(dstream);
-}
-EXPORT_SYMBOL(zstd_reset_dstream);
-
-size_t zstd_decompress_stream(zstd_dstream *dstream, zstd_out_buffer *output,
-	zstd_in_buffer *input)
-{
-	return ZSTD_decompressStream(dstream, output, input);
-}
-EXPORT_SYMBOL(zstd_decompress_stream);
-
-size_t zstd_find_frame_compressed_size(const void *src, size_t src_size)
-{
-	return ZSTD_findFrameCompressedSize(src, src_size);
-}
-EXPORT_SYMBOL(zstd_find_frame_compressed_size);
-
-size_t zstd_get_frame_header(zstd_frame_header *header, const void *src,
-	size_t src_size)
-{
-	return ZSTD_getFrameHeader(header, src, src_size);
-}
-EXPORT_SYMBOL(zstd_get_frame_header);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("Zstd Decompressor");
diff --git a/lib/zstd/zstd_internal.h b/lib/zstd/zstd_internal.h
new file mode 100644
index 000000000000..1a79fab9e13a
--- /dev/null
+++ b/lib/zstd/zstd_internal.h
@@ -0,0 +1,263 @@
+/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd.
+ * An additional grant of patent rights can be found in the PATENTS file in the
+ * same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ */
+
+#ifndef ZSTD_CCOMMON_H_MODULE
+#define ZSTD_CCOMMON_H_MODULE
+
+/*-*******************************************************
+*  Compiler specifics
+*********************************************************/
+#define FORCE_INLINE static __always_inline
+#define FORCE_NOINLINE static noinline
+
+/*-*************************************
+*  Dependencies
+***************************************/
+#include "error_private.h"
+#include "mem.h"
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/xxhash.h>
+#include <linux/zstd.h>
+
+/*-*************************************
+*  shared macros
+***************************************/
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define CHECK_F(f)                       \
+	{                                \
+		size_t const errcod = f; \
+		if (ERR_isError(errcod)) \
+			return errcod;   \
+	} /* check and Forward error code */
+#define CHECK_E(f, e)                    \
+	{                                \
+		size_t const errcod = f; \
+		if (ERR_isError(errcod)) \
+			return ERROR(e); \
+	} /* check and send Error code */
+#define ZSTD_STATIC_ASSERT(c)                                   \
+	{                                                       \
+		enum { ZSTD_static_assert = 1 / (int)(!!(c)) }; \
+	}
+
+/*-*************************************
+*  Common constants
+***************************************/
+#define ZSTD_OPT_NUM (1 << 12)
+#define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */
+
+#define ZSTD_REP_NUM 3		      /* number of repcodes */
+#define ZSTD_REP_CHECK (ZSTD_REP_NUM) /* number of repcodes to check by the optimal parser */
+#define ZSTD_REP_MOVE (ZSTD_REP_NUM - 1)
+#define ZSTD_REP_MOVE_OPT (ZSTD_REP_NUM)
+static const U32 repStartValue[ZSTD_REP_NUM] = {1, 4, 8};
+
+#define KB *(1 << 10)
+#define MB *(1 << 20)
+#define GB *(1U << 30)
+
+#define BIT7 128
+#define BIT6 64
+#define BIT5 32
+#define BIT4 16
+#define BIT1 2
+#define BIT0 1
+
+#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
+static const size_t ZSTD_fcs_fieldSize[4] = {0, 2, 4, 8};
+static const size_t ZSTD_did_fieldSize[4] = {0, 1, 2, 4};
+
+#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
+static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
+typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
+
+#define MIN_SEQUENCES_SIZE 1									  /* nbSeq==0 */
+#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
+
+#define HufLog 12
+typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e;
+
+#define LONGNBSEQ 0x7F00
+
+#define MINMATCH 3
+#define EQUAL_READ32 4
+
+#define Litbits 8
+#define MaxLit ((1 << Litbits) - 1)
+#define MaxML 52
+#define MaxLL 35
+#define MaxOff 28
+#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
+#define MLFSELog 9
+#define LLFSELog 9
+#define OffFSELog 8
+
+static const U32 LL_bits[MaxLL + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+static const S16 LL_defaultNorm[MaxLL + 1] = {4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, -1, -1, -1, -1};
+#define LL_DEFAULTNORMLOG 6 /* for static allocation */
+static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
+
+static const U32 ML_bits[MaxML + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0, 0,
+				       0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+static const S16 ML_defaultNorm[MaxML + 1] = {1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1,  1, 1,
+					      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1};
+#define ML_DEFAULTNORMLOG 6 /* for static allocation */
+static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
+
+static const S16 OF_defaultNorm[MaxOff + 1] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1};
+#define OF_DEFAULTNORMLOG 5 /* for static allocation */
+static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
+
+/*-*******************************************
+*  Shared functions to include for inlining
+*********************************************/
+ZSTD_STATIC void ZSTD_copy8(void *dst, const void *src) {
+	memcpy(dst, src, 8);
+}
+/*! ZSTD_wildcopy() :
+*   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
+#define WILDCOPY_OVERLENGTH 8
+ZSTD_STATIC void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length)
+{
+	const BYTE* ip = (const BYTE*)src;
+	BYTE* op = (BYTE*)dst;
+	BYTE* const oend = op + length;
+	/* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388.
+	 * Avoid the bad case where the loop only runs once by handling the
+	 * special case separately. This doesn't trigger the bug because it
+	 * doesn't involve pointer/integer overflow.
+	 */
+	if (length <= 8)
+		return ZSTD_copy8(dst, src);
+	do {
+		ZSTD_copy8(op, ip);
+		op += 8;
+		ip += 8;
+	} while (op < oend);
+}
+
+/*-*******************************************
+*  Private interfaces
+*********************************************/
+typedef struct ZSTD_stats_s ZSTD_stats_t;
+
+typedef struct {
+	U32 off;
+	U32 len;
+} ZSTD_match_t;
+
+typedef struct {
+	U32 price;
+	U32 off;
+	U32 mlen;
+	U32 litlen;
+	U32 rep[ZSTD_REP_NUM];
+} ZSTD_optimal_t;
+
+typedef struct seqDef_s {
+	U32 offset;
+	U16 litLength;
+	U16 matchLength;
+} seqDef;
+
+typedef struct {
+	seqDef *sequencesStart;
+	seqDef *sequences;
+	BYTE *litStart;
+	BYTE *lit;
+	BYTE *llCode;
+	BYTE *mlCode;
+	BYTE *ofCode;
+	U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
+	U32 longLengthPos;
+	/* opt */
+	ZSTD_optimal_t *priceTable;
+	ZSTD_match_t *matchTable;
+	U32 *matchLengthFreq;
+	U32 *litLengthFreq;
+	U32 *litFreq;
+	U32 *offCodeFreq;
+	U32 matchLengthSum;
+	U32 matchSum;
+	U32 litLengthSum;
+	U32 litSum;
+	U32 offCodeSum;
+	U32 log2matchLengthSum;
+	U32 log2matchSum;
+	U32 log2litLengthSum;
+	U32 log2litSum;
+	U32 log2offCodeSum;
+	U32 factor;
+	U32 staticPrices;
+	U32 cachedPrice;
+	U32 cachedLitLength;
+	const BYTE *cachedLiterals;
+} seqStore_t;
+
+const seqStore_t *ZSTD_getSeqStore(const ZSTD_CCtx *ctx);
+void ZSTD_seqToCodes(const seqStore_t *seqStorePtr);
+int ZSTD_isSkipFrame(ZSTD_DCtx *dctx);
+
+/*= Custom memory allocation functions */
+typedef void *(*ZSTD_allocFunction)(void *opaque, size_t size);
+typedef void (*ZSTD_freeFunction)(void *opaque, void *address);
+typedef struct {
+	ZSTD_allocFunction customAlloc;
+	ZSTD_freeFunction customFree;
+	void *opaque;
+} ZSTD_customMem;
+
+void *ZSTD_malloc(size_t size, ZSTD_customMem customMem);
+void ZSTD_free(void *ptr, ZSTD_customMem customMem);
+
+/*====== stack allocation  ======*/
+
+typedef struct {
+	void *ptr;
+	const void *end;
+} ZSTD_stack;
+
+#define ZSTD_ALIGN(x) ALIGN(x, sizeof(size_t))
+#define ZSTD_PTR_ALIGN(p) PTR_ALIGN(p, sizeof(size_t))
+
+ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize);
+
+void *ZSTD_stackAllocAll(void *opaque, size_t *size);
+void *ZSTD_stackAlloc(void *opaque, size_t size);
+void ZSTD_stackFree(void *opaque, void *address);
+
+/*======  common function  ======*/
+
+ZSTD_STATIC U32 ZSTD_highbit32(U32 val) { return 31 - __builtin_clz(val); }
+
+/* hidden functions */
+
+/* ZSTD_invalidateRepCodes() :
+ * ensures next compression will not use repcodes from previous block.
+ * Note : only works with regular variant;
+ *        do not use with extDict variant ! */
+void ZSTD_invalidateRepCodes(ZSTD_CCtx *cctx);
+
+size_t ZSTD_freeCCtx(ZSTD_CCtx *cctx);
+size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx);
+size_t ZSTD_freeCDict(ZSTD_CDict *cdict);
+size_t ZSTD_freeDDict(ZSTD_DDict *cdict);
+size_t ZSTD_freeCStream(ZSTD_CStream *zcs);
+size_t ZSTD_freeDStream(ZSTD_DStream *zds);
+
+#endif /* ZSTD_CCOMMON_H_MODULE */
diff --git a/lib/zstd/zstd_opt.h b/lib/zstd/zstd_opt.h
new file mode 100644
index 000000000000..55e1b4cba808
--- /dev/null
+++ b/lib/zstd/zstd_opt.h
@@ -0,0 +1,1014 @@
+/**
+ * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd.
+ * An additional grant of patent rights can be found in the PATENTS file in the
+ * same directory.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation. This program is dual-licensed; you may select
+ * either version 2 of the GNU General Public License ("GPL") or BSD license
+ * ("BSD").
+ */
+
+/* Note : this file is intended to be included within zstd_compress.c */
+
+#ifndef ZSTD_OPT_H_91842398743
+#define ZSTD_OPT_H_91842398743
+
+#define ZSTD_LITFREQ_ADD 2
+#define ZSTD_FREQ_DIV 4
+#define ZSTD_MAX_PRICE (1 << 30)
+
+/*-*************************************
+*  Price functions for optimal parser
+***************************************/
+FORCE_INLINE void ZSTD_setLog2Prices(seqStore_t *ssPtr)
+{
+	ssPtr->log2matchLengthSum = ZSTD_highbit32(ssPtr->matchLengthSum + 1);
+	ssPtr->log2litLengthSum = ZSTD_highbit32(ssPtr->litLengthSum + 1);
+	ssPtr->log2litSum = ZSTD_highbit32(ssPtr->litSum + 1);
+	ssPtr->log2offCodeSum = ZSTD_highbit32(ssPtr->offCodeSum + 1);
+	ssPtr->factor = 1 + ((ssPtr->litSum >> 5) / ssPtr->litLengthSum) + ((ssPtr->litSum << 1) / (ssPtr->litSum + ssPtr->matchSum));
+}
+
+ZSTD_STATIC void ZSTD_rescaleFreqs(seqStore_t *ssPtr, const BYTE *src, size_t srcSize)
+{
+	unsigned u;
+
+	ssPtr->cachedLiterals = NULL;
+	ssPtr->cachedPrice = ssPtr->cachedLitLength = 0;
+	ssPtr->staticPrices = 0;
+
+	if (ssPtr->litLengthSum == 0) {
+		if (srcSize <= 1024)
+			ssPtr->staticPrices = 1;
+
+		for (u = 0; u <= MaxLit; u++)
+			ssPtr->litFreq[u] = 0;
+		for (u = 0; u < srcSize; u++)
+			ssPtr->litFreq[src[u]]++;
+
+		ssPtr->litSum = 0;
+		ssPtr->litLengthSum = MaxLL + 1;
+		ssPtr->matchLengthSum = MaxML + 1;
+		ssPtr->offCodeSum = (MaxOff + 1);
+		ssPtr->matchSum = (ZSTD_LITFREQ_ADD << Litbits);
+
+		for (u = 0; u <= MaxLit; u++) {
+			ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> ZSTD_FREQ_DIV);
+			ssPtr->litSum += ssPtr->litFreq[u];
+		}
+		for (u = 0; u <= MaxLL; u++)
+			ssPtr->litLengthFreq[u] = 1;
+		for (u = 0; u <= MaxML; u++)
+			ssPtr->matchLengthFreq[u] = 1;
+		for (u = 0; u <= MaxOff; u++)
+			ssPtr->offCodeFreq[u] = 1;
+	} else {
+		ssPtr->matchLengthSum = 0;
+		ssPtr->litLengthSum = 0;
+		ssPtr->offCodeSum = 0;
+		ssPtr->matchSum = 0;
+		ssPtr->litSum = 0;
+
+		for (u = 0; u <= MaxLit; u++) {
+			ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> (ZSTD_FREQ_DIV + 1));
+			ssPtr->litSum += ssPtr->litFreq[u];
+		}
+		for (u = 0; u <= MaxLL; u++) {
+			ssPtr->litLengthFreq[u] = 1 + (ssPtr->litLengthFreq[u] >> (ZSTD_FREQ_DIV + 1));
+			ssPtr->litLengthSum += ssPtr->litLengthFreq[u];
+		}
+		for (u = 0; u <= MaxML; u++) {
+			ssPtr->matchLengthFreq[u] = 1 + (ssPtr->matchLengthFreq[u] >> ZSTD_FREQ_DIV);
+			ssPtr->matchLengthSum += ssPtr->matchLengthFreq[u];
+			ssPtr->matchSum += ssPtr->matchLengthFreq[u] * (u + 3);
+		}
+		ssPtr->matchSum *= ZSTD_LITFREQ_ADD;
+		for (u = 0; u <= MaxOff; u++) {
+			ssPtr->offCodeFreq[u] = 1 + (ssPtr->offCodeFreq[u] >> ZSTD_FREQ_DIV);
+			ssPtr->offCodeSum += ssPtr->offCodeFreq[u];
+		}
+	}
+
+	ZSTD_setLog2Prices(ssPtr);
+}
+
+FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t *ssPtr, U32 litLength, const BYTE *literals)
+{
+	U32 price, u;
+
+	if (ssPtr->staticPrices)
+		return ZSTD_highbit32((U32)litLength + 1) + (litLength * 6);
+
+	if (litLength == 0)
+		return ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[0] + 1);
+
+	/* literals */
+	if (ssPtr->cachedLiterals == literals) {
+		U32 const additional = litLength - ssPtr->cachedLitLength;
+		const BYTE *literals2 = ssPtr->cachedLiterals + ssPtr->cachedLitLength;
+		price = ssPtr->cachedPrice + additional * ssPtr->log2litSum;
+		for (u = 0; u < additional; u++)
+			price -= ZSTD_highbit32(ssPtr->litFreq[literals2[u]] + 1);
+		ssPtr->cachedPrice = price;
+		ssPtr->cachedLitLength = litLength;
+	} else {
+		price = litLength * ssPtr->log2litSum;
+		for (u = 0; u < litLength; u++)
+			price -= ZSTD_highbit32(ssPtr->litFreq[literals[u]] + 1);
+
+		if (litLength >= 12) {
+			ssPtr->cachedLiterals = literals;
+			ssPtr->cachedPrice = price;
+			ssPtr->cachedLitLength = litLength;
+		}
+	}
+
+	/* literal Length */
+	{
+		const BYTE LL_deltaCode = 19;
+		const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
+		price += LL_bits[llCode] + ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[llCode] + 1);
+	}
+
+	return price;
+}
+
+FORCE_INLINE U32 ZSTD_getPrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength, const int ultra)
+{
+	/* offset */
+	U32 price;
+	BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
+
+	if (seqStorePtr->staticPrices)
+		return ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + ZSTD_highbit32((U32)matchLength + 1) + 16 + offCode;
+
+	price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit32(seqStorePtr->offCodeFreq[offCode] + 1);
+	if (!ultra && offCode >= 20)
+		price += (offCode - 19) * 2;
+
+	/* match Length */
+	{
+		const BYTE ML_deltaCode = 36;
+		const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
+		price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit32(seqStorePtr->matchLengthFreq[mlCode] + 1);
+	}
+
+	return price + ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->factor;
+}
+
+ZSTD_STATIC void ZSTD_updatePrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength)
+{
+	U32 u;
+
+	/* literals */
+	seqStorePtr->litSum += litLength * ZSTD_LITFREQ_ADD;
+	for (u = 0; u < litLength; u++)
+		seqStorePtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
+
+	/* literal Length */
+	{
+		const BYTE LL_deltaCode = 19;
+		const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
+		seqStorePtr->litLengthFreq[llCode]++;
+		seqStorePtr->litLengthSum++;
+	}
+
+	/* match offset */
+	{
+		BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
+		seqStorePtr->offCodeSum++;
+		seqStorePtr->offCodeFreq[offCode]++;
+	}
+
+	/* match Length */
+	{
+		const BYTE ML_deltaCode = 36;
+		const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
+		seqStorePtr->matchLengthFreq[mlCode]++;
+		seqStorePtr->matchLengthSum++;
+	}
+
+	ZSTD_setLog2Prices(seqStorePtr);
+}
+
+#define SET_PRICE(pos, mlen_, offset_, litlen_, price_)           \
+	{                                                         \
+		while (last_pos < pos) {                          \
+			opt[last_pos + 1].price = ZSTD_MAX_PRICE; \
+			last_pos++;                               \
+		}                                                 \
+		opt[pos].mlen = mlen_;                            \
+		opt[pos].off = offset_;                           \
+		opt[pos].litlen = litlen_;                        \
+		opt[pos].price = price_;                          \
+	}
+
+/* Update hashTable3 up to ip (excluded)
+   Assumption : always within prefix (i.e. not within extDict) */
+FORCE_INLINE
+U32 ZSTD_insertAndFindFirstIndexHash3(ZSTD_CCtx *zc, const BYTE *ip)
+{
+	U32 *const hashTable3 = zc->hashTable3;
+	U32 const hashLog3 = zc->hashLog3;
+	const BYTE *const base = zc->base;
+	U32 idx = zc->nextToUpdate3;
+	const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
+	const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
+
+	while (idx < target) {
+		hashTable3[ZSTD_hash3Ptr(base + idx, hashLog3)] = idx;
+		idx++;
+	}
+
+	return hashTable3[hash3];
+}
+
+/*-*************************************
+*  Binary Tree search
+***************************************/
+static U32 ZSTD_insertBtAndGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, U32 nbCompares, const U32 mls, U32 extDict,
+					 ZSTD_match_t *matches, const U32 minMatchLen)
+{
+	const BYTE *const base = zc->base;
+	const U32 curr = (U32)(ip - base);
+	const U32 hashLog = zc->params.cParams.hashLog;
+	const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
+	U32 *const hashTable = zc->hashTable;
+	U32 matchIndex = hashTable[h];
+	U32 *const bt = zc->chainTable;
+	const U32 btLog = zc->params.cParams.chainLog - 1;
+	const U32 btMask = (1U << btLog) - 1;
+	size_t commonLengthSmaller = 0, commonLengthLarger = 0;
+	const BYTE *const dictBase = zc->dictBase;
+	const U32 dictLimit = zc->dictLimit;
+	const BYTE *const dictEnd = dictBase + dictLimit;
+	const BYTE *const prefixStart = base + dictLimit;
+	const U32 btLow = btMask >= curr ? 0 : curr - btMask;
+	const U32 windowLow = zc->lowLimit;
+	U32 *smallerPtr = bt + 2 * (curr & btMask);
+	U32 *largerPtr = bt + 2 * (curr & btMask) + 1;
+	U32 matchEndIdx = curr + 8;
+	U32 dummy32; /* to be nullified at the end */
+	U32 mnum = 0;
+
+	const U32 minMatch = (mls == 3) ? 3 : 4;
+	size_t bestLength = minMatchLen - 1;
+
+	if (minMatch == 3) { /* HC3 match finder */
+		U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(zc, ip);
+		if (matchIndex3 > windowLow && (curr - matchIndex3 < (1 << 18))) {
+			const BYTE *match;
+			size_t currMl = 0;
+			if ((!extDict) || matchIndex3 >= dictLimit) {
+				match = base + matchIndex3;
+				if (match[bestLength] == ip[bestLength])
+					currMl = ZSTD_count(ip, match, iLimit);
+			} else {
+				match = dictBase + matchIndex3;
+				if (ZSTD_readMINMATCH(match, MINMATCH) ==
+				    ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
+					currMl = ZSTD_count_2segments(ip + MINMATCH, match + MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
+			}
+
+			/* save best solution */
+			if (currMl > bestLength) {
+				bestLength = currMl;
+				matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex3;
+				matches[mnum].len = (U32)currMl;
+				mnum++;
+				if (currMl > ZSTD_OPT_NUM)
+					goto update;
+				if (ip + currMl == iLimit)
+					goto update; /* best possible, and avoid read overflow*/
+			}
+		}
+	}
+
+	hashTable[h] = curr; /* Update Hash Table */
+
+	while (nbCompares-- && (matchIndex > windowLow)) {
+		U32 *nextPtr = bt + 2 * (matchIndex & btMask);
+		size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
+		const BYTE *match;
+
+		if ((!extDict) || (matchIndex + matchLength >= dictLimit)) {
+			match = base + matchIndex;
+			if (match[matchLength] == ip[matchLength]) {
+				matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iLimit) + 1;
+			}
+		} else {
+			match = dictBase + matchIndex;
+			matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iLimit, dictEnd, prefixStart);
+			if (matchIndex + matchLength >= dictLimit)
+				match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
+		}
+
+		if (matchLength > bestLength) {
+			if (matchLength > matchEndIdx - matchIndex)
+				matchEndIdx = matchIndex + (U32)matchLength;
+			bestLength = matchLength;
+			matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex;
+			matches[mnum].len = (U32)matchLength;
+			mnum++;
+			if (matchLength > ZSTD_OPT_NUM)
+				break;
+			if (ip + matchLength == iLimit) /* equal : no way to know if inf or sup */
+				break;			/* drop, to guarantee consistency (miss a little bit of compression) */
+		}
+
+		if (match[matchLength] < ip[matchLength]) {
+			/* match is smaller than curr */
+			*smallerPtr = matchIndex;	  /* update smaller idx */
+			commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
+			if (matchIndex <= btLow) {
+				smallerPtr = &dummy32;
+				break;
+			}			  /* beyond tree size, stop the search */
+			smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */
+			matchIndex = nextPtr[1];  /* new matchIndex larger than previous (closer to curr) */
+		} else {
+			/* match is larger than curr */
+			*largerPtr = matchIndex;
+			commonLengthLarger = matchLength;
+			if (matchIndex <= btLow) {
+				largerPtr = &dummy32;
+				break;
+			} /* beyond tree size, stop the search */
+			largerPtr = nextPtr;
+			matchIndex = nextPtr[0];
+		}
+	}
+
+	*smallerPtr = *largerPtr = 0;
+
+update:
+	zc->nextToUpdate = (matchEndIdx > curr + 8) ? matchEndIdx - 8 : curr + 1;
+	return mnum;
+}
+
+/** Tree updater, providing best match */
+static U32 ZSTD_BtGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls, ZSTD_match_t *matches,
+				const U32 minMatchLen)
+{
+	if (ip < zc->base + zc->nextToUpdate)
+		return 0; /* skipped area */
+	ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
+	return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
+}
+
+static U32 ZSTD_BtGetAllMatches_selectMLS(ZSTD_CCtx *zc, /* Index table will be updated */
+					  const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
+					  ZSTD_match_t *matches, const U32 minMatchLen)
+{
+	switch (matchLengthSearch) {
+	case 3: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
+	default:
+	case 4: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
+	case 5: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
+	case 7:
+	case 6: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
+	}
+}
+
+/** Tree updater, providing best match */
+static U32 ZSTD_BtGetAllMatches_extDict(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls,
+					ZSTD_match_t *matches, const U32 minMatchLen)
+{
+	if (ip < zc->base + zc->nextToUpdate)
+		return 0; /* skipped area */
+	ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
+	return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
+}
+
+static U32 ZSTD_BtGetAllMatches_selectMLS_extDict(ZSTD_CCtx *zc, /* Index table will be updated */
+						  const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
+						  ZSTD_match_t *matches, const U32 minMatchLen)
+{
+	switch (matchLengthSearch) {
+	case 3: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
+	default:
+	case 4: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
+	case 5: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
+	case 7:
+	case 6: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
+	}
+}
+
+/*-*******************************
+*  Optimal parser
+*********************************/
+FORCE_INLINE
+void ZSTD_compressBlock_opt_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
+{
+	seqStore_t *seqStorePtr = &(ctx->seqStore);
+	const BYTE *const istart = (const BYTE *)src;
+	const BYTE *ip = istart;
+	const BYTE *anchor = istart;
+	const BYTE *const iend = istart + srcSize;
+	const BYTE *const ilimit = iend - 8;
+	const BYTE *const base = ctx->base;
+	const BYTE *const prefixStart = base + ctx->dictLimit;
+
+	const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
+	const U32 sufficient_len = ctx->params.cParams.targetLength;
+	const U32 mls = ctx->params.cParams.searchLength;
+	const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
+
+	ZSTD_optimal_t *opt = seqStorePtr->priceTable;
+	ZSTD_match_t *matches = seqStorePtr->matchTable;
+	const BYTE *inr;
+	U32 offset, rep[ZSTD_REP_NUM];
+
+	/* init */
+	ctx->nextToUpdate3 = ctx->nextToUpdate;
+	ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
+	ip += (ip == prefixStart);
+	{
+		U32 i;
+		for (i = 0; i < ZSTD_REP_NUM; i++)
+			rep[i] = ctx->rep[i];
+	}
+
+	/* Match Loop */
+	while (ip < ilimit) {
+		U32 cur, match_num, last_pos, litlen, price;
+		U32 u, mlen, best_mlen, best_off, litLength;
+		memset(opt, 0, sizeof(ZSTD_optimal_t));
+		last_pos = 0;
+		litlen = (U32)(ip - anchor);
+
+		/* check repCode */
+		{
+			U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
+			for (i = (ip == anchor); i < last_i; i++) {
+				const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
+				if ((repCur > 0) && (repCur < (S32)(ip - prefixStart)) &&
+				    (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
+					mlen = (U32)ZSTD_count(ip + minMatch, ip + minMatch - repCur, iend) + minMatch;
+					if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
+						best_mlen = mlen;
+						best_off = i;
+						cur = 0;
+						last_pos = 1;
+						goto _storeSequence;
+					}
+					best_off = i - (ip == anchor);
+					do {
+						price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+						if (mlen > last_pos || price < opt[mlen].price)
+							SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
+						mlen--;
+					} while (mlen >= minMatch);
+				}
+			}
+		}
+
+		match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
+
+		if (!last_pos && !match_num) {
+			ip++;
+			continue;
+		}
+
+		if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+			best_mlen = matches[match_num - 1].len;
+			best_off = matches[match_num - 1].off;
+			cur = 0;
+			last_pos = 1;
+			goto _storeSequence;
+		}
+
+		/* set prices using matches at position = 0 */
+		best_mlen = (last_pos) ? last_pos : minMatch;
+		for (u = 0; u < match_num; u++) {
+			mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+			best_mlen = matches[u].len;
+			while (mlen <= best_mlen) {
+				price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+				if (mlen > last_pos || price < opt[mlen].price)
+					SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
+				mlen++;
+			}
+		}
+
+		if (last_pos < minMatch) {
+			ip++;
+			continue;
+		}
+
+		/* initialize opt[0] */
+		{
+			U32 i;
+			for (i = 0; i < ZSTD_REP_NUM; i++)
+				opt[0].rep[i] = rep[i];
+		}
+		opt[0].mlen = 1;
+		opt[0].litlen = litlen;
+
+		/* check further positions */
+		for (cur = 1; cur <= last_pos; cur++) {
+			inr = ip + cur;
+
+			if (opt[cur - 1].mlen == 1) {
+				litlen = opt[cur - 1].litlen + 1;
+				if (cur > litlen) {
+					price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
+				} else
+					price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
+			} else {
+				litlen = 1;
+				price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
+			}
+
+			if (cur > last_pos || price <= opt[cur].price)
+				SET_PRICE(cur, 1, 0, litlen, price);
+
+			if (cur == last_pos)
+				break;
+
+			if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
+				continue;
+
+			mlen = opt[cur].mlen;
+			if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
+				opt[cur].rep[2] = opt[cur - mlen].rep[1];
+				opt[cur].rep[1] = opt[cur - mlen].rep[0];
+				opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
+			} else {
+				opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
+				opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
+				opt[cur].rep[0] =
+				    ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
+			}
+
+			best_mlen = minMatch;
+			{
+				U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
+				for (i = (opt[cur].mlen != 1); i < last_i; i++) { /* check rep */
+					const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
+					if ((repCur > 0) && (repCur < (S32)(inr - prefixStart)) &&
+					    (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
+						mlen = (U32)ZSTD_count(inr + minMatch, inr + minMatch - repCur, iend) + minMatch;
+
+						if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
+							best_mlen = mlen;
+							best_off = i;
+							last_pos = cur + 1;
+							goto _storeSequence;
+						}
+
+						best_off = i - (opt[cur].mlen != 1);
+						if (mlen > best_mlen)
+							best_mlen = mlen;
+
+						do {
+							if (opt[cur].mlen == 1) {
+								litlen = opt[cur].litlen;
+								if (cur > litlen) {
+									price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
+															best_off, mlen - MINMATCH, ultra);
+								} else
+									price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+							} else {
+								litlen = 0;
+								price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
+							}
+
+							if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
+								SET_PRICE(cur + mlen, mlen, i, litlen, price);
+							mlen--;
+						} while (mlen >= minMatch);
+					}
+				}
+			}
+
+			match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
+
+			if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+				best_mlen = matches[match_num - 1].len;
+				best_off = matches[match_num - 1].off;
+				last_pos = cur + 1;
+				goto _storeSequence;
+			}
+
+			/* set prices using matches at position = cur */
+			for (u = 0; u < match_num; u++) {
+				mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+				best_mlen = matches[u].len;
+
+				while (mlen <= best_mlen) {
+					if (opt[cur].mlen == 1) {
+						litlen = opt[cur].litlen;
+						if (cur > litlen)
+							price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
+													matches[u].off - 1, mlen - MINMATCH, ultra);
+						else
+							price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+					} else {
+						litlen = 0;
+						price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
+					}
+
+					if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
+						SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
+
+					mlen++;
+				}
+			}
+		}
+
+		best_mlen = opt[last_pos].mlen;
+		best_off = opt[last_pos].off;
+		cur = last_pos - best_mlen;
+
+	/* store sequence */
+_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
+		opt[0].mlen = 1;
+
+		while (1) {
+			mlen = opt[cur].mlen;
+			offset = opt[cur].off;
+			opt[cur].mlen = best_mlen;
+			opt[cur].off = best_off;
+			best_mlen = mlen;
+			best_off = offset;
+			if (mlen > cur)
+				break;
+			cur -= mlen;
+		}
+
+		for (u = 0; u <= last_pos;) {
+			u += opt[u].mlen;
+		}
+
+		for (cur = 0; cur < last_pos;) {
+			mlen = opt[cur].mlen;
+			if (mlen == 1) {
+				ip++;
+				cur++;
+				continue;
+			}
+			offset = opt[cur].off;
+			cur += mlen;
+			litLength = (U32)(ip - anchor);
+
+			if (offset > ZSTD_REP_MOVE_OPT) {
+				rep[2] = rep[1];
+				rep[1] = rep[0];
+				rep[0] = offset - ZSTD_REP_MOVE_OPT;
+				offset--;
+			} else {
+				if (offset != 0) {
+					best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
+					if (offset != 1)
+						rep[2] = rep[1];
+					rep[1] = rep[0];
+					rep[0] = best_off;
+				}
+				if (litLength == 0)
+					offset--;
+			}
+
+			ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+			ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+			anchor = ip = ip + mlen;
+		}
+	} /* for (cur=0; cur < last_pos; ) */
+
+	/* Save reps for next block */
+	{
+		int i;
+		for (i = 0; i < ZSTD_REP_NUM; i++)
+			ctx->repToConfirm[i] = rep[i];
+	}
+
+	/* Last Literals */
+	{
+		size_t const lastLLSize = iend - anchor;
+		memcpy(seqStorePtr->lit, anchor, lastLLSize);
+		seqStorePtr->lit += lastLLSize;
+	}
+}
+
+FORCE_INLINE
+void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
+{
+	seqStore_t *seqStorePtr = &(ctx->seqStore);
+	const BYTE *const istart = (const BYTE *)src;
+	const BYTE *ip = istart;
+	const BYTE *anchor = istart;
+	const BYTE *const iend = istart + srcSize;
+	const BYTE *const ilimit = iend - 8;
+	const BYTE *const base = ctx->base;
+	const U32 lowestIndex = ctx->lowLimit;
+	const U32 dictLimit = ctx->dictLimit;
+	const BYTE *const prefixStart = base + dictLimit;
+	const BYTE *const dictBase = ctx->dictBase;
+	const BYTE *const dictEnd = dictBase + dictLimit;
+
+	const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
+	const U32 sufficient_len = ctx->params.cParams.targetLength;
+	const U32 mls = ctx->params.cParams.searchLength;
+	const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
+
+	ZSTD_optimal_t *opt = seqStorePtr->priceTable;
+	ZSTD_match_t *matches = seqStorePtr->matchTable;
+	const BYTE *inr;
+
+	/* init */
+	U32 offset, rep[ZSTD_REP_NUM];
+	{
+		U32 i;
+		for (i = 0; i < ZSTD_REP_NUM; i++)
+			rep[i] = ctx->rep[i];
+	}
+
+	ctx->nextToUpdate3 = ctx->nextToUpdate;
+	ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
+	ip += (ip == prefixStart);
+
+	/* Match Loop */
+	while (ip < ilimit) {
+		U32 cur, match_num, last_pos, litlen, price;
+		U32 u, mlen, best_mlen, best_off, litLength;
+		U32 curr = (U32)(ip - base);
+		memset(opt, 0, sizeof(ZSTD_optimal_t));
+		last_pos = 0;
+		opt[0].litlen = (U32)(ip - anchor);
+
+		/* check repCode */
+		{
+			U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
+			for (i = (ip == anchor); i < last_i; i++) {
+				const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
+				const U32 repIndex = (U32)(curr - repCur);
+				const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
+				const BYTE *const repMatch = repBase + repIndex;
+				if ((repCur > 0 && repCur <= (S32)curr) &&
+				    (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+				    && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
+					/* repcode detected we should take it */
+					const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
+					mlen = (U32)ZSTD_count_2segments(ip + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
+
+					if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
+						best_mlen = mlen;
+						best_off = i;
+						cur = 0;
+						last_pos = 1;
+						goto _storeSequence;
+					}
+
+					best_off = i - (ip == anchor);
+					litlen = opt[0].litlen;
+					do {
+						price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+						if (mlen > last_pos || price < opt[mlen].price)
+							SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
+						mlen--;
+					} while (mlen >= minMatch);
+				}
+			}
+		}
+
+		match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
+
+		if (!last_pos && !match_num) {
+			ip++;
+			continue;
+		}
+
+		{
+			U32 i;
+			for (i = 0; i < ZSTD_REP_NUM; i++)
+				opt[0].rep[i] = rep[i];
+		}
+		opt[0].mlen = 1;
+
+		if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+			best_mlen = matches[match_num - 1].len;
+			best_off = matches[match_num - 1].off;
+			cur = 0;
+			last_pos = 1;
+			goto _storeSequence;
+		}
+
+		best_mlen = (last_pos) ? last_pos : minMatch;
+
+		/* set prices using matches at position = 0 */
+		for (u = 0; u < match_num; u++) {
+			mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+			best_mlen = matches[u].len;
+			litlen = opt[0].litlen;
+			while (mlen <= best_mlen) {
+				price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+				if (mlen > last_pos || price < opt[mlen].price)
+					SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
+				mlen++;
+			}
+		}
+
+		if (last_pos < minMatch) {
+			ip++;
+			continue;
+		}
+
+		/* check further positions */
+		for (cur = 1; cur <= last_pos; cur++) {
+			inr = ip + cur;
+
+			if (opt[cur - 1].mlen == 1) {
+				litlen = opt[cur - 1].litlen + 1;
+				if (cur > litlen) {
+					price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
+				} else
+					price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
+			} else {
+				litlen = 1;
+				price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
+			}
+
+			if (cur > last_pos || price <= opt[cur].price)
+				SET_PRICE(cur, 1, 0, litlen, price);
+
+			if (cur == last_pos)
+				break;
+
+			if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
+				continue;
+
+			mlen = opt[cur].mlen;
+			if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
+				opt[cur].rep[2] = opt[cur - mlen].rep[1];
+				opt[cur].rep[1] = opt[cur - mlen].rep[0];
+				opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
+			} else {
+				opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
+				opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
+				opt[cur].rep[0] =
+				    ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
+			}
+
+			best_mlen = minMatch;
+			{
+				U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
+				for (i = (mlen != 1); i < last_i; i++) {
+					const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
+					const U32 repIndex = (U32)(curr + cur - repCur);
+					const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
+					const BYTE *const repMatch = repBase + repIndex;
+					if ((repCur > 0 && repCur <= (S32)(curr + cur)) &&
+					    (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
+					    && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
+						/* repcode detected */
+						const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
+						mlen = (U32)ZSTD_count_2segments(inr + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
+
+						if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
+							best_mlen = mlen;
+							best_off = i;
+							last_pos = cur + 1;
+							goto _storeSequence;
+						}
+
+						best_off = i - (opt[cur].mlen != 1);
+						if (mlen > best_mlen)
+							best_mlen = mlen;
+
+						do {
+							if (opt[cur].mlen == 1) {
+								litlen = opt[cur].litlen;
+								if (cur > litlen) {
+									price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
+															best_off, mlen - MINMATCH, ultra);
+								} else
+									price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
+							} else {
+								litlen = 0;
+								price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
+							}
+
+							if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
+								SET_PRICE(cur + mlen, mlen, i, litlen, price);
+							mlen--;
+						} while (mlen >= minMatch);
+					}
+				}
+			}
+
+			match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
+
+			if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
+				best_mlen = matches[match_num - 1].len;
+				best_off = matches[match_num - 1].off;
+				last_pos = cur + 1;
+				goto _storeSequence;
+			}
+
+			/* set prices using matches at position = cur */
+			for (u = 0; u < match_num; u++) {
+				mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
+				best_mlen = matches[u].len;
+
+				while (mlen <= best_mlen) {
+					if (opt[cur].mlen == 1) {
+						litlen = opt[cur].litlen;
+						if (cur > litlen)
+							price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
+													matches[u].off - 1, mlen - MINMATCH, ultra);
+						else
+							price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
+					} else {
+						litlen = 0;
+						price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
+					}
+
+					if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
+						SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
+
+					mlen++;
+				}
+			}
+		} /* for (cur = 1; cur <= last_pos; cur++) */
+
+		best_mlen = opt[last_pos].mlen;
+		best_off = opt[last_pos].off;
+		cur = last_pos - best_mlen;
+
+	/* store sequence */
+_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
+		opt[0].mlen = 1;
+
+		while (1) {
+			mlen = opt[cur].mlen;
+			offset = opt[cur].off;
+			opt[cur].mlen = best_mlen;
+			opt[cur].off = best_off;
+			best_mlen = mlen;
+			best_off = offset;
+			if (mlen > cur)
+				break;
+			cur -= mlen;
+		}
+
+		for (u = 0; u <= last_pos;) {
+			u += opt[u].mlen;
+		}
+
+		for (cur = 0; cur < last_pos;) {
+			mlen = opt[cur].mlen;
+			if (mlen == 1) {
+				ip++;
+				cur++;
+				continue;
+			}
+			offset = opt[cur].off;
+			cur += mlen;
+			litLength = (U32)(ip - anchor);
+
+			if (offset > ZSTD_REP_MOVE_OPT) {
+				rep[2] = rep[1];
+				rep[1] = rep[0];
+				rep[0] = offset - ZSTD_REP_MOVE_OPT;
+				offset--;
+			} else {
+				if (offset != 0) {
+					best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
+					if (offset != 1)
+						rep[2] = rep[1];
+					rep[1] = rep[0];
+					rep[0] = best_off;
+				}
+
+				if (litLength == 0)
+					offset--;
+			}
+
+			ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+			ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
+			anchor = ip = ip + mlen;
+		}
+	} /* for (cur=0; cur < last_pos; ) */
+
+	/* Save reps for next block */
+	{
+		int i;
+		for (i = 0; i < ZSTD_REP_NUM; i++)
+			ctx->repToConfirm[i] = rep[i];
+	}
+
+	/* Last Literals */
+	{
+		size_t lastLLSize = iend - anchor;
+		memcpy(seqStorePtr->lit, anchor, lastLLSize);
+		seqStorePtr->lit += lastLLSize;
+	}
+}
+
+#endif /* ZSTD_OPT_H_91842398743 */
-- 
2.30.2



From a.fatoum at pengutronix.de  Thu Sep 29 23:16:21 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 08:16:21 +0200
Subject: [PATCH] bootm: wrap image_data::dryrun in new bootm_abort helper
Message-ID: <20220930061621.60683-1-a.fatoum@pengutronix.de>

bootm handlers are expected to check the dryrun member just before
shutting down barebox and handing off execution. In future, we may want
to do the same dependent on board code decision, e.g. OTG port is placed
into host mode, then boot proceeds normally, then at the very end,
attached USB drives are checked for an alternate boot method that would
abort the current boot mode. Doing it this way eliminates waiting times
for normal boot compared to the alternative of waiting for a while until
USB drives may be enumerated correctly.

As first step towards enabling this in the future, replace direct
evaluation of image_data::dryrun with the new bootm_abort() helper.

At present, this introduces no functional change, but we may extend
bootm_abort() in future to call board code a supplied abort check
function.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/lib32/bootm.c            | 2 +-
 arch/arm/lib64/armlinux.c         | 2 +-
 arch/arm/mach-omap/omap_generic.c | 2 +-
 arch/kvx/lib/bootm.c              | 2 +-
 arch/mips/lib/bootm.c             | 2 +-
 arch/powerpc/lib/ppclinux.c       | 2 +-
 arch/riscv/lib/bootm.c            | 2 +-
 common/efi/payload/image.c        | 2 +-
 include/bootm.h                   | 5 +++++
 9 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c
index e814593dce43..562837be10bc 100644
--- a/arch/arm/lib32/bootm.c
+++ b/arch/arm/lib32/bootm.c
@@ -324,7 +324,7 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
 		       bootm_arm_security_state_name(state));
 	}
 
-	if (data->dryrun)
+	if (bootm_abort(data))
 		return 0;
 
 	ret = of_overlay_load_firmware();
diff --git a/arch/arm/lib64/armlinux.c b/arch/arm/lib64/armlinux.c
index 8382ffdf1b04..cca26adee30a 100644
--- a/arch/arm/lib64/armlinux.c
+++ b/arch/arm/lib64/armlinux.c
@@ -17,7 +17,7 @@ static int do_bootm_linux(struct image_data *data)
 	if (IS_ERR(fn))
 		return PTR_ERR(fn);
 
-	if (data->dryrun)
+	if (bootm_abort(data))
 		return 0;
 
 	ret = of_overlay_load_firmware();
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index 6bb26a6ef0fa..7992d6c8aaec 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -97,7 +97,7 @@ static int do_bootm_omap_barebox(struct image_data *data)
 	if (!barebox)
 		return -EINVAL;
 
-	if (data->dryrun) {
+	if (bootm_abort(data)) {
 		free(barebox);
 		return 0;
 	}
diff --git a/arch/kvx/lib/bootm.c b/arch/kvx/lib/bootm.c
index 4c77f676ec0b..69e09ab11fc0 100644
--- a/arch/kvx/lib/bootm.c
+++ b/arch/kvx/lib/bootm.c
@@ -27,7 +27,7 @@ static int do_boot_entry(struct image_data *data, boot_func_entry entry,
 
 	printf("starting elf (entry at %p)\n", entry);
 
-	if (data->dryrun)
+	if (bootm_abort(data))
 		return 0;
 
 	ret = of_overlay_load_firmware();
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 655535737ec8..9aa53d0fa966 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -22,7 +22,7 @@ static int do_bootm_barebox(struct image_data *data)
 	if (!barebox)
 		return -EINVAL;
 
-	if (data->dryrun) {
+	if (bootm_abort(data)) {
 		free(barebox);
 		return 0;
 	}
diff --git a/arch/powerpc/lib/ppclinux.c b/arch/powerpc/lib/ppclinux.c
index 9b8404962cea..a50408b6803b 100644
--- a/arch/powerpc/lib/ppclinux.c
+++ b/arch/powerpc/lib/ppclinux.c
@@ -66,7 +66,7 @@ static int do_bootm_linux(struct image_data *data)
 		return -EINVAL;
 	}
 
-	if (data->dryrun)
+	if (bootm_abort(data))
 		return 0;
 
 	ret = of_overlay_load_firmware();
diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index 6984f282be4d..2678bcd985d5 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -16,7 +16,7 @@ static int do_bootm_linux(struct image_data *data)
 	if (IS_ERR(fn))
 		return PTR_ERR(fn);
 
-	if (data->dryrun)
+	if (bootm_abort(data))
 		return 0;
 
 	ret = of_overlay_load_firmware();
diff --git a/common/efi/payload/image.c b/common/efi/payload/image.c
index e63da9ddf06f..36c70131d6b8 100644
--- a/common/efi/payload/image.c
+++ b/common/efi/payload/image.c
@@ -241,7 +241,7 @@ static int do_bootm_efi(struct image_data *data)
 		printf("...\n");
 	}
 
-	if (data->dryrun) {
+	if (bootm_abort(data)) {
 		BS->unload_image(handle);
 		free(boot_header);
 		free(initrd);
diff --git a/include/bootm.h b/include/bootm.h
index 655c5152d97e..4d7eab28c2a9 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -132,6 +132,11 @@ static inline int bootm_verbose(struct image_data *data)
 }
 #endif
 
+static inline int bootm_abort(struct image_data *data)
+{
+	return data->dryrun;
+}
+
 void bootm_data_init_defaults(struct bootm_data *data);
 
 int bootm_load_os(struct image_data *data, unsigned long load_address);
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 04:19:40 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 13:19:40 +0200
Subject: [PATCH master] mci: bcm2835: reset host controller on barebox shutdown
Message-ID: <20220930111940.1323140-1-a.fatoum@pengutronix.de>

We don't usually disable MMC controllers on barebox shutdown, because
they don't DMA on their own, unlike e.g. network controllers.

Booting Linux v5.17.0 on a Raspberry Pi 4 in 32-bit mode still has the
MMC host controller driver complain:

  [   22.464887] mmc1: Got data interrupt 0x00000002 even though no
  			data operation was in progress.

Fix this by resetting the SDHCI once barebox is done with it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/mci/mci-bcm2835.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c
index f092156f9a83..c5b226ba033c 100644
--- a/drivers/mci/mci-bcm2835.c
+++ b/drivers/mci/mci-bcm2835.c
@@ -385,6 +385,8 @@ static int bcm2835_mci_probe(struct device_d *hw_dev)
 	host->sdhci.read32 = bcm2835_sdhci_read32;
 	host->sdhci.write32 = bcm2835_sdhci_write32;
 
+	hw_dev->priv = host;
+
 	mci_of_parse(&host->mci);
 
 	iores = dev_request_mem_resource(hw_dev, 0);
@@ -420,6 +422,15 @@ static int bcm2835_mci_probe(struct device_d *hw_dev)
 	return mci_register(&host->mci);
 }
 
+static void bcm2835_mci_remove(struct device_d *dev)
+{
+	struct bcm2835_mci_host *host = dev->priv;
+
+	sdhci_write32(&host->sdhci,
+		      SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
+		      0x00);
+}
+
 static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = {
 	{
 		.compatible = "brcm,bcm2835-sdhci",
@@ -433,6 +444,7 @@ static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = {
 static struct driver_d bcm2835_mci_driver = {
 	.name = "bcm2835_mci",
 	.probe = bcm2835_mci_probe,
+	.remove = bcm2835_mci_remove,
 	.of_compatible = DRV_OF_COMPAT(bcm2835_mci_compatible),
 };
 
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:51 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:51 +0200
Subject: [PATCH 5/7] imx-bbu-nand-fcb: pass imx_handler further down
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <20220930121553.335796-6-s.hauer@pengutronix.de>

Pass the struct bbu_handler *handler context pointer further down the
road. We'll need that in the next patches. No functional change.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/imx-bbu-nand-fcb.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index f268503f38..002e35bde9 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -843,7 +843,8 @@ out:
  *
  * return: 0 if the FCB/DBBT are valid, a negative error code otherwise
  */
-static int fcb_dbbt_check(struct mtd_info *mtd, int num, struct fcb_block *fcb)
+static int fcb_dbbt_check(struct imx_nand_fcb_bbu_handler *imx_handler,
+			  struct mtd_info *mtd, int num, struct fcb_block *fcb)
 {
 	int ret;
 	struct fcb_block *f;
@@ -885,7 +886,8 @@ out:
  *
  * return: 0 for success or a negative error code otherwise.
  */
-static int imx_bbu_write_fcbs_dbbts(struct mtd_info *mtd, struct fcb_block *fcb)
+static int imx_bbu_write_fcbs_dbbts(struct imx_nand_fcb_bbu_handler *imx_handler,
+				    struct mtd_info *mtd, struct fcb_block *fcb)
 {
 	void *dbbt = NULL;
 	int i, ret, valid = 0;
@@ -928,7 +930,7 @@ static int imx_bbu_write_fcbs_dbbts(struct mtd_info *mtd, struct fcb_block *fcb)
 		if (mtd_peb_is_bad(mtd, i))
 			continue;
 
-		if (!fcb_dbbt_check(mtd, i, fcb)) {
+		if (!fcb_dbbt_check(imx_handler, mtd, i, fcb)) {
 			valid++;
 			pr_info("FCB/DBBT on block %d still valid\n", i);
 			continue;
@@ -1326,7 +1328,7 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
 	 * just written as primary firmware. From now on the new
 	 * firmware will be booted.
 	 */
-	ret = imx_bbu_write_fcbs_dbbts(mtd, fcb);
+	ret = imx_bbu_write_fcbs_dbbts(imx_handler, mtd, fcb);
 	if (ret < 0)
 		goto out;
 
@@ -1347,7 +1349,7 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
 	 */
 	if (ret > 0) {
 		pr_info("New bad blocks detected, writing FCBs/DBBTs again\n");
-		ret = imx_bbu_write_fcbs_dbbts(mtd, fcb);
+		ret = imx_bbu_write_fcbs_dbbts(imx_handler, mtd, fcb);
 		if (ret < 0)
 			goto out;
 	}
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:50 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:50 +0200
Subject: [PATCH 4/7] imx-bbu-nand-fcb: isolate i.MX28 specific parts
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <20220930121553.335796-5-s.hauer@pengutronix.de>

From: Johannes Zink <j.zink at pengutronix.de>

imx28_fcb_create() reads back some parameters from the BCH and GPMI
unlike imx6_fcb_create() which has same parameters hardcoded.

For i.MX7, we will need a mixture of both: Some values are hardcoded
(albeit differently than i.MX6), while some others need be read from the
BCH. In preparation for adding i.MX7 support, move common defines out of
the #ifdef CONFIG_ARCH_IMX28 and prefix constants that are not
applicable to i.MX6 and later with an IMX28_ prefix. No such constants
are currently in use.

Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
---
 common/imx-bbu-nand-fcb.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index bde0b227f8..f268503f38 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -1393,9 +1393,6 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
 	return ret;
 }
 
-#ifdef CONFIG_ARCH_IMX28
-#include <mach/imx28-regs.h>
-
 #define GPMI_TIMING0				0x00000070
 #define	GPMI_TIMING0_ADDRESS_SETUP_MASK			(0xff << 16)
 #define	GPMI_TIMING0_ADDRESS_SETUP_OFFSET		16
@@ -1413,19 +1410,28 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
 #define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
 #define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
 #define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
-#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
-#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
-#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	MX28_BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
+#define	MX28_BCH_FLASHLAYOUT0_ECC0_OFFSET		12
+#define	BCH_FLASHLAYOUT0_ECC0_MASK			(0x1f << 11)
+#define	BCH_FLASHLAYOUT0_ECC0_OFFSET			11
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0x3ff
+#define	MX28_BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
 #define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
 
 #define BCH_FLASH0LAYOUT1			0x00000090
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
-#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
-#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
-#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_ECCN_MASK			(0x1f << 11)
+#define	BCH_FLASHLAYOUT1_ECCN_OFFSET			11
+#define	MX28_BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
+#define	MX28_BCH_FLASHLAYOUT1_ECCN_OFFSET		12
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0x3ff
+#define	MX28_BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
 #define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
 
+#ifdef CONFIG_ARCH_IMX28
+#include <mach/imx28-regs.h>
+
 static void imx28_fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
 		struct fcb_block *fcb, struct mtd_info *mtd)
 {
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:46 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:46 +0200
Subject: [PATCH 0/7] Add i.MX7 NAND boot support
Message-ID: <20220930121553.335796-1-s.hauer@pengutronix.de>

NAND boot on i.MX7 is the same as on i.MX6, just a little different.
This series adds a barebox update handler to allow writing barebox
to NAND flash.

Sascha

Johannes Zink (4):
  mtd: nand-mxs: refactor flash layout configuration
  mtd: nand-mxs: add i.MX7 FCB write support
  imx-bbu-nand-fcb: isolate i.MX28 specific parts
  imx-bbu-nand-fcb: extend for i.MX7 support

Sascha Hauer (3):
  mtd: nand-mxs: Factor out a bch read function
  imx-bbu-nand-fcb: pass imx_handler further down
  imx-bbu-nand-fcb: add fcb_read/fcb_write function hooks

 arch/arm/mach-imx/include/mach/imx7-regs.h |   3 +
 common/Kconfig                             |   2 +-
 common/imx-bbu-nand-fcb.c                  | 267 ++++++++++++++----
 drivers/mtd/nand/nand_mxs.c                | 297 ++++++++++++++++++---
 include/bbu.h                              |   5 +
 include/linux/mtd/nand_mxs.h               |   4 +
 include/soc/imx/imx-nand-bcb.h             |  11 +
 7 files changed, 492 insertions(+), 97 deletions(-)

-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:47 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:47 +0200
Subject: [PATCH 1/7] mtd: nand-mxs: refactor flash layout configuration
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <20220930121553.335796-2-s.hauer@pengutronix.de>

From: Johannes Zink <j.zink at pengutronix.de>

No functional change.
---
 drivers/mtd/nand/nand_mxs.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index 8991758e2b..8fc5105d98 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -732,25 +732,24 @@ static void mxs_nand_config_bch(struct nand_chip *chip, int readlen)
 	struct mxs_nand_info *nand_info = chip->priv;
 	int chunk_size;
 	void __iomem *bch_regs = nand_info->bch_base;
+	u32 fl0, fl1;
 
 	if (mxs_nand_is_imx6(nand_info))
 		chunk_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE >> 2;
 	else
 		chunk_size = MXS_NAND_CHUNK_DATA_CHUNK_SIZE;
 
-	writel((mxs_nand_ecc_chunk_cnt(readlen) - 1)
-			<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET |
-		MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET |
-		(chip->ecc.strength >> 1)
-			<< IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET |
-		chunk_size,
-		bch_regs + BCH_FLASH0LAYOUT0);
-
-	writel(readlen	<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET |
-		(chip->ecc.strength >> 1)
-			<< IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET |
-		chunk_size,
-		bch_regs + BCH_FLASH0LAYOUT1);
+	fl0 = (mxs_nand_ecc_chunk_cnt(readlen) - 1)
+			<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	fl0 |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	fl0 |= (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	fl0 |= chunk_size;
+	writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
+
+	fl1 = readlen << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	fl1 |= (chip->ecc.strength >> 1) << IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	fl1 |= chunk_size;
+	writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
 }
 
 /*
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:48 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:48 +0200
Subject: [PATCH 2/7] mtd: nand-mxs: Factor out a bch read function
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <20220930121553.335796-3-s.hauer@pengutronix.de>

We can reuse setting up the DMA descriptors for reading the FCBs in
upcoming i.MX7 FCB support. Factor out a function for it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/mtd/nand/nand_mxs.c | 67 ++++++++++++++++++++++---------------
 1 file changed, 40 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index 8fc5105d98..1d0a38dc9e 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -752,31 +752,11 @@ static void mxs_nand_config_bch(struct nand_chip *chip, int readlen)
 	writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
 }
 
-/*
- * Read a page from NAND.
- */
-static int __mxs_nand_ecc_read_page(struct nand_chip *chip,
-					uint8_t *buf, int oob_required, int page,
-					int readlen)
+static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtotal)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct mxs_nand_info *nand_info = chip->priv;
 	struct mxs_dma_desc *d;
-	uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip;
-	uint32_t corrected = 0, failed = 0;
-	uint8_t	*status;
-	unsigned int  max_bitflips = 0;
-	int i, ret, readtotal, nchunks;
-
-	nand_read_page_op(chip, page, 0, NULL, 0);
-
-	readlen = roundup(readlen, MXS_NAND_CHUNK_DATA_CHUNK_SIZE);
-	nchunks = mxs_nand_ecc_chunk_cnt(readlen);
-	readtotal =  MXS_NAND_METADATA_SIZE;
-	readtotal += MXS_NAND_CHUNK_DATA_CHUNK_SIZE * nchunks;
-	readtotal += DIV_ROUND_UP(13 * chip->ecc.strength * nchunks, 8);
-
-	mxs_nand_config_bch(chip, readtotal);
+	int ret;
 
 	/* Compile the DMA descriptor - wait for ready. */
 	d = mxs_nand_get_dma_desc(nand_info);
@@ -853,16 +833,49 @@ static int __mxs_nand_ecc_read_page(struct nand_chip *chip,
 	/* Execute the DMA chain. */
 	ret = mxs_dma_go(channel);
 	if (ret) {
-		printf("MXS NAND: DMA read error (ecc)\n");
-		goto rtn;
+		dev_err(nand_info->dev, "MXS NAND: DMA read error (ecc)\n");
+		goto out;
 	}
 
 	ret = mxs_nand_wait_for_bch_complete(nand_info);
 	if (ret) {
-		printf("MXS NAND: BCH read timeout\n");
-		goto rtn;
+		dev_err(nand_info->dev, "MXS NAND: BCH read timeout\n");
+		goto out;
 	}
 
+out:
+	mxs_nand_return_dma_descs(nand_info);
+
+	return ret;
+}
+
+/*
+ * Read a page from NAND.
+ */
+static int __mxs_nand_ecc_read_page(struct nand_chip *chip,
+					uint8_t *buf, int oob_required, int page,
+					int readlen)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mxs_nand_info *nand_info = chip->priv;
+	uint32_t channel = nand_info->dma_channel_base + nand_info->cur_chip;
+	uint32_t corrected = 0, failed = 0;
+	uint8_t	*status;
+	unsigned int  max_bitflips = 0;
+	int i, ret, readtotal, nchunks;
+
+	nand_read_page_op(chip, page, 0, NULL, 0);
+
+	readlen = roundup(readlen, MXS_NAND_CHUNK_DATA_CHUNK_SIZE);
+	nchunks = mxs_nand_ecc_chunk_cnt(readlen);
+	readtotal =  MXS_NAND_METADATA_SIZE;
+	readtotal += MXS_NAND_CHUNK_DATA_CHUNK_SIZE * nchunks;
+	readtotal += DIV_ROUND_UP(13 * chip->ecc.strength * nchunks, 8);
+
+	mxs_nand_config_bch(chip, readtotal);
+
+	mxs_nand_do_bch_read(chip, channel, readtotal);
+
 	/* Read DMA completed, now do the mark swapping. */
 	mxs_nand_swap_block_mark(chip, nand_info->data_buf, nand_info->oob_buf);
 
@@ -942,7 +955,7 @@ static int __mxs_nand_ecc_read_page(struct nand_chip *chip,
 	chip->oob_poi[0] = nand_info->oob_buf[0];
 
 	ret = 0;
-rtn:
+
 	mxs_nand_return_dma_descs(nand_info);
 
 	mxs_nand_config_bch(chip, mtd->writesize + mtd->oobsize);
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:53 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:53 +0200
Subject: [PATCH 7/7] imx-bbu-nand-fcb: extend for i.MX7 support
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <20220930121553.335796-8-s.hauer@pengutronix.de>

From: Johannes Zink <j.zink at pengutronix.de>

This adds a barebox update handler for i.MX7 NAND

Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/mach-imx/include/mach/imx7-regs.h |  3 +
 common/Kconfig                             |  2 +-
 common/imx-bbu-nand-fcb.c                  | 91 ++++++++++++++++++++--
 include/bbu.h                              |  5 ++
 4 files changed, 94 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-imx/include/mach/imx7-regs.h b/arch/arm/mach-imx/include/mach/imx7-regs.h
index f116916717..1ee7d86e0e 100644
--- a/arch/arm/mach-imx/include/mach/imx7-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx7-regs.h
@@ -118,6 +118,9 @@
 #define MX7_ENET1_BASE_ADDR		(MX7_AIPS3_BASE_ADDR + 0x3E0000)
 #define MX7_ENET2_BASE_ADDR		(MX7_AIPS3_BASE_ADDR + 0x3F0000)
 
+#define MX7_GPMI_BASE			0x33002000
+#define MX7_BCH_BASE			0x33004000
+
 #define MX7_DDR_BASE_ADDR		0x80000000
 
 #endif /* __MACH_IMX7_REGS_H */
diff --git a/common/Kconfig b/common/Kconfig
index 43dd92b08a..350e6aeea7 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -78,7 +78,7 @@ config ARCH_DMA_ADDR_T_64BIT
 
 config BAREBOX_UPDATE_IMX_NAND_FCB
 	bool
-	depends on ARCH_IMX6 || ARCH_IMX28
+	depends on ARCH_IMX7 || ARCH_IMX6 || ARCH_IMX28
 	depends on BAREBOX_UPDATE
 	depends on MTD_WRITE
 	depends on NAND_MXS
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 5d4841a554..63c81e4ed6 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -27,16 +27,16 @@
 #include <mtd/mtd-peb.h>
 #include <soc/imx/imx-nand-bcb.h>
 
-#ifdef CONFIG_ARCH_IMX6
-#include <mach/imx6.h>
+#ifdef CONFIG_ARCH_IMX28
 static inline int fcb_is_bch_encoded(void)
 {
-       return cpu_is_mx6ul() || cpu_is_mx6ull();
+       return 0;
 }
 #else
+#include <mach/imx6.h>
 static inline int fcb_is_bch_encoded(void)
 {
-       return 0;
+       return cpu_is_mx6ul() || cpu_is_mx6ull();
 }
 #endif
 
@@ -517,6 +517,9 @@ static int fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
 
 	imx_handler->fcb_create(imx_handler, fcb, mtd);
 
+	fcb->DISBBM = 0;
+	fcb->disbbm_search = 0;
+
 	fcb->Checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
 
 	return 0;
@@ -1482,9 +1485,11 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
 #define	MX28_BCH_FLASHLAYOUT0_ECC0_OFFSET		12
 #define	BCH_FLASHLAYOUT0_ECC0_MASK			(0x1f << 11)
 #define	BCH_FLASHLAYOUT0_ECC0_OFFSET			11
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1_MASK		BIT(10)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET		10
 #define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0x3ff
-#define	MX28_BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
 #define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+#define	MX28_BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
 
 #define BCH_FLASH0LAYOUT1			0x00000090
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
@@ -1493,9 +1498,11 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
 #define	BCH_FLASHLAYOUT1_ECCN_OFFSET			11
 #define	MX28_BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
 #define	MX28_BCH_FLASHLAYOUT1_ECCN_OFFSET		12
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK		BIT(10)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET		10
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
 #define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0x3ff
 #define	MX28_BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
-#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
 
 #ifdef CONFIG_ARCH_IMX28
 #include <mach/imx28-regs.h>
@@ -1546,3 +1553,75 @@ int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
 	return ret;
 }
 #endif
+
+#ifdef CONFIG_ARCH_IMX7
+#include <mach/imx7-regs.h>
+
+static void imx7_fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+		struct fcb_block *fcb, struct mtd_info *mtd)
+{
+	void __iomem *bch_regs = IOMEM(MX7_BCH_BASE);
+	u32 fl0, fl1;
+
+	/* Also hardcoded in kobs-ng */
+	fcb->DataSetup = 10;
+	fcb->DataHold = 7;
+	fcb->AddressSetup = 15;
+	fcb->DSAMPLE_TIME = 6;
+
+	fl0 = readl(bch_regs + BCH_FLASH0LAYOUT0);
+	fcb->MetadataBytes = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+	fcb->NumEccBlocksPerPage = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS);
+
+	fl1 = readl(bch_regs + BCH_FLASH0LAYOUT1);
+	fcb->EccBlock0Size = 4 * BF_VAL(fl1, BCH_FLASHLAYOUT0_DATA0_SIZE);
+	fcb->EccBlock0EccType = BF_VAL(fl1, BCH_FLASHLAYOUT0_ECC0);
+	fcb->EccBlockNSize = 4 * BF_VAL(fl1, BCH_FLASHLAYOUT1_DATAN_SIZE);
+	fcb->EccBlockNEccType = BF_VAL(fl1, BCH_FLASHLAYOUT1_ECCN);
+	fcb->BCHType = BF_VAL(fl1, BCH_FLASHLAYOUT1_GF13_0_GF14_1);
+}
+
+static int imx7_fcb_read(struct mtd_info *mtd, int block, struct fcb_block **retfcb)
+{
+	struct fcb_block *fcb = xzalloc(mtd->writesize);
+	int ret;
+
+	ret = mxs_nand_read_fcb_bch62(block, fcb, sizeof(*fcb));
+	if (ret)
+		free(fcb);
+	else
+		*retfcb = fcb;
+
+	return ret;
+}
+
+static int imx7_fcb_write(struct mtd_info *mtd, int block, struct fcb_block *fcb)
+{
+	return mxs_nand_write_fcb_bch62(block, fcb, sizeof(*fcb));
+}
+
+int imx7_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+	struct imx_nand_fcb_bbu_handler *imx_handler;
+	struct bbu_handler *handler;
+	int ret;
+
+	imx_handler = xzalloc(sizeof(*imx_handler));
+	imx_handler->fcb_create = imx7_fcb_create;
+	imx_handler->fcb_read = imx7_fcb_read;
+	imx_handler->fcb_write = imx7_fcb_write;
+	imx_handler->filetype = filetype_arm_barebox;
+
+	handler = &imx_handler->handler;
+	handler->devicefile = "nand0.barebox";
+	handler->name = name;
+	handler->flags = flags | BBU_HANDLER_CAN_REFRESH;
+	handler->handler = imx_bbu_nand_update;
+
+	ret = bbu_register_handler(handler);
+	if (ret)
+		free(handler);
+
+	return ret;
+}
+#endif
diff --git a/include/bbu.h b/include/bbu.h
index 2dad26a127..cec7e22d4d 100644
--- a/include/bbu.h
+++ b/include/bbu.h
@@ -88,12 +88,17 @@ static inline void bbu_append_handlers_to_file_list(struct file_list *files)
 
 #if defined(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB)
 int imx6_bbu_nand_register_handler(const char *name, unsigned long flags);
+int imx7_bbu_nand_register_handler(const char *name, unsigned long flags);
 int imx28_bbu_nand_register_handler(const char *name, unsigned long flags);
 #else
 static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
 {
 	return -ENOSYS;
 }
+static inline int imx7_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+	return -ENOSYS;
+}
 static inline int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
 {
 	return -ENOSYS;
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:52 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:52 +0200
Subject: [PATCH 6/7] imx-bbu-nand-fcb: add fcb_read/fcb_write function hooks
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <20220930121553.335796-7-s.hauer@pengutronix.de>

Reading the FCB on i.MX7 needs special tweaks. As we already have two
different variants of how the the FCB is read/written already, make
function hooks from it.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/imx-bbu-nand-fcb.c | 144 ++++++++++++++++++++++++++++----------
 1 file changed, 106 insertions(+), 38 deletions(-)

diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 002e35bde9..5d4841a554 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -45,6 +45,8 @@ struct imx_nand_fcb_bbu_handler {
 
 	void (*fcb_create)(struct imx_nand_fcb_bbu_handler *imx_handler,
 		struct fcb_block *fcb, struct mtd_info *mtd);
+	int (*fcb_read)(struct mtd_info *mtd, int block, struct fcb_block **retfcb);
+	int (*fcb_write)(struct mtd_info *mtd, int block, struct fcb_block *fcb);
 	enum filetype filetype;
 };
 
@@ -123,7 +125,7 @@ static void encode_bch_ecc(void *buf, struct fcb_block *fcb, int eccbits)
 	free_bch(bch);
 }
 
-static struct fcb_block *read_fcb_bch(void *rawpage, int eccbits)
+static struct fcb_block *fcb_decode_bch(void *rawpage, int eccbits)
 {
 	int i, j, ret, errbit, m = 13;
 	int blocksize = 128;
@@ -227,7 +229,7 @@ static uint32_t calc_chksum(void *buf, size_t size)
 	return ~chksum;
 }
 
-static struct fcb_block *read_fcb_hamming_13_8(void *rawpage)
+static struct fcb_block *fcb_decode_hamming_13_8(void *rawpage)
 {
 	int i;
 	int bitflips = 0, bit_to_flip;
@@ -367,7 +369,7 @@ static ssize_t raw_write_page(struct mtd_info *mtd, void *buf, loff_t offset)
         return ret;
 }
 
-static int read_fcb(struct mtd_info *mtd, int num, struct fcb_block **retfcb)
+static int fcb_read_hamming_13_8(struct mtd_info *mtd, int block, struct fcb_block **retfcb)
 {
 	int ret;
 	struct fcb_block *fcb;
@@ -377,19 +379,71 @@ static int read_fcb(struct mtd_info *mtd, int num, struct fcb_block **retfcb)
 
 	rawpage = xmalloc(mtd->writesize + mtd->oobsize);
 
-	ret = raw_read_page(mtd, rawpage, mtd->erasesize * num);
+	ret = raw_read_page(mtd, rawpage, mtd->erasesize * block);
 	if (ret) {
-		pr_err("Cannot read block %d\n", num);
+		pr_err("Cannot read block %d\n", block);
 		goto err;
 	}
 
-	if (fcb_is_bch_encoded())
-		fcb = read_fcb_bch(rawpage, 40);
-	else
-		fcb = read_fcb_hamming_13_8(rawpage);
+	fcb = fcb_decode_hamming_13_8(rawpage);
+	if (IS_ERR(fcb)) {
+		pr_err("Cannot decode fcb on block %d\n", block);
+		ret = PTR_ERR(fcb);
+		goto err;
+	}
+
+	*retfcb = fcb;
+	ret = 0;
+err:
+	free(rawpage);
+
+	return ret;
+}
+
+static int fcb_write_hamming_13_8(struct mtd_info *mtd, int block, struct fcb_block *fcb)
+{
+	void *fcb_raw_page = xzalloc(mtd->writesize + mtd->oobsize);
+	int ret;
+
+	memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
+
+	/*
+	 * Set the first and second byte of OOB data to 0xFF, not 0x00. These
+	 * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
+	 * the FCB is mostly written to the first page in a block, a scan for
+	 * factory bad blocks will detect these blocks as bad, e.g. when
+	 * function nand_scan_bbt() is executed to build a new bad block table.
+	 */
+	memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
+
+	encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
+
+	ret = raw_write_page(mtd, fcb_raw_page, block * mtd->erasesize);
+
+	free(fcb_raw_page);
+
+	return ret;
+}
 
+static int fcb_read_bch(struct mtd_info *mtd, int block, struct fcb_block **retfcb)
+{
+	int ret;
+	struct fcb_block *fcb;
+	void *rawpage;
+
+	*retfcb = NULL;
+
+	rawpage = xmalloc(mtd->writesize + mtd->oobsize);
+
+	ret = raw_read_page(mtd, rawpage, mtd->erasesize * block);
+	if (ret) {
+		pr_err("Cannot read block %d\n", block);
+		goto err;
+	}
+
+	fcb = fcb_decode_bch(rawpage, 40);
 	if (IS_ERR(fcb)) {
-		pr_err("Cannot read fcb on block %d\n", num);
+		pr_err("Cannot decode fcb on block %d\n", block);
 		ret = PTR_ERR(fcb);
 		goto err;
 	}
@@ -402,6 +456,31 @@ err:
 	return ret;
 }
 
+static int fcb_write_bch(struct mtd_info *mtd, int block, struct fcb_block *fcb)
+{
+	void *fcb_raw_page = xzalloc(mtd->writesize + mtd->oobsize);
+	int ret;
+
+	/* 40 bit BCH, for i.MX6UL(L) */
+	encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
+
+	/*
+	 * Set the first and second byte of OOB data to 0xFF, not 0x00. These
+	 * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
+	 * the FCB is mostly written to the first page in a block, a scan for
+	 * factory bad blocks will detect these blocks as bad, e.g. when
+	 * function nand_scan_bbt() is executed to build a new bad block table.
+	 */
+	memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
+
+	ret = raw_write_page(mtd, fcb_raw_page, block * mtd->erasesize);
+
+	free(fcb_raw_page);
+
+	return ret;
+}
+
+
 static int fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
 		struct fcb_block *fcb, struct mtd_info *mtd)
 {
@@ -651,7 +730,7 @@ static void imx28_dbbt_create(struct dbbt_block *dbbt, int num_bad_blocks)
  * imx_bbu_write_fcb - Write FCB and DBBT raw data to the device
  * @mtd: The mtd Nand device
  * @block: The block to write to
- * @fcb_raw_page: The raw FCB data
+ * @fcb: FCB
  * @dbbt_data_page: The DBBT data
  *
  * This function writes the FCB/DBBT data to the block given in @block
@@ -660,7 +739,8 @@ static void imx28_dbbt_create(struct dbbt_block *dbbt, int num_bad_blocks)
  *
  * return: 0 on success or a negative error code otherwise.
  */
-static int imx_bbu_write_fcb(struct mtd_info *mtd, int block, void *fcb_raw_page,
+static int imx_bbu_write_fcb(struct imx_nand_fcb_bbu_handler *imx_handler,
+			     struct mtd_info *mtd, int block, struct fcb_block *fcb,
 			     void *dbbt_data_page)
 {
 	struct dbbt_block *dbbt;
@@ -682,7 +762,7 @@ again:
 	if (ret)
 		return ret;
 
-	ret = raw_write_page(mtd, fcb_raw_page, block * mtd->erasesize);
+	ret = imx_handler->fcb_write(mtd, block, fcb);
 	if (ret) {
 		pr_err("Writing FCB on block %d failed with %s\n",
 		       block, strerror(-ret));
@@ -850,7 +930,7 @@ static int fcb_dbbt_check(struct imx_nand_fcb_bbu_handler *imx_handler,
 	struct fcb_block *f;
 	int pages_per_block = mtd->erasesize / mtd->writesize;
 
-	ret = read_fcb(mtd, num, &f);
+	ret = imx_handler->fcb_read(mtd, num, &f);
 	if (ret)
 		return ret;
 
@@ -891,7 +971,6 @@ static int imx_bbu_write_fcbs_dbbts(struct imx_nand_fcb_bbu_handler *imx_handler
 {
 	void *dbbt = NULL;
 	int i, ret, valid = 0;
-	void *fcb_raw_page;
 
 	/*
 	 * The DBBT search start page is configurable in the FCB block.
@@ -901,28 +980,8 @@ static int imx_bbu_write_fcbs_dbbts(struct imx_nand_fcb_bbu_handler *imx_handler
 	if (fcb->DBBTSearchAreaStartAddress != 1)
 		return -EINVAL;
 
-	fcb_raw_page = xzalloc(mtd->writesize + mtd->oobsize);
-
-	if (fcb_is_bch_encoded()) {
-		/* 40 bit BCH, for i.MX6UL(L) */
-		encode_bch_ecc(fcb_raw_page + 32, fcb, 40);
-	} else {
-		memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
-		encode_hamming_13_8(fcb_raw_page + 12,
-				    fcb_raw_page + 12 + 512, 512);
-	}
-
 	dbbt = dbbt_data_create(mtd);
 
-	/*
-	 * Set the first and second byte of OOB data to 0xFF, not 0x00. These
-	 * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
-	 * the FCB is mostly written to the first page in a block, a scan for
-	 * factory bad blocks will detect these blocks as bad, e.g. when
-	 * function nand_scan_bbt() is executed to build a new bad block table.
-	 */
-	memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
-
 	pr_info("Writing FCBs/DBBTs with primary/secondary Firmwares at pages %d/%d\n",
 		fcb->Firmware1_startingPage, fcb->Firmware2_startingPage);
 
@@ -938,14 +997,13 @@ static int imx_bbu_write_fcbs_dbbts(struct imx_nand_fcb_bbu_handler *imx_handler
 
 		pr_info("Writing FCB/DBBT on block %d\n", i);
 
-		ret = imx_bbu_write_fcb(mtd, i, fcb_raw_page, dbbt);
+		ret = imx_bbu_write_fcb(imx_handler, mtd, i, fcb, dbbt);
 		if (ret)
 			pr_err("Writing FCB/DBBT %d failed with: %s\n", i, strerror(-ret));
 		else
 			valid++;
 	}
 
-	free(fcb_raw_page);
 	free(dbbt);
 
 	if (!valid)
@@ -1185,7 +1243,7 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
 	}
 
 	for (i = 0; i < 4; i++) {
-		read_fcb(mtd, i, &fcb);
+		imx_handler->fcb_read(mtd, i, &fcb);
 		if (fcb)
 			break;
 	}
@@ -1382,6 +1440,14 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
 	imx_handler->fcb_create = imx6_fcb_create;
 	imx_handler->filetype = filetype_arm_barebox;
 
+	if (fcb_is_bch_encoded()) {
+		imx_handler->fcb_read = fcb_read_bch;
+		imx_handler->fcb_write = fcb_write_bch;
+	} else {
+		imx_handler->fcb_read = fcb_read_hamming_13_8;
+		imx_handler->fcb_write = fcb_write_hamming_13_8;
+	}
+
 	handler = &imx_handler->handler;
 	handler->devicefile = "nand0.barebox";
 	handler->name = name;
@@ -1462,6 +1528,8 @@ int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
 
 	imx_handler = xzalloc(sizeof(*imx_handler));
 	imx_handler->fcb_create = imx28_fcb_create;
+	imx_handler->fcb_read = fcb_read_hamming_13_8;
+	imx_handler->fcb_write = fcb_write_hamming_13_8;
 
 	imx_handler->filetype = filetype_mxs_bootstream;
 
-- 
2.30.2



From s.hauer at pengutronix.de  Fri Sep 30 05:15:49 2022
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:15:49 +0200
Subject: [PATCH 3/7] mtd: nand-mxs: add i.MX7 FCB write support
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <20220930121553.335796-4-s.hauer@pengutronix.de>

From: Johannes Zink <j.zink at pengutronix.de>

The FCB on the i.MX7 is written in BCH62 mode and with randomizer
enabled. This needs special FCB read/write functions. Add them to the
driver.

Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/mtd/nand/nand_mxs.c    | 209 ++++++++++++++++++++++++++++++++-
 include/linux/mtd/nand_mxs.h   |   4 +
 include/soc/imx/imx-nand-bcb.h |  11 ++
 3 files changed, 222 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index 1d0a38dc9e..5faa17a4bd 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -108,6 +108,10 @@
 #define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
 #define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
 #define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define GPMI_ECCCTRL_RANDOMIZER_ENABLE                  (1 << 11)
+#define GPMI_ECCCTRL_RANDOMIZER_TYPE0                   0
+#define GPMI_ECCCTRL_RANDOMIZER_TYPE1                   (1 << 9)
+#define GPMI_ECCCTRL_RANDOMIZER_TYPE2                   (2 << 9)
 #define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
 #define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
 #define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
@@ -138,6 +142,9 @@
 #define	BCH_FLASHLAYOUT0_ECC0_MASK			(0xf << 12)
 #define	BCH_FLASHLAYOUT0_ECC0_OFFSET			12
 #define	IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET		11
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1_MASK		BIT(10)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET		10
 
 #define BCH_FLASH0LAYOUT1			0x00000090
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
@@ -145,6 +152,9 @@
 #define	BCH_FLASHLAYOUT1_ECCN_MASK			(0xf << 12)
 #define	BCH_FLASHLAYOUT1_ECCN_OFFSET			12
 #define	IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET		11
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK		BIT(10)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET		10
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
 
 #define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
 
@@ -752,7 +762,8 @@ static void mxs_nand_config_bch(struct nand_chip *chip, int readlen)
 	writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
 }
 
-static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtotal)
+static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtotal,
+				bool randomizer, int page)
 {
 	struct mxs_nand_info *nand_info = chip->priv;
 	struct mxs_dma_desc *d;
@@ -798,6 +809,12 @@ static int mxs_nand_do_bch_read(struct nand_chip *chip, int channel, int readtot
 	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
 	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
 
+	if (randomizer) {
+		d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
+				       GPMI_ECCCTRL_RANDOMIZER_TYPE2;
+		d->cmd.pio_words[3] |= (page % 256) << 16;
+	}
+
 	mxs_dma_desc_append(channel, d);
 
 	/* Compile the DMA descriptor - disable the BCH block. */
@@ -874,7 +891,7 @@ static int __mxs_nand_ecc_read_page(struct nand_chip *chip,
 
 	mxs_nand_config_bch(chip, readtotal);
 
-	mxs_nand_do_bch_read(chip, channel, readtotal);
+	mxs_nand_do_bch_read(chip, channel, readtotal, false, page);
 
 	/* Read DMA completed, now do the mark swapping. */
 	mxs_nand_swap_block_mark(chip, nand_info->data_buf, nand_info->oob_buf);
@@ -1247,6 +1264,194 @@ static int mxs_nand_block_markbad(struct nand_chip *chip , loff_t ofs)
 	return 0;
 }
 
+#define BCH62_WRITESIZE		1024
+#define BCH62_OOBSIZE		838
+#define BCH62_PAGESIZE		(BCH62_WRITESIZE + BCH62_OOBSIZE)
+
+static void mxs_nand_mode_fcb_62bit(struct mxs_nand_info *nand_info)
+{
+	void __iomem *bch_regs;
+	u32 fl0, fl1;
+
+	bch_regs = nand_info->bch_base;
+
+	/* 8 ecc_chunks */
+	fl0 = 7 << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	/* 32 bytes for metadata */
+	fl0 |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	/* using ECC62 level to be performed */
+	fl0 |= 0x1F << IMX6_BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	/* 0x20 * 4 bytes of the data0 block */
+	fl0 |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
+	fl0 |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
+	writel(fl0, bch_regs + BCH_FLASH0LAYOUT0);
+
+	/* 1024 for data + 838 for OOB */
+	fl1 = BCH62_PAGESIZE << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	/* using ECC62 level to be performed */
+	fl1 |= 0x1f << IMX6_BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	/* 0x20 * 4 bytes of the data0 block */
+	fl1 |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
+	fl1 |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
+	writel(fl1, bch_regs + BCH_FLASH0LAYOUT1);
+}
+
+int mxs_nand_read_fcb_bch62(unsigned int block, void *buf, size_t size)
+{
+	struct nand_chip *chip;
+	struct mxs_nand_info *nand_info;
+	struct mtd_info *mtd = mxs_nand_mtd;
+	int ret;
+	int page;
+	int flips = 0;
+	uint8_t	*status;
+	int i;
+
+	if (!mtd)
+		return -ENODEV;
+
+	chip = mtd_to_nand(mtd);
+	nand_info = chip->priv;
+
+	nand_select_target(chip, 0);
+
+	page = block * (mtd->erasesize / mtd->writesize);
+
+	mxs_nand_mode_fcb_62bit(nand_info);
+
+	nand_read_page_op(chip, page, 0, NULL, 0);
+
+	ret = mxs_nand_do_bch_read(chip, 0, BCH62_PAGESIZE, true, page);
+	if (ret)
+		goto out;
+
+	/* Read DMA completed, now do the mark swapping. */
+	mxs_nand_swap_block_mark(chip, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = nand_info->oob_buf + 32;
+
+	for (i = 0; i < 8; i++) {
+		switch (status[i]) {
+		case 0x0:
+			break;
+		case 0xff:
+			/*
+			 * A status of 0xff means the chunk is erased, but due to
+			 * the randomizer we see this as random data. Explicitly
+			 * memset it.
+			 */
+			memset(nand_info->data_buf + 0x80 * i, 0xff, 0x80);
+			break;
+		case 0xfe:
+			ret = -EBADMSG;
+			goto out;
+		default:
+			flips += status[0];
+			break;
+		}
+	}
+
+	memcpy(buf, nand_info->data_buf, size);
+
+out:
+	mxs_nand_config_bch(chip, mtd->writesize + mtd->oobsize);
+	nand_deselect_target(chip);
+
+	return ret;
+}
+
+int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size)
+{
+	struct nand_chip *chip;
+	struct mtd_info *mtd = mxs_nand_mtd;
+	struct mxs_nand_info *nand_info;
+	struct mxs_dma_desc *d;
+	uint32_t channel;
+	int ret = 0;
+	int page;
+
+	if (!mtd)
+		return -ENODEV;
+
+	if (size > BCH62_WRITESIZE)
+		return -EINVAL;
+
+	chip = mtd_to_nand(mtd);
+	nand_info = chip->priv;
+	channel = nand_info->dma_channel_base;
+
+	mxs_nand_mode_fcb_62bit(nand_info);
+
+	nand_select_target(chip, 0);
+
+	page = block * (mtd->erasesize / mtd->writesize);
+
+	nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+
+	memset(nand_info->data_buf, 0x0, BCH62_WRITESIZE);
+	memcpy(nand_info->data_buf, buf, size);
+
+	/* Handle block mark swapping. */
+	mxs_nand_swap_block_mark(chip, nand_info->data_buf, nand_info->oob_buf);
+
+	/* Compile the DMA descriptor - write data. */
+	d = mxs_nand_get_dma_desc(nand_info);
+	d->cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | MXS_DMA_DESC_IRQ |
+		      MXS_DMA_DESC_DEC_SEM | MXS_DMA_DESC_WAIT4END |
+		      (6 << MXS_DMA_DESC_PIO_WORDS_OFFSET);
+
+	d->cmd.address = 0;
+
+	d->cmd.pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+			      GPMI_CTRL0_WORD_LENGTH |
+			      GPMI_CTRL0_ADDRESS_NAND_DATA;
+	d->cmd.pio_words[1] = 0;
+	d->cmd.pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC |
+			      GPMI_ECCCTRL_ECC_CMD_ENCODE |
+			      GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+	d->cmd.pio_words[3] = BCH62_PAGESIZE;
+	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
+	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
+
+	d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
+			       GPMI_ECCCTRL_RANDOMIZER_TYPE2;
+	/*
+	 * Write NAND page number needed to be randomized
+	 * to GPMI_ECCCOUNT register.
+	 *
+	 * The value is between 0-255. For additional details
+	 * check 9.6.6.4 of i.MX7D Applications Processor reference
+	 */
+	d->cmd.pio_words[3] |= (page % 256) << 16;
+
+	mxs_dma_desc_append(channel, d);
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_go(channel);
+	if (ret) {
+		dev_err(nand_info->dev, "MXS NAND: DMA write error: %d\n", ret);
+		goto out;
+	}
+
+	ret = mxs_nand_wait_for_bch_complete(nand_info);
+	if (ret) {
+		dev_err(nand_info->dev, "MXS NAND: BCH write timeout\n");
+		goto out;
+	}
+
+out:
+	mxs_nand_return_dma_descs(nand_info);
+
+	if (!ret)
+		ret = nand_prog_page_end_op(chip);
+
+	mxs_nand_config_bch(chip, mtd->writesize + mtd->oobsize);
+	nand_deselect_target(chip);
+
+	return ret;
+}
+
 /*
  * Nominally, the purpose of this function is to look for or create the bad
  * block table. In fact, since the we call this function at the very end of
diff --git a/include/linux/mtd/nand_mxs.h b/include/linux/mtd/nand_mxs.h
index 7eda0b8e63..4c1e90d6f0 100644
--- a/include/linux/mtd/nand_mxs.h
+++ b/include/linux/mtd/nand_mxs.h
@@ -28,5 +28,9 @@
  */
 
 int mxs_nand_get_geo(int *ecc_strength, int *bb_mark_bit_offset);
+int mxs_nand_read_fcb_bch62(unsigned int block, void *buf, size_t size);
+int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size);
+
+struct mtd_info;
 
 #endif /* __NAND_MXS_H */
diff --git a/include/soc/imx/imx-nand-bcb.h b/include/soc/imx/imx-nand-bcb.h
index 6c42d80428..c5481e602e 100644
--- a/include/soc/imx/imx-nand-bcb.h
+++ b/include/soc/imx/imx-nand-bcb.h
@@ -77,6 +77,17 @@ struct fcb_block {
 
 	uint32_t DISBBM;	/* the flag to enable (1)/disable(0) bi swap */
 	uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
+
+	/* iMX7 only */
+	uint32_t onfi_sync_enable; /* enable Onfi nand sync support */
+	uint32_t onfi_sync_speed;  /* Speed for Onfi nand sync mode */
+	uint32_t onfi_sync_nand_data; /* parameters for Onfi nand sync mode timing */
+	uint32_t reserved[6];
+	uint32_t disbbm_search; /* disable bad block search function when reading the firmware, only using DBBT */
+	uint32_t disbbm_search_limit; /* ???randomizer type 2 enable ???*/
+	uint32_t reserved1[15]; /* reserved for future use */
+	uint32_t read_retry_enable; /* enable read retry for DBBT and firmware */
+	uint32_t reserved2[1]; /*reserved, keep at 0 */
 };
 
 #endif /* __MACH_IMX_NAND_BCB_H */
-- 
2.30.2



From sha at pengutronix.de  Fri Sep 30 05:24:14 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:24:14 +0200
Subject: [PATCH master] mci: bcm2835: reset host controller on barebox
 shutdown
In-Reply-To: <20220930111940.1323140-1-a.fatoum@pengutronix.de>
References: <20220930111940.1323140-1-a.fatoum@pengutronix.de>
Message-ID: <20220930122414.GZ986@pengutronix.de>

On Fri, Sep 30, 2022 at 01:19:40PM +0200, Ahmad Fatoum wrote:
> We don't usually disable MMC controllers on barebox shutdown, because
> they don't DMA on their own, unlike e.g. network controllers.
> 
> Booting Linux v5.17.0 on a Raspberry Pi 4 in 32-bit mode still has the
> MMC host controller driver complain:
> 
>   [   22.464887] mmc1: Got data interrupt 0x00000002 even though no
>   			data operation was in progress.
> 
> Fix this by resetting the SDHCI once barebox is done with it.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  drivers/mci/mci-bcm2835.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c
> index f092156f9a83..c5b226ba033c 100644
> --- a/drivers/mci/mci-bcm2835.c
> +++ b/drivers/mci/mci-bcm2835.c
> @@ -385,6 +385,8 @@ static int bcm2835_mci_probe(struct device_d *hw_dev)
>  	host->sdhci.read32 = bcm2835_sdhci_read32;
>  	host->sdhci.write32 = bcm2835_sdhci_write32;
>  
> +	hw_dev->priv = host;
> +
>  	mci_of_parse(&host->mci);
>  
>  	iores = dev_request_mem_resource(hw_dev, 0);
> @@ -420,6 +422,15 @@ static int bcm2835_mci_probe(struct device_d *hw_dev)
>  	return mci_register(&host->mci);
>  }
>  
> +static void bcm2835_mci_remove(struct device_d *dev)
> +{
> +	struct bcm2835_mci_host *host = dev->priv;
> +
> +	sdhci_write32(&host->sdhci,
> +		      SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
> +		      0x00);
> +}
> +
>  static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = {
>  	{
>  		.compatible = "brcm,bcm2835-sdhci",
> @@ -433,6 +444,7 @@ static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = {
>  static struct driver_d bcm2835_mci_driver = {
>  	.name = "bcm2835_mci",
>  	.probe = bcm2835_mci_probe,
> +	.remove = bcm2835_mci_remove,
>  	.of_compatible = DRV_OF_COMPAT(bcm2835_mci_compatible),
>  };
>  
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Fri Sep 30 05:25:39 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:25:39 +0200
Subject: [PATCH] of: overlay: fix overly strict check for symbols
In-Reply-To: <20220926100610.1457821-1-michael.riesch@wolfvision.net>
References: <20220926100610.1457821-1-michael.riesch@wolfvision.net>
Message-ID: <20220930122539.GA986@pengutronix.de>

On Mon, Sep 26, 2022 at 12:06:10PM +0200, Michael Riesch wrote:
> The recent patch "of: overlay: improve error handling in
> of_overlay_apply_tree" introduced overly strict checks for symbols
> in the root device tree and the overlay. However, it is legal for
> both to have no symbols. Fix the checks in order to implement the
> status quo.
> 
> Fixes: bc475fd88810 ("of: overlay: improve error handling in of_overlay_apply_tree")
> Signed-off-by: Michael Riesch <michael.riesch at wolfvision.net>
> ---
>  drivers/of/overlay.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index 0fc440fdcf..9d112b67f1 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -131,12 +131,12 @@ static int of_overlay_apply_symbols(struct device_node *root,
>  
>  	if (!overlay_symbols) {
>  		pr_debug("overlay doesn't have a __symbols__ node\n");
> -		return -EINVAL;
> +		return 0;
>  	}
>  
>  	if (!root_symbols) {
>  		pr_info("root doesn't have a __symbols__ node\n");
> -		return -EINVAL;
> +		return 0;
>  	}
>  
>  	list_for_each_entry(prop, &overlay_symbols->properties, list) {
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From sha at pengutronix.de  Fri Sep 30 05:37:52 2022
From: sha at pengutronix.de (Sascha Hauer)
Date: Fri, 30 Sep 2022 14:37:52 +0200
Subject: [PATCH master] bbu: fix exporting i.MX NAND bbu handler over
 fastboot
In-Reply-To: <20220928085622.2677478-1-a.fatoum@pengutronix.de>
References: <20220928085622.2677478-1-a.fatoum@pengutronix.de>
Message-ID: <20220930123752.GC986@pengutronix.de>

On Wed, Sep 28, 2022 at 10:56:22AM +0200, Ahmad Fatoum wrote:
> handler->devicefile for i.MX NAND is nand0.barebox, which lacks a /dev/
> prefix. This is ok for detection, as device_detect_by_name expects the
> cdev name and devpath_to_name() will strip a /dev/ if available.
> 
> For stat() however, we need to add back /dev/, otherwise the file can't
> be found. Rework the code to do that.
> 
> This fixes an issue where usbgadget -A '' -b would not export a i.MX
> NAND barebox update handler.
> 
> Fixes: 726a802456bc ("common: bbu: only add available handlers")
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  common/bbu.c | 37 ++++++++++++++++++-------------------
>  1 file changed, 18 insertions(+), 19 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/common/bbu.c b/common/bbu.c
> index d243ac89dd9f..3ec17216cb15 100644
> --- a/common/bbu.c
> +++ b/common/bbu.c
> @@ -24,43 +24,42 @@
>  
>  static LIST_HEAD(bbu_image_handlers);
>  
> -static void append_bbu_entry(struct bbu_handler *handler, struct file_list *files)
> +static void append_bbu_entry(const char *_name,
> +			     const char *devicefile,
> +			     struct file_list *files)
>  {
>  	char *name;
>  
> -	name = basprintf("bbu-%s", handler->name);
> +	name = basprintf("bbu-%s", _name);
>  
> -	if (file_list_add_entry(files, name, handler->devicefile, 0))
> +	if (file_list_add_entry(files, name, devicefile, 0))
>  		pr_warn("duplicate partition name %s\n", name);
>  
>  	free(name);
>  }
>  
> -static bool bbu_handler_is_available(struct bbu_handler *handler)
> -{
> -	struct stat s;
> -	int ret;
> -
> -	device_detect_by_name(devpath_to_name(handler->devicefile));
> -
> -	ret = stat(handler->devicefile, &s);
> -	if (ret)
> -		return false;
> -
> -	return true;
> -}
> -
>  void bbu_append_handlers_to_file_list(struct file_list *files)
>  {
>  	struct bbu_handler *handler;
>  
>  	list_for_each_entry(handler, &bbu_image_handlers, list) {
> -		if (bbu_handler_is_available(handler)) {
> -			append_bbu_entry(handler, files);
> +		const char *cdevname;
> +		struct stat s;
> +		char *devpath;
> +
> +		cdevname = devpath_to_name(handler->devicefile);
> +		device_detect_by_name(cdevname);
> +
> +		devpath = basprintf("/dev/%s", cdevname);
> +
> +		if (stat(devpath, &s) == 0) {
> +			append_bbu_entry(handler->name, devpath, files);
>  		} else {
>  			pr_info("Skipping unavailable handler bbu-%s\n",
>  				handler->name);
>  		}
> +
> +		free(devpath);
>  	}
>  }
>  
> -- 
> 2.30.2
> 
> 
> 

-- 
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-5555 |


From j.zink at pengutronix.de  Fri Sep 30 06:21:20 2022
From: j.zink at pengutronix.de (Johannes Zink)
Date: Fri, 30 Sep 2022 15:21:20 +0200
Subject: [PATCH 0/7] Add i.MX7 NAND boot support
In-Reply-To: <20220930121553.335796-1-s.hauer@pengutronix.de>
References: <20220930121553.335796-1-s.hauer@pengutronix.de>
Message-ID: <a660829b86bf2edd88515e205845a0da0085cfa7.camel@pengutronix.de>

On Fri, 2022-09-30 at 14:15 +0200, Sascha Hauer wrote:
> NAND boot on i.MX7 is the same as on i.MX6, just a little different.
> This series adds a barebox update handler to allow writing barebox
> to NAND flash.
> 
> Sascha
> 
> Johannes Zink (4):
> ? mtd: nand-mxs: refactor flash layout configuration
> ? mtd: nand-mxs: add i.MX7 FCB write support
> ? imx-bbu-nand-fcb: isolate i.MX28 specific parts
> ? imx-bbu-nand-fcb: extend for i.MX7 support
> 
> Sascha Hauer (3):
> ? mtd: nand-mxs: Factor out a bch read function
> ? imx-bbu-nand-fcb: pass imx_handler further down
> ? imx-bbu-nand-fcb: add fcb_read/fcb_write function hooks
> 
> ?arch/arm/mach-imx/include/mach/imx7-regs.h |?? 3 +
> ?common/Kconfig???????????????????????????? |?? 2 +-
> ?common/imx-bbu-nand-fcb.c????????????????? | 267 ++++++++++++++----
> ?drivers/mtd/nand/nand_mxs.c??????????????? | 297 ++++++++++++++++++-
> --
> ?include/bbu.h????????????????????????????? |?? 5 +
> ?include/linux/mtd/nand_mxs.h?????????????? |?? 4 +
> ?include/soc/imx/imx-nand-bcb.h???????????? |? 11 +
> ?7 files changed, 492 insertions(+), 97 deletions(-)
> 

Tested-by: Johannes Zink <j.zink at pengutronix.de> # innocomm S810
(i.MX7D)

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



From j.zink at pengutronix.de  Fri Sep 30 06:37:02 2022
From: j.zink at pengutronix.de (Johannes Zink)
Date: Fri, 30 Sep 2022 15:37:02 +0200
Subject: [PATCH master] ARM: i.MX7: enable caches when booted over USB
Message-ID: <20220930133702.518949-1-j.zink@pengutronix.de>

From: Ahmad Fatoum <a.fatoum at pengutronix.de>

BootROM on the i.MX7 doesn't set the SMP bit when booted
over serial download. This leads to vastly worse performance
when doing memory-heavy operations in a USB-booted system,
as the caches are not utilized. Example running md5sum over
a 25M image in ramfs:

  without patch: 10796ms
  with    patch: 457ms

This issue isn't unique to the i.MX7, but exists for the i.MX6UL as
well, which also has the Cortex-A7 as CPU. Like with
imx6ul_cpu_lowlevel_init(), adapt imx7_cpu_lowlevel_init() to avoid this
slow down.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
Signed-off-by: Johannes Zink <j.zink at pengutronix.de>
---
 arch/arm/mach-imx/cpu_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c
index ea36215419..ede2076102 100644
--- a/arch/arm/mach-imx/cpu_init.c
+++ b/arch/arm/mach-imx/cpu_init.c
@@ -49,7 +49,7 @@ void imx6ul_cpu_lowlevel_init(void)
 
 void imx7_cpu_lowlevel_init(void)
 {
-	arm_cpu_lowlevel_init();
+	cortex_a7_lowlevel_init();
 	imx_cpu_timer_init(IOMEM(MX7_SYSCNT_CTRL_BASE_ADDR));
 }
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 07:18:29 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 15:18:29 +0100
Subject: [PATCH master] mci: bcm2835: reset host controller on barebox
 shutdown
In-Reply-To: <20220930122414.GZ986@pengutronix.de>
References: <20220930111940.1323140-1-a.fatoum@pengutronix.de>
 <20220930122414.GZ986@pengutronix.de>
Message-ID: <e6743279-3842-5595-66bc-4b2d793ab8ba@pengutronix.de>

On 30.09.22 13:24, Sascha Hauer wrote:
> On Fri, Sep 30, 2022 at 01:19:40PM +0200, Ahmad Fatoum wrote:
>> We don't usually disable MMC controllers on barebox shutdown, because
>> they don't DMA on their own, unlike e.g. network controllers.
>>
>> Booting Linux v5.17.0 on a Raspberry Pi 4 in 32-bit mode still has the
>> MMC host controller driver complain:
>>
>>   [   22.464887] mmc1: Got data interrupt 0x00000002 even though no
>>   			data operation was in progress.
>>
>> Fix this by resetting the SDHCI once barebox is done with it.
>>
>> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
>> ---
>>  drivers/mci/mci-bcm2835.c | 12 ++++++++++++
>>  1 file changed, 12 insertions(+)
> 
> Applied, thanks

Please drop again. The warning is spurious and it just happened to not
show up in my testing runs afterwards. I am looking into a proper fix
and will let it do more reboot cycles to make sure issue is indeed
resolved.

> 
> Sascha
> 
>>
>> diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c
>> index f092156f9a83..c5b226ba033c 100644
>> --- a/drivers/mci/mci-bcm2835.c
>> +++ b/drivers/mci/mci-bcm2835.c
>> @@ -385,6 +385,8 @@ static int bcm2835_mci_probe(struct device_d *hw_dev)
>>  	host->sdhci.read32 = bcm2835_sdhci_read32;
>>  	host->sdhci.write32 = bcm2835_sdhci_write32;
>>  
>> +	hw_dev->priv = host;
>> +
>>  	mci_of_parse(&host->mci);
>>  
>>  	iores = dev_request_mem_resource(hw_dev, 0);
>> @@ -420,6 +422,15 @@ static int bcm2835_mci_probe(struct device_d *hw_dev)
>>  	return mci_register(&host->mci);
>>  }
>>  
>> +static void bcm2835_mci_remove(struct device_d *dev)
>> +{
>> +	struct bcm2835_mci_host *host = dev->priv;
>> +
>> +	sdhci_write32(&host->sdhci,
>> +		      SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
>> +		      0x00);
>> +}
>> +
>>  static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = {
>>  	{
>>  		.compatible = "brcm,bcm2835-sdhci",
>> @@ -433,6 +444,7 @@ static __maybe_unused struct of_device_id bcm2835_mci_compatible[] = {
>>  static struct driver_d bcm2835_mci_driver = {
>>  	.name = "bcm2835_mci",
>>  	.probe = bcm2835_mci_probe,
>> +	.remove = bcm2835_mci_remove,
>>  	.of_compatible = DRV_OF_COMPAT(bcm2835_mci_compatible),
>>  };
>>  
>> -- 
>> 2.30.2
>>
>>
>>
> 


-- 
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-5555 |


From a.fatoum at pengutronix.de  Fri Sep 30 08:33:15 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:33:15 +0200
Subject: [PATCH v2 1/3] mci: core: act upon broken-cd device tree property
Message-ID: <20220930153317.731088-1-a.fatoum@pengutronix.de>

We didn't care much for broken-cd so far, still we have some drivers
implementing the card_present callback, which we should ignore when
card-detect is marked broken.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - new patch
---
 drivers/mci/mci-core.c | 12 ++++++++----
 include/mci.h          |  1 +
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 8c08a4f61f63..5f4457bab3df 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1750,10 +1750,13 @@ static int mci_card_probe(struct mci *mci)
 	int i, rc, disknum, ret;
 	bool has_bootpart = false;
 
-	if (host->card_present && !host->card_present(host) &&
-	    !host->non_removable) {
-		dev_err(&mci->dev, "no card inserted\n");
-		return -ENODEV;
+	if (host->card_present && !host->card_present(host) && !host->non_removable) {
+		if (!host->broken_cd) {
+			dev_err(&mci->dev, "no card inserted\n");
+			return -ENODEV;
+		}
+
+		dev_info(&mci->dev, "no card inserted (ignoring)\n");
 	}
 
 	ret = regulator_enable(host->supply);
@@ -2043,6 +2046,7 @@ void mci_of_parse_node(struct mci_host *host,
 		}
 	}
 
+	host->broken_cd = of_property_read_bool(np, "broken-cd");
 	host->non_removable = of_property_read_bool(np, "non-removable");
 	host->no_sd = of_property_read_bool(np, "no-sd");
 	host->disable_wp = of_property_read_bool(np, "disable-wp");
diff --git a/include/mci.h b/include/mci.h
index 2098b4fbf084..d949310fac30 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -404,6 +404,7 @@ struct mci_host {
 	unsigned max_req_size;
 	unsigned dsr_val;	/**< optional dsr value */
 	int use_dsr;		/**< optional dsr usage flag */
+	int broken_cd;		/**< card detect is broken */
 	bool non_removable;	/**< device is non removable */
 	bool no_sd;		/**< do not send SD commands during initialization */
 	bool disable_wp;	/**< ignore write-protect detection logic */
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:33:17 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:33:17 +0200
Subject: [PATCH v2 3/3] mci: core: fixup broken-cd information into kernel DT
In-Reply-To: <20220930153317.731088-1-a.fatoum@pengutronix.de>
References: <20220930153317.731088-1-a.fatoum@pengutronix.de>
Message-ID: <20220930153317.731088-3-a.fatoum@pengutronix.de>

In remote labs co-located with other hardware, we've observed card
detect levers of different boards to sporadically fail to detect
the card, e.g. because the cable on the usbsdmux was yanked around
by accident. When this happens, barebox usually boots up normally as
the card detect is ignored and then Linux waits indefinitely for
the card-detect to turn active. We already maintain a broken_cd flag
for each card. Use this to fixup the kernel DT appropriately.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - apply to all controllers that have broken-cd and not only
    to probed ones (Sascha)
---
 drivers/mci/mci-core.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 26b524007609..82f39d8fc9b8 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1739,6 +1739,31 @@ static int mci_register_partition(struct mci_part *part)
 	return 0;
 }
 
+static int of_broken_cd_fixup(struct device_node *root, void *ctx)
+{
+	struct mci_host *host = ctx;
+	struct device_d *hw_dev = host->hw_dev;
+	struct device_node *np;
+	char *name;
+
+	if (!host->broken_cd)
+		return 0;
+
+	name = of_get_reproducible_name(hw_dev->device_node);
+	np = of_find_node_by_reproducible_name(root, name);
+	free(name);
+	if (!np) {
+		dev_warn(hw_dev, "Cannot find nodepath %s, cannot fixup\n",
+			 hw_dev->device_node->full_name);
+		return -EINVAL;
+	}
+
+	of_property_write_bool(np, "cd-gpios", false);
+	of_property_write_bool(np, "broken-cd", true);
+
+	return 0;
+}
+
 /**
  * Probe an MCI card at the given host interface
  * @param mci MCI device instance
@@ -1989,6 +2014,9 @@ int mci_register(struct mci_host *host)
 	if (IS_ENABLED(CONFIG_MCI_STARTUP))
 		mci_card_probe(mci);
 
+	if (!host->no_sd && dev_of_node(host->hw_dev))
+		of_register_fixup(of_broken_cd_fixup, host);
+
 	list_add_tail(&mci->list, &mci_list);
 
 	return 0;
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:33:16 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:33:16 +0200
Subject: [PATCH v2 2/3] mci: core: add broken_cd device parameter
In-Reply-To: <20220930153317.731088-1-a.fatoum@pengutronix.de>
References: <20220930153317.731088-1-a.fatoum@pengutronix.de>
Message-ID: <20220930153317.731088-2-a.fatoum@pengutronix.de>

Sometimes a broken card-detect is not a general issue affecting all
boards, but only a given board. Allow setting broken_cd for such boards
via a device parameter.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - replace Kconfig option with device parameter (Marco, Sascha)
---
 drivers/mci/mci-core.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 5f4457bab3df..26b524007609 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1919,7 +1919,7 @@ int mci_register(struct mci_host *host)
 {
 	struct mci *mci;
 	struct device_d *hw_dev;
-	struct param_d *param_probe;
+	struct param_d *param_probe, *param_broken_cd;
 	int ret;
 
 	mci = xzalloc(sizeof(*mci));
@@ -1973,6 +1973,15 @@ int mci_register(struct mci_host *host)
 		goto err_unregister;
 	}
 
+	param_broken_cd = dev_add_param_bool(&mci->dev, "broken_cd",
+					     NULL, NULL, &host->broken_cd, mci);
+
+	if (IS_ERR(param_broken_cd) && PTR_ERR(param_broken_cd) != -ENOSYS) {
+		ret = PTR_ERR(param_broken_cd);
+		dev_dbg(&mci->dev, "Failed to add 'broken_cd' parameter to the MCI device\n");
+		goto err_unregister;
+	}
+
 	if (IS_ENABLED(CONFIG_MCI_INFO))
 		mci->dev.info = mci_info;
 
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:38:19 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:38:19 +0200
Subject: [PATCH] include: define SSIZE_MAX in <linux/limits.h>
Message-ID: <20220930153819.744833-1-a.fatoum@pengutronix.de>

For symmetry with SIZE_MAX, which we already define, define SIZE_MAX as
well. Definition taken from Linux.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 include/linux/limits.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/limits.h b/include/linux/limits.h
index e1aa2de84519..eab3848bbf7a 100644
--- a/include/linux/limits.h
+++ b/include/linux/limits.h
@@ -19,6 +19,7 @@
 #define SIZE_MAX	(~(size_t)0)
 #define PHYS_ADDR_MAX	(~(phys_addr_t)0)
 #define UINTPTR_MAX	ULONG_MAX
+#define SSIZE_MAX	((ssize_t)(SIZE_MAX >> 1))
 
 #define U8_MAX		((u8)~0U)
 #define S8_MAX		((s8)(U8_MAX >> 1))
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:40:17 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:40:17 +0200
Subject: [PATCH] fs: implement cdev_mount()
Message-ID: <20220930154017.750867-1-a.fatoum@pengutronix.de>

EFI loaders provide both block device and file system access to software
running under it. For file system access, we will just want to get a
mount if available and mount at a default location if not. Provide a
helper that does just that.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 fs/fs.c      | 19 +++++++++++++++++++
 include/fs.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/fs/fs.c b/fs/fs.c
index 78878e7112d5..a314a49b2db7 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -999,6 +999,25 @@ const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions)
 	return cdev_get_mount_path(cdev);
 }
 
+/*
+ * cdev_mount - return existing mount or mount a cdev to the default path
+ *
+ * If a cdev is already mounted anywhere return the path
+ * it's mounted on.
+ * Otherwise mount it to /mnt/<cdevname> and return the path. Returns an
+ * error pointer on failure.
+ */
+const char *cdev_mount(struct cdev *cdev)
+{
+	const char *path;
+
+	path = cdev_get_mount_path(cdev);
+	if (path)
+		return path;
+
+	return cdev_mount_default(cdev, NULL);
+}
+
 /*
  * mount_all - iterate over block devices and mount all devices we are able to
  */
diff --git a/include/fs.h b/include/fs.h
index 894cae3e4c2f..9ea522dc2cc3 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -164,6 +164,7 @@ int fs_init_legacy(struct fs_device_d *fsdev);
 int fsdev_open_cdev(struct fs_device_d *fsdev);
 const char *cdev_get_mount_path(struct cdev *cdev);
 const char *cdev_mount_default(struct cdev *cdev, const char *fsoptions);
+const char *cdev_mount(struct cdev *cdev);
 void mount_all(void);
 
 void fsdev_set_linux_rootarg(struct fs_device_d *fsdev, const char *str);
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:40:53 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:40:53 +0200
Subject: [PATCH] fs: export file system detection functionality
Message-ID: <20220930154053.752237-1-a.fatoum@pengutronix.de>

This will come in handy when using barebox as EFI loader, so give it a
more generic name and export it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 fs/fs.c      | 4 ++--
 include/fs.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/fs.c b/fs/fs.c
index a314a49b2db7..95813b6089c7 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -756,7 +756,7 @@ int register_fs_driver(struct fs_driver_d *fsdrv)
 }
 EXPORT_SYMBOL(register_fs_driver);
 
-static const char *detect_fs(const char *filename, const char *fsoptions)
+const char *fs_detect(const char *filename, const char *fsoptions)
 {
 	enum filetype type;
 	struct driver_d *drv;
@@ -2980,7 +2980,7 @@ int mount(const char *device, const char *fsname, const char *pathname,
 			device, pathname, fsname, fsoptions);
 
 	if (!fsname)
-		fsname = detect_fs(device, fsoptions);
+		fsname = fs_detect(device, fsoptions);
 
 	if (!fsname) {
 		ret = -ENOENT;
diff --git a/include/fs.h b/include/fs.h
index 9ea522dc2cc3..b501db38addd 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -179,4 +179,6 @@ static inline const char *devpath_to_name(const char *devpath)
 	return devpath;
 }
 
+const char *fs_detect(const char *filename, const char *fsoptions);
+
 #endif /* __FS_H */
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:41:45 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:41:45 +0200
Subject: [PATCH] common: console_common: output log messages to CONSOLE_STDERR
Message-ID: <20220930154145.754181-1-a.fatoum@pengutronix.de>

Like U-Boot, barebox has two standard output streams:
CONSOLE_STDOUT and CONSOLE_STDERR in addition to the input stream
CONSOLE_STDIN.

>From a consumer view, the console.active device parameter allows
restricting which of these streams interact with a given console.

>From a provider view, only CONSOLE_STDOUT is ever used. dputs
dputc allow passing in CONSOLE_STDERR instead, but nothing in-tree
does so.

Change this by having all log messages (e.g. pr_debug or dev_err)
go to CONSOLE_STDERR. For nearly all systems that just use the default
of console.active="ioe" or "oe", there is no difference. But now
systems that use either "o" or "e" can use different console
devices for barebox log messages and for standard output by commands.
This is especially useful to debug interactive applications like edit
or for monitoring barebox debug messages during execution of payloads
when barebox acts as EFI loader.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 common/console_common.c | 10 +++++-----
 pbl/console.c           |  6 +++---
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/common/console_common.c b/common/console_common.c
index 7bef74c54391..ca1dad0f159f 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -68,7 +68,7 @@ void log_clean(unsigned int limit)
 	}
 }
 
-static void print_colored_log_level(const int level)
+static void print_colored_log_level(unsigned int ch, const int level)
 {
 	if (!console_allow_color())
 		return;
@@ -77,7 +77,7 @@ static void print_colored_log_level(const int level)
 	if (!colored_log_level[level])
 		return;
 
-	puts(colored_log_level[level]);
+	console_puts(ch, colored_log_level[level]);
 }
 
 static void pr_puts(int level, const char *str)
@@ -112,8 +112,8 @@ nolog:
 	if (level > barebox_loglevel)
 		return;
 
-	print_colored_log_level(level);
-	puts(str);
+	print_colored_log_level(CONSOLE_STDERR, level);
+	console_puts(CONSOLE_STDERR, str);
 }
 
 int pr_print(int level, const char *fmt, ...)
@@ -217,7 +217,7 @@ void log_print(unsigned flags, unsigned levels)
 
 		if (!(flags & (BAREBOX_LOG_PRINT_RAW | BAREBOX_LOG_PRINT_TIME
 			       | BAREBOX_LOG_DIFF_TIME)))
-			print_colored_log_level(log->level);
+			print_colored_log_level(CONSOLE_STDOUT, log->level);
 
 		if (flags & BAREBOX_LOG_PRINT_RAW)
 			printf("<%i>", log->level);
diff --git a/pbl/console.c b/pbl/console.c
index fc8e8cdf1383..a147e2a19e49 100644
--- a/pbl/console.c
+++ b/pbl/console.c
@@ -39,9 +39,9 @@ int console_puts(unsigned int ch, const char *str)
 
 	while (*str) {
 		if (*str == '\n')
-			console_putc(CONSOLE_STDOUT, '\r');
+			console_putc(ch, '\r');
 
-		console_putc(CONSOLE_STDOUT, *str);
+		console_putc(ch, *str);
 		str++;
 		n++;
 	}
@@ -74,7 +74,7 @@ int pr_print(int level, const char *fmt, ...)
 	i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
 	va_end(args);
 
-	console_puts(CONSOLE_STDOUT, printbuffer);
+	console_puts(CONSOLE_STDERR, printbuffer);
 
 	return i;
 }
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:42:47 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:42:47 +0200
Subject: [PATCH 2/2] relocate_to_current_adr: hang directly on error instead of panic()
In-Reply-To: <20220930154247.756577-1-a.fatoum@pengutronix.de>
References: <20220930154247.756577-1-a.fatoum@pengutronix.de>
Message-ID: <20220930154247.756577-2-a.fatoum@pengutronix.de>

panic() will format a panic message, turn on a panic LED, dump a
stack trace and finally either restart the system or print a
message to ask the user to restart the system before hanging.

When relocation fails, all of these aren't possible, so instead of
devolving into undefined behavior, fall directly into an infinite loop.

Motivation for this change is to avoid linking printf code when it's
only usage is the relocation error case.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/cpu/common.c  | 4 ++--
 arch/riscv/lib/reloc.c | 2 +-
 include/common.h       | 6 ++++++
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/cpu/common.c b/arch/arm/cpu/common.c
index 5ccacf204751..7cd97e938b3d 100644
--- a/arch/arm/cpu/common.c
+++ b/arch/arm/cpu/common.c
@@ -90,7 +90,7 @@ void relocate_to_current_adr(void)
 			putc_ll(' ');
 			puthex_ll(rel->r_addend);
 			putc_ll('\n');
-			panic("");
+			__hang();
 		}
 
 		dstart += sizeof(*rel);
@@ -120,7 +120,7 @@ void relocate_to_current_adr(void)
 			putc_ll(' ');
 			puthex_ll(rel->r_offset);
 			putc_ll('\n');
-			panic("");
+			__hang();
 		}
 
 		dstart += sizeof(*rel);
diff --git a/arch/riscv/lib/reloc.c b/arch/riscv/lib/reloc.c
index da53c50448d7..13118a9ac54f 100644
--- a/arch/riscv/lib/reloc.c
+++ b/arch/riscv/lib/reloc.c
@@ -66,7 +66,7 @@ void relocate_to_current_adr(void)
 			putc_ll(' ');
 			puthex_ll(rela->r_addend);
 			putc_ll('\n');
-			panic("");
+			__hang();
 		}
 	}
 
diff --git a/include/common.h b/include/common.h
index bd120356883a..cf3e0447a09a 100644
--- a/include/common.h
+++ b/include/common.h
@@ -43,6 +43,12 @@
  */
 void reginfo(void);
 
+/* For use when unrelocated */
+static inline void __hang(void)
+{
+	while (1);
+}
+
 void __noreturn hang (void);
 
 char *size_human_readable(unsigned long long size);
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 08:42:46 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:42:46 +0200
Subject: [PATCH 1/2] include: move panic() prototype to <printk.h>
Message-ID: <20220930154247.756577-1-a.fatoum@pengutronix.de>

The panic declaration in <linux/kernel.h> is out of place and unexpected
as it's not a Linux kernel. printf() and printk() are defined in
<printk.h>, so move it there too. Most files making use of panic(), pull
it in via <common.h>, so we only need to adjust two headers for the
new location.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/cpu/mmu-common.h | 1 +
 include/firmware.h        | 1 +
 include/linux/kernel.h    | 2 --
 include/printk.h          | 2 ++
 4 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/cpu/mmu-common.h b/arch/arm/cpu/mmu-common.h
index c9ea2c122857..7a69122ee6fa 100644
--- a/arch/arm/cpu/mmu-common.h
+++ b/arch/arm/cpu/mmu-common.h
@@ -3,6 +3,7 @@
 #ifndef __ARM_MMU_COMMON_H
 #define __ARM_MMU_COMMON_H
 
+#include <printk.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
diff --git a/include/firmware.h b/include/firmware.h
index 2cfaeb1e6a91..cfb88993222a 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -7,6 +7,7 @@
 #define FIRMWARE_H
 
 #include <pbl.h>
+#include <printk.h>
 #include <types.h>
 #include <driver.h>
 #include <debug_ll.h>
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 4483d33e65bb..44fc02df0bf9 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -82,8 +82,6 @@
 		(__x < 0) ? -__x : __x;         \
 	})
 
-void __noreturn panic(const char *fmt, ...);
-
 extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 extern long simple_strtol(const char *,char **,unsigned int);
 extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
diff --git a/include/printk.h b/include/printk.h
index 8de8202af97c..b313b408a97b 100644
--- a/include/printk.h
+++ b/include/printk.h
@@ -27,6 +27,8 @@ static inline int printf(const char *fmt, ...)
 }
 #endif
 
+void __attribute__((noreturn)) panic(const char *fmt, ...);
+
 #define printk			printf
 
 #define printk_once(fmt, ...)					\
-- 
2.30.2



From a.fatoum at pengutronix.de  Fri Sep 30 09:22:47 2022
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 30 Sep 2022 17:22:47 +0100
Subject: [PATCH v2 1/3] mci: core: act upon broken-cd device tree property
In-Reply-To: <20220930153317.731088-1-a.fatoum@pengutronix.de>
References: <20220930153317.731088-1-a.fatoum@pengutronix.de>
Message-ID: <753f19e9-71f5-6a16-c900-9ffadccd0209@pengutronix.de>

On 30.09.22 16:33, Ahmad Fatoum wrote:
> We didn't care much for broken-cd so far, still we have some drivers
> implementing the card_present callback, which we should ignore when
> card-detect is marked broken.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
> v1 -> v2:
>   - new patch

Sorry, this was meant to be v3.

> ---
>  drivers/mci/mci-core.c | 12 ++++++++----
>  include/mci.h          |  1 +
>  2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
> index 8c08a4f61f63..5f4457bab3df 100644
> --- a/drivers/mci/mci-core.c
> +++ b/drivers/mci/mci-core.c
> @@ -1750,10 +1750,13 @@ static int mci_card_probe(struct mci *mci)
>  	int i, rc, disknum, ret;
>  	bool has_bootpart = false;
>  
> -	if (host->card_present && !host->card_present(host) &&
> -	    !host->non_removable) {
> -		dev_err(&mci->dev, "no card inserted\n");
> -		return -ENODEV;
> +	if (host->card_present && !host->card_present(host) && !host->non_removable) {
> +		if (!host->broken_cd) {
> +			dev_err(&mci->dev, "no card inserted\n");
> +			return -ENODEV;
> +		}
> +
> +		dev_info(&mci->dev, "no card inserted (ignoring)\n");
>  	}
>  
>  	ret = regulator_enable(host->supply);
> @@ -2043,6 +2046,7 @@ void mci_of_parse_node(struct mci_host *host,
>  		}
>  	}
>  
> +	host->broken_cd = of_property_read_bool(np, "broken-cd");
>  	host->non_removable = of_property_read_bool(np, "non-removable");
>  	host->no_sd = of_property_read_bool(np, "no-sd");
>  	host->disable_wp = of_property_read_bool(np, "disable-wp");
> diff --git a/include/mci.h b/include/mci.h
> index 2098b4fbf084..d949310fac30 100644
> --- a/include/mci.h
> +++ b/include/mci.h
> @@ -404,6 +404,7 @@ struct mci_host {
>  	unsigned max_req_size;
>  	unsigned dsr_val;	/**< optional dsr value */
>  	int use_dsr;		/**< optional dsr usage flag */
> +	int broken_cd;		/**< card detect is broken */
>  	bool non_removable;	/**< device is non removable */
>  	bool no_sd;		/**< do not send SD commands during initialization */
>  	bool disable_wp;	/**< ignore write-protect detection logic */


-- 
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-5555 |


