diff --git a/.dwarves.metadata b/.dwarves.metadata
index 9538a36..9f7fdfd 100644
--- a/.dwarves.metadata
+++ b/.dwarves.metadata
@@ -1 +1 @@
-4bd8a111efefbf4058942e76d1193810e4ee5515 SOURCES/dwarves-1.21.tar.xz
+ca9684e13a39c9333d2c54b09d421fd65c23d951 SOURCES/dwarves-1.22.tar.xz
diff --git a/.gitignore b/.gitignore
index a738b0b..08686e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/dwarves-1.21.tar.xz
+SOURCES/dwarves-1.22.tar.xz
diff --git a/SOURCES/0001-btf-Remove-ftrace-filter.patch b/SOURCES/0001-btf-Remove-ftrace-filter.patch
deleted file mode 100644
index 2cb3a1c..0000000
--- a/SOURCES/0001-btf-Remove-ftrace-filter.patch
+++ /dev/null
@@ -1,392 +0,0 @@
-From 58a98f76ac95b1bb11920ff2b58206b2364e6b3b Mon Sep 17 00:00:00 2001
-From: Martin KaFai Lau <kafai@fb.com>
-Date: Thu, 6 May 2021 13:56:22 -0700
-Subject: [PATCH] btf: Remove ftrace filter
-
-BTF is currently generated for functions that are in ftrace list
-or extern.
-
-A recent use case also needs BTF generated for functions included in
-allowlist.
-
-In particular, the kernel commit:
-
-  e78aea8b2170 ("bpf: tcp: Put some tcp cong functions in allowlist for bpf-tcp-cc")
-
-allows bpf program to directly call a few tcp cc kernel functions. Those
-kernel functions are currently allowed only if CONFIG_DYNAMIC_FTRACE
-is set to ensure they are in the ftrace list but this kconfig dependency
-is unnecessary.
-
-Those kernel functions are specified under an ELF section .BTF_ids.
-There was an earlier attempt [0] to add another filter for the functions in
-the .BTF_ids section.  That discussion concluded that the ftrace filter
-should be removed instead.
-
-This patch is to remove the ftrace filter and its related functions.
-
-Number of BTF FUNC with and without is_ftrace_func():
-My kconfig in x86: 40643 vs 46225
-Jiri reported on arm: 25022 vs 55812
-
-[0]: https://lore.kernel.org/dwarves/20210423213728.3538141-1-kafai@fb.com/
-
-Signed-off-by: Martin KaFai Lau <kafai@fb.com>
-Tested-by: Nathan Chancellor <nathan@kernel.org> # build
-Acked-by: Jiri Olsa <jolsa@kernel.org>
-Acked-by: Jiri Slaby <jirislaby@kernel.org>
-Cc: Andrii Nakryiko <andrii@kernel.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: kernel-team@fb.com
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
----
- btf_encoder.c | 285 ++------------------------------------------------
- 1 file changed, 7 insertions(+), 278 deletions(-)
-
-diff --git a/btf_encoder.c b/btf_encoder.c
-index 80e896961d4e..c711f124b31e 100644
---- a/btf_encoder.c
-+++ b/btf_encoder.c
-@@ -27,17 +27,8 @@
-  */
- #define KSYM_NAME_LEN 128
- 
--struct funcs_layout {
--	unsigned long mcount_start;
--	unsigned long mcount_stop;
--	unsigned long mcount_sec_idx;
--};
--
- struct elf_function {
- 	const char	*name;
--	unsigned long	 addr;
--	unsigned long	 size;
--	unsigned long	 sh_addr;
- 	bool		 generated;
- };
- 
-@@ -64,12 +55,9 @@ static void delete_functions(void)
- #define max(x, y) ((x) < (y) ? (y) : (x))
- #endif
- 
--static int collect_function(struct btf_elf *btfe, GElf_Sym *sym,
--			    size_t sym_sec_idx)
-+static int collect_function(struct btf_elf *btfe, GElf_Sym *sym)
- {
- 	struct elf_function *new;
--	static GElf_Shdr sh;
--	static size_t last_idx;
- 	const char *name;
- 
- 	if (elf_sym__type(sym) != STT_FUNC)
-@@ -91,257 +79,12 @@ static int collect_function(struct btf_elf *btfe, GElf_Sym *sym,
- 		functions = new;
- 	}
- 
--	if (sym_sec_idx != last_idx) {
--		if (!elf_section_by_idx(btfe->elf, &sh, sym_sec_idx))
--			return 0;
--		last_idx = sym_sec_idx;
--	}
--
- 	functions[functions_cnt].name = name;
--	functions[functions_cnt].addr = elf_sym__value(sym);
--	functions[functions_cnt].size = elf_sym__size(sym);
--	functions[functions_cnt].sh_addr = sh.sh_addr;
- 	functions[functions_cnt].generated = false;
- 	functions_cnt++;
- 	return 0;
- }
- 
--static int addrs_cmp(const void *_a, const void *_b)
--{
--	const __u64 *a = _a;
--	const __u64 *b = _b;
--
--	if (*a == *b)
--		return 0;
--	return *a < *b ? -1 : 1;
--}
--
--static int get_vmlinux_addrs(struct btf_elf *btfe, struct funcs_layout *fl,
--			     __u64 **paddrs, __u64 *pcount)
--{
--	__u64 *addrs, count, offset;
--	unsigned int addr_size, i;
--	Elf_Data *data;
--	GElf_Shdr shdr;
--	Elf_Scn *sec;
--
--	/* Initialize for the sake of all error paths below. */
--	*paddrs = NULL;
--	*pcount = 0;
--
--	if (!fl->mcount_start || !fl->mcount_stop)
--		return 0;
--
--	/*
--	 * Find mcount addressed marked by __start_mcount_loc
--	 * and __stop_mcount_loc symbols and load them into
--	 * sorted array.
--	 */
--	sec = elf_getscn(btfe->elf, fl->mcount_sec_idx);
--	if (!sec || !gelf_getshdr(sec, &shdr)) {
--		fprintf(stderr, "Failed to get section(%lu) header.\n",
--			fl->mcount_sec_idx);
--		return -1;
--	}
--
--	/* Get address size from processed file's ELF class. */
--	addr_size = gelf_getclass(btfe->elf) == ELFCLASS32 ? 4 : 8;
--
--	offset = fl->mcount_start - shdr.sh_addr;
--	count  = (fl->mcount_stop - fl->mcount_start) / addr_size;
--
--	data = elf_getdata(sec, 0);
--	if (!data) {
--		fprintf(stderr, "Failed to get section(%lu) data.\n",
--			fl->mcount_sec_idx);
--		return -1;
--	}
--
--	addrs = malloc(count * sizeof(addrs[0]));
--	if (!addrs) {
--		fprintf(stderr, "Failed to allocate memory for ftrace addresses.\n");
--		return -1;
--	}
--
--	if (addr_size == sizeof(__u64)) {
--		memcpy(addrs, data->d_buf + offset, count * addr_size);
--	} else {
--		for (i = 0; i < count; i++)
--			addrs[i] = (__u64) *((__u32 *) (data->d_buf + offset + i * addr_size));
--	}
--
--	*paddrs = addrs;
--	*pcount = count;
--	return 0;
--}
--
--static int
--get_kmod_addrs(struct btf_elf *btfe, __u64 **paddrs, __u64 *pcount)
--{
--	__u64 *addrs, count;
--	unsigned int addr_size, i;
--	GElf_Shdr shdr_mcount;
--	Elf_Data *data;
--	Elf_Scn *sec;
--
--	/* Initialize for the sake of all error paths below. */
--	*paddrs = NULL;
--	*pcount = 0;
--
--	/* get __mcount_loc */
--	sec = elf_section_by_name(btfe->elf, &btfe->ehdr, &shdr_mcount,
--				  "__mcount_loc", NULL);
--	if (!sec) {
--		if (btf_elf__verbose) {
--			printf("%s: '%s' doesn't have __mcount_loc section\n", __func__,
--			       btfe->filename);
--		}
--		return 0;
--	}
--
--	data = elf_getdata(sec, NULL);
--	if (!data) {
--		fprintf(stderr, "Failed to data for __mcount_loc section.\n");
--		return -1;
--	}
--
--	/* Get address size from processed file's ELF class. */
--	addr_size = gelf_getclass(btfe->elf) == ELFCLASS32 ? 4 : 8;
--
--	count = data->d_size / addr_size;
--
--	addrs = malloc(count * sizeof(addrs[0]));
--	if (!addrs) {
--		fprintf(stderr, "Failed to allocate memory for ftrace addresses.\n");
--		return -1;
--	}
--
--	if (addr_size == sizeof(__u64)) {
--		memcpy(addrs, data->d_buf, count * addr_size);
--	} else {
--		for (i = 0; i < count; i++)
--			addrs[i] = (__u64) *((__u32 *) (data->d_buf + i * addr_size));
--	}
--
--	/*
--	 * We get Elf object from dwfl_module_getelf function,
--	 * which performs all possible relocations, including
--	 * __mcount_loc section.
--	 *
--	 * So addrs array now contains relocated values, which
--	 * we need take into account when we compare them to
--	 * functions values, see comment in setup_functions
--	 * function.
--	 */
--	*paddrs = addrs;
--	*pcount = count;
--	return 0;
--}
--
--static int is_ftrace_func(struct elf_function *func, __u64 *addrs, __u64 count)
--{
--	__u64 start = func->addr;
--	__u64 addr, end = func->addr + func->size;
--
--	/*
--	 * The invariant here is addr[r] that is the smallest address
--	 * that is >= than function start addr. Except the corner case
--	 * where there is no such r, but for that we have a final check
--	 * in the return.
--	 */
--	size_t l = 0, r = count - 1, m;
--
--	/* make sure we don't use invalid r */
--	if (count == 0)
--		return false;
--
--	while (l < r) {
--		m = l + (r - l) / 2;
--		addr = addrs[m];
--
--		if (addr >= start) {
--			/* we satisfy invariant, so tighten r */
--			r = m;
--		} else {
--			/* m is not good enough as l, maybe m + 1 will be */
--			l = m + 1;
--		}
--	}
--
--	return start <= addrs[r] && addrs[r] < end;
--}
--
--static int setup_functions(struct btf_elf *btfe, struct funcs_layout *fl)
--{
--	__u64 *addrs, count, i;
--	int functions_valid = 0;
--	bool kmod = false;
--
--	/*
--	 * Check if we are processing vmlinux image and
--	 * get mcount data if it's detected.
--	 */
--	if (get_vmlinux_addrs(btfe, fl, &addrs, &count))
--		return -1;
--
--	/*
--	 * Check if we are processing kernel module and
--	 * get mcount data if it's detected.
--	 */
--	if (!addrs) {
--		if (get_kmod_addrs(btfe, &addrs, &count))
--			return -1;
--		kmod = true;
--	}
--
--	if (!addrs) {
--		if (btf_elf__verbose)
--			printf("ftrace symbols not detected, falling back to DWARF data\n");
--		delete_functions();
--		return 0;
--	}
--
--	qsort(addrs, count, sizeof(addrs[0]), addrs_cmp);
--	qsort(functions, functions_cnt, sizeof(functions[0]), functions_cmp);
--
--	/*
--	 * Let's got through all collected functions and filter
--	 * out those that are not in ftrace.
--	 */
--	for (i = 0; i < functions_cnt; i++) {
--		struct elf_function *func = &functions[i];
--		/*
--		 * For vmlinux image both addrs[x] and functions[x]::addr
--		 * values are final address and are comparable.
--		 *
--		 * For kernel module addrs[x] is final address, but
--		 * functions[x]::addr is relative address within section
--		 * and needs to be relocated by adding sh_addr.
--		 */
--		if (kmod)
--			func->addr += func->sh_addr;
--
--		/* Make sure function is within ftrace addresses. */
--		if (is_ftrace_func(func, addrs, count)) {
--			/*
--			 * We iterate over sorted array, so we can easily skip
--			 * not valid item and move following valid field into
--			 * its place, and still keep the 'new' array sorted.
--			 */
--			if (i != functions_valid)
--				functions[functions_valid] = functions[i];
--			functions_valid++;
--		}
--	}
--
--	functions_cnt = functions_valid;
--	free(addrs);
--
--	if (btf_elf__verbose)
--		printf("Found %d functions!\n", functions_cnt);
--	return 0;
--}
--
- static struct elf_function *find_function(const struct btf_elf *btfe,
- 					  const char *name)
- {
-@@ -620,23 +363,8 @@ static int collect_percpu_var(struct btf_elf *btfe, GElf_Sym *sym,
- 	return 0;
- }
- 
--static void collect_symbol(GElf_Sym *sym, struct funcs_layout *fl,
--			   size_t sym_sec_idx)
--{
--	if (!fl->mcount_start &&
--	    !strcmp("__start_mcount_loc", elf_sym__name(sym, btfe->symtab))) {
--		fl->mcount_start = sym->st_value;
--		fl->mcount_sec_idx = sym_sec_idx;
--	}
--
--	if (!fl->mcount_stop &&
--	    !strcmp("__stop_mcount_loc", elf_sym__name(sym, btfe->symtab)))
--		fl->mcount_stop = sym->st_value;
--}
--
- static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
- {
--	struct funcs_layout fl = { };
- 	Elf32_Word sym_sec_idx;
- 	uint32_t core_id;
- 	GElf_Sym sym;
-@@ -648,9 +376,8 @@ static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
- 	elf_symtab__for_each_symbol_index(btfe->symtab, core_id, sym, sym_sec_idx) {
- 		if (collect_percpu_vars && collect_percpu_var(btfe, &sym, sym_sec_idx))
- 			return -1;
--		if (collect_function(btfe, &sym, sym_sec_idx))
-+		if (collect_function(btfe, &sym))
- 			return -1;
--		collect_symbol(&sym, &fl, sym_sec_idx);
- 	}
- 
- 	if (collect_percpu_vars) {
-@@ -661,9 +388,11 @@ static int collect_symbols(struct btf_elf *btfe, bool collect_percpu_vars)
- 			printf("Found %d per-CPU variables!\n", percpu_var_cnt);
- 	}
- 
--	if (functions_cnt && setup_functions(btfe, &fl)) {
--		fprintf(stderr, "Failed to filter DWARF functions\n");
--		return -1;
-+	if (functions_cnt) {
-+		qsort(functions, functions_cnt, sizeof(functions[0]),
-+		      functions_cmp);
-+		if (btf_elf__verbose)
-+			printf("Found %d functions!\n", functions_cnt);
- 	}
- 
- 	return 0;
--- 
-2.31.1
-
diff --git a/SPECS/dwarves.spec b/SPECS/dwarves.spec
index 9806f29..6c5de6c 100644
--- a/SPECS/dwarves.spec
+++ b/SPECS/dwarves.spec
@@ -2,14 +2,13 @@
 %define libver 1
 
 Name: dwarves
-Version: 1.21
-Release: 2%{?dist}
+Version: 1.22
+Release: 1%{?dist}
 License: GPLv2
 Summary: Debugging Information Manipulation Tools (pahole & friends)
 URL: http://acmel.wordpress.com
 Source: http://fedorapeople.org/~acme/dwarves/%{name}-%{version}.tar.xz
 Requires: %{libname}%{libver} = %{version}-%{release}
-Patch1: 0001-btf-Remove-ftrace-filter.patch
 BuildRequires: gcc
 BuildRequires: cmake >= 2.8.12
 BuildRequires: zlib-devel
@@ -66,7 +65,6 @@ Debugging information processing library development files.
 
 %prep
 %setup -q
-%patch1 -p1
 
 %build
 %cmake -DCMAKE_BUILD_TYPE=Release .
@@ -81,7 +79,7 @@ rm -Rf %{buildroot}
 %files
 %doc README.ctracer
 %doc README.btf
-%doc changes-v1.21
+%doc changes-v1.22
 %doc NEWS
 %{_bindir}/btfdiff
 %{_bindir}/codiff
@@ -116,7 +114,6 @@ rm -Rf %{buildroot}
 %doc MANIFEST README
 %{_includedir}/dwarves/btf_encoder.h
 %{_includedir}/dwarves/config.h
-%{_includedir}/dwarves/ctf_encoder.h
 %{_includedir}/dwarves/ctf.h
 %{_includedir}/dwarves/dutil.h
 %{_includedir}/dwarves/dwarves.h
@@ -126,16 +123,34 @@ rm -Rf %{buildroot}
 %{_includedir}/dwarves/elf_symtab.h
 %{_includedir}/dwarves/gobuffer.h
 %{_includedir}/dwarves/hash.h
-%{_includedir}/dwarves/libbtf.h
 %{_includedir}/dwarves/libctf.h
 %{_includedir}/dwarves/list.h
 %{_includedir}/dwarves/rbtree.h
-%{_includedir}/dwarves/pahole_strings.h
 %{_libdir}/%{libname}.so
 %{_libdir}/%{libname}_emit.so
 %{_libdir}/%{libname}_reorganize.so
 
 %changelog
+* Wed Oct 6 2021 Jiri Olsa <jolsa@redhat.com> - 1.22-1
+- New release: v1.22
+- Resolves: rhbz#2010414
+- Introduce -j/--jobs option to specify the number of threads to use.
+- Multithreaded DWARF loading, requires elfutils >= 0.178.
+- Preparatory work for multithreaded BTF encoding, the focus for 1.23.
+- Allow encoding BTF to a separate file.
+- Show all different types with the same name, not just the first one found.
+- Stop assuming that reading from stdin means pretty, add --prettify.
+- Improve type resolution for the --header command line option.
+- Do not consider the ftrace filter when encoding BTF for kernel functions.
+- Lock calls to non-thread safe elfutils' dwarf_decl_file() and dwarf_decl_line().
+- Change hash table size to one that performs better with current typical vmlinux files.
+- Allow tweaking the hash table size from the command line.
+- Add --kabi_prefix to avoid deduplication woes when using _RH_KABI_REPLACE().
+- Add --with_flexible_array to show just types with flexible arrays.
+- Support btfdiff with a detached BTF file.
+- Introduce sorted type output (--sort).
+- Disable incomplete CTF encoder.
+
 * Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 1.21-2
 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
   Related: rhbz#1991688