6.4.5-rc1 review
Subsystems (9)
Greg Kroah-Hartman
maintainerPATCH 137/292 kasan: use internal prototypes matching gcc-13 builtins
In reply to Greg Kroah-HartmanFrom: Arnd Bergmann <[email protected]>
commit bb6e04a173f06e51819a4bb512e127dfbc50dcfa upstream.
gcc-13 warns about function definitions for builtin interfaces that have a different prototype, e.g.:
In file included from kasan_test.c:31:
kasan.h:574:6: error: conflicting types for built-in function '__asan_register_globals'; expected 'void(void *, long int)' [-Werror=builtin-declaration-mismatch]
574 | void __asan_register_globals(struct kasan_global *globals, size_t size);
kasan.h:577:6: error: conflicting types for built-in function '__asan_alloca_poison'; expected 'void(void *, long int)' [-Werror=builtin-declaration-mismatch]
577 | void __asan_alloca_poison(unsigned long addr, size_t size);
kasan.h:580:6: error: conflicting types for built-in function '__asan_load1'; expected 'void(void *)' [-Werror=builtin-declaration-mismatch]
580 | void __asan_load1(unsigned long addr);
kasan.h:581:6: error: conflicting types for built-in function '__asan_store1'; expected 'void(void *)' [-Werror=builtin-declaration-mismatch]
581 | void __asan_store1(unsigned long addr);
kasan.h:643:6: error: conflicting types for built-in function '__hwasan_tag_memory'; expected 'void(void *, unsigned char, long int)' [-Werror=builtin-declaration-mismatch]
643 | void __hwasan_tag_memory(unsigned long addr, u8 tag, unsigned long size);
The two problems are:
- Addresses are passes as 'unsigned long' in the kernel, but gcc-13 expects a 'void *'.
- sizes meant to use a signed ssize_t rather than size_t.
Change all the prototypes to match these. Using 'void *' consistently for addresses gets rid of a couple of type casts, so push that down to the leaf functions where possible.
This now passes all randconfig builds on arm, arm64 and x86, but I have not tested it on the other architectures that support kasan, since they tend to fail randconfig builds in other ways. This might fail if any of the 32-bit architectures expect a 'long' instead of 'int' for the size argument.
The __asan_allocas_unpoison() function prototype is somewhat weird, since it uses a pointer for 'stack_top' and an size_t for 'stack_bottom'. This looks like it is meant to be 'addr' and 'size' like the others, but the implementation clearly treats them as 'top' and 'bottom'.
--- arch/arm64/kernel/traps.c | 2 arch/arm64/mm/fault.c | 2 include/linux/kasan.h | 2 mm/kasan/common.c | 2 mm/kasan/generic.c | 72 ++++++++++----------- mm/kasan/kasan.h | 156 +++++++++++++++++++++++----------------------- mm/kasan/report.c | 17 ++--- mm/kasan/report_generic.c | 12 +-- mm/kasan/report_hw_tags.c | 2 mm/kasan/report_sw_tags.c | 2 mm/kasan/shadow.c | 36 +++++----- mm/kasan/sw_tags.c | 20 ++--- 12 files changed, 162 insertions(+), 163 deletions(-)
arch/arm64/kernel/traps.c +1 -1
@@ -1044,7 +1044,7 @@ static int kasan_handler(struct pt_regsbool recover = esr &KASAN_ESR_RECOVER ;bool write = esr &KASAN_ESR_WRITE ;size_t size =KASAN_ESR_SIZE (esr); -u64 addr = regs->regs[0 ]; +void *addr = (void *)regs->regs[0 ];u64 pc = regs->pc;kasan_report (addr, size, write, pc);
arch/arm64/mm/fault.c +1 -1
@@ -317,7 +317,7 @@ static void report_tag_fault(unsigned lo* find out access size. */ bool is_write = !!(esr & ESR_ELx_WNR); - kasan_report(addr, 0, is_write, regs->pc); + kasan_report((void *)addr, 0, is_write, regs->pc); }#else /* Tag faults aren't enabled without CONFIG_KASAN_HW_TAGS. */
include/linux/kasan.h +1 -1
@@ -343,7 +343,7 @@ static inline void *kasan_reset_tag(cons* @is_write: whether the bad access is a write or a read * @ip: instruction pointer for the accessibility check or the bad access itself */ -bool kasan_report (unsigned long addr,size_t size, +bool kasan_report (const void *addr,size_t size,bool is_write,unsigned long ip);#else /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS */
mm/kasan/common.c +1 -1
@@ -445,7 +445,7 @@ void * __must_check __kasan_krealloc(conbool __kasan_check_byte (const void *address,unsigned long ip) {if (!kasan_byte_accessible (address)) { -kasan_report ((unsigned long )address,1 , false, ip); +kasan_report (address,1 , false, ip);return false; }return true;
mm/kasan/generic.c +36 -36
214 lines not on this page · raw message
mm/kasan/kasan.h +78 -78
194 lines not on this page · raw message
mm/kasan/report.c +8 -9
@@ -211,7 +211,7 @@ static void start_report(unsigned long *pr_err ("==================================================================\n" ); } -static void end_report (unsigned long *flags,void *addr) +static void end_report (unsigned long *flags,const void *addr) {if (addr) trace_error_report_end(ERROR_DETECTOR_KASAN,
@@ -450,8 +450,8 @@ static void print_memory_metadata(conststatic void print_report (struct kasan_report_info *info) { -void *addr =kasan_reset_tag (info->access_addr); -u8 tag =get_tag (info->access_addr); +void *addr =kasan_reset_tag ((void *)info->access_addr); +u8 tag =get_tag ((void *)info->access_addr);print_error_description (info);if (addr_has_metadata (addr))
@@ -468,12 +468,12 @@ static void print_report(struct kasan_restatic void complete_report_info (struct kasan_report_info *info) { -void *addr =kasan_reset_tag (info->access_addr); +void *addr =kasan_reset_tag ((void *)info->access_addr);struct slab *slab;if (info->type ==KASAN_REPORT_ACCESS ) info->first_bad_addr =kasan_find_first_bad_addr ( - info->access_addr, info->access_size); + (void *)info->access_addr, info->access_size);else info->first_bad_addr = addr;
@@ -544,11 +544,10 @@ void kasan_report_invalid_free(void *ptr* user_access_save/restore(): kasan_report_invalid_free() cannot be called * from a UACCESS region, and kasan_report_async() is not used on x86. */ -bool kasan_report (unsigned long addr,size_t size,bool is_write, +bool kasan_report (const void *addr,size_t size,bool is_write,unsigned long ip) {bool ret = true; -void *ptr = (void *)addr;unsigned long ua_flags =user_access_save ();unsigned long irq_flags;struct kasan_report_info info;
@@ -562,7 +561,7 @@ bool kasan_report(unsigned long addr, simemset (&info,0 ,sizeof (info)); info.type =KASAN_REPORT_ACCESS ; - info.access_addr = ptr; + info.access_addr = addr; info.access_size = size; info.is_write = is_write; info.ip = ip;
@@ -571,7 +570,7 @@ bool kasan_report(unsigned long addr, siprint_report (&info); -end_report (&irq_flags, ptr); +end_report (&irq_flags, (void *)addr); out:user_access_restore (ua_flags);
mm/kasan/report_generic.c +6 -6
@@ -30,9 +30,9 @@#include "kasan.h" #include "../slab.h" -void *kasan_find_first_bad_addr (void *addr,size_t size) +const void *kasan_find_first_bad_addr (const void *addr,size_t size) { -void *p = addr; +const void *p = addr;if (!addr_has_metadata (p))return p;
@@ -362,14 +362,14 @@ void kasan_print_address_stack_frame(con#endif /* CONFIG_KASAN_STACK */ #define DEFINE_ASAN_REPORT_LOAD (size) \ -void __asan_report_load##size##_noabort(unsigned long addr) \ +void __asan_report_load##size##_noabort(void *addr) \ { \ kasan_report(addr, size, false, _RET_IP_); \ } \ EXPORT_SYMBOL(__asan_report_load##size##_noabort)#define DEFINE_ASAN_REPORT_STORE (size) \ -void __asan_report_store##size##_noabort(unsigned long addr) \ +void __asan_report_store##size##_noabort(void *addr) \ { \ kasan_report(addr, size, true, _RET_IP_); \ } \
@@ -386,13 +386,13 @@ DEFINE_ASAN_REPORT_STORE(4);DEFINE_ASAN_REPORT_STORE (8 );DEFINE_ASAN_REPORT_STORE (16 ); -void __asan_report_load_n_noabort (unsigned long addr,size_t size) +void __asan_report_load_n_noabort (void *addr,ssize_t size) {kasan_report (addr, size, false, _RET_IP_); }EXPORT_SYMBOL (__asan_report_load_n_noabort); -void __asan_report_store_n_noabort (unsigned long addr,size_t size) +void __asan_report_store_n_noabort (void *addr,ssize_t size) {kasan_report (addr, size, true, _RET_IP_); }
mm/kasan/report_hw_tags.c +1 -1
@@ -15,7 +15,7 @@#include "kasan.h" -void *kasan_find_first_bad_addr (void *addr,size_t size) +const void *kasan_find_first_bad_addr (const void *addr,size_t size) {/* * Hardware Tag-Based KASAN only calls this function for normal memory
mm/kasan/report_sw_tags.c +1 -1
@@ -30,7 +30,7 @@#include "kasan.h" #include "../slab.h" -void *kasan_find_first_bad_addr (void *addr,size_t size) +const void *kasan_find_first_bad_addr (const void *addr,size_t size) {u8 tag =get_tag (addr);void *p =kasan_reset_tag (addr);
mm/kasan/shadow.c +18 -18
@@ -28,13 +28,13 @@bool __kasan_check_read (const volatile void *p,unsigned int size) { -return kasan_check_range ((unsigned long )p, size, false, _RET_IP_); +return kasan_check_range ((void *)p, size, false, _RET_IP_); }EXPORT_SYMBOL (__kasan_check_read);bool __kasan_check_write (const volatile void *p,unsigned int size) { -return kasan_check_range ((unsigned long )p, size, true, _RET_IP_); +return kasan_check_range ((void *)p, size, true, _RET_IP_); }EXPORT_SYMBOL (__kasan_check_write);
@@ -50,7 +50,7 @@ EXPORT_SYMBOL(__kasan_check_write);#undef memsetvoid *memset (void *addr,int c,size_t len) { -if (!kasan_check_range ((unsigned long )addr, len, true, _RET_IP_)) +if (!kasan_check_range (addr, len, true, _RET_IP_))return NULL ;return __memset (addr, c, len);
@@ -60,8 +60,8 @@ void *memset(void *addr, int c, size_t l#undef memmovevoid *memmove (void *dest,const void *src,size_t len) { -if (!kasan_check_range ((unsigned long )src, len, false, _RET_IP_) || - !kasan_check_range ((unsigned long )dest, len, true, _RET_IP_)) +if (!kasan_check_range (src, len, false, _RET_IP_) || + !kasan_check_range (dest, len, true, _RET_IP_))return NULL ;return __memmove (dest, src, len);
@@ -71,17 +71,17 @@ void *memmove(void *dest, const void *sr#undef memcpyvoid *memcpy (void *dest,const void *src,size_t len) { -if (!kasan_check_range ((unsigned long )src, len, false, _RET_IP_) || - !kasan_check_range ((unsigned long )dest, len, true, _RET_IP_)) +if (!kasan_check_range (src, len, false, _RET_IP_) || + !kasan_check_range (dest, len, true, _RET_IP_))return NULL ;return __memcpy (dest, src, len); }#endif -void *__asan_memset (void *addr,int c,size_t len) +void *__asan_memset (void *addr,int c,ssize_t len) { -if (!kasan_check_range ((unsigned long )addr, len, true, _RET_IP_)) +if (!kasan_check_range (addr, len, true, _RET_IP_))return NULL ;return __memset (addr, c, len);
@@ -89,10 +89,10 @@ void *__asan_memset(void *addr, int c, sEXPORT_SYMBOL (__asan_memset);#ifdef __HAVE_ARCH_MEMMOVE -void *__asan_memmove (void *dest,const void *src,size_t len) +void *__asan_memmove (void *dest,const void *src,ssize_t len) { -if (!kasan_check_range ((unsigned long )src, len, false, _RET_IP_) || - !kasan_check_range ((unsigned long )dest, len, true, _RET_IP_)) +if (!kasan_check_range (src, len, false, _RET_IP_) || + !kasan_check_range (dest, len, true, _RET_IP_))return NULL ;return __memmove (dest, src, len);
@@ -100,10 +100,10 @@ void *__asan_memmove(void *dest, const vEXPORT_SYMBOL (__asan_memmove);#endif -void *__asan_memcpy (void *dest,const void *src,size_t len) +void *__asan_memcpy (void *dest,const void *src,ssize_t len) { -if (!kasan_check_range ((unsigned long )src, len, false, _RET_IP_) || - !kasan_check_range ((unsigned long )dest, len, true, _RET_IP_)) +if (!kasan_check_range (src, len, false, _RET_IP_) || + !kasan_check_range (dest, len, true, _RET_IP_))return NULL ;return __memcpy (dest, src, len);
@@ -111,13 +111,13 @@ void *__asan_memcpy(void *dest, const voEXPORT_SYMBOL (__asan_memcpy);#ifdef CONFIG_KASAN_SW_TAGS -void *__hwasan_memset (void *addr,int c,size_t len)__alias (__asan_memset); +void *__hwasan_memset (void *addr,int c,ssize_t len)__alias (__asan_memset);EXPORT_SYMBOL (__hwasan_memset);#ifdef __HAVE_ARCH_MEMMOVE -void *__hwasan_memmove (void *dest,const void *src,size_t len)__alias (__asan_memmove); +void *__hwasan_memmove (void *dest,const void *src,ssize_t len)__alias (__asan_memmove);EXPORT_SYMBOL (__hwasan_memmove);#endif -void *__hwasan_memcpy (void *dest,const void *src,size_t len)__alias (__asan_memcpy); +void *__hwasan_memcpy (void *dest,const void *src,ssize_t len)__alias (__asan_memcpy);EXPORT_SYMBOL (__hwasan_memcpy);#endif
mm/kasan/sw_tags.c +10 -10
@@ -70,8 +70,8 @@ u8 kasan_random_tag(void)return (u8)(state % (KASAN_TAG_MAX +1 )); } -bool kasan_check_range (unsigned long addr,size_t size,bool write, -unsigned long ret_ip) +bool kasan_check_range (const void *addr,size_t size,bool write, +unsigned long ret_ip) {u8 tag;u8 *shadow_first, *shadow_last, *shadow;
@@ -133,12 +133,12 @@ bool kasan_byte_accessible(const void *a }#define DEFINE_HWASAN_LOAD_STORE (size) \ - void __hwasan_load##size##_noabort(unsigned long addr) \ + void __hwasan_load##size##_noabort(void *addr) \ { \ - kasan_check_range(addr, size, false, _RET_IP_); \ + kasan_check_range(addr, size, false, _RET_IP_); \ } \ EXPORT_SYMBOL(__hwasan_load##size##_noabort); \ - void __hwasan_store##size##_noabort(unsigned long addr) \ + void __hwasan_store##size##_noabort(void *addr) \ { \ kasan_check_range(addr, size, true, _RET_IP_); \ } \
@@ -150,25 +150,25 @@ DEFINE_HWASAN_LOAD_STORE(4);DEFINE_HWASAN_LOAD_STORE (8 );DEFINE_HWASAN_LOAD_STORE (16 ); -void __hwasan_loadN_noabort (unsigned long addr,unsigned long size) +void __hwasan_loadN_noabort (void *addr,ssize_t size) {kasan_check_range (addr, size, false, _RET_IP_); }EXPORT_SYMBOL (__hwasan_loadN_noabort); -void __hwasan_storeN_noabort (unsigned long addr,unsigned long size) +void __hwasan_storeN_noabort (void *addr,ssize_t size) {kasan_check_range (addr, size, true, _RET_IP_); }EXPORT_SYMBOL (__hwasan_storeN_noabort); -void __hwasan_tag_memory (unsigned long addr,u8 tag,unsigned long size) +void __hwasan_tag_memory (void *addr,u8 tag,ssize_t size) { -kasan_poison ((void *)addr, size, tag, false); +kasan_poison (addr, size, tag, false); }EXPORT_SYMBOL (__hwasan_tag_memory); -void kasan_tag_mismatch (unsigned long addr,unsigned long access_info, +void kasan_tag_mismatch (void *addr,unsigned long access_info,unsigned long ret_ip) { kasan_report(addr, 1 << (access_info & 0xf), access_info & 0x10,
Greg Kroah-Hartman
maintainerPATCH 138/292 kasan, slub: fix HW_TAGS zeroing with slub_debug
In reply to Greg Kroah-HartmanFrom: Andrey Konovalov <[email protected]>
commit fdb54d96600aafe45951f549866cd6fc1af59954 upstream.
Commit 946fa0dbf2d8 ("mm/slub: extend redzone check to extra allocated kmalloc space than requested") added precise kmalloc redzone poisoning to the slub_debug functionality.
However, this commit didn't account for HW_TAGS KASAN fully initializing the object via its built-in memory initialization feature. Even though HW_TAGS KASAN memory initialization contains special memory initialization handling for when slub_debug is enabled, it does not account for in-object slub_debug redzones. As a result, HW_TAGS KASAN can overwrite these redzones and cause false-positive slub_debug reports.
To fix the issue, avoid HW_TAGS KASAN memory initialization when slub_debug is enabled altogether. Implement this by moving the __slub_debug_enabled check to slab_post_alloc_hook. Common slab code seems like a more appropriate place for a slub_debug check anyway.
--- mm/kasan/kasan.h | 12 ------------ mm/slab.h | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 14 deletions(-)
mm/kasan/kasan.h +0 -12
@@ -466,18 +466,6 @@ static inline void kasan_unpoison(constif (WARN_ON ((unsigned long )addr &KASAN_GRANULE_MASK ))return ; -/* -* Explicitly initialize the memory with the precise object size to -* avoid overwriting the slab redzone. This disables initialization in -* the arch code and may thus lead to performance penalty. This penalty -* does not affect production builds, as slab redzones are not enabled -* there. -*/ -if (__slub_debug_enabled () && - init && ((unsigned long )size &KASAN_GRANULE_MASK )) { - init = false; -memzero_explicit ((void *)addr, size); - } size =round_up (size,KASAN_GRANULE_SIZE );hw_set_mem_tag_range ((void *)addr, size, tag, init);
mm/slab.h +14 -2
@@ -684,6 +684,7 @@ static inline void slab_post_alloc_hook( unsigned int orig_size) {unsigned int zero_size = s->object_size; +bool kasan_init = init;size_t i; flags &= gfp_allowed_mask;
@@ -701,6 +702,17 @@ static inline void slab_post_alloc_hook( zero_size = orig_size;/* +* When slub_debug is enabled, avoid memory initialization integrated +* into KASAN and instead zero out the memory via the memset below with +* the proper size. Otherwise, KASAN might overwrite SLUB redzones and +* cause false-positive reports. This does not lead to a performance +* penalty on production builds, as slub_debug is not intended to be +* enabled there. +*/ +if (__slub_debug_enabled ()) + kasan_init = false; + +/* * As memory initialization might be integrated into KASAN, * kasan_slab_alloc and initialization memset must be * kept together to avoid discrepancies in behavior.
@@ -708,8 +720,8 @@ static inline void slab_post_alloc_hook(* As p[i] might get tagged, memset and kmemleak hook come after KASAN. */ for (i =0 ; i < size; i++) { - p[i] =kasan_slab_alloc (s, p[i], flags, init); -if (p[i] && init && !kasan_has_integrated_init ()) + p[i] =kasan_slab_alloc (s, p[i], flags, kasan_init); +if (p[i] && init && (!kasan_init || !kasan_has_integrated_init ()))memset (p[i],0 , zero_size);kmemleak_alloc_recursive (p[i], s->object_size,1 , s->flags, flags);
Greg Kroah-Hartman
maintainerPATCH 139/292 kasan: fix type cast in memory_is_poisoned_n
In reply to Greg Kroah-HartmanFrom: Andrey Konovalov <[email protected]>
commit 05c56e7b4319d7f6352f27da876a1acdc8fa5cc4 upstream.
Commit bb6e04a173f0 ("kasan: use internal prototypes matching gcc-13 builtins") introduced a bug into the memory_is_poisoned_n implementation:
it effectively removed the cast to a signed integer type after applying KASAN_GRANULE_MASK.
As a result, KASAN started failing to properly check memset, memcpy, and other similar functions.
Fix the bug by adding the cast back (through an additional signed integer variable to make the code more readable).
--- mm/kasan/generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
mm/kasan/generic.c +2 -1
@@ -130,9 +130,10 @@ static __always_inline bool memory_is_poif (unlikely (ret)) {const void *last_byte = addr + size -1 ;s8 *last_shadow = (s8 *)kasan_mem_to_shadow (last_byte); +s8 last_accessible_byte = (unsigned long )last_byte &KASAN_GRANULE_MASK ;if (unlikely (ret != (unsigned long )last_shadow || - (((long )last_byte &KASAN_GRANULE_MASK ) >= *last_shadow))) + last_accessible_byte >= *last_shadow))return true; }return false;
Greg Kroah-Hartman
maintainerPATCH 140/292 tracing/user_events: Fix incorrect return value for writing operation when events are disabled
In reply to Greg Kroah-HartmanFrom: sunliming <[email protected]>
commit f6d026eea390d59787a6cdc2ef5c983d02e029d0 upstream.
The writing operation return the count of writes regardless of whether events are enabled or disabled. Switch it to return -EBADF to indicates that the event is disabled.
Cc: [email protected]7f5a08c79df35 ("user_events: Add minimal support for trace_event into ftrace")
--- kernel/trace/trace_events_user.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/trace_events_user.c +2 -1
@@ -2096,7 +2096,8 @@ static ssize_t user_events_write_core(stif (unlikely (faulted))return -EFAULT ; - } + }else +return -EBADF ;return ret; }
Greg Kroah-Hartman
maintainerPATCH 141/292 powerpc: Fail build if using recordmcount with binutils v2.37
In reply to Greg Kroah-HartmanFrom: Naveen N Rao <[email protected]>
commit 25ea739ea1d4d3de41acc4f4eb2d1a97eee0eb75 upstream.
binutils v2.37 drops unused section symbols, which prevents recordmcount from capturing mcount locations in sections that have no non-weak symbols. This results in a build failure with a message such as:
Cannot find symbol for section 12: .text.perf_callchain_kernel. kernel/events/callchain.o: failed
The change to binutils was reverted for v2.38, so this behavior is specific to binutils v2.37:
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=c09c8b42021180eee9495bd50d8b35e683d3901b
Objtool is able to cope with such sections, so this issue is specific to recordmcount.
Fail the build and print a warning if binutils v2.37 is detected and if we are using recordmcount.
--- arch/powerpc/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/powerpc/Makefile +8 -0
@@ -409,3 +409,11 @@ checkbin: echo -n '*** Please use a different binutils version.' ; \ false ; \ fi + @if test "x${CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT}" = "xy" -a \ + "x${CONFIG_LD_IS_BFD}" = "xy" -a \ + "${CONFIG_LD_VERSION}" = "23700" ; then \ + echo -n '*** binutils 2.37 drops unused section symbols, which recordmcount ' ; \ + echo 'is unable to handle.' ; \ + echo '*** Please use a different binutils version.' ; \ + false ; \ + fi
Greg Kroah-Hartman
maintainerPATCH 142/292 misc: fastrpc: Create fastrpc scalar with correct buffer count
In reply to Greg Kroah-HartmanFrom: Ekansh Gupta <[email protected]>
commit 0b4e32df3e09406b835d8230b9331273f2805058 upstream.
A process can spawn a PD on DSP with some attributes that can be associated with the PD during spawn and run. The invocation corresponding to the create request with attributes has total 4 buffers at the DSP side implementation. If this number is not correct, the invocation is expected to fail on DSP. Added change to use correct number of buffer count for creating fastrpc scalar.
Message-ID: <[email protected]>
--- drivers/misc/fastrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/misc/fastrpc.c +1 -1
@@ -1437,7 +1437,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl, sc =FASTRPC_SCALARS (FASTRPC_RMID_INIT_CREATE ,4 ,0 );if (init.attrs) - sc =FASTRPC_SCALARS (FASTRPC_RMID_INIT_CREATE_ATTR ,6 ,0 ); + sc =FASTRPC_SCALARS (FASTRPC_RMID_INIT_CREATE_ATTR ,4 ,0 ); err =fastrpc_internal_invoke (fl, true,FASTRPC_INIT_HANDLE , sc, args);
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 143/292 powerpc/security: Fix Speculation_Store_Bypass reporting on Power10
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit 5bcedc5931e7bd6928a2d8207078d4cb476b3b55 upstream.
Nageswara reported that /proc/self/status was showing "vulnerable" for the Speculation_Store_Bypass feature on Power10, eg:
$ grep Speculation_Store_Bypass: /proc/self/status Speculation_Store_Bypass: vulnerable
But at the same time the sysfs files, and lscpu, were showing "Not affected".
This turns out to simply be a bug in the reporting of the Speculation_Store_Bypass, aka. PR_SPEC_STORE_BYPASS, case.
When SEC_FTR_STF_BARRIER was added, so that firmware could communicate the vulnerability was not present, the code in ssb_prctl_get() was not updated to check the new flag.
So add the check for SEC_FTR_STF_BARRIER being disabled. Rather than adding the new check to the existing if block and expanding the comment to cover both cases, rewrite the three cases to be separate so they can be commented separately for clarity.
--- arch/powerpc/kernel/security.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
arch/powerpc/kernel/security.c +18 -17
@@ -364,26 +364,27 @@ ssize_t cpu_show_spec_store_bypass(strucstatic int ssb_prctl_get (struct task_struct *task) { +/* +* The STF_BARRIER feature is on by default, so if it's off that means +* firmware has explicitly said the CPU is not vulnerable via either +* the hypercall or device tree. +*/ +if (!security_ftr_enabled (SEC_FTR_STF_BARRIER )) +return PR_SPEC_NOT_AFFECTED ; + +/* +* If the system's CPU has no known barrier (see setup_stf_barrier()) +* then assume that the CPU is not vulnerable. +*/ if (stf_enabled_flush_types ==STF_BARRIER_NONE ) -/* -* We don't have an explicit signal from firmware that we're -* vulnerable or not, we only have certain CPU revisions that -* are known to be vulnerable. -* -* We assume that if we're on another CPU, where the barrier is -* NONE, then we are not vulnerable. -*/ return PR_SPEC_NOT_AFFECTED ; -else -/* -* If we do have a barrier type then we are vulnerable. The -* barrier is not a global or per-process mitigation, so the -* only value we can report here is PR_SPEC_ENABLE, which -* appears as "vulnerable" in /proc. -*/ -return PR_SPEC_ENABLE ; -return -EINVAL ; +/* +* Otherwise the CPU is vulnerable. The barrier is not a global or +* per-process mitigation, so the only value that can be reported here +* is PR_SPEC_ENABLE, which appears as "vulnerable" in /proc. +*/ +return PR_SPEC_ENABLE ; }int arch_prctl_spec_ctrl_get (struct task_struct *task,unsigned long which)
Greg Kroah-Hartman
maintainerPATCH 144/292 powerpc/64s: Fix native_hpte_remove() to be irq-safe
In reply to Greg Kroah-HartmanFrom: Michael Ellerman <[email protected]>
commit 8bbe9fee5848371d4af101be445303cac8d880c5 upstream.
Lockdep warns that the use of the hpte_lock in native_hpte_remove() is not safe against an IRQ coming in:
================================
WARNING: inconsistent lock state
6.4.0-rc2-g0c54f4d30ecc #1 Not tainted
--------------------------------
inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage. qemu-system-ppc/93865 [HC0[0]:SC0[0]:HE1:SE1] takes:
c0000000021f5180 (hpte_lock){+.?.}-{0:0}, at: native_lock_hpte+0x8/0xd0 {IN-SOFTIRQ-W} state was registered at:
lock_acquire+0x134/0x3f0
native_lock_hpte+0x44/0xd0
native_hpte_insert+0xd4/0x2a0
__hash_page_64K+0x218/0x4f0
hash_page_mm+0x464/0x840
do_hash_fault+0x11c/0x260
data_access_common_virt+0x210/0x220
__ip_select_ident+0x140/0x150
...
net_rx_action+0x3bc/0x440
__do_softirq+0x180/0x534
...
sys_sendmmsg+0x34/0x50
system_call_exception+0x128/0x320
system_call_common+0x160/0x2e4
...
Possible unsafe locking scenario: CPU0
----
lock(hpte_lock);
<Interrupt>
lock(hpte_lock); *** DEADLOCK ***
...
Call Trace:
dump_stack_lvl+0x98/0xe0 (unreliable)
print_usage_bug.part.0+0x250/0x278
mark_lock+0xc9c/0xd30
__lock_acquire+0x440/0x1ca0
lock_acquire+0x134/0x3f0
native_lock_hpte+0x44/0xd0
native_hpte_remove+0xb0/0x190
kvmppc_mmu_map_page+0x650/0x698 [kvm_pr]
kvmppc_handle_pagefault+0x534/0x6e8 [kvm_pr]
kvmppc_handle_exit_pr+0x6d8/0xe90 [kvm_pr]
after_sprg3_load+0x80/0x90 [kvm_pr]
kvmppc_vcpu_run_pr+0x108/0x270 [kvm_pr]
kvmppc_vcpu_run+0x34/0x48 [kvm]
kvm_arch_vcpu_ioctl_run+0x340/0x470 [kvm]
kvm_vcpu_ioctl+0x338/0x8b8 [kvm]
sys_ioctl+0x7c4/0x13e0
system_call_exception+0x128/0x320
system_call_common+0x160/0x2e4I suspect kvm_pr is the only caller that doesn't already have IRQs disabled, which is why this hasn't been reported previously.
Fix it by disabling IRQs in native_hpte_remove().
--- arch/powerpc/mm/book3s64/hash_native.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
arch/powerpc/mm/book3s64/hash_native.c +9 -4
@@ -328,10 +328,12 @@ static long native_hpte_insert(unsignedstatic long native_hpte_remove (unsigned long hpte_group) { +unsigned long hpte_v, flags;struct hash_pte *hptep;int i;int slot_offset; -unsigned long hpte_v; + +local_irq_save (flags);DBG_LOW (" remove(group=%lx)\n" , hpte_group);
@@ -356,13 +358,16 @@ static long native_hpte_remove(unsigned slot_offset &=0x7 ; } -if (i ==HPTES_PER_GROUP ) -return -1 ; +if (i ==HPTES_PER_GROUP ) { + i =-1 ; + goto out; + }/* Invalidate the hpte. NOTE: this also unlocks it */ release_hpte_lock (); hptep->v =0 ; - +out: +local_irq_restore (flags);return i; }
Greg Kroah-Hartman
maintainerPATCH 145/292 drm/amd/display: perform a bounds check before filling dirty rectangles
In reply to Greg Kroah-HartmanFrom: Hamza Mahfooz <[email protected]>
commit af22d6a869cc26b519bfdcd54293c53f2e491870 upstream.
Currently, it is possible for us to access memory that we shouldn't. Since, we acquire (possibly dangling) pointers to dirty rectangles before doing a bounds check to make sure we can actually accommodate the number of dirty rectangles userspace has requested to fill. This issue is especially evident if a compositor requests both MPO and damage clips at the same time, in which case I have observed a soft-hang. So, to avoid this issue, perform the bounds check before filling a single dirty rectangle and WARN() about it, if it is ever attempted in fill_dc_dirty_rect().
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +4 -9
@@ -5057,11 +5057,7 @@ static inline void fill_dc_dirty_rect(st s32 y, s32 width, s32 height, int *i, bool ffu) { - if (*i > DC_MAX_DIRTY_RECTS) - return; - -if (*i ==DC_MAX_DIRTY_RECTS ) - goto out; + WARN_ON(*i >= DC_MAX_DIRTY_RECTS); dirty_rect->x = x; dirty_rect->y = y;
@@ -5077,7 +5073,6 @@ static inline void fill_dc_dirty_rect(st"[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)" , plane->base.id, x, y, width, height); -out: (*i)++; }
@@ -5164,6 +5159,9 @@ static void fill_dc_dirty_rects(struct d *dirty_regions_changed = bb_changed; +if ((num_clips + (bb_changed ?2 :0 )) >DC_MAX_DIRTY_RECTS ) + goto ffu; +if (bb_changed) { fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i], new_plane_state->crtc_x,
@@ -5193,9 +5191,6 @@ static void fill_dc_dirty_rects(struct d new_plane_state->crtc_h, &i, false); } -if (i >DC_MAX_DIRTY_RECTS ) - goto ffu; - flip_addrs->dirty_rect_count = i;return ;
Greg Kroah-Hartman
maintainerPATCH 146/292 MIPS: cpu-features: Use boot_cpu_type for CPU type based features
In reply to Greg Kroah-HartmanFrom: Jiaxun Yang <[email protected]>
commit 5487a7b60695a92cf998350e4beac17144c91fcd upstream.
Some CPU feature macros were using current_cpu_type to mark feature availability.
However current_cpu_type will use smp_processor_id, which is prohibited under preemptable context.
Since those features are all uniform on all CPUs in a SMP system, use boot_cpu_type instead of current_cpu_type to fix preemptable kernel.
--- arch/mips/include/asm/cpu-features.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/mips/include/asm/cpu-features.h +2 -2
@@ -125,7 +125,7 @@ ({ \ int __res; \ \ - switch (current_cpu_type()) { \ + switch (boot_cpu_type()) { \ case CPU_CAVIUM_OCTEON: \ case CPU_CAVIUM_OCTEON_PLUS: \ case CPU_CAVIUM_OCTEON2: \
@@ -368,7 +368,7 @@ ({ \ int __res; \ \ - switch (current_cpu_type()) { \ + switch (boot_cpu_type()) { \ case CPU_M14KC: \ case CPU_74K: \ case CPU_1074K: \
Greg Kroah-Hartman
maintainerPATCH 147/292 MIPS: Loongson: Fix cpu_probe_loongson() again
In reply to Greg Kroah-HartmanFrom: Huacai Chen <[email protected]>
commit 65fee014dc41a774bcd94896f3fb380bc39d8dda upstream.
Commit 7db5e9e9e5e6c10d7d ("MIPS: loongson64: fix FTLB configuration") move decode_configs() from the beginning of cpu_probe_loongson() to the end in order to fix FTLB configuration. However, it breaks the CPUCFG decoding because decode_configs() use "c->options = xxxx" rather than "c->options |= xxxx", all information get from CPUCFG by decode_cpucfg() is lost.
This causes error when creating a KVM guest on Loongson-3A4000:
Exception Code: 4 not handled @ PC: 0000000087ad5981, inst: 0xcb7a1898 BadVaddr: 0x0 Status: 0x0
Fix this by moving the c->cputype setting to the beginning and moving decode_configs() after that.
--- arch/mips/kernel/cpu-probe.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
arch/mips/kernel/cpu-probe.c +3 -6
@@ -1677,7 +1677,10 @@ static inline void decode_cpucfg(structstatic inline void cpu_probe_loongson (struct cpuinfo_mips *c,unsigned int cpu) { + c->cputype =CPU_LOONGSON64 ; +/* All Loongson processors covered here define ExcCode 16 as GSExc. */ +decode_configs (c); c->options |=MIPS_CPU_GSEXCEX ;switch (c->processor_id &PRID_IMP_MASK ) {
@@ -1687,7 +1690,6 @@ static inline void cpu_probe_loongson(stcase PRID_REV_LOONGSON2K_R1_1 :case PRID_REV_LOONGSON2K_R1_2 :case PRID_REV_LOONGSON2K_R1_3 : - c->cputype =CPU_LOONGSON64 ; __cpu_name[cpu] ="Loongson-2K" ;set_elf_platform (cpu,"gs264e" );set_isa (c,MIPS_CPU_ISA_M64R2 );
@@ -1700,14 +1702,12 @@ static inline void cpu_probe_loongson(stswitch (c->processor_id &PRID_REV_MASK ) {case PRID_REV_LOONGSON3A_R2_0 :case PRID_REV_LOONGSON3A_R2_1 : - c->cputype =CPU_LOONGSON64 ; __cpu_name[cpu] ="ICT Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 );break ;case PRID_REV_LOONGSON3A_R3_0 :case PRID_REV_LOONGSON3A_R3_1 : - c->cputype =CPU_LOONGSON64 ; __cpu_name[cpu] ="ICT Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 );
@@ -1727,7 +1727,6 @@ static inline void cpu_probe_loongson(st c->ases &= ~MIPS_ASE_VZ ;/* VZ of Loongson-3A2000/3000 is incomplete */ break ;case PRID_IMP_LOONGSON_64G : - c->cputype =CPU_LOONGSON64 ; __cpu_name[cpu] ="ICT Loongson-3" ;set_elf_platform (cpu,"loongson3a" );set_isa (c,MIPS_CPU_ISA_M64R2 );
@@ -1737,8 +1736,6 @@ static inline void cpu_probe_loongson(stpanic ("Unknown Loongson Processor ID!" ); break; } - -decode_configs (c); }#else static inline void cpu_probe_loongson (struct cpuinfo_mips *c,unsigned int cpu) { }
Greg Kroah-Hartman
maintainerPATCH 148/292 MIPS: Loongson: Fix build error when make modules_install
In reply to Greg Kroah-HartmanFrom: Huacai Chen <[email protected]>
commit 531b3d1195d096f14e030c4b01ec3a53b80276bf upstream.
After commit 0e96ea5c3eb5904e5dc2f ("MIPS: Loongson64: Clean up use of cc-ifversion") we get a build error when make modules_install:
cc1: error: '-mloongson-mmi' must be used with '-mhard-float'
The reason is when make modules_install, 'call cc-option' doesn't work in $(KBUILD_CFLAGS) of 'CHECKFLAGS'. Then there is no -mno-loongson-mmi applied and -march=loongson3a enable MMI instructions.
To be detail, the error message comes from the CHECKFLAGS invocation of $(CC) but it has no impact on the final result of make modules_install, it is purely a cosmetic issue. The error occurs because cc-option is defined in scripts/Makefile.compiler, which is not included in Makefile when running 'make modules_install', as install targets are not supposed to require the compiler; see commit 805b2e1d427aab4b ("kbuild: include Makefile.compiler only when compiler is needed"). As a result, the call to check for '-mno-loongson-mmi' just never happens.
Fix this by partially reverting to the old logic, use 'call cc-option' to conditionally apply -march=loongson3a and -march=mips64r2.
By the way, Loongson-2E/2F is also broken in commit 13ceb48bc19c563e05f4 ("MIPS: Loongson2ef: Remove unnecessary {as,cc}-option calls") so fix it together.
--- arch/mips/Makefile | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
arch/mips/Makefile +3 -7
@@ -181,16 +181,12 @@ endif cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1 cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap -cflags-$(CONFIG_CPU_LOONGSON2E) += -march=loongson2e -Wa,--trap -cflags-$(CONFIG_CPU_LOONGSON2F) += -march=loongson2f -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2E) += $(call cc-option,-march=loongson2e) -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON2F) += $(call cc-option,-march=loongson2f) -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON64) += $(call cc-option,-march=loongson3a,-march=mips64r2) -Wa,--trap # Some -march= flags enable MMI instructions, and GCC complains about that # support being enabled alongside -msoft-float. Thus explicitly disable MMI. cflags-$(CONFIG_CPU_LOONGSON2EF) += $(call cc-option,-mno-loongson-mmi) -ifdef CONFIG_CPU_LOONGSON64 -cflags-$(CONFIG_CPU_LOONGSON64) += -Wa,--trap -cflags-$(CONFIG_CC_IS_GCC) += -march=loongson3a -cflags-$(CONFIG_CC_IS_CLANG) += -march=mips64r2 -endif cflags-$(CONFIG_CPU_LOONGSON64) += $(call cc-option,-mno-loongson-mmi) cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
Greg Kroah-Hartman
maintainerPATCH 149/292 MIPS: KVM: Fix NULL pointer dereference
In reply to Greg Kroah-HartmanFrom: Huacai Chen <[email protected]>
commit e4de2057698636c0ee709e545d19b169d2069fa3 upstream.
After commit 45c7e8af4a5e3f0bea4ac209 ("MIPS: Remove KVM_TE support") we get a NULL pointer dereference when creating a KVM guest:
[ 146.243409] Starting KVM with MIPS VZ extensions [ 149.849151] CPU 3 Unable to handle kernel paging request at virtual address 0000000000000300, epc == ffffffffc06356ec, ra == ffffffffc063568c [ 149.849177] Oops[#1]: [ 149.849182] CPU: 3 PID: 2265 Comm: qemu-system-mip Not tainted 6.4.0-rc3+ #1671 [ 149.849188] Hardware name: THTF CX TL630 Series/THTF-LS3A4000-7A1000-ML4A, BIOS KL4.1F.TF.D.166.201225.R 12/25/2020 [ 149.849192] $ 0 : 0000000000000000 000000007400cce0 0000000000400004 ffffffff8119c740 [ 149.849209] $ 4 : 000000007400cce1 000000007400cce1 0000000000000000 0000000000000000 [ 149.849221] $ 8 : 000000240058bb36 ffffffff81421ac0 0000000000000000 0000000000400dc0 [ 149.849233] $12 : 9800000102a07cc8 ffffffff80e40e38 0000000000000001 0000000000400dc0 [ 149.849245] $16 : 0000000000000000 9800000106cd0000 9800000106cd0000 9800000100cce000 [ 149.849257] $20 : ffffffffc0632b28 ffffffffc05b31b0 9800000100ccca00 0000000000400000 [ 149.849269] $24 : 9800000106cd09ce ffffffff802f69d0 [ 149.849281] $28 : 9800000102a04000 9800000102a07cd0 98000001106a8000 ffffffffc063568c [ 149.849293] Hi : 00000335b2111e66 [ 149.849295] Lo : 6668d90061ae0ae9 [ 149.849298] epc : ffffffffc06356ec kvm_vz_vcpu_setup+0xc4/0x328 [kvm] [ 149.849324] ra : ffffffffc063568c kvm_vz_vcpu_setup+0x64/0x328 [kvm] [ 149.849336] Status: 7400cce3 KX SX UX KERNEL EXL IE [ 149.849351] Cause : 1000000c (ExcCode 03) [ 149.849354] BadVA : 0000000000000300 [ 149.849357] PrId : 0014c004 (ICT Loongson-3) [ 149.849360] Modules linked in: kvm nfnetlink_queue nfnetlink_log nfnetlink fuse sha256_generic libsha256 cfg80211 rfkill binfmt_misc vfat fat snd_hda_codec_hdmi input_leds led_class snd_hda_intel snd_intel_dspcfg snd_hda_codec snd_hda_core snd_pcm snd_timer snd serio_raw xhci_pci radeon drm_suballoc_helper drm_display_helper xhci_hcd ip_tables x_tables [ 149.849432] Process qemu-system-mip (pid: 2265, threadinfo=00000000ae2982d2, task=0000000038e09ad4, tls=000000ffeba16030) [ 149.849439] Stack : 9800000000000003 9800000100ccca00 9800000100ccc000 ffffffffc062cef4 [ 149.849453] 9800000102a07d18 c89b63a7ab338e00 0000000000000000 ffffffff811a0000 [ 149.849465] 0000000000000000 9800000106cd0000 ffffffff80e59938 98000001106a8920 [ 149.849476] ffffffff80e57f30 ffffffffc062854c ffffffff811a0000 9800000102bf4240 [ 149.849488] ffffffffc05b0000 ffffffff80e3a798 000000ff78000000 000000ff78000010 [ 149.849500] 0000000000000255 98000001021f7de0 98000001023f0078 ffffffff81434000 [ 149.849511] 0000000000000000 0000000000000000 9800000102ae0000 980000025e92ae28 [ 149.849523] 0000000000000000 c89b63a7ab338e00 0000000000000001 ffffffff8119dce0 [ 149.849535] 000000ff78000010 ffffffff804f3d3c 9800000102a07eb0 0000000000000255 [ 149.849546] 0000000000000000 ffffffff8049460c 000000ff78000010 0000000000000255 [ 149.849558] ... [ 149.849565] Call Trace: [ 149.849567] [<ffffffffc06356ec>] kvm_vz_vcpu_setup+0xc4/0x328 [kvm] [ 149.849586] [<ffffffffc062cef4>] kvm_arch_vcpu_create+0x184/0x228 [kvm] [ 149.849605] [<ffffffffc062854c>] kvm_vm_ioctl+0x64c/0xf28 [kvm] [ 149.849623] [<ffffffff805209c0>] sys_ioctl+0xc8/0x118 [ 149.849631] [<ffffffff80219eb0>] syscall_common+0x34/0x58
The root cause is the deletion of kvm_mips_commpage_init() leaves vcpu ->arch.cop0 NULL. So fix it by making cop0 from a pointer to an embedded object.
--- arch/mips/include/asm/kvm_host.h | 6 +++--- arch/mips/kvm/emulate.c | 22 +++++++++++----------- arch/mips/kvm/mips.c | 16 ++++++++-------- arch/mips/kvm/trace.h | 8 ++++---- arch/mips/kvm/vz.c | 20 ++++++++++---------- 5 files changed, 36 insertions(+), 36 deletions(-)
arch/mips/include/asm/kvm_host.h +3 -3
@@ -317,7 +317,7 @@ struct kvm_vcpu_arch {unsigned int aux_inuse;/* COP0 State */ -struct mips_coproc *cop0; +struct mips_coproc cop0;/* Resume PC after MMIO completion */ unsigned long io_pc;
@@ -698,7 +698,7 @@ static inline bool kvm_mips_guest_can_hastatic inline bool kvm_mips_guest_has_fpu (struct kvm_vcpu_arch *vcpu) {return kvm_mips_guest_can_have_fpu (vcpu) && -kvm_read_c0_guest_config1 (vcpu->cop0) &MIPS_CONF1_FP ; +kvm_read_c0_guest_config1 (&vcpu->cop0) &MIPS_CONF1_FP ; }static inline bool kvm_mips_guest_can_have_msa (struct kvm_vcpu_arch *vcpu)
@@ -710,7 +710,7 @@ static inline bool kvm_mips_guest_can_hastatic inline bool kvm_mips_guest_has_msa (struct kvm_vcpu_arch *vcpu) {return kvm_mips_guest_can_have_msa (vcpu) && -kvm_read_c0_guest_config3 (vcpu->cop0) &MIPS_CONF3_MSA ; +kvm_read_c0_guest_config3 (&vcpu->cop0) &MIPS_CONF3_MSA ; }struct kvm_mips_callbacks {
arch/mips/kvm/emulate.c +11 -11
@@ -312,7 +312,7 @@ int kvm_get_badinstrp(u32 *opc, struct k*/ int kvm_mips_count_disabled (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;return (vcpu->arch.count_ctl &KVM_REG_MIPS_COUNT_CTL_DC ) || (kvm_read_c0_guest_cause (cop0) &CAUSEF_DC );
@@ -384,7 +384,7 @@ static inline ktime_t kvm_mips_count_tim*/ static u32 kvm_mips_read_count_running (struct kvm_vcpu *vcpu,ktime_t now) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;ktime_t expires, threshold;u32 count, compare;int running;
@@ -444,7 +444,7 @@ static u32 kvm_mips_read_count_running(s*/ u32 kvm_mips_read_count (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;/* If count disabled just read static copy of count */ if (kvm_mips_count_disabled (vcpu))
@@ -502,7 +502,7 @@ ktime_t kvm_mips_freeze_hrtimer(struct kstatic void kvm_mips_resume_hrtimer (struct kvm_vcpu *vcpu,ktime_t now,u32 count) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;u32 compare;u64 delta;ktime_t expire;
@@ -603,7 +603,7 @@ resume:*/ void kvm_mips_write_count (struct kvm_vcpu *vcpu,u32 count) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;ktime_t now;/* Calculate bias */
@@ -649,7 +649,7 @@ void kvm_mips_init_count(struct kvm_vcpu*/ int kvm_mips_set_count_hz (struct kvm_vcpu *vcpu,s64 count_hz) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;int dc;ktime_t now;u32 count;
@@ -696,7 +696,7 @@ int kvm_mips_set_count_hz(struct kvm_vcp*/ void kvm_mips_write_compare (struct kvm_vcpu *vcpu,u32 compare,bool ack) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;int dc;u32 old_compare =kvm_read_c0_guest_compare (cop0);s32 delta = compare - old_compare;
@@ -779,7 +779,7 @@ void kvm_mips_write_compare(struct kvm_v*/ static ktime_t kvm_mips_count_disable (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;u32 count;ktime_t now;
@@ -806,7 +806,7 @@ static ktime_t kvm_mips_count_disable(st*/ void kvm_mips_count_disable_cause (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;kvm_set_c0_guest_cause (cop0,CAUSEF_DC );if (!(vcpu->arch.count_ctl &KVM_REG_MIPS_COUNT_CTL_DC ))
@@ -826,7 +826,7 @@ void kvm_mips_count_disable_cause(struct*/ void kvm_mips_count_enable_cause (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;u32 count;kvm_clear_c0_guest_cause (cop0,CAUSEF_DC );
@@ -852,7 +852,7 @@ void kvm_mips_count_enable_cause(struct*/ int kvm_mips_set_count_ctl (struct kvm_vcpu *vcpu,s64 count_ctl) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;s64 changed = count_ctl ^ vcpu->arch.count_ctl;s64 delta;ktime_t expire, now;
arch/mips/kvm/mips.c +8 -8
@@ -649,7 +649,7 @@ static int kvm_mips_copy_reg_indices(strstatic int kvm_mips_get_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;struct mips_fpu_struct *fpu = &vcpu->arch.fpu;int ret;s64 v;
@@ -761,7 +761,7 @@ static int kvm_mips_get_reg(struct kvm_vstatic int kvm_mips_set_reg (struct kvm_vcpu *vcpu,const struct kvm_one_reg *reg) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;struct mips_fpu_struct *fpu = &vcpu->arch.fpu;s64 v;s64 vs[2 ];
@@ -1086,7 +1086,7 @@ int kvm_vm_ioctl_check_extension(structint kvm_cpu_has_pending_timer (struct kvm_vcpu *vcpu) {return kvm_mips_pending_timer (vcpu) || -kvm_read_c0_guest_cause (vcpu->arch.cop0) &C_TI ; +kvm_read_c0_guest_cause (&vcpu->arch.cop0) &C_TI ; }int kvm_arch_vcpu_dump_regs (struct kvm_vcpu *vcpu)
@@ -1110,7 +1110,7 @@ int kvm_arch_vcpu_dump_regs(struct kvm_vkvm_debug ("\thi: 0x%08lx\n" , vcpu->arch.hi);kvm_debug ("\tlo: 0x%08lx\n" , vcpu->arch.lo); - cop0 = vcpu->arch.cop0; + cop0 = &vcpu->arch.cop0;kvm_debug ("\tStatus: 0x%08x, Cause: 0x%08x\n" ,kvm_read_c0_guest_status (cop0),kvm_read_c0_guest_cause (cop0));
@@ -1232,7 +1232,7 @@ static int __kvm_mips_handle_exit(structcase EXCCODE_TLBS :kvm_debug ("TLB ST fault: cause %#x, status %#x, PC: %p, BadVaddr: %#lx\n" , - cause,kvm_read_c0_guest_status (vcpu->arch.cop0), opc, + cause,kvm_read_c0_guest_status (&vcpu->arch.cop0), opc, badvaddr); ++vcpu->stat.tlbmiss_st_exits;
@@ -1304,7 +1304,7 @@ static int __kvm_mips_handle_exit(structkvm_get_badinstr (opc, vcpu, &inst);kvm_err ("Exception Code: %d, not yet handled, @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#x\n" , exccode, opc, inst, badvaddr, -kvm_read_c0_guest_status (vcpu->arch.cop0)); +kvm_read_c0_guest_status (&vcpu->arch.cop0));kvm_arch_vcpu_dump_regs (vcpu); run->exit_reason =KVM_EXIT_INTERNAL_ERROR ; ret =RESUME_HOST ;
@@ -1377,7 +1377,7 @@ int noinstr kvm_mips_handle_exit(struct/* Enable FPU for guest and restore context */ void kvm_own_fpu (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;unsigned int sr, cfg5;preempt_disable ();
@@ -1421,7 +1421,7 @@ void kvm_own_fpu(struct kvm_vcpu *vcpu)/* Enable MSA for guest and restore context */ void kvm_own_msa (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;unsigned int sr, cfg5;preempt_disable ();
arch/mips/kvm/trace.h +4 -4
@@ -322,11 +322,11 @@ TRACE_EVENT_FN(kvm_guest_mode_change, ),TP_fast_assign ( - __entry->epc = kvm_read_c0_guest_epc(vcpu->arch.cop0); + __entry->epc = kvm_read_c0_guest_epc(&vcpu->arch.cop0); __entry->pc = vcpu->arch.pc; - __entry->badvaddr =kvm_read_c0_guest_badvaddr (vcpu->arch.cop0); - __entry->status =kvm_read_c0_guest_status (vcpu->arch.cop0); - __entry->cause =kvm_read_c0_guest_cause (vcpu->arch.cop0); + __entry->badvaddr =kvm_read_c0_guest_badvaddr (&vcpu->arch.cop0); + __entry->status =kvm_read_c0_guest_status (&vcpu->arch.cop0); + __entry->cause =kvm_read_c0_guest_cause (&vcpu->arch.cop0); ), TP_printk("EPC: 0x%08lx PC: 0x%08lx Status: 0x%08x Cause: 0x%08x BadVAddr: 0x%08lx",
arch/mips/kvm/vz.c +10 -10
@@ -422,7 +422,7 @@ static void _kvm_vz_restore_htimer(struc*/ static void kvm_vz_restore_timer (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;u32 cause, compare; compare =kvm_read_sw_gc0_compare (cop0);
@@ -517,7 +517,7 @@ static void _kvm_vz_save_htimer(struct k*/ static void kvm_vz_save_timer (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;u32 gctl0, compare, cause; gctl0 =read_c0_guestctl0 ();
@@ -863,7 +863,7 @@ static unsigned long mips_process_maar(ustatic void kvm_write_maari (struct kvm_vcpu *vcpu,unsigned long val) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0; val &=MIPS_MAARI_INDEX ;if (val ==MIPS_MAARI_INDEX )
@@ -876,7 +876,7 @@ static enum emulation_result kvm_vz_gpsi u32 *opc, u32 cause, struct kvm_vcpu *vcpu) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0;enum emulation_result er =EMULATE_DONE ;u32 rt, rd, sel;unsigned long curr_pc;
@@ -1911,7 +1911,7 @@ static int kvm_vz_get_one_reg(struct kvmconst struct kvm_one_reg *reg, s64 *v) { - struct mips_coproc *cop0 = vcpu->arch.cop0; + struct mips_coproc *cop0 = &vcpu->arch.cop0;unsigned int idx;switch (reg->id) {
@@ -2081,7 +2081,7 @@ static int kvm_vz_get_one_reg(struct kvmcase KVM_REG_MIPS_CP0_MAARI :if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar)return -EINVAL ; - *v =kvm_read_sw_gc0_maari (vcpu->arch.cop0); + *v =kvm_read_sw_gc0_maari (&vcpu->arch.cop0);break ;#ifdef CONFIG_64BIT case KVM_REG_MIPS_CP0_XCONTEXT :
@@ -2135,7 +2135,7 @@ static int kvm_vz_set_one_reg(struct kvm const struct kvm_one_reg *reg, s64 v) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;unsigned int idx;int ret =0 ;unsigned int cur, change;
@@ -2562,7 +2562,7 @@ static void kvm_vz_vcpu_load_tlb(structstatic int kvm_vz_vcpu_load (struct kvm_vcpu *vcpu,int cpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;bool migrated, all;/*
@@ -2704,7 +2704,7 @@ static int kvm_vz_vcpu_load(struct kvm_vstatic int kvm_vz_vcpu_put (struct kvm_vcpu *vcpu,int cpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;if (current->flags &PF_VCPU )kvm_vz_vcpu_save_wired (vcpu);
@@ -3076,7 +3076,7 @@ static void kvm_vz_vcpu_uninit(struct kvstatic int kvm_vz_vcpu_setup (struct kvm_vcpu *vcpu) { -struct mips_coproc *cop0 = vcpu->arch.cop0; +struct mips_coproc *cop0 = &vcpu->arch.cop0;unsigned long count_hz =100 *1000 *1000 ;/* default to 100 MHz */ /*
Greg Kroah-Hartman
maintainerPATCH 150/292 ext4: Fix reusing stale buffer heads from last failed mounting
In reply to Greg Kroah-HartmanFrom: Zhihao Cheng <[email protected]>
commit 26fb5290240dc31cae99b8b4dd2af7f46dfcba6b upstream.
Following process makes ext4 load stale buffer heads from last failed mounting in a new mounting operation:mount_bdev
ext4_fill_super
| ext4_load_and_init_journal
| ext4_load_journal
| jbd2_journal_load
| load_superblock
| journal_get_superblock
| set_buffer_verified(bh) // buffer head is verified
| jbd2_journal_recover // failed caused by EIO
| goto failed_mount3a // skip 'sb->s_root' initialization
deactivate_locked_super
kill_block_super
generic_shutdown_super
if (sb->s_root)
// false, skip ext4_put_super->invalidate_bdev->
// invalidate_mapping_pages->mapping_evict_folio->
// filemap_release_folio->try_to_free_buffers, which
// cannot drop buffer head.
blkdev_put
blkdev_put_whole
if (atomic_dec_and_test(&bdev->bd_openers))
// false, systemd-udev happens to open the device. Then
// blkdev_flush_mapping->kill_bdev->truncate_inode_pages->
// truncate_inode_folio->truncate_cleanup_folio->
// folio_invalidate->block_invalidate_folio->
// filemap_release_folio->try_to_free_buffers will be skipped,
// dropping buffer head is missed again.Second mount:ext4_fill_super
ext4_load_and_init_journal
ext4_load_journal
ext4_get_journal
jbd2_journal_init_inode
journal_init_common
bh = getblk_unmovable
bh = __find_get_block // Found stale bh in last failed mounting
journal->j_sb_buffer = bh
jbd2_journal_load
load_superblock
journal_get_superblock
if (buffer_verified(bh))
// true, skip journal->j_format_version = 2, value is 0
jbd2_journal_recover
do_one_pass
next_log_block += count_tags(journal, bh)
// According to journal_tag_bytes(), 'tag_bytes' calculating is
// affected by jbd2_has_feature_csum3(), jbd2_has_feature_csum3()
// returns false because 'j->j_format_version >= 2' is not true,
// then we get wrong next_log_block. The do_one_pass may exit
// early whenoccuring non JBD2_MAGIC_NUMBER in 'next_log_block'.The filesystem is corrupted here, journal is partially replayed, and new journal sequence number actually is already used by last mounting.
The invalidate_bdev() can drop all buffer heads even racing with bare reading block device(eg. systemd-udev), so we can fix it by invalidating bdev in error handling path in __ext4_fill_super().
Fetch a reproducer in [Link].
--- fs/ext4/super.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
fs/ext4/super.c +7 -6
@@ -1128,6 +1128,12 @@ static void ext4_blkdev_remove(struct exstruct block_device *bdev; bdev = sbi->s_journal_bdev;if (bdev) { +/* +* Invalidate the journal device's buffers. We don't want them +* floating about in memory - the physical journal device may +* hotswapped, and it breaks the `ro-after' testing code. +*/ +invalidate_bdev (bdev);ext4_blkdev_put (bdev); sbi->s_journal_bdev =NULL ; }
@@ -1328,13 +1334,7 @@ static void ext4_put_super(struct super_sync_blockdev (sb->s_bdev);invalidate_bdev (sb->s_bdev);if (sbi->s_journal_bdev && sbi->s_journal_bdev != sb->s_bdev) { -/* -* Invalidate the journal device's buffers. We don't want them -* floating about in memory - the physical journal device may -* hotswapped, and it breaks the `ro-after' testing code. -*/ sync_blockdev (sbi->s_journal_bdev); -invalidate_bdev (sbi->s_journal_bdev);ext4_blkdev_remove (sbi); }
@@ -5645,6 +5645,7 @@ failed_mount:brelse (sbi->s_sbh);ext4_blkdev_remove (sbi); out_fail: +invalidate_bdev (sb->s_bdev); sb->s_fs_info =NULL ;return err; }
Greg Kroah-Hartman
maintainerPATCH 151/292 ext4: fix wrong unit use in ext4_mb_clear_bb
In reply to Greg Kroah-HartmanFrom: Kemeng Shi <[email protected]>
commit 247c3d214c23dfeeeb892e91a82ac1188bdaec9f upstream.
Function ext4_issue_discard need count in cluster. Pass count_clusters instead of count to fix the mismatch.
--- fs/ext4/mballoc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ext4/mballoc.c +2 -2
@@ -6243,8 +6243,8 @@ do_more:* them with group lock_held */ if (test_opt (sb,DISCARD )) { - err =ext4_issue_discard (sb, block_group, bit, count, -NULL ); + err =ext4_issue_discard (sb, block_group, bit, + count_clusters,NULL );if (err && err != -EOPNOTSUPP )ext4_msg (sb,KERN_WARNING ,"discard request in" " group:%u block:%d count:%lu failed"
Greg Kroah-Hartman
maintainerPATCH 152/292 ext4: get block from bh in ext4_free_blocks for fast commit replay
In reply to Greg Kroah-HartmanFrom: Kemeng Shi <[email protected]>
commit 11b6890be0084ad4df0e06d89a9fdcc948472c65 upstream.
ext4_free_blocks will retrieve block from bh if block parameter is zero. Retrieve block before ext4_free_blocks_simple to avoid potentially passing wrong block to ext4_free_blocks_simple.
--- fs/ext4/mballoc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
fs/ext4/mballoc.c +7 -6
@@ -6328,12 +6328,6 @@ void ext4_free_blocks(handle_t *handle, sbi =EXT4_SB (sb); -if (sbi->s_mount_state &EXT4_FC_REPLAY ) { -ext4_free_blocks_simple (inode, block, count); -return ; - } - -might_sleep ();if (bh) {if (block)BUG_ON (block != bh->b_blocknr);
@@ -6341,6 +6335,13 @@ void ext4_free_blocks(handle_t *handle, block = bh->b_blocknr; } +if (sbi->s_mount_state &EXT4_FC_REPLAY ) { +ext4_free_blocks_simple (inode, block, count); +return ; + } + +might_sleep (); +if (!(flags &EXT4_FREE_BLOCKS_VALIDATED ) && !ext4_inode_block_valid (inode, block, count)) { ext4_error(sb, "Freeing blocks not in datazone - "
Greg Kroah-Hartman
maintainerPATCH 153/292 ext4: fix wrong unit use in ext4_mb_new_blocks
In reply to Greg Kroah-HartmanFrom: Kemeng Shi <[email protected]>
commit 2ec6d0a5ea72689a79e6f725fd8b443a788ae279 upstream.
Function ext4_free_blocks_simple needs count in cluster. Function ext4_free_blocks accepts count in block. Convert count to cluster to fix the mismatch.
--- fs/ext4/mballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/mballoc.c +1 -1
@@ -6336,7 +6336,7 @@ void ext4_free_blocks(handle_t *handle, }if (sbi->s_mount_state &EXT4_FC_REPLAY ) { -ext4_free_blocks_simple (inode, block, count); +ext4_free_blocks_simple (inode, block,EXT4_NUM_B2C (sbi, count));return ; }
Greg Kroah-Hartman
maintainerPATCH 154/292 ext4: avoid updating the superblock on a r/o mount if not needed
In reply to Greg Kroah-HartmanFrom: Theodore Ts'o <[email protected]>
commit 2ef6c32a914b85217b44a0a2418e830e520b085e upstream.
This was noticed by a user who noticied that the mtime of a file backing a loopback device was getting bumped when the loopback device is mounted read/only. Note: This doesn't show up when doing a loopback mount of a file directly, via "mount -o ro /tmp/foo.img /mnt", since the loop device is set read-only when mount automatically creates loop device. However, this is noticeable for a LUKS loop device like this:
% cryptsetup luksOpen /tmp/foo.img test
% mount -o ro /dev/loop0 /mnt ; umount /mnt
or, if LUKS is not in use, if the user manually creates the loop device like this:
% losetup /dev/loop0 /tmp/foo.img
% mount -o ro /dev/loop0 /mnt ; umount /mnt
The modified mtime causes rsync to do a rolling checksum scan of the file on the local and remote side, incrementally increasing the time to rsync the not-modified-but-touched image file.
--- fs/ext4/super.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
fs/ext4/super.c +10 -2
@@ -5980,19 +5980,27 @@ static int ext4_load_journal(struct supe err =jbd2_journal_wipe (journal, !really_read_only);if (!err) {char *save =kmalloc (EXT4_S_ERR_LEN ,GFP_KERNEL ); +__le16 orig_state; +bool changed = false;if (save)memcpy (save, ((char *) es) +EXT4_S_ERR_START ,EXT4_S_ERR_LEN ); err =jbd2_journal_load (journal); -if (save) +if (save &&memcmp (((char *) es) +EXT4_S_ERR_START , + save,EXT4_S_ERR_LEN )) {memcpy (((char *) es) +EXT4_S_ERR_START , save,EXT4_S_ERR_LEN ); + changed = true; + }kfree (save); + orig_state = es->s_state; es->s_state |=cpu_to_le16 (EXT4_SB (sb)->s_mount_state &EXT4_ERROR_FS ); +if (orig_state != es->s_state) + changed = true;/* Write out restored error information to the superblock */ -if (!bdev_read_only (sb->s_bdev)) { +if (changed && !really_read_only) {int err2; err2 =ext4_commit_super (sb); err = err ? : err2;
Greg Kroah-Hartman
maintainerPATCH 155/292 ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
In reply to Greg Kroah-HartmanFrom: Chao Yu <[email protected]>
commit c4d13222afd8a64bf11bc7ec68645496ee8b54b9 upstream.
freeze_bdev() can fail due to a lot of reasons, it needs to check its reason before later process.
--- fs/ext4/ioctl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
fs/ext4/ioctl.c +4 -1
@@ -797,6 +797,7 @@ static int ext4_shutdown(struct super_bl {struct ext4_sb_info *sbi =EXT4_SB (sb);__u32 flags; +int ret;if (!capable (CAP_SYS_ADMIN ))return -EPERM ;
@@ -815,7 +816,9 @@ static int ext4_shutdown(struct super_blswitch (flags) {case EXT4_GOING_FLAGS_DEFAULT : -freeze_bdev (sb->s_bdev); + ret =freeze_bdev (sb->s_bdev); +if (ret) +return ret;set_bit (EXT4_FLAGS_SHUTDOWN , &sbi->s_ext4_flags);thaw_bdev (sb->s_bdev);break ;
Greg Kroah-Hartman
maintainerPATCH 156/292 ext4: turn quotas off if mount failed after enabling quotas
In reply to Greg Kroah-HartmanFrom: Baokun Li <[email protected]>
commit d13f99632748462c32fc95d729f5e754bab06064 upstream.
Yi found during a review of the patch "ext4: don't BUG on inconsistent journal feature" that when ext4_mark_recovery_complete() returns an error value, the error handling path does not turn off the enabled quotas, which triggers the following kmemleak:
================================================================
unreferenced object 0xffff8cf68678e7c0 (size 64):
comm "mount", pid 746, jiffies 4294871231 (age 11.540s) hex dump (first 32 bytes):
00 90 ef 82 f6 8c ff ff 00 00 00 00 41 01 00 00 ............A... c7 00 00 00 bd 00 00 00 0a 00 00 00 48 00 00 00 ............H... backtrace:
[<00000000c561ef24>] __kmem_cache_alloc_node+0x4d4/0x880 [<00000000d4e621d7>] kmalloc_trace+0x39/0x140 [<00000000837eee74>] v2_read_file_info+0x18a/0x3a0 [<0000000088f6c877>] dquot_load_quota_sb+0x2ed/0x770 [<00000000340a4782>] dquot_load_quota_inode+0xc6/0x1c0 [<0000000089a18bd5>] ext4_enable_quotas+0x17e/0x3a0 [ext4] [<000000003a0268fa>] __ext4_fill_super+0x3448/0x3910 [ext4] [<00000000b0f2a8a8>] ext4_fill_super+0x13d/0x340 [ext4] [<000000004a9489c4>] get_tree_bdev+0x1dc/0x370 [<000000006e723bf1>] ext4_get_tree+0x1d/0x30 [ext4] [<00000000c7cb663d>] vfs_get_tree+0x31/0x160 [<00000000320e1bed>] do_new_mount+0x1d5/0x480 [<00000000c074654c>] path_mount+0x22e/0xbe0 [<0000000003e97a8e>] do_mount+0x95/0xc0 [<000000002f3d3736>] __x64_sys_mount+0xc4/0x160 [<0000000027d2140c>] do_syscall_64+0x3f/0x90 ================================================================
To solve this problem, we add a "failed_mount10" tag, and call ext4_quota_off_umount() in this tag to release the enabled qoutas.
--- fs/ext4/super.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/ext4/super.c +4 -2
@@ -5567,7 +5567,7 @@ static int __ext4_fill_super(struct fs_cext4_msg (sb,KERN_INFO ,"recovery complete" ); err =ext4_mark_recovery_complete (sb, es);if (err) - goto failed_mount9; + goto failed_mount10; }if (test_opt (sb,DISCARD ) && !bdev_max_discard_sectors (sb->s_bdev))
@@ -5586,7 +5586,9 @@ static int __ext4_fill_super(struct fs_creturn 0 ; -failed_mount9: +failed_mount10: +ext4_quota_off_umount (sb); +failed_mount9:__maybe_unused ext4_release_orphan_info (sb); failed_mount8:ext4_unregister_sysfs (sb);
Greg Kroah-Hartman
maintainerPATCH 157/292 ext4: only update i_reserved_data_blocks on successful block allocation
In reply to Greg Kroah-HartmanFrom: Baokun Li <[email protected]>
commit de25d6e9610a8b30cce9bbb19b50615d02ebca02 upstream.
In our fault injection test, we create an ext4 file, migrate it to non-extent based file, then punch a hole and finally trigger a WARN_ON in the ext4_da_update_reserve_space():
EXT4-fs warning (device sda): ext4_da_update_reserve_space:369:
ino 14, used 11 with only 10 reserved data blocks
When writing back a non-extent based file, if we enable delalloc, the number of reserved blocks will be subtracted from the number of blocks mapped by ext4_ind_map_blocks(), and the extent status tree will be updated. We update the extent status tree by first removing the old extent_status and then inserting the new extent_status. If the block range we remove happens to be in an extent, then we need to allocate another extent_status with ext4_es_alloc_extent().
use old to remove to add new
|----------|------------|------------|
old extent_status
The problem is that the allocation of a new extent_status failed due to a fault injection, and __es_shrink() did not get free memory, resulting in a return of -ENOMEM. Then do_writepages() retries after receiving -ENOMEM, we map to the same extent again, and the number of reserved blocks is again subtracted from the number of blocks in that extent. Since the blocks in the same extent are subtracted twice, we end up triggering WARN_ON at ext4_da_update_reserve_space() because used > ei->i_reserved_data_blocks.
For non-extent based file, we update the number of reserved blocks after ext4_ind_map_blocks() is executed, which causes a problem that when we call ext4_ind_map_blocks() to create a block, it doesn't always create a block, but we always reduce the number of reserved blocks. So we move the logic for updating reserved blocks to ext4_ind_map_blocks() to ensure that the number of reserved blocks is updated only after we do succeed in allocating some new blocks.
--- fs/ext4/indirect.c | 8 ++++++++ fs/ext4/inode.c | 10 ---------- 2 files changed, 8 insertions(+), 10 deletions(-)
fs/ext4/indirect.c +8 -0
@@ -651,6 +651,14 @@ int ext4_ind_map_blocks(handle_t *handleext4_update_inode_fsync_trans (handle, inode,1 ); count = ar.len; + +/* +* Update reserved blocks/metadata blocks after successful block +* allocation which had been deferred till now. +*/ +if (flags &EXT4_GET_BLOCKS_DELALLOC_RESERVE ) +ext4_da_update_reserve_space (inode, count,1 ); + got_it: map->m_flags |=EXT4_MAP_MAPPED ; map->m_pblk =le32_to_cpu (chain[depth-1 ].key);
fs/ext4/inode.c +0 -10
@@ -632,16 +632,6 @@ found:*/ ext4_clear_inode_state (inode,EXT4_STATE_EXT_MIGRATE ); } - -/* -* Update reserved blocks/metadata blocks after successful -* block allocation which had been deferred till now. We don't -* support fallocate for non extent files. So we can update -* reserve space here. -*/ -if ((retval >0 ) && - (flags &EXT4_GET_BLOCKS_DELALLOC_RESERVE )) -ext4_da_update_reserve_space (inode, retval,1 ); }if (retval >0 ) {
Greg Kroah-Hartman
maintainerPATCH 158/292 fs: dlm: revert check required context while close
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit c6b6d6dcc7f32767d57740e0552337c8de40610b upstream.
This patch reverts commit 2c3fa6ae4d52 ("dlm: check required context while close"). The function dlm_midcomms_close(), which will call later dlm_lowcomms_close(), is called when the cluster manager tells the node got fenced which means on midcomms/lowcomms layer to disconnect the node from the cluster communication. The node can rejoin the cluster later. This patch was ensuring no new message were able to be triggered when we are in the close() function context. This was done by checking if the lockspace has been stopped. However there is a missing check that we only need to check specific lockspaces where the fenced node is member of. This is currently complicated because there is no way to easily check if a node is part of a specific lockspace without stopping the recovery. For now we just revert this commit as it is just a check to finding possible leaks of stopping lockspaces before close() is called.
--- fs/dlm/lockspace.c | 12 ------------ fs/dlm/lockspace.h | 1 - fs/dlm/midcomms.c | 3 --- 3 files changed, 16 deletions(-)
fs/dlm/lockspace.c +0 -12
@@ -935,15 +935,3 @@ void dlm_stop_lockspaces(void)log_print ("dlm user daemon left %d lockspaces" , count); } -void dlm_stop_lockspaces_check (void ) -{ -struct dlm_ls *ls; - -spin_lock (&lslist_lock); -list_for_each_entry (ls, &lslist, ls_list) { -if (WARN_ON (!rwsem_is_locked (&ls->ls_in_recovery) || - !dlm_locking_stopped (ls))) -break ; - } -spin_unlock (&lslist_lock); -}
fs/dlm/lockspace.h +0 -1
@@ -27,7 +27,6 @@ struct dlm_ls *dlm_find_lockspace_local(struct dlm_ls *dlm_find_lockspace_device (int minor);void dlm_put_lockspace (struct dlm_ls *ls);void dlm_stop_lockspaces (void ); -void dlm_stop_lockspaces_check (void ); int dlm_new_user_lockspace(const char *name, const char *cluster, uint32_t flags, int lvblen, const struct dlm_lockspace_ops *ops,
fs/dlm/midcomms.c +0 -3
@@ -136,7 +136,6 @@#include <net/tcp.h> #include "dlm_internal.h" -#include "lockspace.h" #include "lowcomms.h" #include "config.h" #include "memory.h"
@@ -1491,8 +1490,6 @@ int dlm_midcomms_close(int nodeid)if (nodeid ==dlm_our_nodeid ())return 0 ; -dlm_stop_lockspaces_check (); - idx =srcu_read_lock (&nodes_srcu);/* Abort pending close/remove operation */ node =nodeid2node (nodeid,0 );
Greg Kroah-Hartman
maintainerPATCH 159/292 mm/mmap: Fix error return in do_vmi_align_munmap()
In reply to Greg Kroah-HartmanFrom: David Woodhouse <[email protected]>
commit 6c26bd4384da24841bac4f067741bbca18b0fb74 upstream.
If mas_store_gfp() in the gather loop failed, the 'error' variable that ultimately gets returned was not being set. In many cases, its original value of -ENOMEM was still in place, and that was fine. But if VMAs had been split at the start or end of the range, then 'error' could be zero.
Change to the 'error = foo(); if (error) goto …' idiom to fix the bug.
Also clean up a later case which avoided the same bug by *explicitly* setting error = -ENOMEM right before calling the function that might return -ENOMEM.
In a final cosmetic change, move the 'Point of no return' comment to *after* the goto. That's been in the wrong place since the preallocation was removed, and this new error path was added.
--- mm/mmap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
mm/mmap.c +5 -4
@@ -2480,7 +2480,8 @@ do_vmi_align_munmap(struct vma_iterator }vma_start_write (next);mas_set_range (&mas_detach, next->vm_start, next->vm_end -1 ); -if (mas_store_gfp (&mas_detach, next,GFP_KERNEL )) + error =mas_store_gfp (&mas_detach, next,GFP_KERNEL ); +if (error) goto munmap_gather_failed;vma_mark_detached (next, true);if (next->vm_flags &VM_LOCKED )
@@ -2529,12 +2530,12 @@ do_vmi_align_munmap(struct vma_iterator BUG_ON(count != test_count); }#endif -/* Point of no return */ - error = -ENOMEM ;vma_iter_set (vmi, start); -if (vma_iter_clear_gfp (vmi, start, end,GFP_KERNEL )) + error =vma_iter_clear_gfp (vmi, start, end,GFP_KERNEL ); +if (error) goto clear_tree_failed; +/* Point of no return */ mm->locked_vm -= locked_vm; mm->map_count -= count;/*
Greg Kroah-Hartman
maintainerPATCH 160/292 soc: qcom: mdt_loader: Fix unconditional call to scm_pas_mem_setup
In reply to Greg Kroah-HartmanFrom: Christian Marangi <[email protected]>
commit bcb889891371c3cf767f2b9e8768cfe2fdd3810f upstream.
Commit ebeb20a9cd3f ("soc: qcom: mdt_loader: Always invoke PAS mem_setup") dropped the relocate check and made pas_mem_setup run unconditionally. The code was later moved with commit f4e526ff7e38 ("soc: qcom: mdt_loader: Extract PAS operations") to qcom_mdt_pas_init() effectively losing track of what was actually done.
The assumption that PAS mem_setup can be done anytime was effectively wrong, with no good reason and this caused regression on some SoC that use remoteproc to bringup ath11k. One example is IPQ8074 SoC that effectively broke resulting in remoteproc silently die and ath11k not working.
On this SoC FW relocate is not enabled and PAS mem_setup was correctly skipped in previous kernel version resulting in correct bringup and function of remoteproc and ath11k.
To fix the regression, reintroduce the relocate check in qcom_mdt_pas_init() and correctly skip PAS mem_setup where relocate is not enabled.
--- drivers/soc/qcom/mdt_loader.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/soc/qcom/mdt_loader.c +11 -5
@@ -210,6 +210,7 @@ int qcom_mdt_pas_init(struct device *devconst struct elf32_hdr *ehdr;phys_addr_t min_addr =PHYS_ADDR_MAX ;phys_addr_t max_addr =0 ; +bool relocate = false;size_t metadata_len;void *metadata;int ret;
@@ -224,6 +225,9 @@ int qcom_mdt_pas_init(struct device *devif (!mdt_phdr_valid (phdr))continue ; +if (phdr->p_flags &QCOM_MDT_RELOCATABLE ) + relocate = true; +if (phdr->p_paddr < min_addr) min_addr = phdr->p_paddr;
@@ -246,11 +250,13 @@ int qcom_mdt_pas_init(struct device *dev goto out; } - ret =qcom_scm_pas_mem_setup (pas_id, mem_phys, max_addr - min_addr); -if (ret) { -/* Unable to set up relocation */ -dev_err (dev,"error %d setting up firmware %s\n" , ret, fw_name); - goto out; +if (relocate) { + ret =qcom_scm_pas_mem_setup (pas_id, mem_phys, max_addr - min_addr); +if (ret) { +/* Unable to set up relocation */ +dev_err (dev,"error %d setting up firmware %s\n" , ret, fw_name); + goto out; + } } out:
Greg Kroah-Hartman
maintainerPATCH 161/292 ext2/dax: Fix ext2_setsize when len is page aligned
In reply to Greg Kroah-HartmanFrom: Ritesh Harjani (IBM) <[email protected]>
commit fcced95b6ba2a507a83b8b3e0358a8ac16b13e35 upstream.
PAGE_ALIGN(x) macro gives the next highest value which is multiple of pagesize. But if x is already page aligned then it simply returns x. So, if x passed is 0 in dax_zero_range() function, that means the length gets passed as 0 to ->iomap_begin().
In ext2 it then calls ext2_get_blocks -> max_blocks as 0 and hits bug_on here in ext2_get_blocks().
BUG_ON(maxblocks == 0);
Instead we should be calling dax_truncate_page() here which takes care of it. i.e. it only calls dax_zero_range if the offset is not page/block aligned.
This can be easily triggered with following on fsdax mounted pmem device.
dd if=/dev/zero of=file count=1 bs=512
truncate -s 0 file
[79.525838] EXT2-fs (pmem0): DAX enabled. Warning: EXPERIMENTAL, use at your own risk [79.529376] ext2 filesystem being mounted at /mnt1/test supports timestamps until 2038 (0x7fffffff) [93.793207] ------------[ cut here ]------------ [93.795102] kernel BUG at fs/ext2/inode.c:637! [93.796904] invalid opcode: 0000 [#1] PREEMPT SMP PTI [93.798659] CPU: 0 PID: 1192 Comm: truncate Not tainted 6.3.0-rc2-xfstests-00056-g131086faa369 #139 [93.806459] RIP: 0010:ext2_get_blocks.constprop.0+0x524/0x610 <...> [93.835298] Call Trace: [93.836253] <TASK> [93.837103] ? lock_acquire+0xf8/0x110 [93.838479] ? d_lookup+0x69/0xd0 [93.839779] ext2_iomap_begin+0xa7/0x1c0 [93.841154] iomap_iter+0xc7/0x150 [93.842425] dax_zero_range+0x6e/0xa0 [93.843813] ext2_setsize+0x176/0x1b0 [93.845164] ext2_setattr+0x151/0x200 [93.846467] notify_change+0x341/0x4e0 [93.847805] ? lock_acquire+0xf8/0x110 [93.849143] ? do_truncate+0x74/0xe0 [93.850452] ? do_truncate+0x84/0xe0 [93.851739] do_truncate+0x84/0xe0 [93.852974] do_sys_ftruncate+0x2b4/0x2f0 [93.854404] do_syscall_64+0x3f/0x90 [93.855789] entry_SYSCALL_64_after_hwframe+0x72/0xdc
Message-Id: <046a58317f29d9603d1068b2bbae47c2332c17ae.1682069716.git.ritesh.list@gmail.com>
--- fs/ext2/inode.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
fs/ext2/inode.c +2 -3
@@ -1259,9 +1259,8 @@ static int ext2_setsize(struct inode *ininode_dio_wait (inode);if (IS_DAX (inode)) - error =dax_zero_range (inode, newsize, -PAGE_ALIGN (newsize) - newsize,NULL , - &ext2_iomap_ops); + error =dax_truncate_page (inode, newsize,NULL , + &ext2_iomap_ops);else error =block_truncate_page (inode->i_mapping, newsize, ext2_get_block);
Greg Kroah-Hartman
maintainerPATCH 162/292 jfs: jfs_dmap: Validate db_l2nbperpage while mounting
In reply to Greg Kroah-HartmanFrom: Siddh Raman Pant <[email protected]>
commit 11509910c599cbd04585ec35a6d5e1a0053d84c1 upstream.
In jfs_dmap.c at line 381, BLKTODMAP is used to get a logical block number inside dbFree(). db_l2nbperpage, which is the log2 number of blocks per page, is passed as an argument to BLKTODMAP which uses it for shifting.
Syzbot reported a shift out-of-bounds crash because db_l2nbperpage is too big. This happens because the large value is set without any validation in dbMount() at line 181.
Thus, make sure that db_l2nbperpage is correct while mounting.
Max number of blocks per page = Page size / Min block size => log2(Max num_block per page) = log2(Page size / Min block size)
= log2(Page size) - log2(Min block size)
=> Max db_l2nbperpage = L2PSIZE - L2MINBLOCKSIZE
--- fs/jfs/jfs_dmap.c | 6 ++++++ fs/jfs/jfs_filsys.h | 2 ++ 2 files changed, 8 insertions(+)
fs/jfs/jfs_dmap.c +6 -0
@@ -178,7 +178,13 @@ int dbMount(struct inode *ipbmap) dbmp_le = (struct dbmap_disk *) mp->data; bmp->db_mapsize =le64_to_cpu (dbmp_le->dn_mapsize); bmp->db_nfree =le64_to_cpu (dbmp_le->dn_nfree); + bmp->db_l2nbperpage =le32_to_cpu (dbmp_le->dn_l2nbperpage); +if (bmp->db_l2nbperpage >L2PSIZE -L2MINBLOCKSIZE ) { + err = -EINVAL ; + goto err_release_metapage; + } + bmp->db_numag =le32_to_cpu (dbmp_le->dn_numag);if (!bmp->db_numag) { err = -EINVAL ;
fs/jfs/jfs_filsys.h +2 -0
@@ -122,7 +122,9 @@#define NUM_INODE_PER_IAG INOSPERIAG#define MINBLOCKSIZE 512 +#define L2MINBLOCKSIZE 9#define MAXBLOCKSIZE 4096 +#define L2MAXBLOCKSIZE 12#define MAXFILESIZE ((s64)1 << 52)#define JFS_LINK_MAX 0xffffffff
Greg Kroah-Hartman
maintainerPATCH 163/292 arm64: dts: mt7986: use size of reserved partition for bl2
In reply to Greg Kroah-HartmanFrom: Frank Wunderlich <[email protected]>
commit 7afe7b5969329175ac4f55a6b9c13ba4f6dc267e upstream.
To store uncompressed bl2 more space is required than partition is actually defined.
There is currently no known usage of this reserved partition. Openwrt uses same partition layout.
We added same change to u-boot with commit d7bb1099 [1].
[1] https://source.denx.de/u-boot/u-boot/-/commit/d7bb109900c1ca754a0198b9afb50e3161ffc21e
--- .../boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtso +1 -6
@@ -27,15 +27,10 @@ partitions { partition@0 { label = "bl2"; - reg = <0x0 0x20000>; + reg = <0x0 0x40000>; read-only; }; - partition@20000 { - label = "reserved"; - reg = <0x20000 0x20000>; - }; - partition@40000 { label = "u-boot-env"; reg = <0x40000 0x40000>;
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 164/292 arm64: dts: ti: k3-j721s2: Fix wkup pinmux range
In reply to Greg Kroah-HartmanFrom: Sinthu Raja <[email protected]>
commit 6bc829ceea4158c7aeb3a9e73d5c52634d78fb6f upstream.
The WKUP_PADCONFIG register region in J721S2 has multiple non-addressable regions, accordingly split the existing wkup_pmx region as follows to avoid the non-addressable regions and include the rest of valid WKUP_PADCONFIG registers. Also update references to old nodes with new ones.
wkup_pmx0 -> 13 pins (WKUP_PADCONFIG 0 - 12)wkup_pmx1 -> 11 pins (WKUP_PADCONFIG 14 - 24)wkup_pmx2 -> 72 pins (WKUP_PADCONFIG 26 - 97)wkup_pmx3 -> 1 pin (WKUP_PADCONFIG 100)
--- arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts | 42 ++++----- arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts | 76 ++++++++--------- arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi | 29 ++++++ 3 files changed, 87 insertions(+), 60 deletions(-)
arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts +21 -21
@@ -175,49 +175,49 @@ }; }; -&wkup_pmx0 { +&wkup_pmx2 { mcu_cpsw_pins_default: mcu-cpsw-pins-default { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x094, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */ - J721S2_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */ - J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */ - J721S2_WKUP_IOPAD(0x088, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */ - J721S2_WKUP_IOPAD(0x084, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */ - J721S2_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */ - J721S2_WKUP_IOPAD(0x07c, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */ - J721S2_WKUP_IOPAD(0x078, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */ - J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */ - J721S2_WKUP_IOPAD(0x070, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */ - J721S2_WKUP_IOPAD(0x080, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */ - J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */ + J721S2_WKUP_IOPAD(0x02C, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */ + J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */ + J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */ + J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */ + J721S2_WKUP_IOPAD(0x01C, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */ + J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */ + J721S2_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */ + J721S2_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */ + J721S2_WKUP_IOPAD(0x00C, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */ + J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */ + J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */ + J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */ >; }; mcu_mdio_pins_default: mcu-mdio-pins-default { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x09c, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */ - J721S2_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */ + J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */ + J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */ >; }; mcu_mcan0_pins_default: mcu-mcan0-pins-default { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0bc, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */ - J721S2_WKUP_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */ + J721S2_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */ + J721S2_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */ >; }; mcu_mcan1_pins_default: mcu-mcan1-pins-default { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */ - J721S2_WKUP_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX*/ + J721S2_WKUP_IOPAD(0x06C, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */ + J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX*/ >; }; mcu_i2c1_pins_default: mcu-i2c1-pins-default { pinctrl-single,pins = < - J721S2_WKUP_IOPAD(0x0e0, PIN_INPUT, 0) /* (F24) WKUP_GPIO0_8.MCU_I2C1_SCL */ - J721S2_WKUP_IOPAD(0x0e4, PIN_INPUT, 0) /* (H26) WKUP_GPIO0_9.MCU_I2C1_SDA */ + J721S2_WKUP_IOPAD(0x078, PIN_INPUT, 0) /* (F24) WKUP_GPIO0_8.MCU_I2C1_SCL */ + J721S2_WKUP_IOPAD(0x07c, PIN_INPUT, 0) /* (H26) WKUP_GPIO0_9.MCU_I2C1_SDA */ >; }; };
arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts +38 -38
119 lines not on this page · raw message
arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi +28 -1
@@ -50,7 +50,34 @@ wkup_pmx0: pinctrl@4301c000 { compatible = "pinctrl-single"; /* Proxy 0 addressing */ - reg = <0x00 0x4301c000 0x00 0x178>; + reg = <0x00 0x4301c000 0x00 0x034>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx1: pinctrl@4301c038 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c038 0x00 0x02C>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx2: pinctrl@4301c068 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c068 0x00 0x120>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + wkup_pmx3: pinctrl@4301c190 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ + reg = <0x00 0x4301c190 0x00 0x004>; #pinctrl-cells = <1>; pinctrl-single,register-width = <32>; pinctrl-single,function-mask = <0xffffffff>;
Greg Kroah-Hartman
maintainerPATCH 165/292 hwrng: imx-rngc - fix the timeout for init and self check
In reply to Greg Kroah-HartmanFrom: Martin Kaiser <[email protected]>
commit d744ae7477190967a3ddc289e2cd4ae59e8b1237 upstream.
Fix the timeout that is used for the initialisation and for the self test. wait_for_completion_timeout expects a timeout in jiffies, but RNGC_TIMEOUT is in milliseconds. Call msecs_to_jiffies to do the conversion.
--- drivers/char/hw_random/imx-rngc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/char/hw_random/imx-rngc.c +2 -4
@@ -110,7 +110,7 @@ static int imx_rngc_self_test(struct imx cmd =readl (rngc->base +RNGC_COMMAND );writel (cmd |RNGC_CMD_SELF_TEST , rngc->base +RNGC_COMMAND ); - ret =wait_for_completion_timeout (&rngc->rng_op_done,RNGC_TIMEOUT ); + ret =wait_for_completion_timeout (&rngc->rng_op_done,msecs_to_jiffies (RNGC_TIMEOUT ));imx_rngc_irq_mask_clear (rngc);if (!ret)return -ETIMEDOUT ;
@@ -187,9 +187,7 @@ static int imx_rngc_init(struct hwrng *r cmd =readl (rngc->base +RNGC_COMMAND );writel (cmd |RNGC_CMD_SEED , rngc->base +RNGC_COMMAND ); - ret =wait_for_completion_timeout (&rngc->rng_op_done, -RNGC_TIMEOUT ); - + ret =wait_for_completion_timeout (&rngc->rng_op_done,msecs_to_jiffies (RNGC_TIMEOUT ));if (!ret) { ret = -ETIMEDOUT ; goto err;
Greg Kroah-Hartman
maintainerPATCH 166/292 dm integrity: reduce vmalloc space footprint on 32-bit architectures
In reply to Greg Kroah-HartmanFrom: Mikulas Patocka <[email protected]>
commit 6d50eb4725934fd22f5eeccb401000687c790fd0 upstream.
It was reported that dm-integrity runs out of vmalloc space on 32-bit architectures. On x86, there is only 128MiB vmalloc space and dm-integrity consumes it quickly because it has a 64MiB journal and 8MiB recalculate buffer.
Fix this by reducing the size of the journal to 4MiB and the size of the recalculate buffer to 1MiB, so that multiple dm-integrity devices can be created and activated on 32-bit architectures.
--- drivers/md/dm-integrity.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/dm-integrity.c +2 -2
@@ -34,11 +34,11 @@#define DEFAULT_BUFFER_SECTORS 128#define DEFAULT_JOURNAL_WATERMARK 50#define DEFAULT_SYNC_MSEC 10000 -#define DEFAULT_MAX_JOURNAL_SECTORS 131072 +#define DEFAULT_MAX_JOURNAL_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 131072 : 8192)#define MIN_LOG2_INTERLEAVE_SECTORS 3#define MAX_LOG2_INTERLEAVE_SECTORS 31#define METADATA_WORKQUEUE_MAX_ACTIVE 16 -#define RECALC_SECTORS 32768 +#define RECALC_SECTORS (IS_ENABLED(CONFIG_64BIT) ? 32768 : 2048)#define RECALC_WRITE_SUPER 16#define BITMAP_BLOCK_SIZE 4096/* don't change it */ #define BITMAP_FLUSH_INTERVAL (10 * HZ)
Greg Kroah-Hartman
maintainerPATCH 167/292 scsi: mpi3mr: Propagate sense data for admin queue SCSI I/O
In reply to Greg Kroah-HartmanFrom: Sathya Prakash <[email protected]>
commit f762326b2baa86ae647e2ba6832bc87e238f68ad upstream.
Copy the sense data to internal driver buffer when the firmware completes any SCSI I/O command sent through admin queue with sense data for further use.
--- drivers/scsi/mpi3mr/mpi3mr_fw.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/scsi/mpi3mr/mpi3mr_fw.c +5 -0
@@ -402,6 +402,11 @@ static void mpi3mr_process_admin_reply_dmemcpy ((u8 *)cmdptr->reply, (u8 *)def_reply, mrioc->reply_sz); } +if (sense_buf && cmdptr->sensebuf) { + cmdptr->is_sense =1 ; +memcpy (cmdptr->sensebuf, sense_buf, +MPI3MR_SENSE_BUF_SZ ); + }if (cmdptr->is_waiting) {complete (&cmdptr->done); cmdptr->is_waiting =0 ;
Greg Kroah-Hartman
maintainerPATCH 168/292 s390/zcrypt: do not retry administrative requests
In reply to Greg Kroah-HartmanFrom: Harald Freudenberger <[email protected]>
commit af40322e90d4e0093569eceb7d3a28ab635f3e75 upstream.
All kind of administrative requests should not been retried. Some card firmware detects this and assumes a replay attack. This patch checks on failure if the low level functions indicate a retry (EAGAIN) and checks for the ADMIN flag set on the request message. If this both are true, the response code for this message is changed to EIO to make sure the zcrypt API layer does not attempt to retry the request. As of now the ADMIN flag is set for a request message when
- for EP11 the field 'flags' of the EP11 CPRB struct has the leftmost bit set.
- for CCA when the CPRB minor version is 'T3', 'T5', 'T6' or 'T7'.
Please note that the do-not-retry only applies to a request which has been sent to the card (= has been successfully enqueued) but the reply indicates some kind of failure and by default it would be replied. It is totally fine to retry a request if a previous attempt to enqueue the msg into the firmware queue had some kind of failure and thus the card has never seen this request.
--- drivers/s390/crypto/zcrypt_msgtype6.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/s390/crypto/zcrypt_msgtype6.c +6 -0
@@ -1143,6 +1143,9 @@ static long zcrypt_msgtype6_send_cprb(boap_cancel_message (zq->queue, ap_msg); } +if (rc == -EAGAIN && ap_msg->flags &AP_MSG_FLAG_ADMIN ) + rc = -EIO ;/* do not retry administrative requests */ + out:if (rc) ZCRYPT_DBF_DBG("%s send cprb at dev=%02x.%04x rc=%d\n",
@@ -1263,6 +1266,9 @@ static long zcrypt_msgtype6_send_ep11_cpap_cancel_message (zq->queue, ap_msg); } +if (rc == -EAGAIN && ap_msg->flags &AP_MSG_FLAG_ADMIN ) + rc = -EIO ;/* do not retry administrative requests */ + out:if (rc) ZCRYPT_DBF_DBG("%s send cprb at dev=%02x.%04x rc=%d\n",
Greg Kroah-Hartman
maintainerPATCH 169/292 PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
In reply to Greg Kroah-HartmanFrom: Ondrej Zary <[email protected]>
commit 9e30fd26f43b89cb6b4e850a86caa2e50dedb454 upstream.
The quirk for Elo i2 introduced in commit 92597f97a40b ("PCI/PM: Avoid putting Elo i2 PCIe Ports in D3cold") is also needed by EloPOS E2/S2/H2 which uses the same Continental Z2 board.
Change the quirk to match the board instead of system.
--- drivers/pci/pci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/pci/pci.c +5 -5
@@ -2949,13 +2949,13 @@ static const struct dmi_system_id bridge { /* * Downstream device is not accessible after putting a root port - * into D3cold and back into D0 on Elo i2. + * into D3cold and back into D0 on Elo Continental Z2 board */ - .ident = "Elo i2", + .ident = "Elo Continental Z2", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Elo Touch Solutions"), - DMI_MATCH(DMI_PRODUCT_NAME, "Elo i2"), - DMI_MATCH(DMI_PRODUCT_VERSION, "RevB"), + DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"), + DMI_MATCH(DMI_BOARD_NAME, "Geminilake"), + DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"), }, }, #endif
Greg Kroah-Hartman
maintainerPATCH 170/292 PCI: Release resource invalidated by coalescing
In reply to Greg Kroah-HartmanFrom: Ross Lagerwall <[email protected]>
commit e54223275ba1bc6f704a6bab015fcd2ae4f72572 upstream.
When contiguous windows are coalesced by pci_register_host_bridge(), the second resource is expanded to include the first, and the first is invalidated and consequently not added to the bus. However, it remains in the resource hierarchy. For example, these windows:
fec00000-fec7ffff : PCI Bus 0000:00
fec80000-fecbffff : PCI Bus 0000:00
are coalesced into this, where the first resource remains in the tree with start/end zeroed out:
00000000-00000000 : PCI Bus 0000:00
fec00000-fecbffff : PCI Bus 0000:00
In some cases (e.g. the Xen scratch region), this causes future calls to allocate_resource() to choose an inappropriate location which the caller cannot handle.
Fix by releasing the zeroed-out resource and removing it from the resource hierarchy.
--- drivers/pci/probe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/pci/probe.c +3 -1
@@ -997,8 +997,10 @@ static int pci_register_host_bridge(struresource_list_for_each_entry_safe (window, n, &resources) { offset = window->offset; res = window->res; -if (!res->flags && !res->start && !res->end) +if (!res->flags && !res->start && !res->end) { +release_resource (res);continue ; + }list_move_tail (&window->node, &bridge->windows);
Greg Kroah-Hartman
maintainerPATCH 171/292 PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
In reply to Greg Kroah-HartmanFrom: Robin Murphy <[email protected]>
commit 88d341716b83abd355558523186ca488918627ee upstream.
Marvell's own product brief implies the 92xx series are a closely related family, and sure enough it turns out that 9235 seems to need the same quirk as the other three, although possibly only when certain ports are used.
--- drivers/pci/quirks.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/pci/quirks.c +2 -0
@@ -4174,6 +4174,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_M/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */ DECLARE_PCI_FIXUP_HEADER (PCI_VENDOR_ID_MARVELL_EXT ,0x9230 , quirk_dma_func1_alias); +DECLARE_PCI_FIXUP_HEADER (PCI_VENDOR_ID_MARVELL_EXT ,0x9235 , + quirk_dma_func1_alias);DECLARE_PCI_FIXUP_HEADER (PCI_VENDOR_ID_TTI ,0x0642 , quirk_dma_func1_alias); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645,
Greg Kroah-Hartman
maintainerPATCH 172/292 PCI: acpiphp: Reassign resources on bridge if necessary
In reply to Greg Kroah-HartmanFrom: Igor Mammedov <[email protected]>
commit 40613da52b13fb21c5566f10b287e0ca8c12c4e9 upstream.
When using ACPI PCI hotplug, hotplugging a device with large BARs may fail if bridge windows programmed by firmware are not large enough.
Reproducer:
$ qemu-kvm -monitor stdio -M q35 -m 4G \
-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=on \
-device id=rp1,pcie-root-port,bus=pcie.0,chassis=4 \
disk_image wait till linux guest boots, then hotplug device:
(qemu) device_add qxl,bus=rp1
hotplug on guest side fails with:
pci 0000:01:00.0: [1b36:0100] type 00 class 0x038000 pci 0000:01:00.0: reg 0x10: [mem 0x00000000-0x03ffffff] pci 0000:01:00.0: reg 0x14: [mem 0x00000000-0x03ffffff] pci 0000:01:00.0: reg 0x18: [mem 0x00000000-0x00001fff] pci 0000:01:00.0: reg 0x1c: [io 0x0000-0x001f]
pci 0000:01:00.0: BAR 0: no space for [mem size 0x04000000] pci 0000:01:00.0: BAR 0: failed to assign [mem size 0x04000000] pci 0000:01:00.0: BAR 1: no space for [mem size 0x04000000] pci 0000:01:00.0: BAR 1: failed to assign [mem size 0x04000000] pci 0000:01:00.0: BAR 2: assigned [mem 0xfe800000-0xfe801fff] pci 0000:01:00.0: BAR 3: assigned [io 0x1000-0x101f] qxl 0000:01:00.0: enabling device (0000 -> 0003) Unable to create vram_mapping
qxl: probe of 0000:01:00.0 failed with error -12
However when using native PCIe hotplug
'-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off'
it works fine, since kernel attempts to reassign unused resources.
Use the same machinery as native PCIe hotplug to (re)assign resources.
--- drivers/pci/hotplug/acpiphp_glue.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/pci/hotplug/acpiphp_glue.c +1 -4
@@ -498,7 +498,6 @@ static void enable_slot(struct acpiphp_sacpiphp_native_scan_bridge (dev); } }else { -LIST_HEAD (add_list);int max, pass;acpiphp_rescan_slot (slot);
@@ -512,12 +511,10 @@ static void enable_slot(struct acpiphp_sif (pass && dev->subordinate) {check_hotplug_bridge (slot, dev);pcibios_resource_survey_bus (dev->subordinate); -__pci_bus_size_bridges (dev->subordinate, - &add_list); } } } -__pci_bus_assign_resources (bus, &add_list,NULL ); +pci_assign_unassigned_bridge_resources (bus->self); }acpiphp_sanitize_bus (bus);
Thorsten Leemhuis
maintainerRe: [PATCH 6.4 172/292] PCI: acpiphp: Reassign resources on bridge if necessary
Quoted 13 lines · Greg Kroah-Hartman
From: Igor Mammedov <[email protected]>
commit
40613da52b13fb21c5566f10b287e0ca8c12c4e9upstream.When using ACPI PCI hotplug, hotplugging a device with large BARs may fail if bridge windows programmed by firmware are not large enough.
Reproducer:
$ qemu-kvm -monitor stdio -M q35 -m 4G \ -global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=on \ -device id=rp1,pcie-root-port,bus=pcie.0,chassis=4 \ disk_image
Quoted 4 lines
wait till linux guest boots, then hotplug device:
(qemu)device_addqxl,bus=rp1[...]
Greg, just so you know, that patch (which is also queued for 6.1 and 5.15) is known to cause a regression in 6.5-rc. To quote
https://lore.kernel.org/all/[email protected]/
``` Laptop shows a kernel crash trace after a first suspend to ram, on a second attempt to suspend it becomes frozen solid. This is 100% repeatable with a 6.5-rc2 kernel, not happening with a 6.4 kernel - see the attached dmesg output. I have bisected the kernel uilds and it points to : [40613da52b13fb21c5566f10b287e0ca8c12c4e9] PCI: acpiphp: Reassign resources on bridge if necessary Reversing this patch seems to fix the kernel crash problem on my laptop. ```
Ciao, Thorsten
P.S.: I only noticed this by chance and yet again wonder how to handle these situations better. I guess exporting the list of regressions regzbot tracks in some simple format might be a start; then the stable scripts could simply look up commit ids there when a patch is queued and warn if they find it (which won't help in caes the regression is reported after the patch is queued :-/ ).
Re: [PATCH 6.4 172/292] PCI: acpiphp: Reassign resources on bridge if necessary
Quoted 14 lines · Thorsten Leemhuis
Quoted 8 lines · Greg Kroah-Hartman
From: Igor Mammedov <[email protected]>
commit
40613da52b13fb21c5566f10b287e0ca8c12c4e9upstream.When using ACPI PCI hotplug, hotplugging a device with large BARs may fail if bridge windows programmed by firmware are not large enough.
[...]
Greg, just so you know, that patch (which is also queued for 6.1 and 5.15) is known to cause a regression in 6.5-rc. To quote
https://lore.kernel.org/all/[email protected]/
Quoted 12 lines
``` Laptop shows a kernel crash trace after a first suspend to ram, on a second attempt to suspend it becomes frozen solid. This is 100% repeatable with a 6.5-rc2 kernel, not happening with a 6.4 kernel - see the attached dmesg output. I have bisected the kernel uilds and it points to : [40613da52b13fb21c5566f10b287e0ca8c12c4e9] PCI: acpiphp: Reassign resources on bridge if necessary Reversing this patch seems to fix the kernel crash problem on my laptop. ```
Forgot to mention the reply from Bjorn:
```
I queued up a revert of 40613da52b13 ("PCI: acpiphp: Reassign
resources on bridge if necessary") (on my for-linus branch for v6.5).
It looks like a NULL pointer dereference; hopefully the fix is obvious
and I can drop the revert and replace it with the fix.
```Ciao, Thorsten
Greg Kroah-Hartman
maintainerRe: [PATCH 6.4 172/292] PCI: acpiphp: Reassign resources on bridge if necessary
Quoted 30 lines · Linux regression tracking (Thorsten Leemhuis)
Quoted 14 lines · Thorsten Leemhuis
Quoted 8 lines · Greg Kroah-Hartman
From: Igor Mammedov <[email protected]>
commit
40613da52b13fb21c5566f10b287e0ca8c12c4e9upstream.When using ACPI PCI hotplug, hotplugging a device with large BARs may fail if bridge windows programmed by firmware are not large enough.
[...]
Greg, just so you know, that patch (which is also queued for 6.1 and 5.15) is known to cause a regression in 6.5-rc. To quote
https://lore.kernel.org/all/[email protected]/Quoted 12 lines
``` Laptop shows a kernel crash trace after a first suspend to ram, on a second attempt to suspend it becomes frozen solid. This is 100% repeatable with a 6.5-rc2 kernel, not happening with a 6.4 kernel - see the attached dmesg output. I have bisected the kernel uilds and it points to : [40613da52b13fb21c5566f10b287e0ca8c12c4e9] PCI: acpiphp: Reassign resources on bridge if necessary Reversing this patch seems to fix the kernel crash problem on my laptop. ```Forgot to mention the reply from Bjorn:
Quoted 7 lines
```
I queued up a revert of 40613da52b13 ("PCI: acpiphp: Reassign
resources on bridge if necessary") (on my for-linus branch for v6.5).
It looks like a NULL pointer dereference; hopefully the fix is obvious
and I can drop the revert and replace it with the fix.
```Thanks, I've dropped this from the stable queues now.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 173/292 PCI: qcom: Disable write access to read only registers for IP v2.3.3
In reply to Greg Kroah-HartmanFrom: Manivannan Sadhasivam <[email protected]>
commit a33d700e8eea76c62120cb3dbf5e01328f18319a upstream.
In the post init sequence of v2.9.0, write access to read only registers are not disabled after updating the registers. Fix it by disabling the access after register update.
--- drivers/pci/controller/dwc/pcie-qcom.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/pci/controller/dwc/pcie-qcom.c +2 -0
@@ -834,6 +834,8 @@ static int qcom_pcie_post_init_2_3_3(strwritel (PCI_EXP_DEVCTL2_COMP_TMOUT_DIS , pci->dbi_base + offset +PCI_EXP_DEVCTL2 ); +dw_pcie_dbi_ro_wr_dis (pci); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 174/292 PCI: epf-test: Fix DMA transfer completion initialization
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit 4aca56f8eae8aa44867ddd6aa107e06f7613226f upstream.
Reinitialize the transfer_complete DMA transfer completion before calling tx_submit(), to avoid seeing the DMA transfer complete before the completion is initialized, thus potentially losing the completion notification.
--- drivers/pci/endpoint/functions/pci-epf-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/endpoint/functions/pci-epf-test.c +1 -1
@@ -151,10 +151,10 @@ static int pci_epf_test_data_transfer(streturn -EIO ; } +reinit_completion (&epf_test->transfer_complete); tx->callback = pci_epf_test_dma_callback; tx->callback_param = epf_test; cookie = tx->tx_submit (tx); -reinit_completion (&epf_test->transfer_complete); ret =dma_submit_error (cookie);if (ret) {
Greg Kroah-Hartman
maintainerPATCH 175/292 PCI: epf-test: Fix DMA transfer completion detection
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit 933f31a2fe1f20e5b1ee065579f652cd1b317183 upstream.
pci_epf_test_data_transfer() and pci_epf_test_dma_callback() are not handling DMA transfer completion correctly, leading to completion notifications to the RC side that are too early. This problem can be detected when the RC side is running an IOMMU with messages such as:
pci-endpoint-test 0000:0b:00.0: AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x001c address=0xfff00000 flags=0x0000]
When running the pcitest.sh tests: the address used for a previous test transfer generates the above error while the next test transfer is running.
Fix this by testing the DMA transfer status in pci_epf_test_dma_callback() and notifying the completion only when the transfer status is DMA_COMPLETE or DMA_ERROR. Furthermore, in pci_epf_test_data_transfer(), be paranoid and check again the transfer status and always call dmaengine_terminate_sync() before returning.
--- drivers/pci/endpoint/functions/pci-epf-test.c | 36 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 10 deletions(-)
drivers/pci/endpoint/functions/pci-epf-test.c +26 -10
@@ -54,6 +54,9 @@ struct pci_epf_test {struct delayed_work cmd_handler;struct dma_chan *dma_chan_tx;struct dma_chan *dma_chan_rx; +struct dma_chan *transfer_chan; +dma_cookie_t transfer_cookie; +enum dma_status transfer_status;struct completion transfer_complete;bool dma_supported;bool dma_private;
@@ -85,8 +88,14 @@ static size_t bar_size[] = { 512, 512, 1static void pci_epf_test_dma_callback (void *param) {struct pci_epf_test *epf_test = param; +struct dma_tx_state state; -complete (&epf_test->transfer_complete); + epf_test->transfer_status = +dmaengine_tx_status (epf_test->transfer_chan, + epf_test->transfer_cookie, &state); +if (epf_test->transfer_status ==DMA_COMPLETE || + epf_test->transfer_status ==DMA_ERROR ) +complete (&epf_test->transfer_complete); }/**
@@ -120,7 +129,6 @@ static int pci_epf_test_data_transfer(ststruct dma_async_tx_descriptor *tx;struct dma_slave_config sconf = {};struct device *dev = &epf->dev; -dma_cookie_t cookie;int ret;if (IS_ERR_OR_NULL (chan)) {
@@ -152,25 +160,33 @@ static int pci_epf_test_data_transfer(st }reinit_completion (&epf_test->transfer_complete); + epf_test->transfer_chan = chan; tx->callback = pci_epf_test_dma_callback; tx->callback_param = epf_test; - cookie = tx->tx_submit (tx); + epf_test->transfer_cookie = tx->tx_submit (tx); - ret =dma_submit_error (cookie); + ret =dma_submit_error (epf_test->transfer_cookie);if (ret) { -dev_err (dev,"Failed to do DMA tx_submit %d\n" , cookie); -return -EIO ; +dev_err (dev,"Failed to do DMA tx_submit %d\n" , ret); + goto terminate; }dma_async_issue_pending (chan); ret =wait_for_completion_interruptible (&epf_test->transfer_complete);if (ret <0 ) { -dmaengine_terminate_sync (chan); -dev_err (dev,"DMA wait_for_completion_timeout\n" ); -return -ETIMEDOUT ; +dev_err (dev,"DMA wait_for_completion interrupted\n" ); + goto terminate; + } + +if (epf_test->transfer_status ==DMA_ERROR ) { +dev_err (dev,"DMA transfer failed\n" ); + ret = -EIO ; } -return 0 ; +terminate: +dmaengine_terminate_sync (chan); + +return ret; }struct epf_dma_filter {
Greg Kroah-Hartman
maintainerPATCH 176/292 PCI: rockchip: Assert PCI Configuration Enable bit after probe
In reply to Greg Kroah-HartmanFrom: Rick Wertenbroek <[email protected]>
commit f397fd4ac1fa3afcabd8cee030f953ccaed2a364 upstream.
Assert PCI Configuration Enable bit after probe. When this bit is left to 0 in the endpoint mode, the RK3399 PCIe endpoint core will generate configuration request retry status (CRS) messages back to the root complex. Assert this bit after probe to allow the RK3399 PCIe endpoint core to reply to configuration requests from the root complex.
This is documented in section 17.5.8.1.2 of the RK3399 TRM.
--- drivers/pci/controller/pcie-rockchip-ep.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/pci/controller/pcie-rockchip-ep.c +3 -0
@@ -631,6 +631,9 @@ static int rockchip_pcie_ep_probe(struct ep->irq_pci_addr =ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR ; +rockchip_pcie_write (rockchip,PCIE_CLIENT_CONF_ENABLE , +PCIE_CLIENT_CONFIG ); +return 0 ; err_epc_mem_exit:pci_epc_mem_exit (epc);
Greg Kroah-Hartman
maintainerPATCH 177/292 PCI: rockchip: Write PCI Device ID to correct register
In reply to Greg Kroah-HartmanFrom: Rick Wertenbroek <[email protected]>
commit 1f1c42ece18de365c976a060f3c8eb481b038e3a upstream.
Write PCI Device ID (DID) to the correct register. The Device ID was not updated through the correct register. Device ID was written to a read-only register and therefore did not work. The Device ID is now set through the correct register. This is documented in the RK3399 TRM section 17.6.6.1.1
--- drivers/pci/controller/pcie-rockchip-ep.c | 6 ++++-- drivers/pci/controller/pcie-rockchip.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/pci/controller/pcie-rockchip-ep.c +4 -2
@@ -125,6 +125,7 @@ static void rockchip_pcie_prog_ep_ob_atustatic int rockchip_pcie_ep_write_header (struct pci_epc *epc,u8 fn,u8 vfn,struct pci_epf_header *hdr) { +u32 reg;struct rockchip_pcie_ep *ep =epc_get_drvdata (epc);struct rockchip_pcie *rockchip = &ep->rockchip;
@@ -137,8 +138,9 @@ static int rockchip_pcie_ep_write_header PCIE_CORE_CONFIG_VENDOR); } -rockchip_pcie_write (rockchip, hdr->deviceid <<16 , -ROCKCHIP_PCIE_EP_FUNC_BASE (fn) +PCI_VENDOR_ID ); + reg =rockchip_pcie_read (rockchip,PCIE_EP_CONFIG_DID_VID ); + reg = (reg &0xFFFF ) | (hdr->deviceid <<16 ); +rockchip_pcie_write (rockchip, reg,PCIE_EP_CONFIG_DID_VID ); rockchip_pcie_write(rockchip, hdr->revid |
drivers/pci/controller/pcie-rockchip.h +2 -0
@@ -133,6 +133,8 @@#define PCIE_RC_RP_ATS_BASE 0x400000#define PCIE_RC_CONFIG_NORMAL_BASE 0x800000#define PCIE_RC_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_BASE 0xa00000 +#define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00)#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4)#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18
Greg Kroah-Hartman
maintainerPATCH 178/292 PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
In reply to Greg Kroah-HartmanFrom: Rick Wertenbroek <[email protected]>
commit 9dd3c7c4c8c3f7f010d9cdb7c3f42506d93c9527 upstream.
The RK3399 PCIe controller should wait until the PHY PLLs are locked. Add poll and timeout to wait for PHY PLLs to be locked. If they cannot be locked generate error message and jump to error handler. Accessing registers in the PHY clock domain when PLLs are not locked causes hang The PHY PLLs status is checked through a side channel register. This is documented in the TRM section 17.5.8.1 "PCIe Initialization Sequence".
--- drivers/pci/controller/pcie-rockchip.c | 17 +++++++++++++++++ drivers/pci/controller/pcie-rockchip.h | 2 ++ 2 files changed, 19 insertions(+)
drivers/pci/controller/pcie-rockchip.c +17 -0
@@ -14,6 +14,7 @@#include <linux/clk.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> +#include <linux/iopoll.h> #include <linux/of_pci.h> #include <linux/phy/phy.h> #include <linux/platform_device.h>
@@ -153,6 +154,12 @@ int rockchip_pcie_parse_dt(struct rockch }EXPORT_SYMBOL_GPL (rockchip_pcie_parse_dt); +#define rockchip_pcie_read_addr (addr) rockchip_pcie_read(rockchip, addr) +/* 100 ms max wait time for PHY PLLs to lock */ +#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000 +/* Sleep should be less than 20ms */ +#define RK_PHY_PLL_LOCK_SLEEP_US 1000 +int rockchip_pcie_init_port (struct rockchip_pcie *rockchip) {struct device *dev = rockchip->dev;
@@ -254,6 +261,16 @@ int rockchip_pcie_init_port(struct rockc } } + err =readx_poll_timeout (rockchip_pcie_read_addr, +PCIE_CLIENT_SIDE_BAND_STATUS , + regs, !(regs &PCIE_CLIENT_PHY_ST ), +RK_PHY_PLL_LOCK_SLEEP_US , +RK_PHY_PLL_LOCK_TIMEOUT_US ); +if (err) { +dev_err (dev,"PHY PLLs could not lock, %d\n" , err); + goto err_power_off_phy; + } +/* * Please don't reorder the deassert sequence of the following * four reset pins.
drivers/pci/controller/pcie-rockchip.h +2 -0
@@ -38,6 +38,8 @@#define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0)#define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0)#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) +#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20) +#define PCIE_CLIENT_PHY_ST BIT(12)#define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c)#define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0)#define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18
Greg Kroah-Hartman
maintainerPATCH 179/292 PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
In reply to Greg Kroah-HartmanFrom: Rick Wertenbroek <[email protected]>
commit 166e89d99dd85a856343cca51eee781b793801f2 upstream.
Fix legacy IRQ generation for RK3399 PCIe endpoint core according to the technical reference manual (TRM). Assert and deassert legacy interrupt (INTx) through the legacy interrupt control register ("PCIE_CLIENT_LEGACY_INT_CTRL") instead of manually generating a PCIe message. The generation of the legacy interrupt was tested and validated with the PCIe endpoint test driver.
--- drivers/pci/controller/pcie-rockchip-ep.c | 45 +++++++----------------------- drivers/pci/controller/pcie-rockchip.h | 6 +++- 2 files changed, 16 insertions(+), 35 deletions(-)
drivers/pci/controller/pcie-rockchip-ep.c +11 -34
@@ -347,48 +347,25 @@ static int rockchip_pcie_ep_get_msi(stru }static void rockchip_pcie_ep_assert_intx (struct rockchip_pcie_ep *ep,u8 fn, -u8 intx,bool is_asserted) +u8 intx,bool do_assert) {struct rockchip_pcie *rockchip = &ep->rockchip; -u32 r = ep->max_regions -1 ; -u32 offset; -u32 status; -u8 msg_code; - -if (unlikely (ep->irq_pci_addr !=ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR || - ep->irq_pci_fn != fn)) { -rockchip_pcie_prog_ep_ob_atu (rockchip, fn, r, -AXI_WRAPPER_NOR_MSG , - ep->irq_phys_addr,0 ,0 ); - ep->irq_pci_addr =ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR ; - ep->irq_pci_fn = fn; - } intx &=3 ; -if (is_asserted) { + +if (do_assert) { ep->irq_pending |=BIT (intx); - msg_code =ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx; +rockchip_pcie_write (rockchip, +PCIE_CLIENT_INT_IN_ASSERT | +PCIE_CLIENT_INT_PEND_ST_PEND , +PCIE_CLIENT_LEGACY_INT_CTRL ); }else { ep->irq_pending &= ~BIT (intx); - msg_code =ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx; +rockchip_pcie_write (rockchip, +PCIE_CLIENT_INT_IN_DEASSERT | +PCIE_CLIENT_INT_PEND_ST_NORMAL , +PCIE_CLIENT_LEGACY_INT_CTRL ); } - - status =rockchip_pcie_read (rockchip, -ROCKCHIP_PCIE_EP_FUNC_BASE (fn) + -ROCKCHIP_PCIE_EP_CMD_STATUS ); - status &=ROCKCHIP_PCIE_EP_CMD_STATUS_IS ; - -if ((status !=0 ) ^ (ep->irq_pending !=0 )) { - status ^=ROCKCHIP_PCIE_EP_CMD_STATUS_IS ; -rockchip_pcie_write (rockchip, status, -ROCKCHIP_PCIE_EP_FUNC_BASE (fn) + -ROCKCHIP_PCIE_EP_CMD_STATUS ); - } - - offset = -ROCKCHIP_PCIE_MSG_ROUTING (ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX ) | -ROCKCHIP_PCIE_MSG_CODE (msg_code) |ROCKCHIP_PCIE_MSG_NO_DATA ; -writel (0 , ep->irq_cpu_addr + offset); } static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn,
drivers/pci/controller/pcie-rockchip.h +5 -1
@@ -38,6 +38,11 @@#define PCIE_CLIENT_MODE_EP HIWORD_UPDATE(0x0040, 0)#define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0)#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) +#define PCIE_CLIENT_LEGACY_INT_CTRL (PCIE_CLIENT_BASE + 0x0c) +#define PCIE_CLIENT_INT_IN_ASSERT HIWORD_UPDATE_BIT(0x0002) +#define PCIE_CLIENT_INT_IN_DEASSERT HIWORD_UPDATE(0x0002, 0) +#define PCIE_CLIENT_INT_PEND_ST_PEND HIWORD_UPDATE_BIT(0x0001) +#define PCIE_CLIENT_INT_PEND_ST_NORMAL HIWORD_UPDATE(0x0001, 0)#define PCIE_CLIENT_SIDE_BAND_STATUS (PCIE_CLIENT_BASE + 0x20)#define PCIE_CLIENT_PHY_ST BIT(12)#define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c)
@@ -227,7 +232,6 @@#define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16)#define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24)#define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 -#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3#define ROCKCHIP_PCIE_EP_FUNC_BASE (fn) (((fn) << 12) & GENMASK(19, 12))#define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0 (fn, bar) \ (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008)
Greg Kroah-Hartman
maintainerPATCH 180/292 PCI: rockchip: Use u32 variable to access 32-bit registers
In reply to Greg Kroah-HartmanFrom: Rick Wertenbroek <[email protected]>
commit 8962b2cb39119cbda4fc69a1f83957824f102f81 upstream.
Previously u16 variables were used to access 32-bit registers, this resulted in not all of the data being read from the registers. Also the left shift of more than 16-bits would result in moving data out of the variable. Use u32 variables to access 32-bit registers
--- drivers/pci/controller/pcie-rockchip-ep.c | 10 +++++----- drivers/pci/controller/pcie-rockchip.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-)
drivers/pci/controller/pcie-rockchip-ep.c +5 -5
@@ -314,15 +314,15 @@ static int rockchip_pcie_ep_set_msi(stru {struct rockchip_pcie_ep *ep =epc_get_drvdata (epc);struct rockchip_pcie *rockchip = &ep->rockchip; -u16 flags; +u32 flags; flags =rockchip_pcie_read (rockchip,ROCKCHIP_PCIE_EP_FUNC_BASE (fn) +ROCKCHIP_PCIE_EP_MSI_CTRL_REG ); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK ; flags |= - ((multi_msg_cap <<1 ) <<ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET ) | -PCI_MSI_FLAGS_64BIT ; + (multi_msg_cap <<ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET ) | + (PCI_MSI_FLAGS_64BIT <<ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET ); flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP ; rockchip_pcie_write(rockchip, flags, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
@@ -334,7 +334,7 @@ static int rockchip_pcie_ep_get_msi(stru {struct rockchip_pcie_ep *ep =epc_get_drvdata (epc);struct rockchip_pcie *rockchip = &ep->rockchip; -u16 flags; +u32 flags; flags = rockchip_pcie_read(rockchip, ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
@@ -395,7 +395,7 @@ static int rockchip_pcie_ep_send_msi_irq u8 interrupt_num) {struct rockchip_pcie *rockchip = &ep->rockchip; -u16 flags, mme, data, data_mask; +u32 flags, mme, data, data_mask;u8 msi_count;u64 pci_addr, pci_addr_mask =0xff ;
drivers/pci/controller/pcie-rockchip.h +1 -0
@@ -225,6 +225,7 @@#define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4#define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19)#define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 +#define ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET 16#define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17#define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17)#define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20
Greg Kroah-Hartman
maintainerPATCH 181/292 PCI: rockchip: Set address alignment for endpoint mode
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit 7e6689b34a815bd379dfdbe9855d36f395ef056c upstream.
The address translation unit of the rockchip EP controller does not use the lower 8 bits of a PCIe-space address to map local memory. Thus we must set the align feature field to 256 to let the user know about this constraint.
--- drivers/pci/controller/pcie-rockchip-ep.c | 1 + 1 file changed, 1 insertion(+)
drivers/pci/controller/pcie-rockchip-ep.c +1 -0
@@ -485,6 +485,7 @@ static const struct pci_epc_features roc .linkup_notifier = false, .msi_capable = true, .msix_capable = false, + .align = 256, }; static const struct pci_epc_features*
Greg Kroah-Hartman
maintainerPATCH 182/292 misc: pci_endpoint_test: Free IRQs before removing the device
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit f61b7634a3249d12b9daa36ffbdb9965b6f24c6c upstream.
In pci_endpoint_test_remove(), freeing the IRQs after removing the device creates a small race window for IRQs to be received with the test device memory already released, causing the IRQ handler to access invalid memory, resulting in an oops.
Free the device IRQs before removing the device to avoid this issue.
--- drivers/misc/pci_endpoint_test.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/misc/pci_endpoint_test.c +3 -3
@@ -938,6 +938,9 @@ static void pci_endpoint_test_remove(strif (id <0 )return ; +pci_endpoint_test_release_irq (test); +pci_endpoint_test_free_irq_vectors (test); +misc_deregister (&test->miscdev);kfree (misc_device->name);kfree (test->name);
@@ -947,9 +950,6 @@ static void pci_endpoint_test_remove(strpci_iounmap (pdev, test->bar[bar]); } -pci_endpoint_test_release_irq (test); -pci_endpoint_test_free_irq_vectors (test); -pci_release_regions (pdev);pci_disable_device (pdev); }
Greg Kroah-Hartman
maintainerPATCH 183/292 misc: pci_endpoint_test: Re-init completion for every test
In reply to Greg Kroah-HartmanFrom: Damien Le Moal <[email protected]>
commit fb620ae73b70c2f57b9d3e911fc24c024ba2324f upstream.
The irq_raised completion used to detect the end of a test case is initialized when the test device is probed, but never reinitialized again before a test case. As a result, the irq_raised completion synchronization is effective only for the first ioctl test case executed. Any subsequent call to wait_for_completion() by another ioctl() call will immediately return, potentially too early, leading to false positive failures.
Fix this by reinitializing the irq_raised completion before starting a new ioctl() test command.
--- drivers/misc/pci_endpoint_test.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/misc/pci_endpoint_test.c +4 -0
@@ -729,6 +729,10 @@ static long pci_endpoint_test_ioctl(strustruct pci_dev *pdev = test->pdev;mutex_lock (&test->mutex); + +reinit_completion (&test->irq_raised); + test->last_irq = -ENODATA ; +switch (cmd) {case PCITEST_BAR : bar = arg;
Greg Kroah-Hartman
maintainerPATCH 184/292 mfd: pm8008: Fix module autoloading
In reply to Greg Kroah-HartmanFrom: Johan Hovold <[email protected]>
commit d420c9886f5369697047b880221789bf0054e438 upstream.
Add the missing module device table alias to that the driver can be autoloaded when built as a module.
--- drivers/mfd/qcom-pm8008.c | 1 + 1 file changed, 1 insertion(+)
drivers/mfd/qcom-pm8008.c +1 -0
@@ -199,6 +199,7 @@ static const struct of_device_id pm8008_ { .compatible = "qcom,pm8008", }, { }, }; +MODULE_DEVICE_TABLE (of, pm8008_match);static struct i2c_driver pm8008_mfd_driver = { .driver = {
Greg Kroah-Hartman
maintainerPATCH 185/292 md/raid0: add discard support for the original layout
In reply to Greg Kroah-HartmanFrom: Jason Baron <[email protected]>
commit e836007089ba8fdf24e636ef2b007651fb4582e6 upstream.
We've found that using raid0 with the 'original' layout and discard enabled with different disk sizes (such that at least two zones are created) can result in data corruption. This is due to the fact that the discard handling in 'raid0_handle_discard()' assumes the 'alternate' layout. We've seen this corruption using ext4 but other filesystems are likely susceptible as well.
More specifically, while multiple zones are necessary to create the corruption, the corruption may not occur with multiple zones if they layout in such a way the layout matches what the 'alternate' layout would have produced. Thus, not all raid0 devices with the 'original' layout, different size disks and discard enabled will encounter this corruption.
The 3.14 kernel inadvertently changed the raid0 disk layout for different size disks. Thus, running a pre-3.14 kernel and post-3.14 kernel on the same raid0 array could corrupt data. This lead to the creation of the 'original' layout (to match the pre-3.14 layout) and the 'alternate' layout (to match the post 3.14 layout) in the 5.4 kernel time frame and an option to tell the kernel which layout to use (since it couldn't be autodetected). However, when the 'original' layout was added back to 5.4 discard support for the 'original' layout was not added leading this issue.
I've been able to reliably reproduce the corruption with the following test case:
1. create raid0 array with different size disks using original layout
2. mkfs
3. mount -o discard
4. create lots of files
5. remove 1/2 the files
6. fstrim -a (or just the mount point for the raid0 array)
7. umount
8. fsck -fn /dev/md0 (spews all sorts of corruptions)
Let's fix this by adding proper discard support to the 'original' layout. The fix 'maps' the 'original' layout disks to the order in which they are read/written such that we can compare the disks in the same way that the current 'alternate' layout does. A 'disk_shift' field is added to 'struct strip_zone'. This could be computed on the fly in raid0_handle_discard() but by adding this field, we save some computation in the discard path.
Note we could also potentially fix this by re-ordering the disks in the zones that follow the first one, and then always read/writing them using the 'alternate' layout. However, that is seen as a more substantial change, and we are attempting the least invasive fix at this time to remedy the corruption.
I've verified the change using the reproducer mentioned above. Typically, the corruption is seen after less than 3 iterations, while the patch has run 500+ iterations.
--- drivers/md/raid0.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++------- drivers/md/raid0.h | 1 2 files changed, 55 insertions(+), 8 deletions(-)
drivers/md/raid0.c +54 -8
@@ -270,6 +270,18 @@ static int create_strip_zones(struct mdd goto abort; } +if (conf->layout ==RAID0_ORIG_LAYOUT ) { +for (i =1 ; i < conf->nr_strip_zones; i++) { +sector_t first_sector = conf->strip_zone[i-1 ].zone_end; + +sector_div (first_sector, mddev->chunk_sectors); + zone = conf->strip_zone + i; +/* disk_shift is first disk index used in the zone */ + zone->disk_shift =sector_div (first_sector, + zone->nb_dev); + } + } +pr_debug ("md/raid0:%s: done.\n" ,mdname (mddev)); *private_conf = conf;
@@ -431,6 +443,20 @@ exit_acct_set:return ret; } +/* +* Convert disk_index to the disk order in which it is read/written. +* For example, if we have 4 disks, they are numbered 0,1,2,3. If we +* write the disks starting at disk 3, then the read/write order would +* be disk 3, then 0, then 1, and then disk 2 and we want map_disk_shift() +* to map the disks as follows 0,1,2,3 => 1,2,3,0. So disk 0 would map +* to 1, 1 to 2, 2 to 3, and 3 to 0. That way we can compare disks in +* that 'output' space to understand the read/write disk ordering. +*/ +static int map_disk_shift (int disk_index,int num_disks,int disk_shift) +{ +return ((disk_index + num_disks - disk_shift) % num_disks); +} +static void raid0_handle_discard (struct mddev *mddev,struct bio *bio) {struct r0conf *conf = mddev->private;
@@ -444,7 +470,9 @@ static void raid0_handle_discard(structsector_t end_disk_offset;unsigned int end_disk_index;unsigned int disk; +sector_t orig_start, orig_end; + orig_start = start; zone =find_zone (conf, &start);if (bio_end_sector (bio) > zone->zone_end) {
@@ -458,6 +486,7 @@ static void raid0_handle_discard(struct }else end =bio_end_sector (bio); + orig_end = end;if (zone != conf->strip_zone) end = end - zone[-1 ].zone_end;
@@ -469,13 +498,26 @@ static void raid0_handle_discard(struct last_stripe_index = end;sector_div (last_stripe_index, stripe_size); - start_disk_index = (int )(start - first_stripe_index * stripe_size) / - mddev->chunk_sectors; +/* In the first zone the original and alternate layouts are the same */ +if ((conf->layout ==RAID0_ORIG_LAYOUT ) && (zone != conf->strip_zone)) { +sector_div (orig_start, mddev->chunk_sectors); + start_disk_index =sector_div (orig_start, zone->nb_dev); + start_disk_index =map_disk_shift (start_disk_index, + zone->nb_dev, + zone->disk_shift); +sector_div (orig_end, mddev->chunk_sectors); + end_disk_index =sector_div (orig_end, zone->nb_dev); + end_disk_index =map_disk_shift (end_disk_index, + zone->nb_dev, zone->disk_shift); + }else { + start_disk_index = (int )(start - first_stripe_index * stripe_size) / + mddev->chunk_sectors; + end_disk_index = (int )(end - last_stripe_index * stripe_size) / + mddev->chunk_sectors; + } start_disk_offset = ((int )(start - first_stripe_index * stripe_size) % mddev->chunk_sectors) + first_stripe_index * mddev->chunk_sectors; - end_disk_index = (int )(end - last_stripe_index * stripe_size) / - mddev->chunk_sectors; end_disk_offset = ((int )(end - last_stripe_index * stripe_size) % mddev->chunk_sectors) + last_stripe_index * mddev->chunk_sectors;
@@ -483,18 +525,22 @@ static void raid0_handle_discard(structfor (disk =0 ; disk < zone->nb_dev; disk++) {sector_t dev_start, dev_end;struct md_rdev *rdev; +int compare_disk; + + compare_disk =map_disk_shift (disk, zone->nb_dev, + zone->disk_shift); -if (disk < start_disk_index) +if (compare_disk < start_disk_index) dev_start = (first_stripe_index +1 ) * mddev->chunk_sectors; -else if (disk > start_disk_index) +else if (compare_disk > start_disk_index) dev_start = first_stripe_index * mddev->chunk_sectors;else dev_start = start_disk_offset; -if (disk < end_disk_index) +if (compare_disk < end_disk_index) dev_end = (last_stripe_index +1 ) * mddev->chunk_sectors; -else if (disk > end_disk_index) +else if (compare_disk > end_disk_index) dev_end = last_stripe_index * mddev->chunk_sectors;else dev_end = end_disk_offset;
drivers/md/raid0.h +1 -0
@@ -6,6 +6,7 @@ struct strip_zone {sector_t zone_end;/* Start of the next zone (in sectors) */ sector_t dev_start;/* Zone offset in real dev (in sectors) */ int nb_dev;/* # of devices attached to the zone */ +int disk_shift;/* start disk for the original layout */ };/* Linux 3.14 (20d0189b101) made an unintended change to
Greg Kroah-Hartman
maintainerPATCH 186/292 fs: dlm: return positive pid value for F_GETLK
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit 92655fbda5c05950a411eaabc19e025e86e2a291 upstream.
The GETLK pid values have all been negated since commit 9d5b86ac13c5 ("fs/locks: Remove fl_nspid and use fs-specific l_pid for remote locks"). Revert this for local pids, and leave in place negative pids for remote owners.
--- fs/dlm/plock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/dlm/plock.c +3 -1
@@ -360,7 +360,9 @@ int dlm_posix_get(dlm_lockspace_t *lockslocks_init_lock (fl); fl->fl_type = (op->info.ex) ?F_WRLCK :F_RDLCK ; fl->fl_flags =FL_POSIX ; - fl->fl_pid = -op->info.pid; + fl->fl_pid = op->info.pid; +if (op->info.nodeid !=dlm_our_nodeid ()) + fl->fl_pid = -fl->fl_pid; fl->fl_start = op->info.start; fl->fl_end = op->info.end; rv =0 ;
Greg Kroah-Hartman
maintainerPATCH 187/292 fs: dlm: fix cleanup pending ops when interrupted
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit c847f4e203046a2c93d8a1cf0348315c0b655a60 upstream.
Immediately clean up a posix lock request if it is interrupted while waiting for a result from user space (dlm_controld.) This largely reverts the recent commit b92a4e3f86b1 ("fs: dlm: change posix lock sigint handling"). That previous commit attempted to defer lock cleanup to the point in time when a result from user space arrived. The deferred approach was not reliable because some dlm plock ops may not receive replies.
--- fs/dlm/plock.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-)
fs/dlm/plock.c +6 -19
@@ -30,8 +30,6 @@ struct plock_async_data {struct plock_op {struct list_head list;int done; -/* if lock op got interrupted while waiting dlm_controld reply */ -bool sigint;struct dlm_plock_info info;/* if set indicates async handling */ struct plock_async_data *data;
@@ -167,12 +165,14 @@ int dlm_posix_lock(dlm_lockspace_t *lockspin_unlock (&ops_lock); goto do_lock_wait; } - - op->sigint = true; +list_del (&op->list);spin_unlock (&ops_lock); +log_debug (ls,"%s: wait interrupted %x %llx pid %d" , __func__, ls->ls_global_id, (unsigned long long )number, op->info.pid); +do_unlock_close (&op->info); +dlm_release_plock_op (op); goto out; }
@@ -434,19 +434,6 @@ static ssize_t dev_write(struct file *fiif (iter->info.fsid == info.fsid && iter->info.number == info.number && iter->info.owner == info.owner) { -if (iter->sigint) { -list_del (&iter->list); -spin_unlock (&ops_lock); - -pr_debug ("%s: sigint cleanup %x %llx pid %d" , - __func__, iter->info.fsid, - (unsigned long long )iter->info.number, - iter->info.pid); -do_unlock_close (&iter->info); -memcpy (&iter->info, &info,sizeof (info)); -dlm_release_plock_op (iter); -return count; - }list_del_init (&iter->list);memcpy (&iter->info, &info,sizeof (info));if (iter->data)
@@ -465,8 +452,8 @@ static ssize_t dev_write(struct file *fielse wake_up (&recv_wq); }else -log_print ("%s: no op %x %llx" , __func__, - info.fsid, (unsigned long long )info.number); +pr_debug ("%s: no op %x %llx" , __func__, + info.fsid, (unsigned long long )info.number);return count; }
Greg Kroah-Hartman
maintainerPATCH 188/292 fs: dlm: interrupt posix locks only when process is killed
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit 59e45c758ca1b9893ac923dd63536da946ac333b upstream.
If a posix lock request is waiting for a result from user space (dlm_controld), do not let it be interrupted unless the process is killed. This reverts commit a6b1533e9a57 ("dlm: make posix locks interruptible"). The problem with the interruptible change is that all locks were cleared on any signal interrupt. If a signal was received that did not terminate the process, the process could continue running after all its dlm posix locks had been cleared. A future patch will add cancelation to allow proper interruption.
--- fs/dlm/plock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/dlm/plock.c +1 -1
@@ -155,7 +155,7 @@ int dlm_posix_lock(dlm_lockspace_t *locksend_op (op); - rv =wait_event_interruptible (recv_wq, (op->done !=0 )); + rv =wait_event_killable (recv_wq, (op->done !=0 ));if (rv == -ERESTARTSYS ) {spin_lock (&ops_lock);/* recheck under ops_lock if we got a done != 0,
Greg Kroah-Hartman
maintainerPATCH 189/292 fs: dlm: make F_SETLK use unkillable wait_event
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit 0f2b1cb89ccdbdcedf7143f4153a4da700a05f48 upstream.
While a non-waiting posix lock request (F_SETLK) is waiting for user space processing (in dlm_controld), wait for that processing to complete with an unkillable wait_event(). This makes F_SETLK behave the same way for F_RDLCK, F_WRLCK and F_UNLCK. F_SETLKW continues to use wait_event_killable().
--- fs/dlm/plock.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-)
fs/dlm/plock.c +21 -17
@@ -155,25 +155,29 @@ int dlm_posix_lock(dlm_lockspace_t *locksend_op (op); - rv =wait_event_killable (recv_wq, (op->done !=0 )); -if (rv == -ERESTARTSYS ) { -spin_lock (&ops_lock); -/* recheck under ops_lock if we got a done != 0, -* if so this interrupt case should be ignored -*/ -if (op->done !=0 ) { +if (op->info.wait) { + rv =wait_event_killable (recv_wq, (op->done !=0 )); +if (rv == -ERESTARTSYS ) { +spin_lock (&ops_lock); +/* recheck under ops_lock if we got a done != 0, +* if so this interrupt case should be ignored +*/ +if (op->done !=0 ) { +spin_unlock (&ops_lock); + goto do_lock_wait; + } +list_del (&op->list);spin_unlock (&ops_lock); - goto do_lock_wait; - } -list_del (&op->list); -spin_unlock (&ops_lock); -log_debug (ls,"%s: wait interrupted %x %llx pid %d" , - __func__, ls->ls_global_id, - (unsigned long long )number, op->info.pid); -do_unlock_close (&op->info); -dlm_release_plock_op (op); - goto out; +log_debug (ls,"%s: wait interrupted %x %llx pid %d" , + __func__, ls->ls_global_id, + (unsigned long long )number, op->info.pid); +do_unlock_close (&op->info); +dlm_release_plock_op (op); + goto out; + } + }else { +wait_event (recv_wq, (op->done !=0 )); } do_lock_wait:
Greg Kroah-Hartman
maintainerPATCH 190/292 fs: dlm: fix mismatch of plock results from userspace
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit 57e2c2f2d94cfd551af91cedfa1af6d972487197 upstream.
When a waiting plock request (F_SETLKW) is sent to userspace for processing (dlm_controld), the result is returned at a later time. That result could be incorrectly matched to a different waiting request in cases where the owner field is the same (e.g. different threads in a process.) This is fixed by comparing all the properties in the request and reply.
The results for non-waiting plock requests are now matched based on list order because the results are returned in the same order they were sent.
--- fs/dlm/plock.c | 58 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 13 deletions(-)
fs/dlm/plock.c +45 -13
@@ -395,7 +395,7 @@ static ssize_t dev_read(struct file *filif (op->info.flags &DLM_PLOCK_FL_CLOSE )list_del (&op->list);else -list_move (&op->list, &recv_list); +list_move_tail (&op->list, &recv_list);memcpy (&info, &op->info,sizeof (info)); }spin_unlock (&ops_lock);
@@ -433,20 +433,52 @@ static ssize_t dev_write(struct file *fiif (check_version (&info))return -EINVAL ; +/* +* The results for waiting ops (SETLKW) can be returned in any +* order, so match all fields to find the op. The results for +* non-waiting ops are returned in the order that they were sent +* to userspace, so match the result with the first non-waiting op. +*/ spin_lock (&ops_lock); -list_for_each_entry (iter, &recv_list, list) { -if (iter->info.fsid == info.fsid && - iter->info.number == info.number && - iter->info.owner == info.owner) { -list_del_init (&iter->list); -memcpy (&iter->info, &info,sizeof (info)); -if (iter->data) - do_callback =1 ; -else - iter->done =1 ; - op = iter; -break ; +if (info.wait) { +list_for_each_entry (iter, &recv_list, list) { +if (iter->info.fsid == info.fsid && + iter->info.number == info.number && + iter->info.owner == info.owner && + iter->info.pid == info.pid && + iter->info.start == info.start && + iter->info.end == info.end && + iter->info.ex == info.ex && + iter->info.wait) { + op = iter; +break ; + } } + }else { +list_for_each_entry (iter, &recv_list, list) { +if (!iter->info.wait) { + op = iter; +break ; + } + } + } + +if (op) { +/* Sanity check that op and info match. */ +if (info.wait) +WARN_ON (op->info.optype !=DLM_PLOCK_OP_LOCK ); +else +WARN_ON (op->info.fsid != info.fsid || + op->info.number != info.number || + op->info.owner != info.owner || + op->info.optype != info.optype); + +list_del_init (&op->list); +memcpy (&op->info, &info,sizeof (info)); +if (op->data) + do_callback =1 ; +else + op->done =1 ; }spin_unlock (&ops_lock);
Greg Kroah-Hartman
maintainerPATCH 191/292 fs: dlm: clear pending bit when queue was empty
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit 7a931477bff1c7548aa8492bccf600f5f29452b1 upstream.
This patch clears the DLM_IFL_CB_PENDING_BIT flag which will be set when there is callback work queued when there was no callback to dequeue. It is a buggy case and should never happen, that's why there is a WARN_ON(). However if the case happens we are prepared to somehow recover from it.
--- fs/dlm/ast.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/dlm/ast.c +5 -3
@@ -181,10 +181,12 @@ void dlm_callback_work(struct work_struct *work)spin_lock (&lkb->lkb_cb_lock); rv =dlm_dequeue_lkb_callback (lkb, &cb); -spin_unlock (&lkb->lkb_cb_lock); - -if (WARN_ON_ONCE (rv ==DLM_DEQUEUE_CALLBACK_EMPTY )) +if (WARN_ON_ONCE (rv ==DLM_DEQUEUE_CALLBACK_EMPTY )) { +clear_bit (DLM_IFL_CB_PENDING_BIT , &lkb->lkb_iflags); +spin_unlock (&lkb->lkb_cb_lock); goto out; + } +spin_unlock (&lkb->lkb_cb_lock);for (;;) { castfn = lkb->lkb_astfn;
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 192/292 fs: dlm: fix missing pending to false
In reply to Greg Kroah-HartmanFrom: Alexander Aring <[email protected]>
commit f68bb23cad1f128198074ed7b3a4c5fb03dbd9d2 upstream.
This patch sets the process_dlm_messages_pending boolean to false when there was no message to process. It is a case which should not happen but if we are prepared to recover from this situation by setting pending boolean to false.
--- fs/dlm/lowcomms.c | 1 + 1 file changed, 1 insertion(+)
fs/dlm/lowcomms.c +1 -0
@@ -898,6 +898,7 @@ static void process_dlm_messages(struct work_struct *work) pentry =list_first_entry_or_null (&processqueue, struct processqueue_entry, list);if (WARN_ON_ONCE (!pentry)) { + process_dlm_messages_pending = false;spin_unlock (&processqueue_lock);return ; }
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 193/292 scsi: lpfc: Fix double free in lpfc_cmpl_els_logo_acc() caused by lpfc_nlp_not_used()
In reply to Greg Kroah-HartmanFrom: Justin Tee <[email protected]>
commit 97f975823f8196d970bd795087b514271214677a upstream.
Smatch detected a double free path because lpfc_nlp_not_used() releases an ndlp object before reaching lpfc_nlp_put() at the end of lpfc_cmpl_els_logo_acc().
Remove the outdated lpfc_nlp_not_used() routine. In lpfc_mbx_cmpl_ns_reg_login(), replace the call with lpfc_nlp_put(). In lpfc_cmpl_els_logo_acc(), replace the call with lpfc_unreg_rpi() and keep the lpfc_nlp_put() at the end of the routine. If ndlp's rpi was registered, then lpfc_unreg_rpi()'s completion routine performs the final ndlp clean up after lpfc_nlp_put() is called from lpfc_cmpl_els_logo_acc(). Otherwise if ndlp has no rpi registered, the lpfc_nlp_put() at the end of lpfc_cmpl_els_logo_acc() is the final ndlp clean up.
--- drivers/scsi/lpfc/lpfc_crtn.h | 1 - drivers/scsi/lpfc/lpfc_els.c | 30 +++++++----------------------- drivers/scsi/lpfc/lpfc_hbadisc.c | 24 +++--------------------- 3 files changed, 10 insertions(+), 45 deletions(-)
drivers/scsi/lpfc/lpfc_crtn.h +0 -1
@@ -134,7 +134,6 @@ void lpfc_check_nlp_post_devloss(struct struct lpfc_nodelist *ndlp);void lpfc_ignore_els_cmpl (struct lpfc_hba *phba,struct lpfc_iocbq *cmdiocb,struct lpfc_iocbq *rspiocb); -int lpfc_nlp_not_used (struct lpfc_nodelist *ndlp);struct lpfc_nodelist *lpfc_setup_disc_node (struct lpfc_vport *,uint32_t );void lpfc_disc_list_loopmap (struct lpfc_vport *);void lpfc_disc_start (struct lpfc_vport *);
drivers/scsi/lpfc/lpfc_els.c +7 -23
@@ -5205,14 +5205,9 @@ lpfc_els_free_iocb(struct lpfc_hba *phba* * This routine is the completion callback function to the Logout (LOGO) * Accept (ACC) Response ELS command. This routine is invoked to indicate -* the completion of the LOGO process. It invokes the lpfc_nlp_not_used() to -* release the ndlp if it has the last reference remaining (reference count -* is 1). If succeeded (meaning ndlp released), it sets the iocb ndlp -* field to NULL to inform the following lpfc_els_free_iocb() routine no -* ndlp reference count needs to be decremented. Otherwise, the ndlp -* reference use-count shall be decremented by the lpfc_els_free_iocb() -* routine. Finally, the lpfc_els_free_iocb() is invoked to release the -* IOCB data structure. +* the completion of the LOGO process. If the node has transitioned to NPR, +* this routine unregisters the RPI if it is still registered. The +* lpfc_els_free_iocb() is invoked to release the IOCB data structure. **/ static void lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
@@ -5253,19 +5248,9 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * (ndlp->nlp_last_elscmd == ELS_CMD_PLOGI)) goto out; -/* NPort Recovery mode or node is just allocated */ -if (!lpfc_nlp_not_used (ndlp)) { -/* A LOGO is completing and the node is in NPR state. -* Just unregister the RPI because the node is still -* required. -*/ +if (ndlp->nlp_flag &NLP_RPI_REGISTERED )lpfc_unreg_rpi (vport, ndlp); - }else { -/* Indicate the node has already released, should -* not reference to it from within lpfc_els_free_iocb. -*/ - cmdiocb->ndlp =NULL ; - } + } out:/*
@@ -5285,9 +5270,8 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba ** RPI (Remote Port Index) mailbox command to the @phba. It simply releases * the associated lpfc Direct Memory Access (DMA) buffer back to the pool and * decrements the ndlp reference count held for this completion callback -* function. After that, it invokes the lpfc_nlp_not_used() to check -* whether there is only one reference left on the ndlp. If so, it will -* perform one more decrement and trigger the release of the ndlp. +* function. After that, it invokes the lpfc_drop_node to check +* whether it is appropriate to release the node. **/ void lpfc_mbx_cmpl_dflt_rpi (struct lpfc_hba *phba,LPFC_MBOXQ_t *pmb)
drivers/scsi/lpfc/lpfc_hbadisc.c +3 -21
@@ -4333,13 +4333,14 @@ out:/* If the node is not registered with the scsi or nvme * transport, remove the fabric node. The failed reg_login -* is terminal. +* is terminal and forces the removal of the last node +* reference. */ if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD |NVME_XPT_REGD ))) {spin_lock_irq (&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC ;spin_unlock_irq (&ndlp->lock); -lpfc_nlp_not_used (ndlp); +lpfc_nlp_put (ndlp); }if (phba->fc_topology ==LPFC_TOPOLOGY_LOOP ) {
@@ -6704,25 +6705,6 @@ lpfc_nlp_put(struct lpfc_nodelist *ndlp)return ndlp ?kref_put (&ndlp->kref, lpfc_nlp_release) :0 ; } -/* This routine free's the specified nodelist if it is not in use -* by any other discovery thread. This routine returns 1 if the -* ndlp has been freed. A return value of 0 indicates the ndlp is -* not yet been released. -*/ -int -lpfc_nlp_not_used (struct lpfc_nodelist *ndlp) -{ -lpfc_debugfs_disc_trc (ndlp->vport,LPFC_DISC_TRC_NODE , -"node not used: did:x%x flg:x%x refcnt:x%x" , - ndlp->nlp_DID, ndlp->nlp_flag, -kref_read (&ndlp->kref)); - -if (kref_read (&ndlp->kref) ==1 ) -if (lpfc_nlp_put (ndlp)) -return 1 ; -return 0 ; -} -/** * lpfc_fcf_inuse - Check if FCF can be unregistered. * @phba: Pointer to hba context object.
Greg Kroah-Hartman
maintainerPATCH 194/292 drm/atomic: Allow vblank-enabled + self-refresh "disable"
In reply to Greg Kroah-HartmanFrom: Brian Norris <[email protected]>
commit 9d0e3cac3517942a6e00eeecfe583a98715edb16 upstream.
The self-refresh helper framework overloads "disable" to sometimes mean "go into self-refresh mode," and this mode activates automatically (e.g., after some period of unchanging display output). In such cases, the display pipe is still considered "on", and user-space is not aware that we went into self-refresh mode. Thus, users may expect that vblank-related features (such as DRM_IOCTL_WAIT_VBLANK) still work properly.
However, we trigger the WARN_ONCE() here if a CRTC driver tries to leave vblank enabled.
Add a different expectation: that CRTCs *should* leave vblank enabled when going into self-refresh.
This patch is preparation for another patch -- "drm/rockchip: vop: Leave vblank enabled in self-refresh" -- which resolves conflicts between the above self-refresh behavior and the API tests in IGT's kms_vblank test module.
== Some alternatives discussed: ==
It's likely that on many display controllers, vblank interrupts will turn off when the CRTC is disabled, and so in some cases, self-refresh may not support vblank. To support such cases, we might consider additions to the generic helpers such that we fire vblank events based on a timer.
However, there is currently only one driver using the common self-refresh helpers (i.e., rockchip), and at least as of commit bed030a49f3e ("drm/rockchip: Don't fully disable vop on self refresh"), the CRTC hardware is powered enough to continue to generate vblank interrupts.
So we chose the simpler option of leaving vblank interrupts enabled. We can reevaluate this decision and perhaps augment the helpers if/when we gain a second driver that has different requirements.
v3:
* include discussion summary
v2:
* add 'ret != 0' warning case for self-refresh
* describe failing test case and relation to drm/rockchip patch better
# vblank enabled in self-refresh" Signed-off-by: Brian Norris <[email protected]> Signed-off-by: Sean Paul <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/20230109171809.v3.1.I3904f697863649eb1be540ecca147a66e42bfad7@changeid Signed-off-by: Greg Kroah-Hartman <[email protected]> --- drivers/gpu/drm/drm_atomic_helper.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/gpu/drm/drm_atomic_helper.c +10 -1
@@ -1209,7 +1209,16 @@ disable_outputs(struct drm_device *dev,continue ; ret =drm_crtc_vblank_get (crtc); -WARN_ONCE (ret != -EINVAL ,"driver forgot to call drm_crtc_vblank_off()\n" ); +/* +* Self-refresh is not a true "disable"; ensure vblank remains +* enabled. +*/ +if (new_crtc_state->self_refresh_active) +WARN_ONCE (ret !=0 , +"driver disabled vblank in self-refresh\n" ); +else +WARN_ONCE (ret != -EINVAL , +"driver forgot to call drm_crtc_vblank_off()\n" );if (ret ==0 )drm_crtc_vblank_put (crtc); }
Greg Kroah-Hartman
maintainerPATCH 195/292 drm/rockchip: vop: Leave vblank enabled in self-refresh
In reply to Greg Kroah-HartmanFrom: Brian Norris <[email protected]>
commit 2bdba9d4a3baa758c2ca7f5b37b35c7b3391dc42 upstream.
If we disable vblank when entering self-refresh, vblank APIs (like DRM_IOCTL_WAIT_VBLANK) no longer work. But user space is not aware when we enter self-refresh, so this appears to be an API violation -- that DRM_IOCTL_WAIT_VBLANK fails with EINVAL whenever the display is idle and enters self-refresh.
The downstream driver used by many of these systems never used to disable vblank for PSR, and in fact, even upstream, we didn't do that until radically redesigning the state machine in commit 6c836d965bad ("drm/rockchip: Use the helpers for PSR").
Thus, it seems like a reasonable API fix to simply restore that behavior, and leave vblank enabled.
Note that this appears to potentially unbalance the drm_crtc_vblank_{off,on}() calls in some cases, but:
(a) drm_crtc_vblank_on() documents this as OK and
(b) if I do the naive balancing, I find state machine issues such that we're not in sync properly; so it's easier to take advantage of (a).
This issue was exposed by IGT's kms_vblank tests, and reported by KernelCI. The bug has been around a while (longer than KernelCI noticed), but was only exposed once self-refresh was bugfixed more recently, and so KernelCI could properly test it. Some other notes in:
https://lore.kernel.org/dri-devel/[email protected]/
Re: renesas/master bisection: igt-kms-rockchip.kms_vblank.pipe-A-wait-forked on rk3399-gru-kevin
== Backporting notes: ==
Marking as 'Fixes' commit 6c836d965bad ("drm/rockchip: Use the helpers for PSR"), but it probably depends on commit bed030a49f3e ("drm/rockchip: Don't fully disable vop on self refresh") as well.
We also need the previous patch ("drm/atomic: Allow vblank-enabled + self-refresh "disable""), of course.
v3:
* no update
v2:
* skip unnecessary lock/unlock
--- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/rockchip/rockchip_drm_vop.c +4 -4
@@ -714,13 +714,13 @@ static void vop_crtc_atomic_disable(struif (crtc->state->self_refresh_active)rockchip_drm_set_win_enabled (crtc, false); +if (crtc->state->self_refresh_active) + goto out; +mutex_lock (&vop->vop_lock);drm_crtc_vblank_off (crtc); -if (crtc->state->self_refresh_active) - goto out; -/* * Vop standby will take effect at end of current frame, * if dsp hold valid irq happen, it means standby complete.
@@ -754,9 +754,9 @@ static void vop_crtc_atomic_disable(struvop_core_clks_disable (vop);pm_runtime_put (vop->dev); -out:mutex_unlock (&vop->vop_lock); +out:if (crtc->state->event && !crtc->state->active) {spin_lock_irq (&crtc->dev->event_lock);drm_crtc_send_vblank_event (crtc, crtc->state->event);
Greg Kroah-Hartman
maintainerPATCH 196/292 drm/dp_mst: Clear MSG_RDY flag before sending new message
In reply to Greg Kroah-HartmanFrom: Wayne Lin <[email protected]>
commit 72f1de49ffb90b29748284f27f1d6b829ab1de95 upstream.
[Why]
The sequence for collecting down_reply from source perspective should be:
Request_n->repeat (get partial reply of Request_n->clear message ready flag to ack DPRX that the message is received) till all partial replies for Request_n are received->new Request_n+1.
Now there is chance that drm_dp_mst_hpd_irq() will fire new down request in the tx queue when the down reply is incomplete. Source is restricted to generate interveleaved message transactions so we should avoid it.
Also, while assembling partial reply packets, reading out DPCD DOWN_REP Sideband MSG buffer + clearing DOWN_REP_MSG_RDY flag should be wrapped up as a complete operation for reading out a reply packet. Kicking off a new request before clearing DOWN_REP_MSG_RDY flag might be risky. e.g. If the reply of the new request has overwritten the DPRX DOWN_REP Sideband MSG buffer before source writing one to clear DOWN_REP_MSG_RDY flag, source then unintentionally flushes the reply for the new request. Should handle the up request in the same way.
[How]
Separete drm_dp_mst_hpd_irq() into 2 steps. After acking the MST IRQ event, driver calls drm_dp_mst_hpd_irq_send_new_request() and might trigger drm_dp_mst_kick_tx() only when there is no on going message transaction.
Changes since v1:
* Reworked on review comments received
-> Adjust the fix to let driver explicitly kick off new down request when mst irq event is handled and acked
-> Adjust the commit message
Changes since v2:
* Adjust the commit message
* Adjust the naming of the divided 2 functions and add a new input parameter "ack".
* Adjust code flow as per review comments.
Changes since v3:
* Update the function description of drm_dp_mst_hpd_irq_handle_event
Changes since v4:
* Change ack of drm_dp_mst_hpd_irq_handle_event() to be an array align the size of esi[]
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 ++++++------ drivers/gpu/drm/display/drm_dp_mst_topology.c | 54 +++++++++++++++++++--- drivers/gpu/drm/i915/display/intel_dp.c | 7 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 12 +++- include/drm/display/drm_dp_mst_helper.h | 7 ++ 5 files changed, 80 insertions(+), 30 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +16 -14
@@ -3263,6 +3263,7 @@ static void dm_handle_mst_sideband_msg(swhile (dret == dpcd_bytes_to_read && process_count < max_process_count) { +u8 ack[DP_PSR_ERROR_STATUS -DP_SINK_COUNT_ESI ] = {};u8 retry; dret =0 ;
@@ -3271,28 +3272,29 @@ static void dm_handle_mst_sideband_msg(sDRM_DEBUG_DRIVER ("ESI %02x %02x %02x\n" , esi[0 ], esi[1 ], esi[2 ]);/* handle HPD short pulse irq */ if (aconnector->mst_mgr.mst_state) -drm_dp_mst_hpd_irq ( - &aconnector->mst_mgr, - esi, - &new_irq_handled); +drm_dp_mst_hpd_irq_handle_event (&aconnector->mst_mgr, + esi, + ack, + &new_irq_handled);if (new_irq_handled) {/* ACK at DPCD to notify down stream */ -const int ack_dpcd_bytes_to_write = - dpcd_bytes_to_read -1 ; -for (retry =0 ; retry <3 ; retry++) { -u8 wret; +ssize_t wret; - wret =drm_dp_dpcd_write ( - &aconnector->dm_dp_aux.aux, - dpcd_addr +1 , - &esi[1 ], - ack_dpcd_bytes_to_write); -if (wret == ack_dpcd_bytes_to_write) + wret =drm_dp_dpcd_writeb (&aconnector->dm_dp_aux.aux, + dpcd_addr +1 , + ack[1 ]); +if (wret ==1 )break ; } +if (retry ==3 ) { +DRM_ERROR ("Failed to ack MST event.\n" ); +return ; + } + +drm_dp_mst_hpd_irq_send_new_request (&aconnector->mst_mgr);/* check if there is new irq to be handled */ dret = drm_dp_dpcd_read( &aconnector->dm_dp_aux.aux,
drivers/gpu/drm/display/drm_dp_mst_topology.c +47 -7
82 lines not on this page · raw message
drivers/gpu/drm/i915/display/intel_dp.c +4 -3
@@ -3940,9 +3940,7 @@ intel_dp_mst_hpd_irq(struct intel_dp *in {bool handled = false; -drm_dp_mst_hpd_irq (&intel_dp->mst_mgr, esi, &handled); -if (handled) - ack[1 ] |= esi[1 ] & (DP_DOWN_REP_MSG_RDY |DP_UP_REQ_MSG_RDY ); +drm_dp_mst_hpd_irq_handle_event (&intel_dp->mst_mgr, esi, ack, &handled);if (esi[1 ] &DP_CP_IRQ ) {intel_hdcp_handle_cp_irq (intel_dp->attached_connector);
@@ -4017,6 +4015,9 @@ intel_dp_check_mst_status(struct intel_dif (!intel_dp_ack_sink_irq_esi (intel_dp, ack))drm_dbg_kms (&i915->drm,"Failed to ack ESI\n" ); + +if (ack[1 ] & (DP_DOWN_REP_MSG_RDY |DP_UP_REQ_MSG_RDY )) +drm_dp_mst_hpd_irq_send_new_request (&intel_dp->mst_mgr); }return link_ok;
drivers/gpu/drm/nouveau/dispnv50/disp.c +8 -4
@@ -1359,22 +1359,26 @@ nv50_mstm_service(struct nouveau_drm *dru8 esi[8 ] = {};while (handled) { +u8 ack[8 ] = {}; + rc =drm_dp_dpcd_read (aux,DP_SINK_COUNT_ESI , esi,8 );if (rc !=8 ) { ret = false;break ; } -drm_dp_mst_hpd_irq (&mstm->mgr, esi, &handled); +drm_dp_mst_hpd_irq_handle_event (&mstm->mgr, esi, ack, &handled);if (!handled)break ; - rc =drm_dp_dpcd_write (aux,DP_SINK_COUNT_ESI +1 , &esi[1 ], -3 ); -if (rc !=3 ) { + rc =drm_dp_dpcd_writeb (aux,DP_SINK_COUNT_ESI +1 , ack[1 ]); + +if (rc !=1 ) { ret = false;break ; } + +drm_dp_mst_hpd_irq_send_new_request (&mstm->mgr); }if (!ret)
include/drm/display/drm_dp_mst_helper.h +5 -2
@@ -815,8 +815,11 @@ void drm_dp_mst_topology_mgr_destroy(strbool drm_dp_read_mst_cap (struct drm_dp_aux *aux,const u8 dpcd[DP_RECEIVER_CAP_SIZE ]);int drm_dp_mst_topology_mgr_set_mst (struct drm_dp_mst_topology_mgr *mgr,bool mst_state); -int drm_dp_mst_hpd_irq (struct drm_dp_mst_topology_mgr *mgr,u8 *esi,bool *handled); - +int drm_dp_mst_hpd_irq_handle_event (struct drm_dp_mst_topology_mgr *mgr, +const u8 *esi, +u8 *ack, +bool *handled); +void drm_dp_mst_hpd_irq_send_new_request (struct drm_dp_mst_topology_mgr *mgr); int drm_dp_mst_detect_port(struct drm_connector *connector,
Greg Kroah-Hartman
maintainerPATCH 197/292 drm/amd/display: Limit DCN32 8 channel or less parts to DPM1 for FPO
In reply to Greg Kroah-HartmanFrom: Alvin Lee <[email protected]>
commit ee7be8f3de1ccc9665281fe996f9b6d45191ec1a upstream.
- Due to hardware related QoS issues, we need to limit certain SKUs with less memory channels to DPM1 and above.
- At DPM0 + workload running, the urgent return latency can exceed 15us (the expected maximum is 4us) which results in underflow
--- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c | 2 ++ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c | 15 +++++++++++++++ drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h | 2 ++ 3 files changed, 19 insertions(+)
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c +2 -0
@@ -1888,6 +1888,8 @@ bool dcn32_validate_bandwidth(struct dc dc->res_pool->funcs->calculate_wm_and_dlg (dc, context, pipes, pipe_cnt, vlevel); +dcn32_override_min_req_memclk (dc, context); +BW_VAL_TRACE_END_WATERMARKS (); goto validate_out;
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +15 -0
@@ -2882,3 +2882,18 @@ void dcn32_set_clock_limits(const structdc_assert_fp_enabled (); dcn3_2_soc.clock_limits[0 ].dcfclk_mhz =1200.0 ; } + +void dcn32_override_min_req_memclk (struct dc *dc,struct dc_state *context) +{ +// WA: restrict FPO and SubVP to use first non-strobe mode (DCN32 BW issue) +if ((context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching ||dcn32_subvp_in_use (dc, context)) && + dc->dml.soc.num_chans <=8 ) { +int num_mclk_levels = dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels; + +if (context->bw_ctx.dml.vba.DRAMSpeed <= dc->clk_mgr->bw_params->clk_table.entries[0 ].memclk_mhz *16 && + num_mclk_levels >1 ) { + context->bw_ctx.dml.vba.DRAMSpeed = dc->clk_mgr->bw_params->clk_table.entries[1 ].memclk_mhz *16 ; + context->bw_ctx.bw.dcn.clk.dramclk_khz = context->bw_ctx.dml.vba.DRAMSpeed *1000 /16 ; + } + } +}
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h +2 -0
@@ -80,6 +80,8 @@ void dcn32_assign_fpo_vactive_candidate(bool dcn32_find_vactive_pipe (struct dc *dc,const struct dc_state *context,uint32_t vactive_margin_req); +void dcn32_override_min_req_memclk (struct dc *dc,struct dc_state *context); +void dcn32_set_clock_limits (const struct _vcs_dpi_soc_bounding_box_st *soc_bb);#endif
Greg Kroah-Hartman
maintainerPATCH 198/292 drm/amd/display: Fix in secure display context creation
In reply to Greg Kroah-HartmanFrom: Alan Liu <[email protected]>
commit f477c7b5ec3e4ef87606671b340abf3bdb0cccff upstream.
[Why & How]
We need to store CRTC information in secure_display_ctx, so postpone the call to amdgpu_dm_crtc_secure_display_create_contexts() until we initialize all CRTCs.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +++++------ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +5 -6
@@ -1776,12 +1776,6 @@ static int amdgpu_dm_init(struct amdgpu_dc_init_callbacks (adev->dm.dc, &init_params); } -#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY ) - adev->dm.secure_display_ctxs =amdgpu_dm_crtc_secure_display_create_contexts (adev); -if (!adev->dm.secure_display_ctxs) { -DRM_ERROR ("amdgpu: failed to initialize secure_display_ctxs.\n" ); - } -#endif if (dc_is_dmub_outbox_supported (adev->dm.dc)) {init_completion (&adev->dm.dmub_aux_transfer_done); adev->dm.dmub_notify =kzalloc (sizeof (struct dmub_notification ),GFP_KERNEL );
@@ -1840,6 +1834,11 @@ static int amdgpu_dm_init(struct amdgpu_ goto error; } +#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY ) + adev->dm.secure_display_ctxs =amdgpu_dm_crtc_secure_display_create_contexts (adev); +if (!adev->dm.secure_display_ctxs) +DRM_ERROR ("amdgpu: failed to initialize secure display contexts.\n" ); +#endif DRM_DEBUG_DRIVER ("KMS initialized.\n" );
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h +1 -1
@@ -100,7 +100,7 @@ struct secure_display_context *amdgpu_dm#else #define amdgpu_dm_crc_window_is_activated (x)#define amdgpu_dm_crtc_handle_crc_window_irq (x) -#define amdgpu_dm_crtc_secure_display_create_contexts () +#define amdgpu_dm_crtc_secure_display_create_contexts (x)#endif #endif /* AMD_DAL_DEV_AMDGPU_DM_AMDGPU_DM_CRC_H_ */
Greg Kroah-Hartman
maintainerPATCH 199/292 drm/amd/display: fix seamless odm transitions
In reply to Greg Kroah-HartmanFrom: Dmytro Laktyushkin <[email protected]>
commit 75c2b7ed080d7421157c03064be82275364136e7 upstream.
Add missing programming and function pointers
--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 11 +++++++++++ drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +11 -0
@@ -1732,6 +1732,17 @@ static void dcn20_program_pipe(if (hws->funcs.setup_vupdate_interrupt) hws->funcs.setup_vupdate_interrupt (dc, pipe_ctx); + +if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) { +unsigned int k1_div, k2_div; + + hws->funcs.calculate_dccg_k1_k2_values (pipe_ctx, &k1_div, &k2_div); + + dc->res_pool->dccg->funcs->set_pixel_rate_div ( + dc->res_pool->dccg, + pipe_ctx->stream_res.tg->inst, + k1_div, k2_div); + } }if (pipe_ctx->update_flags.bits.odm)
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c +1 -1
@@ -98,7 +98,7 @@ static void optc32_set_odm_combine(struc optc1->opp_count = opp_cnt; } -static void optc32_set_h_timing_div_manual_mode (struct timing_generator *optc,bool manual_mode) +void optc32_set_h_timing_div_manual_mode (struct timing_generator *optc,bool manual_mode) {struct optc *optc1 =DCN10TG_FROM_TG (optc);
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.h +1 -0
@@ -179,5 +179,6 @@ SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh)void dcn32_timing_generator_init (struct optc *optc1); +void optc32_set_h_timing_div_manual_mode (struct timing_generator *optc,bool manual_mode);#endif /* __DC_OPTC_DCN32_H__ */
Greg Kroah-Hartman
maintainerPATCH 200/292 drm/amd/display: edp do not add non-edid timings
In reply to Greg Kroah-HartmanFrom: Hersen Wu <[email protected]>
commit 7a0e005c7957931689a327b2a4e7333a19f13f95 upstream.
[Why] most edp support only timings from edid. applying non-edid timings, especially those timings out of edp bandwidth, may damage edp.
[How] do not add non-edid timings for edp.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +7 -1
@@ -7192,7 +7192,13 @@ static int amdgpu_dm_connector_get_modesdrm_add_modes_noedid (connector,1920 ,1080 ); }else {amdgpu_dm_connector_ddc_get_modes (connector, edid); -amdgpu_dm_connector_add_common_modes (encoder, connector); +/* most eDP supports only timings from its edid, +* usually only detailed timings are available +* from eDP edid. timings which are not from edid +* may damage eDP +*/ +if (connector->connector_type != DRM_MODE_CONNECTOR_eDP) +amdgpu_dm_connector_add_common_modes (encoder, connector);amdgpu_dm_connector_add_freesync_modes (connector, edid); }amdgpu_dm_fbc_init (connector);
Greg Kroah-Hartman
maintainerPATCH 201/292 drm/amd/display: Remove Phantom Pipe Check When Calculating K1 and K2
In reply to Greg Kroah-HartmanFrom: Austin Zheng <[email protected]>
commit 1966bbfdfe476d271b338336254854c5edd5a907 upstream.
[Why]
K1 and K2 not being setting properly when subVP is active.
[How]
Have phantom pipes use the same programing as the main pipes without checking the paired stream
--- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c +0 -4
@@ -1125,10 +1125,6 @@ unsigned int dcn32_calculate_dccg_k1_k2_unsigned int odm_combine_factor =0 ;bool two_pix_per_container = false; -// For phantom pipes, use the same programming as the main pipes -if (pipe_ctx->stream->mall_stream_config.type ==SUBVP_PHANTOM ) { - stream = pipe_ctx->stream->mall_stream_config.paired_stream; - } two_pix_per_container =optc2_is_two_pixels_per_containter (&stream->timing); odm_combine_factor =get_odm_config (pipe_ctx,NULL );
Greg Kroah-Hartman
maintainerPATCH 202/292 drm/amd/display: disable seamless boot if force_odm_combine is enabled
In reply to Greg Kroah-HartmanFrom: Leo Chen <[email protected]>
commit 26518b39181876064850209ecdab48c0ee5924b1 upstream.
[Why & How]
Having seamless boot on while forcing debug option ODM combine 2 to 1 will cause some corruptions because of some missing programmings.
--- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/display/dc/core/dc.c +3 -0
@@ -1602,6 +1602,9 @@ bool dc_validate_boot_timing(const strucreturn false; } +if (dc->debug.force_odm_combine) +return false; +/* Check for enabled DIG to identify enabled display */ if (!link->link_enc->funcs->is_dig_enabled (link->link_enc))return false;
Greg Kroah-Hartman
maintainerPATCH 203/292 drm/amdgpu: fix clearing mappings for BOs that are always valid in VM
In reply to Greg Kroah-HartmanFrom: Samuel Pitoiset <[email protected]>
commit ea2c3c08554601b051d91403a241266e1cf490a5 upstream.
Per VM BOs must be marked as moved or otherwise their ranges are not updated on use which might be necessary when the replace operation splits mappings.
This fixes random GPU hangs when replacing sparse mappings from the userspace, while OP_MAP/OP_UNMAP works fine because always valid BOs are correctly handled there.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +12 -0
@@ -1683,18 +1683,30 @@ int amdgpu_vm_bo_clear_mappings(struct a/* Insert partial mapping before the range */ if (!list_empty (&before->list)) { +struct amdgpu_bo *bo = before->bo_va->base.bo; +amdgpu_vm_it_insert (before, &vm->va);if (before->flags &AMDGPU_PTE_PRT )amdgpu_vm_prt_get (adev); + +if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv && + !before->bo_va->base.moved) +amdgpu_vm_bo_moved (&before->bo_va->base); }else {kfree (before); }/* Insert partial mapping after the range */ if (!list_empty (&after->list)) { +struct amdgpu_bo *bo = after->bo_va->base.bo; +amdgpu_vm_it_insert (after, &vm->va);if (after->flags &AMDGPU_PTE_PRT )amdgpu_vm_prt_get (adev); + +if (bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv && + !after->bo_va->base.moved) +amdgpu_vm_bo_moved (&after->bo_va->base); }else {kfree (after); }
Greg Kroah-Hartman
maintainerPATCH 204/292 drm/amd: Disable PSR-SU on Parade 0803 TCON
In reply to Greg Kroah-HartmanFrom: Mario Limonciello <[email protected]>
commit 072030b1783056b5de8b0fac5303a5e9dbc6cfde upstream.
A number of users have reported that there are random hangs occurring caused by PSR-SU specifically on panels that contain the parade 0803 TCON. Users have been able to work around the issue by disabling PSR entirely.
To avoid these hangs, disable PSR-SU when this TCON is found.
--- drivers/gpu/drm/amd/display/modules/power/power_helpers.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/display/modules/power/power_helpers.c +2 -0
@@ -818,6 +818,8 @@ bool is_psr_su_specific_panel(struct dc_ ((dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x08) || (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x07))) isPSRSUSupported = false; + else if (dpcd_caps->sink_dev_id_str[1] == 0x08 && dpcd_caps->sink_dev_id_str[0] == 0x03) + isPSRSUSupported = false; else if (dpcd_caps->psr_info.force_psrsu_cap == 0x1) isPSRSUSupported = true; }
Greg Kroah-Hartman
maintainerPATCH 205/292 drm/amd/display: add a NULL pointer check
In reply to Greg Kroah-HartmanFrom: Sung-huai Wang <[email protected]>
commit 0f48a4b83610cb0e4e0bc487800ab69f51b4aca6 upstream.
[Why & How]
We have to check if stream is properly initialized before calling find_matching_pll(), otherwise we might end up trying to deferecence a NULL pointer.
--- drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +6 -4
@@ -970,10 +970,12 @@ enum dc_status resource_map_phy_clock_re || dc_is_virtual_signal(pipe_ctx->stream->signal)) pipe_ctx->clock_source = dc->res_pool->dp_clock_source; - else - pipe_ctx->clock_source = find_matching_pll( - &context->res_ctx, dc->res_pool, - stream); + else { +if (stream && stream->link && stream->link->link_enc) + pipe_ctx->clock_source =find_matching_pll ( + &context->res_ctx, dc->res_pool, + stream); + }if (pipe_ctx->clock_source ==NULL )return DC_NO_CLOCK_SOURCE_RESOURCE ;
Greg Kroah-Hartman
maintainerPATCH 206/292 drm/amd/display: Fix 128b132b link loss handling
In reply to Greg Kroah-HartmanFrom: Ilya Bakoulin <[email protected]>
commit ed83fe2abcace898fdec5c2ba0455703178ac9a3 upstream.
[Why]
We don't check 128b132b-specific bits in LANE_ALIGN_STATUS_UPDATED DPCD registers when parsing link loss status, which can cause us to miss a link loss notification from some sinks.
[How]
Add a 128b132b-specific status bit check.
--- .../display/dc/link/protocols/link_dp_irq_handler.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +9 -2
@@ -82,8 +82,15 @@ bool dp_parse_link_loss_status( }/* Check interlane align.*/ -if (sink_status_changed || - !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) { +if (link_dp_get_encoding_format (&link->cur_link_settings) == DP_128b_132b_ENCODING && + (!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b || + !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b)) { + sink_status_changed = true; + }else if (!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) { + sink_status_changed = true; + } + +if (sink_status_changed) {DC_LOG_HW_HPD_IRQ ("%s: Link Status changed.\n" , __func__);
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 207/292 drm/amd/display: Correct `DMUB_FW_VERSION` macro
In reply to Greg Kroah-HartmanFrom: Mario Limonciello <[email protected]>
commit 274d205cb59f43815542e04b42a9e6d0b9b95eff upstream.
The DMUB_FW_VERSION macro has a mistake in that the revision field is off by one byte. The last byte is typically used for other purposes and not a revision.
--- drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dmub/dmub_srv.h +1 -1
@@ -490,7 +490,7 @@ struct dmub_notification {* of a firmware to know if feature or functionality is supported or present. */ #define DMUB_FW_VERSION (major, minor, revision) \ - ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | ((revision) & 0xFFFF)) + ((((major) & 0xFF) << 24) | (((minor) & 0xFF) << 16) | (((revision) & 0xFF) << 8))/** * dmub_srv_create() - creates the DMUB service.
Greg Kroah-Hartman
maintainerPATCH 208/292 drm/amd/display: Add monitor specific edid quirk
In reply to Greg Kroah-HartmanFrom: Aurabindo Pillai <[email protected]>
commit 613a7956deb3b1ffa2810c6d4c90ee9c3d743dbb upstream.
Disable FAMS on a Samsung Odyssey G9 monitor. Experiments show that this monitor does not work well under some use cases, and is likely implementation specific bug on the monitor's firmware.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 26 ++++++++++++++ 1 file changed, 26 insertions(+)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +26 -0
@@ -47,6 +47,30 @@/* MST Dock */ static const uint8_t SYNAPTICS_DEVICE_ID [] ="SYNA" ; +static u32 edid_extract_panel_id (struct edid *edid) +{ +return (u32 )edid->mfg_id[0 ] <<24 | + (u32 )edid->mfg_id[1 ] <<16 | + (u32 )EDID_PRODUCT_ID (edid); +} + +static void apply_edid_quirks (struct edid *edid,struct dc_edid_caps *edid_caps) +{ +uint32_t panel_id =edid_extract_panel_id (edid); + +switch (panel_id) { +/* Workaround for some monitors which does not work well with FAMS */ +case drm_edid_encode_panel_id ('S' ,'A' ,'M' ,0x0E5E ): +case drm_edid_encode_panel_id ('S' ,'A' ,'M' ,0x7053 ): +case drm_edid_encode_panel_id ('S' ,'A' ,'M' ,0x71AC ): +DRM_DEBUG_DRIVER ("Disabling FAMS on monitor with panel id %X\n" , panel_id); + edid_caps->panel_patch.disable_fams = true; +break ; +default : +return ; + } +} +/* dm_helpers_parse_edid_caps * * Parse edid caps
@@ -118,6 +142,8 @@ enum dc_edid_status dm_helpers_parse_edielse edid_caps->speaker_flags =DEFAULT_SPEAKER_LOCATION ; +apply_edid_quirks (edid_buf, edid_caps); +kfree (sads);kfree (sadb);
Greg Kroah-Hartman
maintainerPATCH 209/292 drm/amdgpu: avoid restore process run into dead loop.
In reply to Greg Kroah-HartmanFrom: gaba <[email protected]>
commit 8a774fe912ff09e39c2d3a3589c729330113f388 upstream.
In restore process worker, pinned BO cause update PTE fail, then the function re-schedule the restore_work. This will generate dead loop.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +3 -0
@@ -2792,6 +2792,9 @@ int amdgpu_amdkfd_gpuvm_restore_process_if (!attachment->is_mapped)continue ; +if (attachment->bo_va->base.bo->tbo.pin_count) +continue ; +kfd_mem_dmaunmap_attachment (mem, attachment); ret =update_gpuvm_pte (mem, attachment, &sync_obj);if (ret) {
Greg Kroah-Hartman
maintainerPATCH 210/292 drm/amd/pm: fix smu i2c data read risk
In reply to Greg Kroah-HartmanFrom: Yang Wang <[email protected]>
commit d934e537c14bfe1227ced6341472571f354383e8 upstream.
the smu driver_table is used for all types of smu tables data transcation (e.g: PPtable, Metrics, i2c, Ecc..).
it is necessary to hold this lock to avoiding data tampering during the i2c read operation.
--- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +1 -1
@@ -2113,7 +2113,6 @@ static int arcturus_i2c_xfer(struct i2c_ }mutex_lock (&adev->pm.mutex); r =smu_cmn_update_table (smu,SMU_TABLE_I2C_COMMANDS ,0 , req, true); -mutex_unlock (&adev->pm.mutex);if (r) goto fail;
@@ -2130,6 +2129,7 @@ static int arcturus_i2c_xfer(struct i2c_ } r = num_msgs; fail: +mutex_unlock (&adev->pm.mutex);kfree (req);return r; }
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +1 -1
@@ -3021,7 +3021,6 @@ static int navi10_i2c_xfer(struct i2c_ad }mutex_lock (&adev->pm.mutex); r =smu_cmn_update_table (smu,SMU_TABLE_I2C_COMMANDS ,0 , req, true); -mutex_unlock (&adev->pm.mutex);if (r) goto fail;
@@ -3038,6 +3037,7 @@ static int navi10_i2c_xfer(struct i2c_ad } r = num_msgs; fail: +mutex_unlock (&adev->pm.mutex);kfree (req);return r; }
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +1 -1
@@ -3842,7 +3842,6 @@ static int sienna_cichlid_i2c_xfer(struc }mutex_lock (&adev->pm.mutex); r =smu_cmn_update_table (smu,SMU_TABLE_I2C_COMMANDS ,0 , req, true); -mutex_unlock (&adev->pm.mutex);if (r) goto fail;
@@ -3859,6 +3858,7 @@ static int sienna_cichlid_i2c_xfer(struc } r = num_msgs; fail: +mutex_unlock (&adev->pm.mutex);kfree (req);return r; }
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +1 -1
@@ -1525,7 +1525,6 @@ static int aldebaran_i2c_xfer(struct i2c }mutex_lock (&adev->pm.mutex); r =smu_cmn_update_table (smu,SMU_TABLE_I2C_COMMANDS ,0 , req, true); -mutex_unlock (&adev->pm.mutex);if (r) goto fail;
@@ -1542,6 +1541,7 @@ static int aldebaran_i2c_xfer(struct i2c } r = num_msgs; fail: +mutex_unlock (&adev->pm.mutex);kfree (req);return r; }
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +1 -1
@@ -1838,7 +1838,6 @@ static int smu_v13_0_0_i2c_xfer(struct i }mutex_lock (&adev->pm.mutex); r =smu_cmn_update_table (smu,SMU_TABLE_I2C_COMMANDS ,0 , req, true); -mutex_unlock (&adev->pm.mutex);if (r) goto fail;
@@ -1855,6 +1854,7 @@ static int smu_v13_0_0_i2c_xfer(struct i } r = num_msgs; fail: +mutex_unlock (&adev->pm.mutex);kfree (req);return r; }
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +1 -1
@@ -1639,7 +1639,6 @@ static int smu_v13_0_6_i2c_xfer(struct i }mutex_lock (&adev->pm.mutex); r =smu_v13_0_6_request_i2c_xfer (smu, req); -mutex_unlock (&adev->pm.mutex);if (r) goto fail;
@@ -1656,6 +1655,7 @@ static int smu_v13_0_6_i2c_xfer(struct i } r = num_msgs; fail: +mutex_unlock (&adev->pm.mutex);kfree (req);return r; }
Greg Kroah-Hartman
maintainerPATCH 211/292 drm/ttm: Dont leak a resource on eviction error
In reply to Greg Kroah-HartmanFrom: Thomas Hellström <[email protected]>
commit e8188c461ee015ba0b9ab2fc82dbd5ebca5a5532 upstream.
On eviction errors other than -EMULTIHOP we were leaking a resource. Fix.
v2:
- Avoid yet another goto (Andi Shyti)
--- drivers/gpu/drm/ttm/ttm_bo.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
drivers/gpu/drm/ttm/ttm_bo.c +11 -11
@@ -458,18 +458,18 @@ static int ttm_bo_evict(struct ttm_buffe goto out; } -bounce: - ret =ttm_bo_handle_move_mem (bo, evict_mem, true, ctx, &hop); -if (ret == -EMULTIHOP ) { +do { + ret =ttm_bo_handle_move_mem (bo, evict_mem, true, ctx, &hop); +if (ret != -EMULTIHOP ) +break ; + ret =ttm_bo_bounce_temp_buffer (bo, &evict_mem, ctx, &hop); -if (ret) { -if (ret != -ERESTARTSYS && ret != -EINTR ) -pr_err ("Buffer eviction failed\n" ); -ttm_resource_free (bo, &evict_mem); - goto out; - } -/* try and move to final place now. */ - goto bounce; + }while (!ret); + +if (ret) { +ttm_resource_free (bo, &evict_mem); +if (ret != -ERESTARTSYS && ret != -EINTR ) +pr_err ("Buffer eviction failed\n" ); } out:return ret;
Greg Kroah-Hartman
maintainerPATCH 212/292 drm/ttm: Dont leak a resource on swapout move error
In reply to Greg Kroah-HartmanFrom: Thomas Hellström <[email protected]>
commit a590f03d8de7c4cb7ce4916dc7f2fd10711faabe upstream.
If moving the bo to system for swapout failed, we were leaking a resource. Fix.
--- drivers/gpu/drm/ttm/ttm_bo.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/ttm/ttm_bo.c +1 -0
@@ -1167,6 +1167,7 @@ int ttm_bo_swapout(struct ttm_buffer_obj ret =ttm_bo_handle_move_mem (bo, evict_mem, true, &ctx, &hop);if (unlikely (ret !=0 )) {WARN (ret == -EMULTIHOP ,"Unexpected multihop in swaput - likely driver bug.\n" ); +ttm_resource_free (bo, &evict_mem); goto out; } }
Greg Kroah-Hartman
maintainerPATCH 213/292 drm/ttm: never consider pinned BOs for eviction&swap
In reply to Greg Kroah-HartmanFrom: Christian König <[email protected]>
commit a2848d08742c8e8494675892c02c0d22acbe3cf8 upstream.
There is a small window where we have already incremented the pin count but not yet moved the bo from the lru to the pinned list.
--- drivers/gpu/drm/ttm/ttm_bo.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/ttm/ttm_bo.c +6 -0
@@ -517,6 +517,12 @@ static bool ttm_bo_evict_swapout_allowab {bool ret = false; +if (bo->pin_count) { + *locked = false; + *busy = false; +return false; + } +if (bo->base.resv == ctx->resv) {dma_resv_assert_held (bo->base.resv);if (ctx->allow_res_evict)
Greg Kroah-Hartman
maintainerPATCH 214/292 serial: atmel: dont enable IRQs prematurely
In reply to Greg Kroah-HartmanFrom: Dan Carpenter <[email protected]>
commit 27a826837ec9a3e94cc44bd9328b8289b0fcecd7 upstream.
The atmel_complete_tx_dma() function disables IRQs at the start of the function by calling spin_lock_irqsave(&port->lock, flags); There is no need to disable them a second time using the spin_lock_irq() function and, in fact, doing so is a bug because it will enable IRQs prematurely when we call spin_unlock_irq().
Just use spin_lock/unlock() instead without disabling or enabling IRQs.
--- drivers/tty/serial/atmel_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/atmel_serial.c +2 -2
@@ -868,11 +868,11 @@ static void atmel_complete_tx_dma(void *dmaengine_terminate_all (chan);uart_xmit_advance (port, atmel_port->tx_len); -spin_lock_irq (&atmel_port->lock_tx); +spin_lock (&atmel_port->lock_tx);async_tx_ack (atmel_port->desc_tx); atmel_port->cookie_tx = -EINVAL ; atmel_port->desc_tx =NULL ; -spin_unlock_irq (&atmel_port->lock_tx); +spin_unlock (&atmel_port->lock_tx);if (uart_circ_chars_pending (xmit) <WAKEUP_CHARS )uart_write_wakeup (port);
Greg Kroah-Hartman
maintainerPATCH 215/292 tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in case of error
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
commit a9c09546e903f1068acfa38e1ee18bded7114b37 upstream.
If clk_get_rate() fails, the clk that has just been allocated needs to be freed.
Message-ID: <e4baf6039368f52e5a5453982ddcb9a330fc689e.1686412569.git.christophe.jaillet@wanadoo.fr>
--- drivers/tty/serial/samsung_tty.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/tty/serial/samsung_tty.c +5 -1
@@ -1459,8 +1459,12 @@ static unsigned int s3c24xx_serial_getclcontinue ; rate =clk_get_rate (clk); -if (!rate) +if (!rate) { +dev_err (ourport->port.dev, +"Failed to get clock rate for %s.\n" , clkname); +clk_put (clk);continue ; + }if (ourport->info->has_divslot) {unsigned long div = rate / req_baud;
Greg Kroah-Hartman
maintainerPATCH 216/292 tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when iterating clk
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
commit 832e231cff476102e8204a9e7bddfe5c6154a375 upstream.
When the best clk is searched, we iterate over all possible clk.
If we find a better match, the previous one, if any, needs to be freed. If a better match has already been found, we still need to free the new one, otherwise it leaks.
Message-ID: <cf3e0053d2fc7391b2d906a86cd01a5ef15fb9dc.1686412569.git.christophe.jaillet@wanadoo.fr>
--- drivers/tty/serial/samsung_tty.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/tty/serial/samsung_tty.c +8 -0
@@ -1490,10 +1490,18 @@ static unsigned int s3c24xx_serial_getclk(struct s3c24xx_uart_port *ourport, calc_deviation = -calc_deviation;if (calc_deviation < deviation) { +/* +* If we find a better clk, release the previous one, if +* any. +*/ +if (!IS_ERR (*best_clk)) +clk_put (*best_clk); *best_clk = clk; best_quot = quot; *clk_num = cnt; deviation = calc_deviation; + }else { +clk_put (clk); } }
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 217/292 tty: serial: imx: fix rs485 rx after tx
In reply to Greg Kroah-HartmanFrom: Martin Fuzzey <[email protected]>
commit 639949a7031e04c59ec91614eceb9543e9120f43 upstream.
Since commit 79d0224f6bf2 ("tty: serial: imx: Handle RS485 DE signal active high") RS485 reception no longer works after a transmission.
The following scenario shows the problem:
1) Open a port in RS485 mode
2) Receive data from remote (OK)
3) Transmit data to remote (OK)
4) Receive data from remote (Nothing received)
In RS485 mode, imx_uart_start_tx() calls imx_uart_stop_rx() and, when the transmission is complete, imx_uart_stop_tx() calls imx_uart_start_rx().
Since the above commit imx_uart_stop_rx() now sets the loopback bit but imx_uart_start_rx() does not clear it causing the hardware to remain in loopback mode and not receive external data.
Fix this by moving the existing loopback disable code to a helper function and calling it from imx_uart_start_rx() too.
--- drivers/tty/serial/imx.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
drivers/tty/serial/imx.c +13 -5
@@ -369,6 +369,16 @@ static void imx_uart_soft_reset(struct i sport->idle_counter =0 ; } +static void imx_uart_disable_loopback_rs485 (struct imx_port *sport) +{ +unsigned int uts; + +/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ + uts =imx_uart_readl (sport,imx_uart_uts_reg (sport)); + uts &= ~UTS_LOOP ; +imx_uart_writel (sport, uts,imx_uart_uts_reg (sport)); +} +/* called with port.lock taken and irqs off */ static void imx_uart_start_rx (struct uart_port *port) {
@@ -390,6 +400,7 @@ static void imx_uart_start_rx(struct uar/* Write UCR2 first as it includes RXEN */ imx_uart_writel (sport, ucr2,UCR2 );imx_uart_writel (sport, ucr1,UCR1 ); +imx_uart_disable_loopback_rs485 (sport); }/* called with port.lock taken and irqs off */
@@ -1422,7 +1433,7 @@ static int imx_uart_startup(struct uart_int retval;unsigned long flags;int dma_is_inited =0 ; -u32 ucr1, ucr2, ucr3, ucr4, uts; +u32 ucr1, ucr2, ucr3, ucr4; retval =clk_prepare_enable (sport->clk_per);if (retval)
@@ -1521,10 +1532,7 @@ static int imx_uart_startup(struct uart_imx_uart_writel (sport, ucr2,UCR2 ); } -/* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ - uts =imx_uart_readl (sport,imx_uart_uts_reg (sport)); - uts &= ~UTS_LOOP ; -imx_uart_writel (sport, uts,imx_uart_uts_reg (sport)); +imx_uart_disable_loopback_rs485 (sport);spin_unlock_irqrestore (&sport->port.lock, flags);
Greg Kroah-Hartman
maintainerPATCH 218/292 tty: fix hang on tty device with no_room set
In reply to Greg Kroah-HartmanFrom: Hui Li <[email protected]>
commit 4903fde8047a28299d1fc79c1a0dcc255e928f12 upstream.
It is possible to hang pty devices in this case, the reader was blocking at epoll on master side, the writer was sleeping at wait_woken inside n_tty_write on slave side, and the write buffer on tty_port was full, we found that the reader and writer would never be woken again and blocked forever.
The problem was caused by a race between reader and kworker:n_tty_read(reader): n_tty_receive_buf_common(kworker):
copy_from_read_buf()|
|room = N_TTY_BUF_SIZE - (ldata->read_head - tail)
|room <= 0
n_tty_kick_worker() |
|ldata->no_room = trueAfter writing to slave device, writer wakes up kworker to flush data on tty_port to reader, and the kworker finds that reader has no room to store data so room <= 0 is met. At this moment, reader consumes all the data on reader buffer and calls n_tty_kick_worker to check ldata->no_room which is false and reader quits reading. Then kworker sets ldata->no_room=true and quits too.
If write buffer is not full, writer will wake kworker to flush data again after following writes, but if write buffer is full and writer goes to sleep, kworker will never be woken again and tty device is blocked.
This problem can be solved with a check for read buffer size inside n_tty_receive_buf_common, if read buffer is empty and ldata->no_room is true, a call to n_tty_kick_worker is necessary to keep flushing data to reader.
Message-ID: <[email protected]>
--- drivers/tty/n_tty.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
drivers/tty/n_tty.c +21 -4
@@ -203,8 +203,8 @@ static void n_tty_kick_worker(struct ttystruct n_tty_data *ldata = tty->disc_data;/* Did the input worker stop? Restart it */ -if (unlikely (ldata->no_room)) { - ldata->no_room =0 ; +if (unlikely (READ_ONCE (ldata->no_room))) { +WRITE_ONCE (ldata->no_room,0 );WARN_RATELIMIT (tty->port->itty ==NULL ,"scheduling with invalid itty\n" );
@@ -1697,7 +1697,7 @@ n_tty_receive_buf_common(struct tty_struif (overflow && room <0 ) ldata->read_head--; room = overflow; - ldata->no_room = flow && !room; +WRITE_ONCE (ldata->no_room, flow && !room); }else overflow =0 ;
@@ -1728,6 +1728,17 @@ n_tty_receive_buf_common(struct tty_stru }else n_tty_check_throttle (tty); +if (unlikely (ldata->no_room)) { +/* +* Barrier here is to ensure to read the latest read_tail in +* chars_in_buffer() and to make sure that read_tail is not loaded +* before ldata->no_room is set. +*/ +smp_mb (); +if (!chars_in_buffer (tty)) +n_tty_kick_worker (tty); + } +up_read (&tty->termios_rwsem);return rcvd;
@@ -2281,8 +2292,14 @@ more_to_be_read:if (time) timeout = time; } -if (old_tail != ldata->read_tail) +if (old_tail != ldata->read_tail) { +/* +* Make sure no_room is not read in n_tty_kick_worker() +* before setting ldata->read_tail in copy_from_read_buf(). +*/ +smp_mb ();n_tty_kick_worker (tty); + }up_read (&tty->termios_rwsem);remove_wait_queue (&tty->read_wait, &wait);
Greg Kroah-Hartman
maintainerPATCH 219/292 firmware: stratix10-svc: Fix a potential resource leak in svc_create_memory_pool()
In reply to Greg Kroah-HartmanFrom: Christophe JAILLET <[email protected]>
commit 1995f15590ca222f91193ed11461862b450abfd6 upstream.
svc_create_memory_pool() is only called from stratix10_svc_drv_probe(). Most of resources in the probe are managed, but not this memremap() call.
There is also no memunmap() call in the file.
So switch to devm_memremap() to avoid a resource leak.
Message-ID: <[email protected]>
--- drivers/firmware/stratix10-svc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/stratix10-svc.c +1 -1
@@ -755,7 +755,7 @@ svc_create_memory_pool(struct platform_device *pdev, end =rounddown (sh_memory->addr + sh_memory->size,PAGE_SIZE ); paddr = begin; size = end - begin; - va =memremap (paddr, size,MEMREMAP_WC ); + va =devm_memremap (dev, paddr, size,MEMREMAP_WC );if (!va) {dev_err (dev,"fail to remap shared memory\n" );return ERR_PTR (-EINVAL );
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 220/292 libceph: harden msgr2.1 frame segment length checks
In reply to Greg Kroah-HartmanFrom: Ilya Dryomov <[email protected]>
commit a282a2f10539dce2aa619e71e1817570d557fc97 upstream.
ceph_frame_desc::fd_lens is an int array. decode_preamble() thus effectively casts u32 -> int but the checks for segment lengths are written as if on unsigned values. While reading in HELLO or one of the AUTH frames (before authentication is completed), arithmetic in head_onwire_len() can get duped by negative ctrl_len and produce head_len which is less than CEPH_PREAMBLE_LEN but still positive. This would lead to a buffer overrun in prepare_read_control() as the preamble gets copied to the newly allocated buffer of size head_len.
--- net/ceph/messenger_v2.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-)
net/ceph/messenger_v2.c +26 -15
@@ -391,6 +391,8 @@ static int head_onwire_len(int ctrl_len,int head_len;int rem_len; +BUG_ON (ctrl_len <0 || ctrl_len >CEPH_MSG_MAX_CONTROL_LEN ); +if (secure) { head_len =CEPH_PREAMBLE_SECURE_LEN ;if (ctrl_len >CEPH_PREAMBLE_INLINE_LEN ) {
@@ -409,6 +411,10 @@ static int head_onwire_len(int ctrl_len,static int __tail_onwire_len (int front_len,int middle_len,int data_len,bool secure) { +BUG_ON (front_len <0 || front_len >CEPH_MSG_MAX_FRONT_LEN || + middle_len <0 || middle_len >CEPH_MSG_MAX_MIDDLE_LEN || + data_len <0 || data_len >CEPH_MSG_MAX_DATA_LEN ); +if (!front_len && !middle_len && !data_len)return 0 ;
@@ -521,29 +527,34 @@ static int decode_preamble(void *p, stru desc->fd_aligns[i] =ceph_decode_16 (&p); } -/* -* This would fire for FRAME_TAG_WAIT (it has one empty -* segment), but we should never get it as client. -*/ -if (!desc->fd_lens[desc->fd_seg_cnt -1 ]) { -pr_err ("last segment empty\n" ); +if (desc->fd_lens[0 ] <0 || + desc->fd_lens[0 ] >CEPH_MSG_MAX_CONTROL_LEN ) { +pr_err ("bad control segment length %d\n" , desc->fd_lens[0 ]);return -EINVAL ; } - -if (desc->fd_lens[0 ] >CEPH_MSG_MAX_CONTROL_LEN ) { -pr_err ("control segment too big %d\n" , desc->fd_lens[0 ]); +if (desc->fd_lens[1 ] <0 || + desc->fd_lens[1 ] >CEPH_MSG_MAX_FRONT_LEN ) { +pr_err ("bad front segment length %d\n" , desc->fd_lens[1 ]);return -EINVAL ; } -if (desc->fd_lens[1 ] >CEPH_MSG_MAX_FRONT_LEN ) { -pr_err ("front segment too big %d\n" , desc->fd_lens[1 ]); +if (desc->fd_lens[2 ] <0 || + desc->fd_lens[2 ] >CEPH_MSG_MAX_MIDDLE_LEN ) { +pr_err ("bad middle segment length %d\n" , desc->fd_lens[2 ]);return -EINVAL ; } -if (desc->fd_lens[2 ] >CEPH_MSG_MAX_MIDDLE_LEN ) { -pr_err ("middle segment too big %d\n" , desc->fd_lens[2 ]); +if (desc->fd_lens[3 ] <0 || + desc->fd_lens[3 ] >CEPH_MSG_MAX_DATA_LEN ) { +pr_err ("bad data segment length %d\n" , desc->fd_lens[3 ]);return -EINVAL ; } -if (desc->fd_lens[3 ] >CEPH_MSG_MAX_DATA_LEN ) { -pr_err ("data segment too big %d\n" , desc->fd_lens[3 ]); + +/* +* This would fire for FRAME_TAG_WAIT (it has one empty +* segment), but we should never get it as client. +*/ +if (!desc->fd_lens[desc->fd_seg_cnt -1 ]) { +pr_err ("last segment empty, segment count %d\n" , + desc->fd_seg_cnt);return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 221/292 ceph: add a dedicated private data for netfs rreq
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
commit 23ee27dce30e7d3091d6c3143b79f48dab6f9a3e upstream.
We need to save the 'f_ra.ra_pages' to expand the readahead window later.
--- fs/ceph/addr.c | 45 ++++++++++++++++++++++++++++++++++----------- fs/ceph/super.h | 13 +++++++++++++ 2 files changed, 47 insertions(+), 11 deletions(-)
fs/ceph/addr.c +34 -11
@@ -362,18 +362,28 @@ static int ceph_init_request(struct netf {struct inode *inode = rreq->inode;int got =0 , want =CEPH_CAP_FILE_CACHE ; +struct ceph_netfs_request_data *priv;int ret =0 ;if (rreq->origin !=NETFS_READAHEAD )return 0 ; + priv =kzalloc (sizeof (*priv),GFP_NOFS ); +if (!priv) +return -ENOMEM ; +if (file) {struct ceph_rw_context *rw_ctx;struct ceph_file_info *fi = file->private_data; + priv->file_ra_pages = file->f_ra.ra_pages; + priv->file_ra_disabled = file->f_mode &FMODE_RANDOM ; + rw_ctx =ceph_find_rw_context (fi); -if (rw_ctx) +if (rw_ctx) { + rreq->netfs_priv = priv;return 0 ; + } }/*
@@ -383,27 +393,40 @@ static int ceph_init_request(struct netf ret =ceph_try_get_caps (inode,CEPH_CAP_FILE_RD , want, true, &got);if (ret <0 ) {dout ("start_read %p, error getting cap\n" , inode); -return ret; + goto out; }if (!(got & want)) {dout ("start_read %p, no cache cap\n" , inode); -return -EACCES ; + ret = -EACCES ; + goto out; + } +if (ret ==0 ) { + ret = -EACCES ; + goto out; } -if (ret ==0 ) -return -EACCES ; - rreq->netfs_priv = (void *)(uintptr_t )got; -return 0 ; + priv->caps = got; + rreq->netfs_priv = priv; + +out: +if (ret <0 ) +kfree (priv); + +return ret; }static void ceph_netfs_free_request (struct netfs_io_request *rreq) { -struct ceph_inode_info *ci =ceph_inode (rreq->inode); -int got = (uintptr_t )rreq->netfs_priv; +struct ceph_netfs_request_data *priv = rreq->netfs_priv; + +if (!priv) +return ; -if (got) -ceph_put_cap_refs (ci, got); +if (priv->caps) +ceph_put_cap_refs (ceph_inode (rreq->inode), priv->caps); +kfree (priv); + rreq->netfs_priv =NULL ; }const struct netfs_request_ops ceph_netfs_ops = {
fs/ceph/super.h +13 -0
@@ -451,6 +451,19 @@ struct ceph_inode_info {unsigned long i_work_mask; }; +struct ceph_netfs_request_data { +int caps; + +/* +* Maximum size of a file readahead request. +* The fadvise could update the bdi's default ra_pages. +*/ +unsigned int file_ra_pages; + +/* Set it if fadvise disables file readahead entirely */ +bool file_ra_disabled; +}; +static inline struct ceph_inode_info *ceph_inode (const struct inode *inode) {
Greg Kroah-Hartman
maintainerPATCH 222/292 ceph: fix blindly expanding the readahead windows
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
commit dc94bb8f271c079f69583d0f12a489aaf5202751 upstream.
Blindly expanding the readahead windows will cause unneccessary pagecache thrashing and also will introduce the network workload. We should disable expanding the windows if the readahead is disabled and also shouldn't expand the windows too much.
Expanding forward firstly instead of expanding backward for possible sequential reads.
Bound rreq->len to the actual file size to restore the previous page cache usage.
The posix_fadvise may change the maximum size of a file readahead.
--- fs/ceph/addr.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-)
fs/ceph/addr.c +33 -7
@@ -187,16 +187,42 @@ static void ceph_netfs_expand_readahead(struct inode *inode = rreq->inode;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_file_layout *lo = &ci->i_layout; +unsigned long max_pages = inode->i_sb->s_bdi->ra_pages; +loff_t end = rreq->start + rreq->len, new_end; +struct ceph_netfs_request_data *priv = rreq->netfs_priv; +unsigned long max_len;u32 blockoff; -u64 blockno; -/* Expand the start downward */ - blockno =div_u64_rem (rreq->start, lo->stripe_unit, &blockoff); - rreq->start = blockno * lo->stripe_unit; - rreq->len += blockoff; +if (priv) { +/* Readahead is disabled by posix_fadvise POSIX_FADV_RANDOM */ +if (priv->file_ra_disabled) + max_pages =0 ; +else + max_pages = priv->file_ra_pages; -/* Now, round up the length to the next block */ - rreq->len =roundup (rreq->len, lo->stripe_unit); + } + +/* Readahead is disabled */ +if (!max_pages) +return ; + + max_len = max_pages <<PAGE_SHIFT ; + +/* +* Try to expand the length forward by rounding up it to the next +* block, but do not exceed the file size, unless the original +* request already exceeds it. +*/ + new_end =min (round_up (end, lo->stripe_unit), rreq->i_size); +if (new_end > end && new_end <= rreq->start + max_len) + rreq->len = new_end - rreq->start; + +/* Try to expand the start downward */ +div_u64_rem (rreq->start, lo->stripe_unit, &blockoff); +if (rreq->len + blockoff <= max_len) { + rreq->start -= blockoff; + rreq->len += blockoff; + } }static bool ceph_netfs_clamp_length (struct netfs_io_subrequest *subreq)
Greg Kroah-Hartman
maintainerPATCH 223/292 ceph: dont let check_caps skip sending responses for revoke msgs
In reply to Greg Kroah-HartmanFrom: Xiubo Li <[email protected]>
commit 257e6172ab36ebbe295a6c9ee9a9dd0fe54c1dc2 upstream.
If a client sends out a cap update dropping caps with the prior 'seq' just before an incoming cap revoke request, then the client may drop the revoke because it believes it's already released the requested capabilities.
This causes the MDS to wait indefinitely for the client to respond to the revoke. It's therefore always a good idea to ack the cap revoke request with the bumped up 'seq'.
--- fs/ceph/caps.c | 9 +++++++++ 1 file changed, 9 insertions(+)
fs/ceph/caps.c +9 -0
@@ -3560,6 +3560,15 @@ static void handle_cap_grant(struct inod }BUG_ON (cap->issued & ~cap->implemented); +/* don't let check_caps skip sending a response to MDS for revoke msgs */ +if (le32_to_cpu (grant->op) ==CEPH_CAP_OP_REVOKE ) { + cap->mds_wanted =0 ; +if (cap == ci->i_auth_cap) + check_caps =1 ;/* check auth cap only */ +else + check_caps =2 ;/* check all caps */ + } +if (extra_info->inline_version >0 && extra_info->inline_version >= ci->i_inline_version) { ci->i_inline_version = extra_info->inline_version;
Greg Kroah-Hartman
maintainerPATCH 224/292 nfp: clean mc addresses in application firmware when closing port
In reply to Greg Kroah-HartmanFrom: Yinjun Zhang <[email protected]>
commit cc7eab25b1cf3f9594fe61142d3523ce4d14a788 upstream.
When moving devices from one namespace to another, mc addresses are cleaned in software while not removed from application firmware. Thus the mc addresses are remained and will cause resource leak.
Now use __dev_mc_unsync to clean mc addresses when closing port.
Message-ID: <[email protected]>
--- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/ethernet/netronome/nfp/nfp_net_common.c +5 -0
@@ -53,6 +53,8 @@#include "crypto/crypto.h" #include "crypto/fw.h" +static int nfp_net_mc_unsync (struct net_device *netdev,const unsigned char *addr); +/** * nfp_net_get_fw_version() - Read and parse the FW version * @fw_ver: Output fw_version structure to read to
@@ -1084,6 +1086,9 @@ static int nfp_net_netdev_close(struct net_device *netdev)/* Step 2: Tell NFP */ +if (nn->cap_w1 &NFP_NET_CFG_CTRL_MCAST_FILTER ) +__dev_mc_unsync (netdev, nfp_net_mc_unsync); +nfp_net_clear_config_and_disable (nn);nfp_port_configure (netdev, false);
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 225/292 arm64: errata: Mitigate Ampere1 erratum AC03_CPU_38 at stage-2
In reply to Greg Kroah-HartmanFrom: Oliver Upton <[email protected]>
commit 6df696cd9bc1ceed0e92e36908f88bbd16d18255 upstream.
AmpereOne has an erratum in its implementation of FEAT_HAFDBS that required disabling the feature on the design. This was done by reporting the feature as not implemented in the ID register, although the corresponding control bits were not actually RES0. This does not align well with the requirements of the architecture, which mandates these bits be RES0 if HAFDBS isn't implemented.
The kernel's use of stage-1 is unaffected, as the HA and HD bits are only set if HAFDBS is detected in the ID register. KVM, on the other hand, relies on the RES0 behavior at stage-2 to use the same value for VTCR_EL2 on any cpu in the system. Mitigate the non-RES0 behavior by leaving VTCR_EL2.HA clear on affected systems.
--- Documentation/arm64/silicon-errata.rst | 3 +++ arch/arm64/Kconfig | 19 +++++++++++++++++++ arch/arm64/kernel/cpu_errata.c | 7 +++++++ arch/arm64/kvm/hyp/pgtable.c | 14 +++++++++++--- arch/arm64/tools/cpucaps | 1 + 5 files changed, 41 insertions(+), 3 deletions(-)
Documentation/arm64/silicon-errata.rst +3 -0
@@ -52,6 +52,9 @@ stable kernels. | Allwinner | A64/R18 | UNKNOWN1 | SUN50I_ERRATUM_UNKNOWN1 | +----------------+-----------------+-----------------+-----------------------------+ +----------------+-----------------+-----------------+-----------------------------+ +| Ampere | AmpereOne | AC03_CPU_38 | AMPERE_ERRATUM_AC03_CPU_38 | ++----------------+-----------------+-----------------+-----------------------------+ ++----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A510 | #2457168 | ARM64_ERRATUM_2457168 | +----------------+-----------------+-----------------+-----------------------------+ | ARM | Cortex-A510 | #2064142 | ARM64_ERRATUM_2064142 |
arch/arm64/Kconfig +19 -0
@@ -407,6 +407,25 @@ menu "Kernel Features" menu "ARM errata workarounds via the alternatives framework" +config AMPERE_ERRATUM_AC03_CPU_38 + bool "AmpereOne: AC03_CPU_38: Certain bits in the Virtualization Translation Control Register and Translation Control Registers do not follow RES0 semantics" + default y + help + This option adds an alternative code sequence to work around Ampere + erratum AC03_CPU_38 on AmpereOne. + + The affected design reports FEAT_HAFDBS as not implemented in + ID_AA64MMFR1_EL1.HAFDBS, but (V)TCR_ELx.{HA,HD} are not RES0 + as required by the architecture. The unadvertised HAFDBS + implementation suffers from an additional erratum where hardware + A/D updates can occur after a PTE has been marked invalid. + + The workaround forces KVM to explicitly set VTCR_EL2.HA to 0, + which avoids enabling unadvertised hardware Access Flag management + at stage-2. + + If unsure, say Y. + config ARM64_WORKAROUND_CLEAN_CACHE bool
arch/arm64/kernel/cpu_errata.c +7 -0
@@ -730,6 +730,13 @@ const struct arm64_cpu_capabilities arm6 .cpu_enable = cpu_clear_bf16_from_user_emulation, },#endif +#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 + { + .desc = "AmpereOne erratum AC03_CPU_38", + .capability = ARM64_WORKAROUND_AMPERE_AC03_CPU_38, + ERRATA_MIDR_ALL_VERSIONS(MIDR_AMPERE1), + }, +#endif { } };
arch/arm64/kvm/hyp/pgtable.c +11 -3
@@ -623,10 +623,18 @@ u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u#ifdef CONFIG_ARM64_HW_AFDBM /* * Enable the Hardware Access Flag management, unconditionally -* on all CPUs. The features is RES0 on CPUs without the support -* and must be ignored by the CPUs. +* on all CPUs. In systems that have asymmetric support for the feature +* this allows KVM to leverage hardware support on the subset of cores +* that implement the feature. +* +* The architecture requires VTCR_EL2.HA to be RES0 (thus ignored by +* hardware) on implementations that do not advertise support for the +* feature. As such, setting HA unconditionally is safe, unless you +* happen to be running on a design that has unadvertised support for +* HAFDBS. Here be dragons. */ - vtcr |=VTCR_EL2_HA ; +if (!cpus_have_final_cap (ARM64_WORKAROUND_AMPERE_AC03_CPU_38 )) + vtcr |=VTCR_EL2_HA ;#endif /* CONFIG_ARM64_HW_AFDBM */ /* Set the vmid bits */
arch/arm64/tools/cpucaps +1 -0
@@ -77,6 +77,7 @@ WORKAROUND_2077057 WORKAROUND_2457168 WORKAROUND_2645198 WORKAROUND_2658417 +WORKAROUND_AMPERE_AC03_CPU_38 WORKAROUND_TRBE_OVERWRITE_FILL_MODE WORKAROUND_TSB_FLUSH_FAILURE WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
Greg Kroah-Hartman
maintainerPATCH 226/292 xhci: Fix resume issue of some ZHAOXIN hosts
In reply to Greg Kroah-HartmanFrom: Weitao Wang <[email protected]>
commit f927728186f0de1167262d6a632f9f7e96433d1a upstream.
On ZHAOXIN ZX-100 project, xHCI can't work normally after resume from system Sx state. To fix this issue, when resume from system Sx state, reinitialize xHCI instead of restore.
So, Add XHCI_RESET_ON_RESUME quirk for ZX-100 to fix issue of resuming from system Sx state.
Message-ID: <[email protected]>
--- drivers/usb/host/xhci-pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/host/xhci-pci.c +5 -0
@@ -528,6 +528,11 @@ static void xhci_pci_quirks(struct devic pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4)) xhci->quirks |= XHCI_NO_SOFT_RETRY; +if (pdev->vendor ==PCI_VENDOR_ID_ZHAOXIN ) { +if (pdev->device ==0x9202 ) + xhci->quirks |=XHCI_RESET_ON_RESUME ; + } +/* xHC spec requires PCI devices to support D3hot and D3cold */ if (xhci->hci_version >=0x120 ) xhci->quirks |=XHCI_DEFAULT_PM_RUNTIME_ALLOW ;
Greg Kroah-Hartman
maintainerPATCH 227/292 xhci: Fix TRB prefetch issue of ZHAOXIN hosts
In reply to Greg Kroah-HartmanFrom: Weitao Wang <[email protected]>
commit 2a865a652299f5666f3b785cbe758c5f57453036 upstream.
On some ZHAOXIN hosts, xHCI will prefetch TRB for performance improvement. However this TRB prefetch mechanism may cross page boundary, which may access memory not allocated by xHCI driver. In order to fix this issue, two pages was allocated for a segment and only the first page will be used. And add a quirk XHCI_ZHAOXIN_TRB_FETCH for this issue.
Message-ID: <[email protected]>
--- drivers/usb/host/xhci-mem.c | 8 ++++++-- drivers/usb/host/xhci-pci.c | 7 ++++++- drivers/usb/host/xhci.h | 1 + 3 files changed, 13 insertions(+), 3 deletions(-)
drivers/usb/host/xhci-mem.c +6 -2
@@ -2352,8 +2352,12 @@ int xhci_mem_init(struct xhci_hcd *xhci,* and our use of dma addresses in the trb_address_map radix tree needs * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need. */ - xhci->segment_pool =dma_pool_create ("xHCI ring segments" , dev, -TRB_SEGMENT_SIZE ,TRB_SEGMENT_SIZE , xhci->page_size); +if (xhci->quirks &XHCI_ZHAOXIN_TRB_FETCH ) + xhci->segment_pool =dma_pool_create ("xHCI ring segments" , dev, +TRB_SEGMENT_SIZE *2 ,TRB_SEGMENT_SIZE *2 , xhci->page_size *2 ); +else + xhci->segment_pool =dma_pool_create ("xHCI ring segments" , dev, +TRB_SEGMENT_SIZE ,TRB_SEGMENT_SIZE , xhci->page_size);/* See Table 46 and Note on Figure 55 */ xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
drivers/usb/host/xhci-pci.c +6 -1
@@ -529,8 +529,13 @@ static void xhci_pci_quirks(struct devic xhci->quirks |=XHCI_NO_SOFT_RETRY ;if (pdev->vendor ==PCI_VENDOR_ID_ZHAOXIN ) { -if (pdev->device ==0x9202 ) +if (pdev->device ==0x9202 ) { xhci->quirks |=XHCI_RESET_ON_RESUME ; + xhci->quirks |=XHCI_ZHAOXIN_TRB_FETCH ; + } + +if (pdev->device ==0x9203 ) + xhci->quirks |=XHCI_ZHAOXIN_TRB_FETCH ; }/* xHC spec requires PCI devices to support D3hot and D3cold */
drivers/usb/host/xhci.h +1 -0
@@ -1905,6 +1905,7 @@ struct xhci_hcd {#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42)#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43)#define XHCI_RESET_TO_DEFAULT BIT_ULL(44) +#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45)unsigned int num_active_eps;unsigned int limit_active_eps;
Greg Kroah-Hartman
maintainerPATCH 228/292 xhci: Show ZHAOXIN xHCI root hub speed correctly
In reply to Greg Kroah-HartmanFrom: Weitao Wang <[email protected]>
commit d9b0328d0b8b8298dfdc97cd8e0e2371d4bcc97b upstream.
Some ZHAOXIN xHCI controllers follow usb3.1 spec, but only support gen1 speed 5Gbps. While in Linux kernel, if xHCI suspport usb3.1, root hub speed will show on 10Gbps.
To fix this issue of ZHAOXIN xHCI platforms, read usb speed ID supported by xHCI to determine root hub speed. And add a quirk XHCI_ZHAOXIN_HOST for this issue.
[fix warning about uninitialized symbol -Mathias]
Message-ID: <[email protected]>
--- drivers/usb/host/xhci-mem.c | 31 ++++++++++++++++++++++++------- drivers/usb/host/xhci-pci.c | 2 ++ drivers/usb/host/xhci.h | 1 + 3 files changed, 27 insertions(+), 7 deletions(-)
drivers/usb/host/xhci-mem.c +24 -7
@@ -1968,7 +1968,7 @@ static void xhci_add_in_port(struct xhci {u32 temp, port_offset, port_count;int i; -u8 major_revision, minor_revision; +u8 major_revision, minor_revision, tmp_minor_revision;struct xhci_hub *rhub;struct device *dev =xhci_to_hcd (xhci)->self.sysdev;struct xhci_port_cap *port_cap;
@@ -1988,6 +1988,15 @@ static void xhci_add_in_port(struct xhci*/ if (minor_revision >0x00 && minor_revision <0x10 ) minor_revision <<=4 ; +/* +* Some zhaoxin's xHCI controller that follow usb3.1 spec +* but only support Gen1. +*/ +if (xhci->quirks &XHCI_ZHAOXIN_HOST ) { + tmp_minor_revision = minor_revision; + minor_revision =0 ; + } + }else if (major_revision <=0x02 ) { rhub = &xhci->usb2_rhub; }else {
@@ -1996,10 +2005,6 @@ static void xhci_add_in_port(struct xhci/* Ignoring port protocol we can't understand. FIXME */ return ; } - rhub->maj_rev =XHCI_EXT_PORT_MAJOR (temp); - -if (rhub->min_rev < minor_revision) - rhub->min_rev = minor_revision;/* Port offset and count in the third dword, see section 7.2 */ temp =readl (addr +2 );
@@ -2017,8 +2022,6 @@ static void xhci_add_in_port(struct xhciif (xhci->num_port_caps > max_caps)return ; - port_cap->maj_rev = major_revision; - port_cap->min_rev = minor_revision; port_cap->psi_count =XHCI_EXT_PORT_PSIC (temp);if (port_cap->psi_count) {
@@ -2039,6 +2042,11 @@ static void xhci_add_in_port(struct xhci XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1]))) port_cap->psi_uid_count++; +if (xhci->quirks &XHCI_ZHAOXIN_HOST && + major_revision ==0x03 && +XHCI_EXT_PORT_PSIV (port_cap->psi[i]) >=5 ) + minor_revision = tmp_minor_revision; + xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n", XHCI_EXT_PORT_PSIV(port_cap->psi[i]), XHCI_EXT_PORT_PSIE(port_cap->psi[i]),
@@ -2048,6 +2056,15 @@ static void xhci_add_in_port(struct xhci XHCI_EXT_PORT_PSIM(port_cap->psi[i])); } } + + rhub->maj_rev = major_revision; + +if (rhub->min_rev < minor_revision) + rhub->min_rev = minor_revision; + + port_cap->maj_rev = major_revision; + port_cap->min_rev = minor_revision; +/* cache usb2 port capabilities */ if (major_revision <0x03 && xhci->num_ext_caps < max_caps) xhci->ext_caps[xhci->num_ext_caps++] = temp;
drivers/usb/host/xhci-pci.c +2 -0
@@ -529,6 +529,8 @@ static void xhci_pci_quirks(struct devic xhci->quirks |=XHCI_NO_SOFT_RETRY ;if (pdev->vendor ==PCI_VENDOR_ID_ZHAOXIN ) { + xhci->quirks |=XHCI_ZHAOXIN_HOST ; +if (pdev->device ==0x9202 ) { xhci->quirks |=XHCI_RESET_ON_RESUME ; xhci->quirks |=XHCI_ZHAOXIN_TRB_FETCH ;
drivers/usb/host/xhci.h +1 -0
@@ -1906,6 +1906,7 @@ struct xhci_hcd {#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43)#define XHCI_RESET_TO_DEFAULT BIT_ULL(44)#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45) +#define XHCI_ZHAOXIN_HOST BIT_ULL(46)unsigned int num_active_eps;unsigned int limit_active_eps;
Greg Kroah-Hartman
maintainerPATCH 229/292 meson saradc: fix clock divider mask length
In reply to Greg Kroah-HartmanFrom: George Stark <[email protected]>
commit c57fa0037024c92c2ca34243e79e857da5d2c0a9 upstream.
According to the datasheets of supported meson SoCs length of ADC_CLK_DIV field is 6-bit. Although all supported SoCs have the register with that field documented later SoCs use external clock rather than ADC internal clock so this patch affects only meson8 family (S8* SoCs).
--- drivers/iio/adc/meson_saradc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/adc/meson_saradc.c +1 -1
@@ -72,7 +72,7 @@#define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18)#define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16)#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 -#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 +#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6#define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8)#define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0)
Greg Kroah-Hartman
maintainerPATCH 230/292 opp: Fix use-after-free in lazy_opp_tables after probe deferral
In reply to Greg Kroah-HartmanFrom: Stephan Gerhold <[email protected]>
commit b2a2ab039bd58f51355e33d7d3fc64605d7f870d upstream.
When dev_pm_opp_of_find_icc_paths() in _allocate_opp_table() returns -EPROBE_DEFER, the opp_table is freed again, to wait until all the interconnect paths are available.
However, if the OPP table is using required-opps then it may already have been added to the global lazy_opp_tables list. The error path does not remove the opp_table from the list again.
This can cause crashes later when the provider of the required-opps is added, since we will iterate over OPP tables that have already been freed. E.g.:
Unable to handle kernel NULL pointer dereference when read CPU: 0 PID: 7 Comm: kworker/0:0 Not tainted 6.4.0-rc3 PC is at _of_add_opp_table_v2 (include/linux/of.h:949 drivers/opp/of.c:98 drivers/opp/of.c:344 drivers/opp/of.c:404 drivers/opp/of.c:1032) -> lazy_link_required_opp_table()
Fix this by calling _of_clear_opp_table() to remove the opp_table from the list and clear other allocated resources. While at it, also add the missing mutex_destroy() calls in the error path.
--- drivers/opp/core.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/opp/core.c +3 -0
@@ -1358,7 +1358,10 @@ static struct opp_table *_allocate_opp_treturn opp_table; remove_opp_dev: +_of_clear_opp_table (opp_table);_remove_opp_dev (opp_dev, opp_table); +mutex_destroy (&opp_table->genpd_virt_dev_lock); +mutex_destroy (&opp_table->lock); err:kfree (opp_table);return ERR_PTR (ret);
Greg Kroah-Hartman
maintainerPATCH 231/292 soundwire: qcom: fix storing port config out-of-bounds
In reply to Greg Kroah-HartmanFrom: Krzysztof Kozlowski <[email protected]>
commit 490937d479abe5f6584e69b96df066bc87be92e9 upstream.
The 'qcom_swrm_ctrl->pconfig' has size of QCOM_SDW_MAX_PORTS (14), however we index it starting from 1, not 0, to match real port numbers. This can lead to writing port config past 'pconfig' bounds and overwriting next member of 'qcom_swrm_ctrl' struct. Reported also by smatch:
drivers/soundwire/qcom.c:1269 qcom_swrm_get_port_config() error: buffer overflow 'ctrl->pconfig' 14 <= 14
--- drivers/soundwire/qcom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/soundwire/qcom.c +2 -1
@@ -171,7 +171,8 @@ struct qcom_swrm_ctrl {u32 intr_mask;u8 rcmd_id;u8 wcmd_id; -struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS ]; +/* Port numbers are 1 - 14 */ +struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS +1 ];struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS ];enum sdw_slave_status status[SDW_MAX_DEVICES +1 ];int (*reg_read)(struct qcom_swrm_ctrl *ctrl,int reg,u32 *val);
Greg Kroah-Hartman
maintainerPATCH 232/292 media: uapi: Fix [GS]_ROUTING ACTIVE flag value
In reply to Greg Kroah-HartmanFrom: Sakari Ailus <[email protected]>
commit 950e9a295b984b011bcbfb90af167e4e20a077f3 upstream.
The value of the V4L2_SUBDEV_ROUTE_FL_ACTIVE is 1, not 0. Use hexadecimal numbers as is done elsewhere in the documentation.
--- .../userspace-api/media/v4l/vidioc-subdev-g-routing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst +1 -1
@@ -122,7 +122,7 @@ for all the route entries and call ``VIDIOC_SUBDEV_G_ROUTING`` again. :widths: 3 1 4 * - V4L2_SUBDEV_ROUTE_FL_ACTIVE - - 0 + - 0x0001 - The route is enabled. Set by applications. Return Value
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 233/292 Revert "8250: add support for ASIX devices with a FIFO bug"
In reply to Greg Kroah-HartmanFrom: Jiaqing Zhao <[email protected]>
commit a82d62f708545d22859584e0e0620da8e3759bbc upstream.
This reverts commit eb26dfe8aa7eeb5a5aa0b7574550125f8aa4c3b3.
Commit eb26dfe8aa7e ("8250: add support for ASIX devices with a FIFO bug") merged on Jul 13, 2012 adds a quirk for PCI_VENDOR_ID_ASIX (0x9710). But that ID is the same as PCI_VENDOR_ID_NETMOS defined in 1f8b061050c7 ("[PATCH] Netmos parallel/serial/combo support") merged on Mar 28, 2005. In pci_serial_quirks array, the NetMos entry always takes precedence over the ASIX entry even since it was initially merged, code in that commit is always unreachable.
In my tests, adding the FIFO workaround to pci_netmos_init() makes no difference, and the vendor driver also does not have such workaround. Given that the code was never used for over a decade, it's safe to revert it.
Also, the real PCI_VENDOR_ID_ASIX should be 0x125b, which is used on their newer AX99100 PCIe serial controllers released on 2016. The FIFO workaround should not be intended for these newer controllers, and it was never implemented in vendor driver.
--- drivers/tty/serial/8250/8250.h | 1 - drivers/tty/serial/8250/8250_pci.c | 19 ------------------- drivers/tty/serial/8250/8250_port.c | 11 +++-------- include/linux/serial_8250.h | 1 - 4 files changed, 3 insertions(+), 29 deletions(-)
drivers/tty/serial/8250/8250.h +0 -1
@@ -91,7 +91,6 @@ struct serial8250_config {#define UART_BUG_TXEN BIT(1)/* UART has buggy TX IIR status */ #define UART_BUG_NOMSR BIT(2)/* UART has buggy MSR status bits (Au1x00) */ #define UART_BUG_THRE BIT(3)/* UART has buggy THRE reassertion */ -#define UART_BUG_PARITY BIT(4)/* UART mishandles parity if FIFO enabled */ #define UART_BUG_TXRACE BIT(5)/* UART Tx fails to set remote DR */
drivers/tty/serial/8250/8250_pci.c +0 -19
@@ -1232,14 +1232,6 @@ static int pci_oxsemi_tornado_setup(strureturn pci_default_setup (priv, board, up, idx); } -static int pci_asix_setup (struct serial_private *priv, -const struct pciserial_board *board, -struct uart_8250_port *port,int idx) -{ - port->bugs |=UART_BUG_PARITY ; -return pci_default_setup (priv, board, port, idx); -} -#define QPCR_TEST_FOR1 0x3F#define QPCR_TEST_GET1 0x00#define QPCR_TEST_FOR2 0x40
@@ -1955,7 +1947,6 @@ pci_moxa_setup(struct serial_private *pr#define PCI_DEVICE_ID_WCH_CH355_4S 0x7173#define PCI_VENDOR_ID_AGESTAR 0x5372#define PCI_DEVICE_ID_AGESTAR_9375 0x6872 -#define PCI_VENDOR_ID_ASIX 0x9710#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
@@ -2601,16 +2592,6 @@ static struct pci_serial_quirk pci_seria .setup = pci_wch_ch38x_setup, },/* -* ASIX devices with FIFO bug -*/ - { - .vendor = PCI_VENDOR_ID_ASIX, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_asix_setup, - }, -/* * Broadcom TruManage (NetXtreme) */ {
drivers/tty/serial/8250/8250_port.c +3 -8
@@ -2636,11 +2636,8 @@ static unsigned char serial8250_compute_if (c_cflag &CSTOPB ) cval |=UART_LCR_STOP ; -if (c_cflag &PARENB ) { +if (c_cflag &PARENB ) cval |=UART_LCR_PARITY ; -if (up->bugs &UART_BUG_PARITY ) - up->fifo_bug = true; - }if (!(c_cflag &PARODD )) cval |=UART_LCR_EPAR ;if (c_cflag &CMSPAR )
@@ -2801,8 +2798,7 @@ serial8250_do_set_termios(struct uart_po up->lcr = cval;/* Save computed LCR */ if (up->capabilities &UART_CAP_FIFO && port->fifosize >1 ) { -/* NOTE: If fifo_bug is not set, a user can set RX_trigger. */ -if ((baud <2400 && !up->dma) || up->fifo_bug) { +if (baud <2400 && !up->dma) { up->fcr &= ~UART_FCR_TRIGGER_MASK ; up->fcr |=UART_FCR_TRIGGER_1 ; }
@@ -3138,8 +3134,7 @@ static int do_set_rxtrig(struct tty_portstruct uart_8250_port *up =up_to_u8250p (uport);int rxtrig; -if (!(up->capabilities &UART_CAP_FIFO ) || uport->fifosize <=1 || - up->fifo_bug) +if (!(up->capabilities &UART_CAP_FIFO ) || uport->fifosize <=1 )return -EINVAL ; rxtrig =bytes_to_fcr_rxtrig (up, bytes);
include/linux/serial_8250.h +0 -1
@@ -98,7 +98,6 @@ struct uart_8250_port {struct list_head list;/* ports on this IRQ */ u32 capabilities;/* port capabilities */ unsigned short bugs;/* port bugs */ -bool fifo_bug;/* min RX trigger if enabled */ unsigned int tx_loadsz;/* transmit fifo load size */ unsigned char acr;unsigned char fcr;
Greg Kroah-Hartman
maintainerPATCH 234/292 bus: ixp4xx: fix IXP4XX_EXP_T1_MASK
In reply to Greg Kroah-HartmanFrom: Jonas Gorski <[email protected]>
commit 6722e46513e0af8e2fff4698f7cb78bc50a9f13f upstream.
The IXP4XX_EXP_T1_MASK was shifted one bit to the right, overlapping IXP4XX_EXP_T2_MASK and leaving bit 29 unused. The offset being wrong is also confirmed at least by the datasheet of IXP45X/46X [1].
Fix this by aligning it to IXP4XX_EXP_T1_SHIFT.
--- drivers/bus/intel-ixp4xx-eb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/bus/intel-ixp4xx-eb.c +1 -1
@@ -33,7 +33,7 @@#define IXP4XX_EXP_TIMING_STRIDE 0x04#define IXP4XX_EXP_CS_EN BIT(31)#define IXP456_EXP_PAR_EN BIT(30)/* Only on IXP45x and IXP46x */ -#define IXP4XX_EXP_T1_MASK GENMASK(28, 27) +#define IXP4XX_EXP_T1_MASK GENMASK(29, 28)#define IXP4XX_EXP_T1_SHIFT 28#define IXP4XX_EXP_T2_MASK GENMASK(27, 26)#define IXP4XX_EXP_T2_SHIFT 26
Greg Kroah-Hartman
maintainerPATCH 235/292 s390/decompressor: fix misaligned symbol build error
In reply to Greg Kroah-HartmanFrom: Heiko Carstens <[email protected]>
commit 938f0c35d7d93a822ab9c9728e3205e8e57409d0 upstream.
Nathan Chancellor reported a kernel build error on Fedora 39:
$ clang --version | head -1 clang version 16.0.5 (Fedora 16.0.5-1.fc39)
$ s390x-linux-gnu-ld --version | head -1 GNU ld version 2.40-1.fc39
$ make -skj"$(nproc)" ARCH=s390 CC=clang CROSS_COMPILE=s390x-linux-gnu- olddefconfig all s390x-linux-gnu-ld: arch/s390/boot/startup.o(.text+0x5b4): misaligned symbol `_decompressor_end' (0x35b0f) for relocation R_390_PC32DBL make[3]: *** [.../arch/s390/boot/Makefile:78: arch/s390/boot/vmlinux] Error 1
It turned out that the problem with misaligned symbols on s390 was fixed with commit 80ddf5ce1c92 ("s390: always build relocatable kernel") for the kernel image, but did not take into account that the decompressor uses its own set of CFLAGS, which come without -fPIE.
Add the -fPIE flag also to the decompresser CFLAGS to fix this.
--- arch/s390/Makefile | 1 + 1 file changed, 1 insertion(+)
arch/s390/Makefile +1 -0
@@ -27,6 +27,7 @@ KBUILD_CFLAGS_DECOMPRESSOR += -fno-delet KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding KBUILD_CFLAGS_DECOMPRESSOR += -fno-stack-protector +KBUILD_CFLAGS_DECOMPRESSOR += -fPIE KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,))
Greg Kroah-Hartman
maintainerPATCH 236/292 dm: verity-loadpin: Add NULL pointer check for bdev parameter
In reply to Greg Kroah-HartmanFrom: Matthias Kaehlcke <[email protected]>
commit 47f04616f2c9b2f4f0c9127e30ca515a078db591 upstream.
Add a NULL check for the 'bdev' parameter of dm_verity_loadpin_is_bdev_trusted(). The function is called by loadpin_check(), which passes the block device that corresponds to the super block of the file system from which a file is being loaded. Generally a super_block structure has an associated block device, however that is not always the case (e.g. tmpfs).
--- drivers/md/dm-verity-loadpin.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/md/dm-verity-loadpin.c +3 -0
@@ -58,6 +58,9 @@ bool dm_verity_loadpin_is_bdev_trusted(sint srcu_idx;bool trusted = false; +if (bdev ==NULL ) +return false; +if (list_empty (&dm_verity_loadpin_trusted_root_digests))return false;
Greg Kroah-Hartman
maintainerPATCH 237/292 tracing/histograms: Add histograms to hist_vars if they have referenced variables
In reply to Greg Kroah-HartmanFrom: Mohamed Khalfella <[email protected]>
commit 6018b585e8c6fa7d85d4b38d9ce49a5b67be7078 upstream.
Hist triggers can have referenced variables without having direct variables fields. This can be the case if referenced variables are added for trigger actions. In this case the newly added references will not have field variables. Not taking such referenced variables into consideration can result in a bug where it would be possible to remove hist trigger with variables being refenced. This will result in a bug that is easily reproducable like so
$ cd /sys/kernel/tracing $ echo 'synthetic_sys_enter char[] comm; long id' >> synthetic_events $ echo 'hist:keys=common_pid.execname,id.syscall:vals=hitcount:comm=common_pid.execname' >> events/raw_syscalls/sys_enter/trigger $ echo 'hist:keys=common_pid.execname,id.syscall:onmatch(raw_syscalls.sys_enter).synthetic_sys_enter($comm, id)' >> events/raw_syscalls/sys_enter/trigger $ echo '!hist:keys=common_pid.execname,id.syscall:vals=hitcount:comm=common_pid.execname' >> events/raw_syscalls/sys_enter/trigger
[ 100.263533] ================================================================== [ 100.264634] BUG: KASAN: slab-use-after-free in resolve_var_refs+0xc7/0x180 [ 100.265520] Read of size 8 at addr ffff88810375d0f0 by task bash/439 [ 100.266320] [ 100.266533] CPU: 2 PID: 439 Comm: bash Not tainted 6.5.0-rc1 #4 [ 100.267277] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-20220807_005459-localhost 04/01/2014 [ 100.268561] Call Trace: [ 100.268902] <TASK> [ 100.269189] dump_stack_lvl+0x4c/0x70 [ 100.269680] print_report+0xc5/0x600 [ 100.270165] ? resolve_var_refs+0xc7/0x180 [ 100.270697] ? kasan_complete_mode_report_info+0x80/0x1f0 [ 100.271389] ? resolve_var_refs+0xc7/0x180 [ 100.271913] kasan_report+0xbd/0x100 [ 100.272380] ? resolve_var_refs+0xc7/0x180 [ 100.272920] __asan_load8+0x71/0xa0 [ 100.273377] resolve_var_refs+0xc7/0x180 [ 100.273888] event_hist_trigger+0x749/0x860 [ 100.274505] ? kasan_save_stack+0x2a/0x50 [ 100.275024] ? kasan_set_track+0x29/0x40 [ 100.275536] ? __pfx_event_hist_trigger+0x10/0x10 [ 100.276138] ? ksys_write+0xd1/0x170 [ 100.276607] ? do_syscall_64+0x3c/0x90 [ 100.277099] ? entry_SYSCALL_64_after_hwframe+0x6e/0xd8 [ 100.277771] ? destroy_hist_data+0x446/0x470 [ 100.278324] ? event_hist_trigger_parse+0xa6c/0x3860 [ 100.278962] ? __pfx_event_hist_trigger_parse+0x10/0x10 [ 100.279627] ? __kasan_check_write+0x18/0x20 [ 100.280177] ? mutex_unlock+0x85/0xd0 [ 100.280660] ? __pfx_mutex_unlock+0x10/0x10 [ 100.281200] ? kfree+0x7b/0x120 [ 100.281619] ? ____kasan_slab_free+0x15d/0x1d0 [ 100.282197] ? event_trigger_write+0xac/0x100 [ 100.282764] ? __kasan_slab_free+0x16/0x20 [ 100.283293] ? __kmem_cache_free+0x153/0x2f0 [ 100.283844] ? sched_mm_cid_remote_clear+0xb1/0x250 [ 100.284550] ? __pfx_sched_mm_cid_remote_clear+0x10/0x10 [ 100.285221] ? event_trigger_write+0xbc/0x100 [ 100.285781] ? __kasan_check_read+0x15/0x20 [ 100.286321] ? __bitmap_weight+0x66/0xa0 [ 100.286833] ? _find_next_bit+0x46/0xe0 [ 100.287334] ? task_mm_cid_work+0x37f/0x450 [ 100.287872] event_triggers_call+0x84/0x150 [ 100.288408] trace_event_buffer_commit+0x339/0x430 [ 100.289073] ? ring_buffer_event_data+0x3f/0x60 [ 100.292189] trace_event_raw_event_sys_enter+0x8b/0xe0 [ 100.295434] syscall_trace_enter.constprop.0+0x18f/0x1b0 [ 100.298653] syscall_enter_from_user_mode+0x32/0x40 [ 100.301808] do_syscall_64+0x1a/0x90 [ 100.304748] entry_SYSCALL_64_after_hwframe+0x6e/0xd8 [ 100.307775] RIP: 0033:0x7f686c75c1cb [ 100.310617] Code: 73 01 c3 48 8b 0d 65 3c 10 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 21 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 35 3c 10 00 f7 d8 64 89 01 48 [ 100.317847] RSP: 002b:00007ffc60137a38 EFLAGS: 00000246 ORIG_RAX: 0000000000000021 [ 100.321200] RAX: ffffffffffffffda RBX: 000055f566469ea0 RCX: 00007f686c75c1cb [ 100.324631] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 000000000000000a [ 100.328104] RBP: 00007ffc60137ac0 R08: 00007f686c818460 R09: 000000000000000a [ 100.331509] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000009 [ 100.334992] R13: 0000000000000007 R14: 000000000000000a R15: 0000000000000007 [ 100.338381] </TASK>
We hit the bug because when second hist trigger has was created has_hist_vars() returned false because hist trigger did not have variables. As a result of that save_hist_vars() was not called to add the trigger to trace_array->hist_vars. Later on when we attempted to remove the first histogram find_any_var_ref() failed to detect it is being used because it did not find the second trigger in hist_vars list.
With this change we wait until trigger actions are created so we can take into consideration if hist trigger has variable references. Also, now we check the return value of save_hist_vars() and fail trigger creation if save_hist_vars() fails.
--- kernel/trace/trace_events_hist.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
kernel/trace/trace_events_hist.c +5 -3
@@ -6663,13 +6663,15 @@ static int event_hist_trigger_parse(struif (get_named_trigger_data (trigger_data)) goto enable; -if (has_hist_vars (hist_data)) -save_hist_vars (hist_data); - ret =create_actions (hist_data);if (ret) goto out_unreg; +if (has_hist_vars (hist_data) || hist_data->n_var_refs) { +if (save_hist_vars (hist_data)) + goto out_unreg; + } + ret =tracing_map_init (hist_data->map);if (ret) goto out_unreg;
Greg Kroah-Hartman
maintainerPATCH 238/292 tracing: Fix memory leak of iter->temp when reading trace_pipe
In reply to Greg Kroah-HartmanFrom: Zheng Yejian <[email protected]>
commit d5a821896360cc8b93a15bd888fabc858c038dc0 upstream.
kmemleak reports:
unreferenced object 0xffff88814d14e200 (size 256):
comm "cat", pid 336, jiffies 4294871818 (age 779.490s)
hex dump (first 32 bytes):
04 00 01 03 00 00 00 00 08 00 00 00 00 00 00 00 ................
0c d8 c8 9b ff ff ff ff 04 5a ca 9b ff ff ff ff .........Z......
backtrace:
[<ffffffff9bdff18f>] __kmalloc+0x4f/0x140
[<ffffffff9bc9238b>] trace_find_next_entry+0xbb/0x1d0
[<ffffffff9bc9caef>] trace_print_lat_context+0xaf/0x4e0
[<ffffffff9bc94490>] print_trace_line+0x3e0/0x950
[<ffffffff9bc95499>] tracing_read_pipe+0x2d9/0x5a0
[<ffffffff9bf03a43>] vfs_read+0x143/0x520
[<ffffffff9bf04c2d>] ksys_read+0xbd/0x160
[<ffffffff9d0f0edf>] do_syscall_64+0x3f/0x90
[<ffffffff9d2000aa>] entry_SYSCALL_64_after_hwframe+0x6e/0xd8when reading file 'trace_pipe', 'iter->temp' is allocated or relocated in trace_find_next_entry() but not freed before 'trace_pipe' is closed.
To fix it, free 'iter->temp' in tracing_release_pipe().
--- kernel/trace/trace.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/trace.c +1 -0
@@ -6753,6 +6753,7 @@ static int tracing_release_pipe(struct ifree_cpumask_var (iter->started);kfree (iter->fmt); +kfree (iter->temp);mutex_destroy (&iter->mutex);kfree (iter);
Greg Kroah-Hartman
maintainerPATCH 239/292 nvme: dont reject probe due to duplicate IDs for single-ported PCIe devices
In reply to Greg Kroah-HartmanFrom: Christoph Hellwig <[email protected]>
commit ac522fc6c3165fd0daa2f8da7e07d5f800586daa upstream.
While duplicate IDs are still very harmful, including the potential to easily see changing devices in /dev/disk/by-id, it turn out they are extremely common for cheap end user NVMe devices.
Relax our check for them for so that it doesn't reject the probe on single-ported PCIe devices, but prints a big warning instead. In doubt we'd still like to see quirk entries to disable the potential for changing supposed stable device identifier links, but this will at least allow users how have two (or more) of these devices to use them without having to manually add a new PCI ID entry with the quirk through sysfs or by patching the kernel.
--- drivers/nvme/host/core.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-)
drivers/nvme/host/core.c +33 -3
@@ -4226,10 +4226,40 @@ static int nvme_init_ns_head(struct nvme ret =nvme_global_check_duplicate_ids (ctrl->subsys, &info->ids);if (ret) { -dev_err (ctrl->device, -"globally duplicate IDs for nsid %d\n" , info->nsid); +/* +* We've found two different namespaces on two different +* subsystems that report the same ID. This is pretty nasty +* for anything that actually requires unique device +* identification. In the kernel we need this for multipathing, +* and in user space the /dev/disk/by-id/ links rely on it. +* +* If the device also claims to be multi-path capable back off +* here now and refuse the probe the second device as this is a +* recipe for data corruption. If not this is probably a +* cheap consumer device if on the PCIe bus, so let the user +* proceed and use the shiny toy, but warn that with changing +* probing order (which due to our async probing could just be +* device taking longer to startup) the other device could show +* up at any time. +*/ nvme_print_device_info (ctrl); -return ret; +if ((ns->ctrl->ops->flags &NVME_F_FABRICS ) ||/* !PCIe */ + ((ns->ctrl->subsys->cmic &NVME_CTRL_CMIC_MULTI_CTRL ) && + info->is_shared)) { +dev_err (ctrl->device, +"ignoring nsid %d because of duplicate IDs\n" , + info->nsid); +return ret; + } + +dev_err (ctrl->device, +"clearing duplicate IDs for nsid %d\n" , info->nsid); +dev_err (ctrl->device, +"use of /dev/disk/by-id/ may cause data corruption\n" ); +memset (&info->ids.nguid,0 ,sizeof (info->ids.nguid)); +memset (&info->ids.uuid,0 ,sizeof (info->ids.uuid)); +memset (&info->ids.eui64,0 ,sizeof (info->ids.eui64)); + ctrl->quirks |=NVME_QUIRK_BOGUS_NID ; }mutex_lock (&ctrl->subsys->lock);
Greg Kroah-Hartman
maintainerPATCH 240/292 samples: ftrace: Save required argument registers in sample trampolines
In reply to Greg Kroah-HartmanFrom: Florent Revest <[email protected]>
commit 8564c315876ab86fcaf8e7f558d6a84cb2ce5590 upstream.
The ftrace-direct-too sample traces the handle_mm_fault function whose signature changed since the introduction of the sample. Since:
commit bce617edecad ("mm: do page fault accounting in handle_mm_fault") handle_mm_fault now has 4 arguments. Therefore, the sample trampoline should save 4 argument registers.
s390 saves all argument registers already so it does not need a change but x86_64 needs an extra push and pop.
This also evolves the signature of the tracing function to make it mirror the signature of the traced function.
--- samples/ftrace/ftrace-direct-too.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
samples/ftrace/ftrace-direct-too.c +8 -6
@@ -5,14 +5,14 @@#include <linux/ftrace.h> #include <asm/asm-offsets.h> -extern void my_direct_func (struct vm_area_struct *vma, -unsigned long address,unsigned int flags); +extern void my_direct_func (struct vm_area_struct *vma,unsigned long address, +unsigned int flags,struct pt_regs *regs); -void my_direct_func (struct vm_area_struct *vma, -unsigned long address,unsigned int flags) +void my_direct_func (struct vm_area_struct *vma,unsigned long address, +unsigned int flags,struct pt_regs *regs) { -trace_printk ("handle mm fault vma=%p address=%lx flags=%x\n" , - vma, address, flags); +trace_printk ("handle mm fault vma=%p address=%lx flags=%x regs=%p\n" , + vma, address, flags, regs); }extern void my_tramp (void *);
@@ -34,7 +34,9 @@ asm (" pushq %rdi\n" " pushq %rsi\n" " pushq %rdx\n" +" pushq %rcx\n" " call my_direct_func\n" +" popq %rcx\n" " popq %rdx\n" " popq %rsi\n" " popq %rdi\n"
Greg Kroah-Hartman
maintainerPATCH 241/292 perf: RISC-V: Remove PERF_HES_STOPPED flag checking in riscv_pmu_start()
In reply to Greg Kroah-HartmanFrom: Eric Lin <[email protected]>
commit 66843b14fb71825fdd73ab12f6594f2243b402be upstream.
Since commit 096b52fd2bb4 ("perf: RISC-V: throttle perf events") the perf_sample_event_took() function was added to report time spent in overflow interrupts. If the interrupt takes too long, the perf framework will lower the sysctl_perf_event_sample_rate and max_samples_per_tick. When hwc->interrupts is larger than max_samples_per_tick, the hwc->interrupts will be set to MAX_INTERRUPTS, and events will be throttled within the __perf_event_account_interrupt() function.
However, the RISC-V PMU driver doesn't call riscv_pmu_stop() to update the PERF_HES_STOPPED flag after perf_event_overflow() in pmu_sbi_ovf_handler() function to avoid throttling. When the perf framework unthrottled the event in the timer interrupt handler, it triggers riscv_pmu_start() function and causes a WARN_ON_ONCE() warning, as shown below:
------------[ cut here ]------------ WARNING: CPU: 0 PID: 240 at drivers/perf/riscv_pmu.c:184 riscv_pmu_start+0x7c/0x8e Modules linked in: CPU: 0 PID: 240 Comm: ls Not tainted 6.4-rc4-g19d0788e9ef2 #1 Hardware name: SiFive (DT) epc : riscv_pmu_start+0x7c/0x8e ra : riscv_pmu_start+0x28/0x8e epc : ffffffff80aef864 ra : ffffffff80aef810 sp : ffff8f80004db6f0 gp : ffffffff81c83750 tp : ffffaf80069f9bc0 t0 : ffff8f80004db6c0 t1 : 0000000000000000 t2 : 000000000000001f s0 : ffff8f80004db720 s1 : ffffaf8008ca1068 a0 : 0000ffffffffffff a1 : 0000000000000000 a2 : 0000000000000001 a3 : 0000000000000870 a4 : 0000000000000000 a5 : 0000000000000000 a6 : 0000000000000840 a7 : 0000000000000030 s2 : 0000000000000000 s3 : ffffaf8005165800 s4 : ffffaf800424da00 s5 : ffffffffffffffff s6 : ffffffff81cc7590 s7 : 0000000000000000 s8 : 0000000000000006 s9 : 0000000000000001 s10: ffffaf807efbc340 s11: ffffaf807efbbf00 t3 : ffffaf8006a16028 t4 : 00000000dbfbb796 t5 : 0000000700000000 t6 : ffffaf8005269870 status: 0000000200000100 badaddr: 0000000000000000 cause: 0000000000000003 [<ffffffff80aef864>] riscv_pmu_start+0x7c/0x8e [<ffffffff80185b56>] perf_adjust_freq_unthr_context+0x15e/0x174 [<ffffffff80188642>] perf_event_task_tick+0x88/0x9c [<ffffffff800626a8>] scheduler_tick+0xfe/0x27c [<ffffffff800b5640>] update_process_times+0x9a/0xba [<ffffffff800c5bd4>] tick_sched_handle+0x32/0x66 [<ffffffff800c5e0c>] tick_sched_timer+0x64/0xb0 [<ffffffff800b5e50>] __hrtimer_run_queues+0x156/0x2f4 [<ffffffff800b6bdc>] hrtimer_interrupt+0xe2/0x1fe [<ffffffff80acc9e8>] riscv_timer_interrupt+0x38/0x42 [<ffffffff80090a16>] handle_percpu_devid_irq+0x90/0x1d2 [<ffffffff8008a9f4>] generic_handle_domain_irq+0x28/0x36
After referring other PMU drivers like Arm, Loongarch, Csky, and Mips, they don't call *_pmu_stop() to update with PERF_HES_STOPPED flag after perf_event_overflow() function nor do they add PERF_HES_STOPPED flag checking in *_pmu_start() which don't cause this warning.
Thus, it's recommended to remove this unnecessary check in riscv_pmu_start() function to prevent this warning.
--- drivers/perf/riscv_pmu.c | 3 --- 1 file changed, 3 deletions(-)
drivers/perf/riscv_pmu.c +0 -3
@@ -181,9 +181,6 @@ void riscv_pmu_start(struct perf_event *uint64_t max_period =riscv_pmu_ctr_get_width_mask (event);u64 init_val; -if (WARN_ON_ONCE (!(event->hw.state &PERF_HES_STOPPED ))) -return ; -if (flags &PERF_EF_RELOAD )WARN_ON_ONCE (!(event->hw.state &PERF_HES_UPTODATE ));
Greg Kroah-Hartman
maintainerPATCH 242/292 regmap-irq: Fix out-of-bounds access when allocating config buffers
In reply to Greg Kroah-HartmanFrom: Isaac J. Manjarres <[email protected]>
commit 963b54df82b6d6206d7def273390bf3f7af558e1 upstream.
When allocating the 2D array for handling IRQ type registers in regmap_add_irq_chip_fwnode(), the intent is to allocate a matrix with num_config_bases rows and num_config_regs columns.
This is currently handled by allocating a buffer to hold a pointer for each row (i.e. num_config_bases). After that, the logic attempts to allocate the memory required to hold the register configuration for each row. However, instead of doing this allocation for each row (i.e. num_config_bases allocations), the logic erroneously does this allocation num_config_regs number of times.
This scenario can lead to out-of-bounds accesses when num_config_regs is greater than num_config_bases. Fix this by updating the terminating condition of the loop that allocates the memory for holding the register configuration to allocate memory only for each row in the matrix.
Amit Pundir reported a crash that was occurring on his db845c device due to memory corruption (see "Closes" tag for Amit's report). The KASAN report below helped narrow it down to this issue:
[ 14.033877][ T1] ================================================================== [ 14.042507][ T1] BUG: KASAN: invalid-access in regmap_add_irq_chip_fwnode+0x594/0x1364 [ 14.050796][ T1] Write of size 8 at addr 06ffff8081021850 by task init/1
[ 14.242004][ T1] The buggy address belongs to the object at ffffff8081021850 [ 14.242004][ T1] which belongs to the cache kmalloc-8 of size 8 [ 14.255669][ T1] The buggy address is located 0 bytes inside of [ 14.255669][ T1] 8-byte region [ffffff8081021850, ffffff8081021858)
--- drivers/base/regmap/regmap-irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/base/regmap/regmap-irq.c +1 -1
@@ -852,7 +852,7 @@ int regmap_add_irq_chip_fwnode(struct fwif (!d->config_buf) goto err_alloc; -for (i =0 ; i < chip->num_config_regs; i++) { +for (i =0 ; i < chip->num_config_bases; i++) { d->config_buf[i] =kcalloc (chip->num_config_regs,sizeof (**d->config_buf),GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 243/292 net: ena: fix shift-out-of-bounds in exponential backoff
In reply to Greg Kroah-HartmanFrom: Krister Johansen <[email protected]>
commit 1e9cb763e9bacf0c932aa948f50dcfca6f519a26 upstream.
The ENA adapters on our instances occasionally reset. Once recently logged a UBSAN failure to console in the process:
UBSAN: shift-out-of-bounds in build/linux/drivers/net/ethernet/amazon/ena/ena_com.c:540:13 shift exponent 32 is too large for 32-bit type 'unsigned int' CPU: 28 PID: 70012 Comm: kworker/u72:2 Kdump: loaded not tainted 5.15.117 Hardware name: Amazon EC2 c5d.9xlarge/, BIOS 1.0 10/16/2017 Workqueue: ena ena_fw_reset_device [ena] Call Trace: <TASK> dump_stack_lvl+0x4a/0x63 dump_stack+0x10/0x16 ubsan_epilogue+0x9/0x36 __ubsan_handle_shift_out_of_bounds.cold+0x61/0x10e ? __const_udelay+0x43/0x50 ena_delay_exponential_backoff_us.cold+0x16/0x1e [ena] wait_for_reset_state+0x54/0xa0 [ena] ena_com_dev_reset+0xc8/0x110 [ena] ena_down+0x3fe/0x480 [ena] ena_destroy_device+0xeb/0xf0 [ena] ena_fw_reset_device+0x30/0x50 [ena] process_one_work+0x22b/0x3d0 worker_thread+0x4d/0x3f0 ? process_one_work+0x3d0/0x3d0 kthread+0x12a/0x150 ? set_kthread_struct+0x50/0x50 ret_from_fork+0x22/0x30 </TASK>
Apparently, the reset delays are getting so large they can trigger a UBSAN panic.
Looking at the code, the current timeout is capped at 5000us. Using a base value of 100us, the current code will overflow after (1<<29). Even at values before 32, this function wraps around, perhaps unintentionally.
Cap the value of the exponent used for this backoff at (1<<16) which is larger than currently necessary, but large enough to support bigger values in the future.
--- drivers/net/ethernet/amazon/ena/ena_com.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/amazon/ena/ena_com.c +3 -0
@@ -35,6 +35,8 @@#define ENA_REGS_ADMIN_INTR_MASK 1 +#define ENA_MAX_BACKOFF_DELAY_EXP 16U +#define ENA_MIN_ADMIN_POLL_US 100#define ENA_MAX_ADMIN_POLL_US 5000
@@ -536,6 +538,7 @@ static int ena_com_comp_status_to_errno(static void ena_delay_exponential_backoff_us (u32 exp,u32 delay_us) { + exp =min_t (u32, exp,ENA_MAX_BACKOFF_DELAY_EXP ); delay_us =max_t (u32,ENA_MIN_ADMIN_POLL_US , delay_us); delay_us =min_t (u32, delay_us * (1U << exp),ENA_MAX_ADMIN_POLL_US );usleep_range (delay_us,2 * delay_us);
Greg Kroah-Hartman
maintainerPATCH 244/292 ring-buffer: Fix deadloop issue on reading trace_pipe
In reply to Greg Kroah-HartmanFrom: Zheng Yejian <[email protected]>
commit 7e42907f3a7b4ce3a2d1757f6d78336984daf8f5 upstream.
Soft lockup occurs when reading file 'trace_pipe':
watchdog: BUG: soft lockup - CPU#6 stuck for 22s! [cat:4488] [...] RIP: 0010:ring_buffer_empty_cpu+0xed/0x170 RSP: 0018:ffff88810dd6fc48 EFLAGS: 00000246 RAX: 0000000000000000 RBX: 0000000000000246 RCX: ffffffff93d1aaeb RDX: ffff88810a280040 RSI: 0000000000000008 RDI: ffff88811164b218 RBP: ffff88811164b218 R08: 0000000000000000 R09: ffff88815156600f R10: ffffed102a2acc01 R11: 0000000000000001 R12: 0000000051651901 R13: 0000000000000000 R14: ffff888115e49500 R15: 0000000000000000 [...] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8d853c2000 CR3: 000000010dcd8000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: __find_next_entry+0x1a8/0x4b0 ? peek_next_entry+0x250/0x250 ? down_write+0xa5/0x120 ? down_write_killable+0x130/0x130 trace_find_next_entry_inc+0x3b/0x1d0 tracing_read_pipe+0x423/0xae0 ? tracing_splice_read_pipe+0xcb0/0xcb0 vfs_read+0x16b/0x490 ksys_read+0x105/0x210 ? __ia32_sys_pwrite64+0x200/0x200 ? switch_fpu_return+0x108/0x220 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x61/0xc6
Through the vmcore, I found it's because in tracing_read_pipe(), ring_buffer_empty_cpu() found some buffer is not empty but then it cannot read anything due to "rb_num_of_entries() == 0" always true, Then it infinitely loop the procedure due to user buffer not been filled, see following code path:
tracing_read_pipe() {
... ...
waitagain:
tracing_wait_pipe() // 1. find non-empty buffer here
trace_find_next_entry_inc() // 2. loop here try to find an entry
__find_next_entry()
ring_buffer_empty_cpu(); // 3. find non-empty buffer
peek_next_entry() // 4. but peek always return NULL
ring_buffer_peek()
rb_buffer_peek()
rb_get_reader_page()
// 5. because rb_num_of_entries() == 0 always true here
// then return NULL
// 6. user buffer not been filled so goto 'waitgain'
// and eventually leads to an deadloop in kernel!!!}
By some analyzing, I found that when resetting ringbuffer, the 'entries' of its pages are not all cleared (see rb_reset_cpu()). Then when reducing the ringbuffer, and if some reduced pages exist dirty 'entries' data, they will be added into 'cpu_buffer->overrun' (see rb_remove_pages()), which cause wrong 'overrun' count and eventually cause the deadloop issue.
To fix it, we need to clear every pages in rb_reset_cpu().
--- kernel/trace/ring_buffer.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-)
kernel/trace/ring_buffer.c +15 -9
@@ -5242,28 +5242,34 @@ unsigned long ring_buffer_size(struct tr }EXPORT_SYMBOL_GPL (ring_buffer_size); +static void rb_clear_buffer_page (struct buffer_page *page) +{ +local_set (&page->write,0 ); +local_set (&page->entries,0 ); +rb_init_page (page->page); + page->read =0 ; +} +static void rb_reset_cpu (struct ring_buffer_per_cpu *cpu_buffer) { +struct buffer_page *page; +rb_head_page_deactivate (cpu_buffer); cpu_buffer->head_page = list_entry(cpu_buffer->pages, struct buffer_page, list); -local_set (&cpu_buffer->head_page->write,0 ); -local_set (&cpu_buffer->head_page->entries,0 ); -local_set (&cpu_buffer->head_page->page->commit,0 ); - - cpu_buffer->head_page->read =0 ; +rb_clear_buffer_page (cpu_buffer->head_page); +list_for_each_entry (page, cpu_buffer->pages, list) { +rb_clear_buffer_page (page); + } cpu_buffer->tail_page = cpu_buffer->head_page; cpu_buffer->commit_page = cpu_buffer->head_page;INIT_LIST_HEAD (&cpu_buffer->reader_page->list);INIT_LIST_HEAD (&cpu_buffer->new_pages); -local_set (&cpu_buffer->reader_page->write,0 ); -local_set (&cpu_buffer->reader_page->entries,0 ); -local_set (&cpu_buffer->reader_page->page->commit,0 ); - cpu_buffer->reader_page->read =0 ; +rb_clear_buffer_page (cpu_buffer->reader_page);local_set (&cpu_buffer->entries_bytes,0 );local_set (&cpu_buffer->overrun,0 );
Greg Kroah-Hartman
maintainerPATCH 245/292 ftrace: Fix possible warning on checking all pages used in ftrace_process_locs()
In reply to Greg Kroah-HartmanFrom: Zheng Yejian <[email protected]>
commit 26efd79c4624294e553aeaa3439c646729bad084 upstream.
As comments in ftrace_process_locs(), there may be NULL pointers in mcount_loc section:
Quoted 4 lines
Some architecture linkers will pad between the different
mcount_locsections of different object files to satisfy alignments. Skip any NULL pointers.
After commit 20e5227e9f55 ("ftrace: allow NULL pointers in mcount_loc"), NULL pointers will be accounted when allocating ftrace pages but skipped before adding into ftrace pages, this may result in some pages not being used. Then after commit 706c81f87f84 ("ftrace: Remove extra helper functions"), warning may occur at:
WARN_ON(pg->next);
To fix it, only warn for case that no pointers skipped but pages not used up, then free those unused pages after releasing ftrace_lock.
--- kernel/trace/ftrace.c | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-)
kernel/trace/ftrace.c +31 -14
@@ -3305,6 +3305,22 @@ static int ftrace_allocate_records(strucreturn cnt; } +static void ftrace_free_pages (struct ftrace_page *pages) +{ +struct ftrace_page *pg = pages; + +while (pg) { +if (pg->records) { +free_pages ((unsigned long )pg->records, pg->order); + ftrace_number_of_pages -=1 << pg->order; + } + pages = pg->next; +kfree (pg); + pg = pages; + ftrace_number_of_groups--; + } +} +static struct ftrace_page *ftrace_allocate_pages (unsigned long num_to_init) {
@@ -3343,17 +3359,7 @@ ftrace_allocate_pages(unsigned long num_return start_pg; free_pages: - pg = start_pg; -while (pg) { -if (pg->records) { -free_pages ((unsigned long )pg->records, pg->order); - ftrace_number_of_pages -=1 << pg->order; - } - start_pg = pg->next; -kfree (pg); - pg = start_pg; - ftrace_number_of_groups--; - } +ftrace_free_pages (start_pg);pr_info ("ftrace: FAILED to allocate memory for functions\n" );return NULL ; }
@@ -6434,9 +6440,11 @@ static int ftrace_process_locs(struct mounsigned long *start, unsigned long *end) { + struct ftrace_page *pg_unuse = NULL;struct ftrace_page *start_pg;struct ftrace_page *pg;struct dyn_ftrace *rec; +unsigned long skipped =0 ;unsigned long count;unsigned long *p;unsigned long addr;
@@ -6499,8 +6507,10 @@ static int ftrace_process_locs(struct mo* object files to satisfy alignments. * Skip any NULL pointers. */ -if (!addr) +if (!addr) { + skipped++;continue ; + } end_offset = (pg->index+1 ) *sizeof (pg->records[0 ]);if (end_offset >PAGE_SIZE << pg->order) {
@@ -6514,8 +6524,10 @@ static int ftrace_process_locs(struct mo rec->ip = addr; } -/* We should have used all pages */ -WARN_ON (pg->next); +if (pg->next) { + pg_unuse = pg->next; + pg->next =NULL ; + }/* Assign the last page to ftrace_pages */ ftrace_pages = pg;
@@ -6537,6 +6549,11 @@ static int ftrace_process_locs(struct mo out:mutex_unlock (&ftrace_lock); +/* We should have used all pages unless we skipped some */ +if (pg_unuse) { +WARN_ON (!skipped); +ftrace_free_pages (pg_unuse); + }return ret; }
Greg Kroah-Hartman
maintainerPATCH 246/292 drm/amd/pm: share the code around SMU13 pcie parameters update
In reply to Greg Kroah-HartmanFrom: Evan Quan <[email protected]>
commit dcb489bae65d92cfd26da22c7a0d6665b06ecc63 upstream.
So that SMU13.0.0 and SMU13.0.7 do not need to have one copy each.
--- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h | 4 ++ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 31 +++++++++++++++++ drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 33 ------------------- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 33 ------------------- 4 files changed, 37 insertions(+), 64 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +4 -0
@@ -303,5 +303,9 @@ int smu_v13_0_get_pptable_from_firmware(uint32_t *size, uint32_t pptable_id); +int smu_v13_0_update_pcie_parameters (struct smu_context *smu, +uint32_t pcie_gen_cap, +uint32_t pcie_width_cap); +#endif #endif
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +31 -0
@@ -2453,3 +2453,34 @@ int smu_v13_0_mode1_reset(struct smu_conreturn ret; } + +int smu_v13_0_update_pcie_parameters (struct smu_context *smu, +uint32_t pcie_gen_cap, +uint32_t pcie_width_cap) +{ +struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; +struct smu_13_0_pcie_table *pcie_table = + &dpm_context->dpm_tables.pcie_table; +uint32_t smu_pcie_arg; +int ret, i; + +for (i =0 ; i < pcie_table->num_of_link_levels; i++) { +if (pcie_table->pcie_gen[i] > pcie_gen_cap) + pcie_table->pcie_gen[i] = pcie_gen_cap; +if (pcie_table->pcie_lane[i] > pcie_width_cap) + pcie_table->pcie_lane[i] = pcie_width_cap; + + smu_pcie_arg = i <<16 ; + smu_pcie_arg |= pcie_table->pcie_gen[i] <<8 ; + smu_pcie_arg |= pcie_table->pcie_lane[i]; + + ret =smu_cmn_send_smc_msg_with_param (smu, + SMU_MSG_OverridePcieParameters, + smu_pcie_arg, +NULL ); +if (ret) +return ret; + } + +return 0 ; +}
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +1 -32
@@ -1235,37 +1235,6 @@ static int smu_v13_0_0_force_clk_levels(return ret; } -static int smu_v13_0_0_update_pcie_parameters (struct smu_context *smu, -uint32_t pcie_gen_cap, -uint32_t pcie_width_cap) -{ -struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; -struct smu_13_0_pcie_table *pcie_table = - &dpm_context->dpm_tables.pcie_table; -uint32_t smu_pcie_arg; -int ret, i; - -for (i =0 ; i < pcie_table->num_of_link_levels; i++) { -if (pcie_table->pcie_gen[i] > pcie_gen_cap) - pcie_table->pcie_gen[i] = pcie_gen_cap; -if (pcie_table->pcie_lane[i] > pcie_width_cap) - pcie_table->pcie_lane[i] = pcie_width_cap; - - smu_pcie_arg = i <<16 ; - smu_pcie_arg |= pcie_table->pcie_gen[i] <<8 ; - smu_pcie_arg |= pcie_table->pcie_lane[i]; - - ret =smu_cmn_send_smc_msg_with_param (smu, - SMU_MSG_OverridePcieParameters, - smu_pcie_arg, -NULL ); -if (ret) -return ret; - } - -return 0 ; -} -static const struct smu_temperature_range smu13_thermal_policy[] = { {-273150 ,99000 ,99000 ,-273150 ,99000 ,99000 ,-273150 ,99000 ,99000 }, {120000 ,120000 ,120000 ,120000 ,120000 ,120000 ,120000 ,120000 ,120000 },
@@ -2172,7 +2141,7 @@ static const struct pptable_funcs smu_v1 .feature_is_enabled = smu_cmn_feature_is_enabled, .print_clk_levels = smu_v13_0_0_print_clk_levels, .force_clk_levels = smu_v13_0_0_force_clk_levels, - .update_pcie_parameters = smu_v13_0_0_update_pcie_parameters, + .update_pcie_parameters = smu_v13_0_update_pcie_parameters, .get_thermal_temperature_range = smu_v13_0_0_get_thermal_temperature_range, .register_irq_handler = smu_v13_0_register_irq_handler, .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +1 -32
@@ -1225,37 +1225,6 @@ static int smu_v13_0_7_force_clk_levels(return ret; } -static int smu_v13_0_7_update_pcie_parameters (struct smu_context *smu, -uint32_t pcie_gen_cap, -uint32_t pcie_width_cap) -{ -struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; -struct smu_13_0_pcie_table *pcie_table = - &dpm_context->dpm_tables.pcie_table; -uint32_t smu_pcie_arg; -int ret, i; - -for (i =0 ; i < pcie_table->num_of_link_levels; i++) { -if (pcie_table->pcie_gen[i] > pcie_gen_cap) - pcie_table->pcie_gen[i] = pcie_gen_cap; -if (pcie_table->pcie_lane[i] > pcie_width_cap) - pcie_table->pcie_lane[i] = pcie_width_cap; - - smu_pcie_arg = i <<16 ; - smu_pcie_arg |= pcie_table->pcie_gen[i] <<8 ; - smu_pcie_arg |= pcie_table->pcie_lane[i]; - - ret =smu_cmn_send_smc_msg_with_param (smu, - SMU_MSG_OverridePcieParameters, - smu_pcie_arg, -NULL ); -if (ret) -return ret; - } - -return 0 ; -} -static const struct smu_temperature_range smu13_thermal_policy[] = { {-273150 ,99000 ,99000 ,-273150 ,99000 ,99000 ,-273150 ,99000 ,99000 },
@@ -1752,7 +1721,7 @@ static const struct pptable_funcs smu_v1 .feature_is_enabled = smu_cmn_feature_is_enabled, .print_clk_levels = smu_v13_0_7_print_clk_levels, .force_clk_levels = smu_v13_0_7_force_clk_levels, - .update_pcie_parameters = smu_v13_0_7_update_pcie_parameters, + .update_pcie_parameters = smu_v13_0_update_pcie_parameters, .get_thermal_temperature_range = smu_v13_0_7_get_thermal_temperature_range, .register_irq_handler = smu_v13_0_register_irq_handler, .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
Greg Kroah-Hartman
maintainerPATCH 247/292 drm/amd/pm: conditionally disable pcie lane/speed switching for SMU13
In reply to Greg Kroah-HartmanFrom: Mario Limonciello <[email protected]>
commit 31c7a3b378a136adc63296a2ff17645896fcf303 upstream.
Intel platforms such as Sapphire Rapids and Raptor Lake don't support dynamic pcie lane or speed switching.
This limitation seems to carry over from one generation to another. To be safer, disable dynamic pcie lane width and speed switching when running on an Intel platform.
--- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c | 42 +++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +39 -3
@@ -2454,6 +2454,25 @@ int smu_v13_0_mode1_reset(struct smu_conreturn ret; } +/* +* Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic +* speed switching. Until we have confirmation from Intel that a specific host +* supports it, it's safer that we keep it disabled for all. +* +* https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/ +* https://gitlab.freedesktop.org/drm/amd/-/issues/2663 +*/ +static bool smu_v13_0_is_pcie_dynamic_switching_supported (void ) +{ +#if IS_ENABLED (CONFIG_X86 ) +struct cpuinfo_x86 *c = &cpu_data (0 ); + +if (c->x86_vendor ==X86_VENDOR_INTEL ) +return false; +#endif +return true; +} +int smu_v13_0_update_pcie_parameters (struct smu_context *smu,uint32_t pcie_gen_cap,uint32_t pcie_width_cap)
@@ -2461,15 +2480,32 @@ int smu_v13_0_update_pcie_parameters(strstruct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;struct smu_13_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table; +int num_of_levels = pcie_table->num_of_link_levels;uint32_t smu_pcie_arg;int ret, i; -for (i =0 ; i < pcie_table->num_of_link_levels; i++) { -if (pcie_table->pcie_gen[i] > pcie_gen_cap) +if (!smu_v13_0_is_pcie_dynamic_switching_supported ()) { +if (pcie_table->pcie_gen[num_of_levels -1 ] < pcie_gen_cap) + pcie_gen_cap = pcie_table->pcie_gen[num_of_levels -1 ]; + +if (pcie_table->pcie_lane[num_of_levels -1 ] < pcie_width_cap) + pcie_width_cap = pcie_table->pcie_lane[num_of_levels -1 ]; + +/* Force all levels to use the same settings */ +for (i =0 ; i < num_of_levels; i++) { pcie_table->pcie_gen[i] = pcie_gen_cap; -if (pcie_table->pcie_lane[i] > pcie_width_cap) pcie_table->pcie_lane[i] = pcie_width_cap; + } + }else { +for (i =0 ; i < num_of_levels; i++) { +if (pcie_table->pcie_gen[i] > pcie_gen_cap) + pcie_table->pcie_gen[i] = pcie_gen_cap; +if (pcie_table->pcie_lane[i] > pcie_width_cap) + pcie_table->pcie_lane[i] = pcie_width_cap; + } + } +for (i =0 ; i < num_of_levels; i++) { smu_pcie_arg = i <<16 ; smu_pcie_arg |= pcie_table->pcie_gen[i] <<8 ; smu_pcie_arg |= pcie_table->pcie_lane[i];
Greg Kroah-Hartman
maintainerPATCH 248/292 cifs: if deferred close is disabled then close files immediately
In reply to Greg Kroah-HartmanFrom: Bharath SM <[email protected]>
commit df9d70c18616760c6504b97fec66b6379c172dbb upstream.
If defer close timeout value is set to 0, then there is no need to include files in the deferred close list and utilize the delayed worker for closing. Instead, we can close them immediately.
--- fs/smb/client/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/client/file.c +2 -2
@@ -1080,8 +1080,8 @@ int cifs_close(struct inode *inode, stru cfile = file->private_data; file->private_data =NULL ; dclose =kmalloc (sizeof (struct cifs_deferred_close ),GFP_KERNEL ); -if ((cinode->oplock ==CIFS_CACHE_RHW_FLG ) && - cinode->lease_granted && +if ((cifs_sb->ctx->closetimeo && cinode->oplock ==CIFS_CACHE_RHW_FLG ) + && cinode->lease_granted && !test_bit (CIFS_INO_CLOSE_ON_LOCK , &cinode->flags) && dclose) {if (test_and_clear_bit (CIFS_INO_MODIFIED_ATTR , &cinode->flags)) {
Greg Kroah-Hartman
maintainerPATCH 249/292 xtensa: ISS: fix call to split_if_spec
In reply to Greg Kroah-HartmanFrom: Max Filippov <[email protected]>
commit bc8d5916541fa19ca5bc598eb51a5f78eb891a36 upstream.
split_if_spec expects a NULL-pointer as an end marker for the argument list, but tuntap_probe never supplied that terminating NULL. As a result incorrectly formatted interface specification string may cause a crash because of the random memory access. Fix that by adding NULL terminator to the split_if_spec argument list.
--- arch/xtensa/platforms/iss/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/xtensa/platforms/iss/network.c +1 -1
@@ -237,7 +237,7 @@ static int tuntap_probe(struct iss_net_p init +=sizeof (TRANSPORT_TUNTAP_NAME ) -1 ;if (*init ==',' ) { - rem =split_if_spec (init +1 , &mac_str, &dev_name); + rem =split_if_spec (init +1 , &mac_str, &dev_name,NULL );if (rem !=NULL ) {pr_err ("%s: extra garbage on specification : '%s'\n" , dev->name, rem);
Greg Kroah-Hartman
maintainerPATCH 250/292 perf/x86: Fix lockdep warning in for_each_sibling_event() on SPR
In reply to Greg Kroah-HartmanFrom: Namhyung Kim <[email protected]>
commit 27c68c216ee1f1b086e789a64486e6511e380b8a upstream.
On SPR, the load latency event needs an auxiliary event in the same group to work properly. There's a check in intel_pmu_hw_config() for this to iterate sibling events and find a mem-loads-aux event.
The for_each_sibling_event() has a lockdep assert to make sure if it disabled hardirq or hold leader->ctx->mutex. This works well if the given event has a separate leader event since perf_try_init_event() grabs the leader->ctx->mutex to protect the sibling list. But it can cause a problem when the event itself is a leader since the event is not initialized yet and there's no ctx for the event.
Actually I got a lockdep warning when I run the below command on SPR, but I guess it could be a NULL pointer dereference.
$ perf record -d -e cpu/mem-loads/uP true
The code path to the warning is:
sys_perf_event_open()
perf_event_alloc()
perf_init_event()
perf_try_init_event()
x86_pmu_event_init()
hsw_hw_config()
intel_pmu_hw_config()
for_each_sibling_event()
lockdep_assert_event_ctx()We don't need for_each_sibling_event() when it's a standalone event. Let's return the error code directly.
--- arch/x86/events/intel/core.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/x86/events/intel/core.c +7 -0
@@ -3993,6 +3993,13 @@ static int intel_pmu_hw_config(struct pestruct perf_event *leader = event->group_leader;struct perf_event *sibling =NULL ; +/* +* When this memload event is also the first event (no group +* exists yet), then there is no aux event before it. +*/ +if (leader == event) +return -ENODATA ; +if (!is_mem_loads_aux_event (leader)) {for_each_sibling_event (sibling, leader) {if (is_mem_loads_aux_event (sibling))
Greg Kroah-Hartman
maintainerPATCH 251/292 PM: QoS: Restore support for default value on frequency QoS
In reply to Greg Kroah-HartmanFrom: Chungkai Yang <[email protected]>
commit 3a8395b565b5b4f019b3dc182be4c4541eb35ac8 upstream.
Commit 8d36694245f2 ("PM: QoS: Add check to make sure CPU freq is non-negative") makes sure CPU freq is non-negative to avoid negative value converting to unsigned data type. However, when the value is PM_QOS_DEFAULT_VALUE, pm_qos_update_target specifically uses c->default_value which is set to FREQ_QOS_MIN/MAX_DEFAULT_VALUE when cpufreq_policy_alloc is executed, for this case handling.
Adding check for PM_QOS_DEFAULT_VALUE to let default setting work will fix this problem.
--- kernel/power/qos.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/power/qos.c +7 -2
@@ -426,6 +426,11 @@ late_initcall(cpu_latency_qos_init);/* Definitions related to the frequency QoS below. */ +static inline bool freq_qos_value_invalid (s32 value) +{ +return value <0 && value !=PM_QOS_DEFAULT_VALUE ; +} +/** * freq_constraints_init - Initialize frequency QoS constraints. * @qos: Frequency QoS constraints to initialize.
@@ -531,7 +536,7 @@ int freq_qos_add_request(struct freq_con {int ret; -if (IS_ERR_OR_NULL (qos) || !req || value <0 ) +if (IS_ERR_OR_NULL (qos) || !req ||freq_qos_value_invalid (value))return -EINVAL ; if (WARN(freq_qos_request_active(req),
@@ -563,7 +568,7 @@ EXPORT_SYMBOL_GPL(freq_qos_add_request);*/ int freq_qos_update_request (struct freq_qos_request *req,s32 new_value) { -if (!req || new_value <0 ) +if (!req ||freq_qos_value_invalid (new_value))return -EINVAL ; if (WARN(!freq_qos_request_active(req),
Greg Kroah-Hartman
maintainerPATCH 252/292 pwm: meson: modify and simplify calculation in meson_pwm_get_state
In reply to Greg Kroah-HartmanFrom: Heiner Kallweit <[email protected]>
commit 6b9352f3f8a1a35faf0efc1ad1807ee303467796 upstream.
I don't see a reason why we should treat the case lo < hi differently and return 0 as period and duty_cycle. The current logic was added with c375bcbaabdb ("pwm: meson: Read the full hardware state in meson_pwm_get_state()"), Martin as original author doesn't remember why it was implemented this way back then.
So let's handle it as normal use case and also remove the optimization for lo == 0. I think the improved readability is worth it.
--- drivers/pwm/pwm-meson.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-)
drivers/pwm/pwm-meson.c +2 -12
@@ -351,18 +351,8 @@ static int meson_pwm_get_state(struct pw channel->lo =FIELD_GET (PWM_LOW_MASK , value); channel->hi =FIELD_GET (PWM_HIGH_MASK , value); -if (channel->lo ==0 ) { - state->period =meson_pwm_cnt_to_ns (chip, pwm, channel->hi); - state->duty_cycle = state->period; - }else if (channel->lo >= channel->hi) { - state->period =meson_pwm_cnt_to_ns (chip, pwm, - channel->lo + channel->hi); - state->duty_cycle =meson_pwm_cnt_to_ns (chip, pwm, - channel->hi); - }else { - state->period =0 ; - state->duty_cycle =0 ; - } + state->period =meson_pwm_cnt_to_ns (chip, pwm, channel->lo + channel->hi); + state->duty_cycle =meson_pwm_cnt_to_ns (chip, pwm, channel->hi); state->polarity =PWM_POLARITY_NORMAL ;
Greg Kroah-Hartman
maintainerPATCH 253/292 pwm: meson: fix handling of period/duty if greater than UINT_MAX
In reply to Greg Kroah-HartmanFrom: Heiner Kallweit <[email protected]>
commit 87a2cbf02d7701255f9fcca7e5bd864a7bb397cf upstream.
state->period/duty are of type u64, and if their value is greater than UINT_MAX, then the cast to uint will cause problems. Fix this by changing the type of the respective local variables to u64.
--- drivers/pwm/pwm-meson.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/pwm/pwm-meson.c +7 -7
@@ -156,8 +156,9 @@ static int meson_pwm_calc(struct meson_p const struct pwm_state *state) {struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm]; -unsigned int duty, period, pre_div, cnt, duty_cnt; +unsigned int pre_div, cnt, duty_cnt;unsigned long fin_freq; +u64 duty, period; duty = state->duty_cycle; period = state->period;
@@ -179,19 +180,19 @@ static int meson_pwm_calc(struct meson_pdev_dbg (meson->chip.dev,"fin_freq: %lu Hz\n" , fin_freq); - pre_div =div64_u64 (fin_freq * (u64 )period,NSEC_PER_SEC *0xffffLL ); + pre_div =div64_u64 (fin_freq * period,NSEC_PER_SEC *0xffffLL );if (pre_div >MISC_CLK_DIV_MASK ) {dev_err (meson->chip.dev,"unable to get period pre_div\n" );return -EINVAL ; } - cnt =div64_u64 (fin_freq * (u64 )period,NSEC_PER_SEC * (pre_div +1 )); + cnt =div64_u64 (fin_freq * period,NSEC_PER_SEC * (pre_div +1 ));if (cnt >0xffff ) {dev_err (meson->chip.dev,"unable to get period cnt\n" );return -EINVAL ; } -dev_dbg (meson->chip.dev,"period=%u pre_div=%u cnt=%u\n" , period, +dev_dbg (meson->chip.dev,"period=%llu pre_div=%u cnt=%u\n" , period, pre_div, cnt);if (duty == period) {
@@ -204,14 +205,13 @@ static int meson_pwm_calc(struct meson_p channel->lo = cnt; }else {/* Then check is we can have the duty with the same pre_div */ - duty_cnt =div64_u64 (fin_freq * (u64 )duty, -NSEC_PER_SEC * (pre_div +1 )); + duty_cnt =div64_u64 (fin_freq * duty,NSEC_PER_SEC * (pre_div +1 ));if (duty_cnt >0xffff ) {dev_err (meson->chip.dev,"unable to get duty cycle\n" );return -EINVAL ; } -dev_dbg (meson->chip.dev,"duty=%u pre_div=%u duty_cnt=%u\n" , +dev_dbg (meson->chip.dev,"duty=%llu pre_div=%u duty_cnt=%u\n" , duty, pre_div, duty_cnt); channel->pre_div = pre_div;
Greg Kroah-Hartman
maintainerPATCH 254/292 accel/ivpu: Fix VPU register access in irq disable
In reply to Greg Kroah-HartmanFrom: Karol Wachowski <[email protected]>
commit 020b527b556a35cf636015c1c3cbdfe7c7acd5f0 upstream.
Incorrect REGB_WR32() macro was used to access VPUIP register. Use correct REGV_WR32().
--- drivers/accel/ivpu/ivpu_hw_mtl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/accel/ivpu/ivpu_hw_mtl.c +1 -1
@@ -885,7 +885,7 @@ static void ivpu_hw_mtl_irq_disable(struct ivpu_device *vdev)REGB_WR32 (MTL_BUTTRESS_GLOBAL_INT_MASK ,0x1 );REGB_WR32 (MTL_BUTTRESS_LOCAL_INT_MASK ,BUTTRESS_IRQ_DISABLE_MASK );REGV_WR64 (MTL_VPU_HOST_SS_ICB_ENABLE_0 ,0x0ull ); -REGB_WR32 (MTL_VPU_HOST_SS_FW_SOC_IRQ_EN ,0x0 ); +REGV_WR32 (MTL_VPU_HOST_SS_FW_SOC_IRQ_EN ,0x0 ); }static void ivpu_hw_mtl_irq_wdt_nce_handler (struct ivpu_device *vdev)
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 255/292 accel/ivpu: Clear specific interrupt status bits on C0
In reply to Greg Kroah-HartmanFrom: Karol Wachowski <[email protected]>
commit 7f34e01f77f811ecb2ef83e60301b38cf89af466 upstream.
MTL C0 stepping fixed issue related to butrress interrupt status clearing, to clear an interrupt status it is required to write 1 to specific status bit field. This allows to execute read, modify and write routine.
Writing 0 will not clear the interrupt and will cause interrupt storm.
--- drivers/accel/ivpu/ivpu_drv.h | 1 + drivers/accel/ivpu/ivpu_hw_mtl.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-)
drivers/accel/ivpu/ivpu_drv.h +1 -0
@@ -75,6 +75,7 @@ struct ivpu_wa_table {bool punit_disabled;bool clear_runtime_mem;bool d3hot_after_power_off; +bool interrupt_clear_with_0; };struct ivpu_hw_info ;
drivers/accel/ivpu/ivpu_hw_mtl.c +12 -6
@@ -101,6 +101,9 @@ static void ivpu_hw_wa_init(struct ivpu_ vdev->wa.punit_disabled =ivpu_is_fpga (vdev); vdev->wa.clear_runtime_mem = false; vdev->wa.d3hot_after_power_off = true; + +if (ivpu_device_id (vdev) ==PCI_DEVICE_ID_MTL &&ivpu_revision (vdev) <4 ) + vdev->wa.interrupt_clear_with_0 = true; }static void ivpu_hw_timeouts_init (struct ivpu_device *vdev)
@@ -973,12 +976,15 @@ static u32 ivpu_hw_mtl_irqb_handler(stru schedule_recovery = true; } -/* -* Clear local interrupt status by writing 0 to all bits. -* This must be done after interrupts are cleared at the source. -* Writing 1 triggers an interrupt, so we can't perform read update write. -*/ -REGB_WR32 (MTL_BUTTRESS_INTERRUPT_STAT ,0x0 ); +/* This must be done after interrupts are cleared at the source. */ +if (IVPU_WA (interrupt_clear_with_0)) +/* +* Writing 1 triggers an interrupt, so we can't perform read update write. +* Clear local interrupt status by writing 0 to all bits. +*/ +REGB_WR32 (MTL_BUTTRESS_INTERRUPT_STAT ,0x0 ); +else +REGB_WR32 (MTL_BUTTRESS_INTERRUPT_STAT , status);/* Re-enable global interrupt */ REGB_WR32 (MTL_BUTTRESS_GLOBAL_INT_MASK ,0x0 );
Greg Kroah-Hartman
maintainerPATCH 256/292 fprobe: Release rethook after the ftrace_ops is unregistered
In reply to Greg Kroah-HartmanFrom: Jiri Olsa <[email protected]>
commit 5f81018753dfd4989e33ece1f0cb6b8aae498b82 upstream.
While running bpf selftests it's possible to get following fault:
general protection fault, probably for non-canonical address \ 0x6b6b6b6b6b6b6b6b: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC NOPTI ... Call Trace: <TASK> fprobe_handler+0xc1/0x270 ? __pfx_bpf_testmod_init+0x10/0x10 ? __pfx_bpf_testmod_init+0x10/0x10 ? bpf_fentry_test1+0x5/0x10 ? bpf_fentry_test1+0x5/0x10 ? bpf_testmod_init+0x22/0x80 ? do_one_initcall+0x63/0x2e0 ? rcu_is_watching+0xd/0x40 ? kmalloc_trace+0xaf/0xc0 ? do_init_module+0x60/0x250 ? __do_sys_finit_module+0xac/0x120 ? do_syscall_64+0x37/0x90 ? entry_SYSCALL_64_after_hwframe+0x72/0xdc </TASK>
In unregister_fprobe function we can't release fp->rethook while it's possible there are some of its users still running on another cpu.
Moving rethook_free call after fp->ops is unregistered with unregister_ftrace_function call.
--- kernel/trace/fprobe.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
kernel/trace/fprobe.c +3 -9
@@ -366,19 +366,13 @@ int unregister_fprobe(struct fprobe *fp) fp->ops.saved_func != fprobe_kprobe_handler))return -EINVAL ; -/* -* rethook_free() starts disabling the rethook, but the rethook handlers -* may be running on other processors at this point. To make sure that all -* current running handlers are finished, call unregister_ftrace_function() -* after this. -*/ -if (fp->rethook) -rethook_free (fp->rethook); - ret =unregister_ftrace_function (&fp->ops);if (ret <0 )return ret; +if (fp->rethook) +rethook_free (fp->rethook); +ftrace_free_filter (&fp->ops);return ret;
Hi,
Quoted 5 lines · On Fri, 21 Jul 2023 18:01:49 +0200 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.4.5 release. There are 292 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Quoted 8 lines
Responses should be made by Sun, 23 Jul 2023 16:04:29 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.4.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.4.y
and the diffstat can be found below.
I confirmed that this rc kernel passes DAMON functionality test[1] on my test machine. Attaching the test results summary below.
[1] https://github.com/awslabs/damon-tests/tree/next/corr
Thanks,
SJ
---
ok 1 selftests: damon: debugfs_attrs.sh
ok 2 selftests: damon: debugfs_schemes.sh
ok 3 selftests: damon: debugfs_target_ids.sh
ok 4 selftests: damon: debugfs_empty_targets.sh
ok 5 selftests: damon: debugfs_huge_count_read_write.sh
ok 6 selftests: damon: debugfs_duplicate_context_creation.sh
ok 7 selftests: damon: debugfs_rm_non_contexts.sh
ok 8 selftests: damon: sysfs.sh
ok 9 selftests: damon: sysfs_update_removed_scheme_dir.sh
ok 10 selftests: damon: reclaim.sh
ok 11 selftests: damon: lru_sort.sh
ok 1 selftests: damon-tests: kunit.sh
ok 2 selftests: damon-tests: huge_count_read_write.sh
ok 3 selftests: damon-tests: buffer_overflow.sh
ok 4 selftests: damon-tests: rm_contexts.sh
ok 5 selftests: damon-tests: record_null_deref.sh
ok 6 selftests: damon-tests: dbgfs_target_ids_read_before_terminate_race.sh ok 7 selftests: damon-tests: dbgfs_target_ids_pid_leak.sh
ok 8 selftests: damon-tests: damo_tests.sh
ok 9 selftests: damon-tests: masim-record.sh
ok 10 selftests: damon-tests: build_i386.sh
ok 11 selftests: damon-tests: build_m68k.sh
ok 12 selftests: damon-tests: build_arm64.sh
ok 13 selftests: damon-tests: build_i386_idle_flag.sh
ok 14 selftests: damon-tests: build_i386_highpte.sh
ok 15 selftests: damon-tests: build_nomemcg.sh
PASS
[...]
Hi Greg
Quoted 10 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.4.5 release. There are 292 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Sun, 23 Jul 2023 16:04:29 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.4.5-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.4.y
and the diffstat can be found below.thanks,
greg k-h
6.4.5-rc1 tested.
Build successfully completed.
Boot successfully completed.
No dmesg regressions.
Video output normal.
Sound output normal.
Lenovo ThinkPad X1 Carbon Gen10(Intel i7-1260P(x86_64), arch linux)
Thanks
Greg Kroah-Hartman
maintainerPATCH 257/292 fprobe: Ensure running fprobe_exit_handler() finished before calling rethook_free()
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
commit 195b9cb5b288fec1c871ef89f78cc9a7461aad3a upstream.
Ensure running fprobe_exit_handler() has finished before calling rethook_free() in the unregister_fprobe() so that caller can free the fprobe right after unregister_fprobe().
unregister_fprobe() ensured that all running fprobe_entry/exit_handler() have finished by calling unregister_ftrace_function() which synchronizes RCU. But commit 5f81018753df ("fprobe: Release rethook after the ftrace_ops is unregistered") changed to call rethook_free() after unregister_ftrace_function(). So call rethook_stop() to make rethook disabled before unregister_ftrace_function() and ensure it again.
Here is the possible code flow that can call the exit handler after unregister_fprobe().
------
CPU1 CPU2
call unregister_fprobe(fp)
...
__fprobe_handler() rethook_hook() on probed function
unregister_ftrace_function()
return from probed function rethook hooks
find rh->handler == fprobe_exit_handler call fprobe_exit_handler()
rethook_free():
set rh->handler = NULL;
return from unreigster_fprobe;
call fp->exit_handler() <- (*)------
(*) At this point, the exit handler is called after returning from unregister_fprobe().
This fixes it as following;
------
CPU1 CPU2
call unregister_fprobe()
...
rethook_stop():
set rh->handler = NULL;
__fprobe_handler() rethook_hook() on probed function
unregister_ftrace_function()
return from probed function rethook hooks
find rh->handler == NULL return from rethook
rethook_free()
return from unreigster_fprobe;
------
--- include/linux/rethook.h | 1 + kernel/trace/fprobe.c | 3 +++ kernel/trace/rethook.c | 13 +++++++++++++ 3 files changed, 17 insertions(+)
include/linux/rethook.h +1 -0
@@ -59,6 +59,7 @@ struct rethook_node { };struct rethook *rethook_alloc (void *data,rethook_handler_t handler); +void rethook_stop (struct rethook *rh);void rethook_free (struct rethook *rh);void rethook_add_node (struct rethook *rh,struct rethook_node *node);struct rethook_node *rethook_try_get (struct rethook *rh);
kernel/trace/fprobe.c +3 -0
@@ -366,6 +366,9 @@ int unregister_fprobe(struct fprobe *fp) fp->ops.saved_func != fprobe_kprobe_handler))return -EINVAL ; +if (fp->rethook) +rethook_stop (fp->rethook); + ret =unregister_ftrace_function (&fp->ops);if (ret <0 )return ret;
kernel/trace/rethook.c +13 -0
@@ -54,6 +54,19 @@ static void rethook_free_rcu(struct rcu_ }/** +* rethook_stop() - Stop using a rethook. +* @rh: the struct rethook to stop. +* +* Stop using a rethook to prepare for freeing it. If you want to wait for +* all running rethook handler before calling rethook_free(), you need to +* call this first and wait RCU, and call rethook_free(). +*/ +void rethook_stop (struct rethook *rh) +{ +WRITE_ONCE (rh->handler,NULL ); +} + +/** * rethook_free() - Free struct rethook. * @rh: the struct rethook to be freed. *
Greg Kroah-Hartman
maintainerPATCH 258/292 tracing: Fix null pointer dereference in tracing_err_log_open()
In reply to Greg Kroah-HartmanFrom: Mateusz Stachyra <[email protected]>
commit 02b0095e2fbbc060560c1065f86a211d91e27b26 upstream.
Fix an issue in function 'tracing_err_log_open'.
The function doesn't call 'seq_open' if the file is opened only with write permissions, which results in 'file->private_data' being left as null. If we then use 'lseek' on that opened file, 'seq_lseek' dereferences 'file->private_data' in 'mutex_lock(&m->lock)', resulting in a kernel panic. Writing to this node requires root privileges, therefore this bug has very little security impact.
Tracefs node: /sys/kernel/tracing/error_log
Example Kernel panic:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000038 Call trace: mutex_lock+0x30/0x110 seq_lseek+0x34/0xb8 __arm64_sys_lseek+0x6c/0xb8 invoke_syscall+0x58/0x13c el0_svc_common+0xc4/0x10c do_el0_svc+0x24/0x98 el0_svc+0x24/0x88 el0t_64_sync_handler+0x84/0xe4 el0t_64_sync+0x1b4/0x1b8 Code: d503201f aa0803e0 aa1f03e1 aa0103e9 (c8e97d02) ---[ end trace 561d1b49c12cf8a5 ]--- Kernel panic - not syncing: Oops: Fatal exception
--- kernel/trace/trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace.c +1 -1
@@ -8136,7 +8136,7 @@ static const struct file_operations trac .open = tracing_err_log_open, .write = tracing_err_log_write, .read = seq_read, - .llseek = seq_lseek, + .llseek = tracing_lseek, .release = tracing_err_log_release, };
Greg Kroah-Hartman
maintainerPATCH 259/292 mptcp: do not rely on implicit state check in mptcp_listen()
In reply to Greg Kroah-HartmanFrom: Paolo Abeni <[email protected]>
commit 0226436acf2495cde4b93e7400e5a87305c26054 upstream.
Since the blamed commit, closing the first subflow resets the first subflow socket state to SS_UNCONNECTED.
The current mptcp listen implementation relies only on such state to prevent touching not-fully-disconnected sockets.
Incoming mptcp fastclose (or paired endpoint removal) unconditionally closes the first subflow.
All the above allows an incoming fastclose followed by a listen() call to successfully race with a blocking recvmsg(), potentially causing the latter to hit a divide by zero bug in cleanup_rbuf/__tcp_select_window().
Address the issue explicitly checking the msk socket state in mptcp_listen(). An alternative solution would be moving the first subflow socket state update into mptcp_disconnect(), but in the long term the first subflow socket should be removed: better avoid relaying on it for internal consistency check.
--- net/mptcp/protocol.c | 5 +++++ 1 file changed, 5 insertions(+)
net/mptcp/protocol.c +5 -0
@@ -3697,6 +3697,11 @@ static int mptcp_listen(struct socket *spr_debug ("msk=%p" , msk);lock_sock (sk); + + err = -EINVAL ; +if (sock->state !=SS_UNCONNECTED || sock->type !=SOCK_STREAM ) + goto unlock; + ssock =__mptcp_nmpc_socket (msk);if (IS_ERR (ssock)) { err =PTR_ERR (ssock);
Greg Kroah-Hartman
maintainerPATCH 260/292 mptcp: ensure subflow is unhashed before cleaning the backlog
In reply to Greg Kroah-HartmanFrom: Paolo Abeni <[email protected]>
commit 3fffa15bfef48b0ad6424779c03e68ae8ace5acb upstream.
While tacking care of the mptcp-level listener I unintentionally moved the subflow level unhash after the subflow listener backlog cleanup.
That could cause some nasty race and makes the code harder to read.
Address the issue restoring the proper order of operations.
--- net/mptcp/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mptcp/protocol.c +1 -1
@@ -2908,10 +2908,10 @@ static void mptcp_check_listen_stop(strureturn ;lock_sock_nested (ssk,SINGLE_DEPTH_NESTING ); +tcp_set_state (ssk,TCP_CLOSE );mptcp_subflow_queue_clean (sk, ssk);inet_csk_listen_stop (ssk);mptcp_event_pm_listener (ssk,MPTCP_EVENT_LISTENER_CLOSED ); -tcp_set_state (ssk,TCP_CLOSE );release_sock (ssk); }
Greg Kroah-Hartman
maintainerPATCH 261/292 selftests: mptcp: sockopt: use iptables-legacy if available
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit a5a5990c099dd354e05e89ee77cd2dbf6655d4a1 upstream.
IPTables commands using 'iptables-nft' fail on old kernels, at least on v5.15 because it doesn't see the default IPTables chains:
$ iptables -L iptables/1.8.2 Failed to initialize nft: Protocol not supported
As a first step before switching to NFTables, we can use iptables-legacy if available.
--- tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh +11 -9
@@ -12,6 +12,8 @@ ksft_skip=4 timeout_poll=30 timeout_test=$((timeout_poll * 2 + 1)) mptcp_connect="" +iptables="iptables" +ip6tables="ip6tables" sec=$(date +%s) rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
@@ -25,7 +27,7 @@ add_mark_rules() local m=$2 local t - for t in iptables ip6tables; do + for t in ${iptables} ${ip6tables}; do # just to debug: check we have multiple subflows connection requests ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT
@@ -95,14 +97,14 @@ if [ $? -ne 0 ];then exit $ksft_skip fi -iptables -V > /dev/null 2>&1 -if [ $? -ne 0 ];then +# Use the legacy version if available to support old kernel versions +if iptables-legacy -V &> /dev/null; then + iptables="iptables-legacy" + ip6tables="ip6tables-legacy" +elif ! iptables -V &> /dev/null; then echo "SKIP: Could not run all tests without iptables tool" exit $ksft_skip -fi - -ip6tables -V > /dev/null 2>&1 -if [ $? -ne 0 ];then +elif ! ip6tables -V &> /dev/null; then echo "SKIP: Could not run all tests without ip6tables tool" exit $ksft_skip fi
@@ -112,10 +114,10 @@ check_mark() local ns=$1 local af=$2 - local tables=iptables + local tables=${iptables} if [ $af -eq 6 ];then - tables=ip6tables + tables=${ip6tables} fi local counters values
Greg Kroah-Hartman
maintainerPATCH 262/292 selftests: mptcp: connect: fail if nft supposed to work
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit 221e4550454a822f9a11834e30694c7d1d65747c upstream.
In case of "external" errors when preparing the environment for the TProxy tests, the subtests were marked as skipped.
This is fine but it means these errors are ignored. On MPTCP Public CI, we do want to catch such issues and mark the selftest as failed if there are such issues. We can then use mptcp_lib_fail_if_expected_feature() helper that has been recently added to fail if needed.
--- tools/testing/selftests/net/mptcp/mptcp_connect.sh | 3 +++ 1 file changed, 3 insertions(+)
tools/testing/selftests/net/mptcp/mptcp_connect.sh +3 -0
@@ -718,6 +718,7 @@ table inet mangle { EOF if [ $? -ne 0 ]; then echo "SKIP: $msg, could not load nft ruleset" + mptcp_lib_fail_if_expected_feature "nft rules" return fi
@@ -733,6 +734,7 @@ EOF if [ $? -ne 0 ]; then ip netns exec "$listener_ns" nft flush ruleset echo "SKIP: $msg, ip $r6flag rule failed" + mptcp_lib_fail_if_expected_feature "ip rule" return fi
@@ -741,6 +743,7 @@ EOF ip netns exec "$listener_ns" nft flush ruleset ip -net "$listener_ns" $r6flag rule del fwmark 1 lookup 100 echo "SKIP: $msg, ip route add local $local_addr failed" + mptcp_lib_fail_if_expected_feature "ip route" return fi
Greg Kroah-Hartman
maintainerPATCH 263/292 selftests: mptcp: sockopt: return error if wrong mark
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit 9ac4c28eb70cd5ea5472a5e1c495dcdd597d4597 upstream.
When an error was detected when checking the marks, a message was correctly printed mentioning the error but followed by another one saying everything was OK and the selftest was not marked as failed as expected.
Now the 'ret' variable is directly set to 1 in order to make sure the exit is done with an error, similar to what is done in other functions. While at it, the error is correctly propagated to the caller.
--- tools/testing/selftests/net/mptcp/mptcp_sockopt.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
tools/testing/selftests/net/mptcp/mptcp_sockopt.sh +5 -4
@@ -128,6 +128,7 @@ check_mark() for v in $values; do if [ $v -ne 0 ]; then echo "FAIL: got $tables $values in ns $ns , not 0 - not all expected packets marked" 1>&2 + ret=1 return 1 fi done
@@ -227,11 +228,11 @@ do_transfer() fi if [ $local_addr = "::" ];then - check_mark $listener_ns 6 - check_mark $connector_ns 6 + check_mark $listener_ns 6 || retc=1 + check_mark $connector_ns 6 || retc=1 else - check_mark $listener_ns 4 - check_mark $connector_ns 4 + check_mark $listener_ns 4 || retc=1 + check_mark $connector_ns 4 || retc=1 fi check_transfer $cin $sout "file received by server"
Greg Kroah-Hartman
maintainerPATCH 264/292 selftests: mptcp: userspace_pm: use correct server port
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit d8566d0e03922217f70d9be2d401fcb860986374 upstream.
"server4_port" variable is not set but "app4_port" is the server port in v4 and the correct variable name to use.
The port is optional so there was no visible impact.
--- tools/testing/selftests/net/mptcp/userspace_pm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/net/mptcp/userspace_pm.sh +1 -1
@@ -848,7 +848,7 @@ test_prio() local count # Send MP_PRIO signal from client to server machine - ip netns exec "$ns2" ./pm_nl_ctl set 10.0.1.2 port "$client4_port" flags backup token "$client4_token" rip 10.0.1.1 rport "$server4_port" + ip netns exec "$ns2" ./pm_nl_ctl set 10.0.1.2 port "$client4_port" flags backup token "$client4_token" rip 10.0.1.1 rport "$app4_port" sleep 0.5 # Check TX
Greg Kroah-Hartman
maintainerPATCH 265/292 selftests: mptcp: userspace_pm: report errors with remove tests
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit 966c6c3adfb1257ea8a839cdfad2b74092cc5532 upstream.
A message was mentioning an issue with the "remove" tests but the selftest was not marked as failed.
Directly exit with an error like it is done everywhere else in this selftest.
--- tools/testing/selftests/net/mptcp/userspace_pm.sh | 2 ++ 1 file changed, 2 insertions(+)
tools/testing/selftests/net/mptcp/userspace_pm.sh +2 -0
@@ -423,6 +423,7 @@ test_remove() stdbuf -o0 -e0 printf "[OK]\n" else stdbuf -o0 -e0 printf "[FAIL]\n" + exit 1 fi # RM_ADDR using an invalid addr id should result in no action
@@ -437,6 +438,7 @@ test_remove() stdbuf -o0 -e0 printf "[OK]\n" else stdbuf -o0 -e0 printf "[FAIL]\n" + exit 1 fi # RM_ADDR from the client to server machine
Greg Kroah-Hartman
maintainerPATCH 266/292 selftests: mptcp: depend on SYN_COOKIES
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit 6c8880fcaa5c45355179b759c1d11737775e31fc upstream.
MPTCP selftests are using TCP SYN Cookies for quite a while now, since v5.9.
Some CIs don't have this config option enabled and this is causing issues in the tests:
# ns1 MPTCP -> ns1 (10.0.1.1:10000 ) MPTCP (duration 167ms) sysctl: cannot stat /proc/sys/net/ipv4/tcp_syncookies: No such file or directory # [ OK ]./mptcp_connect.sh: line 554: [: -eq: unary operator expected
There is no impact in the results but the test is not doing what it is supposed to do.
--- tools/testing/selftests/net/mptcp/config | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/net/mptcp/config +1 -0
@@ -6,6 +6,7 @@ CONFIG_INET_DIAG=m CONFIG_INET_MPTCP_DIAG=m CONFIG_VETH=y CONFIG_NET_SCH_NETEM=m +CONFIG_SYN_COOKIES=y CONFIG_NETFILTER=y CONFIG_NETFILTER_ADVANCED=y CONFIG_NETFILTER_NETLINK=m
Greg Kroah-Hartman
maintainerPATCH 267/292 selftests: mptcp: pm_nl_ctl: fix 32-bit support
In reply to Greg Kroah-HartmanFrom: Matthieu Baerts <[email protected]>
commit 61d9658050260dbcbf9055479b7ac5bbbe1e8831 upstream.
When using pm_nl_ctl to validate userspace path-manager's behaviours, it was failing on 32-bit architectures ~half of the time.
pm_nl_ctl was not reporting any error but the command was not doing what it was expected to do. As a result, the expected linked event was not triggered after and the test failed.
This is due to the fact the token given in argument to the application was parsed as an integer with atoi(): in a 32-bit arch, if the number was bigger than INT_MAX, 2147483647 was used instead.
This can simply be fixed by using strtoul() instead of atoi().
The errors have been seen "by chance" when manually looking at the results from LKFT.
--- tools/testing/selftests/net/mptcp/pm_nl_ctl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
tools/testing/selftests/net/mptcp/pm_nl_ctl.c +5 -5
@@ -425,7 +425,7 @@ int dsf(int fd, int pm_family, int argc, }/* token */ - token =atoi (params[4 ]); + token =strtoul (params[4 ],NULL ,10 ); rta = (void *)(data + off); rta->rta_type =MPTCP_PM_ATTR_TOKEN ; rta->rta_len =RTA_LENGTH (4 );
@@ -551,7 +551,7 @@ int csf(int fd, int pm_family, int argc, }/* token */ - token =atoi (params[4 ]); + token =strtoul (params[4 ],NULL ,10 ); rta = (void *)(data + off); rta->rta_type =MPTCP_PM_ATTR_TOKEN ; rta->rta_len =RTA_LENGTH (4 );
@@ -598,7 +598,7 @@ int remove_addr(int fd, int pm_family, iif (++arg >= argc)error (1 ,0 ," missing token value" ); - token =atoi (argv[arg]); + token =strtoul (argv[arg],NULL ,10 ); rta = (void *)(data + off); rta->rta_type =MPTCP_PM_ATTR_TOKEN ; rta->rta_len =RTA_LENGTH (4 );
@@ -710,7 +710,7 @@ int announce_addr(int fd, int pm_family,if (++arg >= argc)error (1 ,0 ," missing token value" ); - token =atoi (argv[arg]); + token =strtoul (argv[arg],NULL ,10 ); }else error (1 ,0 ,"unknown keyword %s" , argv[arg]); }
@@ -1347,7 +1347,7 @@ int set_flags(int fd, int pm_family, interror (1 ,0 ," missing token value" );/* token */ - token =atoi (argv[arg]); + token =strtoul (argv[arg],NULL ,10 ); }else if (!strcmp (argv[arg],"flags" )) {char *tok, *str;
Greg Kroah-Hartman
maintainerPATCH 268/292 smb: client: Fix -Wstringop-overflow issues
In reply to Greg Kroah-HartmanFrom: Gustavo A. R. Silva <[email protected]>
commit f1f047bd7ce0d73788e04ac02268060a565f7ecb upstream.
pSMB->hdr.Protocol is an array of size 4 bytes, hence when the compiler analyzes this line of code
parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
it legitimately complains about the fact that offset points outside the bounds of the array. Notice that the compiler gives priority to the object as an array, rather than merely the address of one more byte in a structure to wich offset should be added (which seems to be the actual intention of the original implementation).
Fix this by explicitly instructing the compiler to treat the code as a sequence of bytes in struct smb_com_transaction2_spi_req, and not as an array accessed through pointer notation.
Notice that ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) points to the same address as ((char *) &pSMB->hdr.Protocol), therefore this results in no differences in binary output.
Fixes the following -Wstringop-overflow warnings when built s390 architecture with defconfig (GCC 13):
CC [M] fs/smb/client/cifssmb.o
In function 'cifs_init_ace',
inlined from 'posix_acl_to_cifs' at fs/smb/client/cifssmb.c:3046:3,
inlined from 'cifs_do_set_acl' at fs/smb/client/cifssmb.c:3191:15:
fs/smb/client/cifssmb.c:2987:31: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
2987 | cifs_ace->cifs_e_perm = local_ace->e_perm;
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
In file included from fs/smb/client/cifssmb.c:27:
fs/smb/client/cifspdu.h: In function 'cifs_do_set_acl':
fs/smb/client/cifspdu.h:384:14: note: at offset [7, 11] into destination object 'Protocol' of size 4
384 | __u8 Protocol[4];
| ^~~~~~~~
In function 'cifs_init_ace',
inlined from 'posix_acl_to_cifs' at fs/smb/client/cifssmb.c:3046:3,
inlined from 'cifs_do_set_acl' at fs/smb/client/cifssmb.c:3191:15:
fs/smb/client/cifssmb.c:2988:30: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
2988 | cifs_ace->cifs_e_tag = local_ace->e_tag;
| ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
fs/smb/client/cifspdu.h: In function 'cifs_do_set_acl':
fs/smb/client/cifspdu.h:384:14: note: at offset [6, 10] into destination object 'Protocol' of size 4
384 | __u8 Protocol[4];
| ^~~~~~~~This helps with the ongoing efforts to globally enable -Wstringop-overflow.
--- fs/smb/client/cifssmb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/client/cifssmb.c +1 -1
@@ -3184,7 +3184,7 @@ setAclRetry: param_offset = offsetof(struct smb_com_transaction2_spi_req , InformationLevel) -4 ; offset = param_offset + params; - parm_data = ((char *) &pSMB->hdr.Protocol) + offset; + parm_data = ((char *)pSMB) +sizeof (pSMB->hdr.smb_buf_length) + offset; pSMB->ParameterOffset =cpu_to_le16 (param_offset);/* convert to on the wire format for POSIX ACL */
Signature · 1 line
2.41.0
Greg Kroah-Hartman
maintainerPATCH 269/292 tracing/probes: Fix to avoid double count of the string length on the array
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
commit 66bcf65d6cf0ca6540e2341e88ee7ef02dbdda08 upstream.
If an array is specified with the ustring or symstr, the length of the strings are accumlated on both of 'ret' and 'total', which means the length is double counted.
Just set the length to the 'ret' value for avoiding double counting.
--- kernel/trace/trace_probe_tmpl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/trace_probe_tmpl.h +2 -2
@@ -156,11 +156,11 @@ stage3: code++; goto array;case FETCH_OP_ST_USTRING : - ret +=fetch_store_strlen_user (val + code->offset); + ret =fetch_store_strlen_user (val + code->offset); code++; goto array;case FETCH_OP_ST_SYMSTR : - ret +=fetch_store_symstrlen (val + code->offset); + ret =fetch_store_symstrlen (val + code->offset); code++; goto array;default :
Greg Kroah-Hartman
maintainerPATCH 270/292 tracing/probes: Fix not to count error code to total length
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
commit b41326b5e0f82e93592c4366359917b5d67b529f upstream.
Fix not to count the error code (which is minus value) to the total used length of array, because it can mess up the return code of process_fetch_insn_bottom(). Also clear the 'ret' value because it will be used for calculating next data_loc entry.
--- kernel/trace/trace_probe_tmpl.h | 2 ++ 1 file changed, 2 insertions(+)
kernel/trace/trace_probe_tmpl.h +2 -0
@@ -204,6 +204,8 @@ stage3: array:/* the last stage: Loop on array */ if (code->op ==FETCH_OP_LP_ARRAY ) { +if (ret <0 ) + ret =0 ; total += ret;if (++i < code->param) { code = s3;
Greg Kroah-Hartman
maintainerPATCH 271/292 tracing/probes: Fix to update dynamic data counter if fetcharg uses it
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
commit e38e2c6a9efc435f9de344b7c91f7697e01b47d5 upstream.
Fix to update dynamic data counter ('dyndata') and max length ('maxlen') only if the fetcharg uses the dynamic data. Also get out arg->dynamic from unlikely(). This makes dynamic data address wrong if process_fetch_insn() returns error on !arg->dynamic case.
--- kernel/trace/trace_probe_tmpl.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
kernel/trace/trace_probe_tmpl.h +7 -5
@@ -267,11 +267,13 @@ store_trace_args(void *data, struct tracif (unlikely (arg->dynamic)) *dl =make_data_loc (maxlen, dyndata - base); ret =process_fetch_insn (arg->code, rec, dl, base); -if (unlikely (ret <0 && arg->dynamic)) { - *dl =make_data_loc (0 , dyndata - base); - }else { - dyndata += ret; - maxlen -= ret; +if (arg->dynamic) { +if (unlikely (ret <0 )) { + *dl =make_data_loc (0 , dyndata - base); + }else { + dyndata += ret; + maxlen -= ret; + } } } }
Greg Kroah-Hartman
maintainerPATCH 272/292 Revert "tracing: Add "(fault)" name injection to kernel probes"
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
commit 4ed8f337dee32df71435689c19d22e4ee846e15a upstream.
This reverts commit 2e9906f84fc7c99388bb7123ade167250d50f1c0.
It was turned out that commit 2e9906f84fc7 ("tracing: Add "(fault)" name injection to kernel probes") did not work correctly and probe events still show just '(fault)' (instead of '"(fault)"'). Also, current '(fault)' is more explicit that it faulted.
This also moves FAULT_STRING macro to trace.h so that synthetic event can keep using it, and uses it in trace_probe.c too.
--- kernel/trace/trace.h | 2 ++ kernel/trace/trace_probe.c | 2 +- kernel/trace/trace_probe_kernel.h | 31 ++++++------------------------- 3 files changed, 9 insertions(+), 26 deletions(-)
kernel/trace/trace.h +2 -0
@@ -113,6 +113,8 @@ enum trace_type {#define MEM_FAIL (condition, fmt, ...) \ DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__) +#define FAULT_STRING "(fault)" +#define HIST_STACKTRACE_DEPTH 16#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long))#define HIST_STACKTRACE_SKIP 5
kernel/trace/trace_probe.c +1 -1
@@ -65,7 +65,7 @@ int PRINT_TYPE_FUNC_NAME(string)(structint len = *(u32 *)data >>16 ;if (!len) -trace_seq_puts (s,"(fault)" ); +trace_seq_puts (s,FAULT_STRING );else trace_seq_printf (s,"\"%s\"" , (const char *)get_loc_data (data, ent));
kernel/trace/trace_probe_kernel.h +6 -25
@@ -2,8 +2,6 @@#ifndef __TRACE_PROBE_KERNEL_H_#define __TRACE_PROBE_KERNEL_H_ -#define FAULT_STRING "(fault)" -/* * This depends on trace_probe.h, but can not include it due to * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c.
@@ -15,16 +13,8 @@ static nokprobe_inline int fetch_store_strlen_user(unsigned long addr) {const void __user *uaddr = (__force const void __user *)addr; -int ret; - ret =strnlen_user_nofault (uaddr,MAX_STRING_SIZE ); -/* -* strnlen_user_nofault returns zero on fault, insert the -* FAULT_STRING when that occurs. -*/ -if (ret <=0 ) -return strlen (FAULT_STRING ) +1 ; -return ret; +return strnlen_user_nofault (uaddr,MAX_STRING_SIZE ); }/* Return the length of string -- including null terminal byte */
@@ -44,18 +34,7 @@ fetch_store_strlen(unsigned long addr) len++; }while (c && ret ==0 && len <MAX_STRING_SIZE ); -/* For faults, return enough to hold the FAULT_STRING */ -return (ret <0 ) ?strlen (FAULT_STRING ) +1 : len; -} - -static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len) -{ -if (ret >=0 ) { - *(u32 *)dest =make_data_loc (ret, __dest - base); - }else { -strscpy (__dest,FAULT_STRING , len); - ret =strlen (__dest) +1 ; - } +return (ret <0 ) ? ret : len; }/*
@@ -76,7 +55,8 @@ fetch_store_string_user(unsigned long ad __dest =get_loc_data (dest, base); ret =strncpy_from_user_nofault (__dest, uaddr, maxlen); -set_data_loc (ret, dest, __dest, base, maxlen); +if (ret >=0 ) + *(u32 *)dest =make_data_loc (ret, __dest - base);return ret; }
@@ -107,7 +87,8 @@ fetch_store_string(unsigned long addr, v* probing. */ ret =strncpy_from_kernel_nofault (__dest, (void *)addr, maxlen); -set_data_loc (ret, dest, __dest, base, maxlen); +if (ret >=0 ) + *(u32 *)dest =make_data_loc (ret, __dest - base);return ret; }
Greg Kroah-Hartman
maintainerPATCH 273/292 tracing/probes: Fix to record 0-length data_loc in fetch_store_string*() if fails
In reply to Greg Kroah-HartmanFrom: Masami Hiramatsu (Google) <[email protected]>
commit 797311bce5c2ac90b8d65e357603cfd410d36ebb upstream.
Fix to record 0-length data to data_loc in fetch_store_string*() if it fails to get the string data.
Currently those expect that the data_loc is updated by store_trace_args() if it returns the error code. However, that does not work correctly if the argument is an array of strings. In that case, store_trace_args() only clears the first entry of the array (which may have no error) and leaves other entries. So it should be cleared by fetch_store_string*() itself. Also, 'dyndata' and 'maxlen' in store_trace_args() should be updated only if it is used (ret > 0 and argument is a dynamic data.)
--- kernel/trace/trace_probe_kernel.h | 13 +++++++++---- kernel/trace/trace_probe_tmpl.h | 10 +++------- kernel/trace/trace_uprobe.c | 3 ++- 3 files changed, 14 insertions(+), 12 deletions(-)
kernel/trace/trace_probe_kernel.h +9 -4
@@ -37,6 +37,13 @@ fetch_store_strlen(unsigned long addr)return (ret <0 ) ? ret : len; } +static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base) +{ +if (ret <0 ) + ret =0 ; + *(u32 *)dest =make_data_loc (ret, __dest - base); +} +/* * Fetch a null-terminated string from user. Caller MUST set *(u32 *)buf * with max length and relative data location.
@@ -55,8 +62,7 @@ fetch_store_string_user(unsigned long ad __dest =get_loc_data (dest, base); ret =strncpy_from_user_nofault (__dest, uaddr, maxlen); -if (ret >=0 ) - *(u32 *)dest =make_data_loc (ret, __dest - base); +set_data_loc (ret, dest, __dest, base);return ret; }
@@ -87,8 +93,7 @@ fetch_store_string(unsigned long addr, v* probing. */ ret =strncpy_from_kernel_nofault (__dest, (void *)addr, maxlen); -if (ret >=0 ) - *(u32 *)dest =make_data_loc (ret, __dest - base); +set_data_loc (ret, dest, __dest, base);return ret; }
kernel/trace/trace_probe_tmpl.h +3 -7
@@ -267,13 +267,9 @@ store_trace_args(void *data, struct tracif (unlikely (arg->dynamic)) *dl =make_data_loc (maxlen, dyndata - base); ret =process_fetch_insn (arg->code, rec, dl, base); -if (arg->dynamic) { -if (unlikely (ret <0 )) { - *dl =make_data_loc (0 , dyndata - base); - }else { - dyndata += ret; - maxlen -= ret; - } +if (arg->dynamic &&likely (ret >0 )) { + dyndata += ret; + maxlen -= ret; } } }
kernel/trace/trace_uprobe.c +2 -1
@@ -170,7 +170,8 @@ fetch_store_string(unsigned long addr, v*/ ret++; *(u32 *)dest =make_data_loc (ret, (void *)dst - base); - } + }else + *(u32 *)dest =make_data_loc (0 , (void *)dst - base);return ret; }
Greg Kroah-Hartman
maintainerPATCH 274/292 tracing/user_events: Fix struct arg size match check
In reply to Greg Kroah-HartmanFrom: Beau Belgrave <[email protected]>
commit d0a3022f30629a208e5944022caeca3568add9e7 upstream.
When users register an event the name of the event and it's argument are checked to ensure they match if the event already exists. Normally all arguments are in the form of "type name", except for when the type starts with "struct ". In those cases, the size of the struct is passed in addition to the name, IE: "struct my_struct a 20" for an argument that is of type "struct my_struct" with a field name of "a" and has the size of 20 bytes.
The current code does not honor the above case properly when comparing a match. This causes the event register to fail even when the same string was used for events that contain a struct argument within them. The example above "struct my_struct a 20" generates a match string of "struct my_struct a" omitting the size field.
Add the struct size of the existing field when generating a comparison string for a struct field to ensure proper match checking.
--- kernel/trace/trace_events_user.c | 3 +++ 1 file changed, 3 insertions(+)
kernel/trace/trace_events_user.c +3 -0
@@ -1317,6 +1317,9 @@ static int user_field_set_string(struct pos +=snprintf (buf + pos,LEN_OR_ZERO ," " ); pos +=snprintf (buf + pos,LEN_OR_ZERO ,"%s" , field->name); +if (str_has_prefix (field->type,"struct " )) + pos +=snprintf (buf + pos,LEN_OR_ZERO ," %d" , field->size); +if (colon) pos +=snprintf (buf + pos,LEN_OR_ZERO ,";" );
Greg Kroah-Hartman
maintainerPATCH 275/292 scsi: qla2xxx: Multi-que support for TMF
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit d90171dd0da50212f5950cc708240831e82f2f91 upstream.
Add queue flush for task management command, before placing it on the wire.
Do IO flush for all Request Q's.
--- drivers/scsi/qla2xxx/qla_def.h | 8 ++++ drivers/scsi/qla2xxx/qla_gbl.h | 2 - drivers/scsi/qla2xxx/qla_init.c | 69 +++++++++++++++++++++++++++++++--------- drivers/scsi/qla2xxx/qla_iocb.c | 5 +- 4 files changed, 66 insertions(+), 18 deletions(-)
drivers/scsi/qla2xxx/qla_def.h +8 -0
@@ -465,6 +465,14 @@ static inline be_id_t port_id_to_be_id(preturn res; } +struct tmf_arg { +struct qla_qpair *qpair; +struct fc_port *fcport; +struct scsi_qla_host *vha; +u64 lun; +u32 flags; +}; +struct els_logo_payload {uint8_t opcode;uint8_t rsvd[3 ];
drivers/scsi/qla2xxx/qla_gbl.h +1 -1
@@ -69,7 +69,7 @@ extern int qla2x00_async_logout(struct sextern int qla2x00_async_prlo (struct scsi_qla_host *,fc_port_t *);extern int qla2x00_async_adisc (struct scsi_qla_host *,fc_port_t *,uint16_t *); -extern int qla2x00_async_tm_cmd (fc_port_t *,uint32_t ,uint32_t ,uint32_t ); +extern int qla2x00_async_tm_cmd (fc_port_t *,uint32_t ,uint64_t ,uint32_t );struct qla_work_evt *qla2x00_alloc_work (struct scsi_qla_host *,enum qla_work_type );extern int qla24xx_async_gnl (struct scsi_qla_host *,fc_port_t *);
drivers/scsi/qla2xxx/qla_init.c +54 -15
104 lines not on this page · raw message
drivers/scsi/qla2xxx/qla_iocb.c +3 -2
@@ -2541,7 +2541,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgscsi_qla_host_t *vha = fcport->vha;struct qla_hw_data *ha = vha->hw;struct srb_iocb *iocb = &sp->u.iocb_cmd; -struct req_que *req = vha->req; +struct req_que *req = sp->qpair->req; flags = iocb->u.tmf.flags; lun = iocb->u.tmf.lun;
@@ -2557,7 +2557,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mg tsk->port_id[2 ] = fcport->d_id.b.domain; tsk->vp_index = fcport->vha->vp_idx; -if (flags ==TCF_LUN_RESET ) { +if (flags & (TCF_LUN_RESET |TCF_ABORT_TASK_SET | +TCF_CLEAR_TASK_SET |TCF_CLEAR_ACA )) {int_to_scsilun (lun, &tsk->lun);host_to_fcp_swap ((uint8_t *)&tsk->lun,sizeof (tsk->lun));
Greg Kroah-Hartman
maintainerPATCH 276/292 scsi: qla2xxx: Fix task management cmd failure
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 9803fb5d27597ea98f2e05b0b6cfc48ae808458e upstream.
Task management cmd failed with status 30h which means FW is not able to finish processing one task management before another task management for the same lun. Hence add wait for completion of marker to space it out.
--- drivers/scsi/qla2xxx/qla_def.h | 6 ++ drivers/scsi/qla2xxx/qla_init.c | 102 +++++++++++++++++++++++++++++++++------- drivers/scsi/qla2xxx/qla_iocb.c | 28 +++++++++- drivers/scsi/qla2xxx/qla_isr.c | 26 +++++++++- 4 files changed, 139 insertions(+), 23 deletions(-)
drivers/scsi/qla2xxx/qla_def.h +6 -0
@@ -471,6 +471,7 @@ struct tmf_arg {struct scsi_qla_host *vha;u64 lun;u32 flags; +uint8_t modifier; };struct els_logo_payload {
@@ -552,6 +553,10 @@ struct srb_iocb {uint32_t data;struct completion comp;__le16 comp_status; + +uint8_t modifier; +uint8_t vp_index; +uint16_t loop_id; } tmf;struct {#define SRB_FXDISC_REQ_DMA_VALID BIT_0
@@ -655,6 +660,7 @@ struct srb_iocb {#define SRB_SA_UPDATE 25#define SRB_ELS_CMD_HST_NOLOGIN 26#define SRB_SA_REPLACE 27 +#define SRB_MARKER 28struct qla_els_pt_arg {u8 els_opcode;
drivers/scsi/qla2xxx/qla_init.c +86 -16
133 lines not on this page · raw message
drivers/scsi/qla2xxx/qla_iocb.c +24 -4
@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vreturn (QLA_FUNCTION_FAILED ); } + mrk24 = (struct mrk_entry_24xx *)mrk; + mrk->entry_type =MARKER_TYPE ; mrk->modifier = type;if (type !=MK_SYNC_ALL ) {if (IS_FWI2_CAPABLE (ha)) { - mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle =cpu_to_le16 (loop_id);int_to_scsilun (lun, (struct scsi_lun *)&mrk24->lun);host_to_fcp_swap (mrk24->lun,sizeof (mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle =make_handle (req->id, mrk24->handle); }else {SET_TARGET_ID (ha, mrk->target, loop_id); mrk->lun =cpu_to_le16 ((uint16_t )lun); } } + +if (IS_FWI2_CAPABLE (ha)) + mrk24->handle =QLA_SKIP_HANDLE ; +wmb ();qla2x00_start_iocbs (vha, req);
@@ -3853,9 +3857,9 @@ static int qla_get_iocbs_resource(structcase SRB_NACK_LOGO :case SRB_LOGOUT_CMD :case SRB_CTRL_VP : - push_it_through = true; - fallthrough; +case SRB_MARKER :default : + push_it_through = true; get_exch = false; }
@@ -3871,6 +3875,19 @@ static int qla_get_iocbs_resource(structreturn qla_get_fw_resources (sp->qpair, &sp->iores); } +static void +qla_marker_iocb (srb_t *sp,struct mrk_entry_24xx *mrk) +{ + mrk->entry_type =MARKER_TYPE ; + mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier; +if (sp->u.iocb_cmd.u.tmf.modifier !=MK_SYNC_ALL ) { + mrk->nport_handle =cpu_to_le16 (sp->u.iocb_cmd.u.tmf.loop_id); +int_to_scsilun (sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun); +host_to_fcp_swap (mrk->lun,sizeof (mrk->lun)); + mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index; + } +} +int qla2x00_start_sp (srb_t *sp) {
@@ -3974,6 +3991,9 @@ qla2x00_start_sp(srb_t *sp)case SRB_SA_REPLACE :qla24xx_sa_replace_iocb (sp, pkt);break ; +case SRB_MARKER : +qla_marker_iocb (sp, pkt); +break ;default :break ; }
drivers/scsi/qla2xxx/qla_isr.c +23 -3
@@ -3750,6 +3750,28 @@ static int qla_chk_cont_iocb_avail(strucreturn rc; } +static void qla_marker_iocb_entry (scsi_qla_host_t *vha,struct req_que *req, +struct mrk_entry_24xx *pkt) +{ +const char func[] ="MRK-IOCB" ; +srb_t *sp; +int res =QLA_SUCCESS ; + +if (!IS_FWI2_CAPABLE (vha->hw)) +return ; + + sp =qla2x00_get_sp_from_handle (vha, func, req, pkt); +if (!sp) +return ; + +if (pkt->entry_status) { +ql_dbg (ql_dbg_taskm, vha,0x8025 ,"marker failure.\n" ); + res =QLA_COMMAND_ERROR ; + } + sp->u.iocb_cmd.u.tmf.data = res; + sp->done (sp, res); +} +/** * qla24xx_process_response_queue() - Process response queue entries. * @vha: SCSI driver HA context
@@ -3866,9 +3888,7 @@ process_err: (struct nack_to_isp *)pkt);break ;case MARKER_TYPE : -/* Do nothing in this case, this check is to prevent it -* from falling into default case -*/ +qla_marker_iocb_entry (vha, rsp->req, (struct mrk_entry_24xx *)pkt);break ;case ABORT_IOCB_TYPE : qla24xx_abort_iocb_entry(vha, rsp->req,
Greg Kroah-Hartman
maintainerPATCH 277/292 scsi: qla2xxx: Fix task management cmd fail due to unavailable resource
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 6a87679626b51b53fbb6be417ad8eb083030b617 upstream.
Task management command failed with status 2Ch which is a result of too many task management commands sent to the same target. Hence limit task management commands to 8 per target.
--- drivers/scsi/qla2xxx/qla_def.h | 3 + drivers/scsi/qla2xxx/qla_init.c | 63 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 5 deletions(-)
drivers/scsi/qla2xxx/qla_def.h +3 -0
@@ -2542,6 +2542,7 @@ enum rscn_addr_format { typedef struct fc_port { struct list_head list; struct scsi_qla_host *vha; + struct list_head tmf_pending; unsigned int conf_compl_supported:1; unsigned int deleted:2;
@@ -2562,6 +2563,8 @@ typedef struct fc_port { unsigned int do_prli_nvme:1;uint8_t nvme_flag; +uint8_t active_tmf; +#define MAX_ACTIVE_TMF 8uint8_t node_name[WWN_SIZE ];uint8_t port_name[WWN_SIZE ];
drivers/scsi/qla2xxx/qla_init.c +58 -5
94 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 278/292 scsi: qla2xxx: Fix hang in task management
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit 9ae615c5bfd37bd091772969b1153de5335ea986 upstream.
Task management command hangs where a side
band chip reset failed to nudge the TMF
from it's current send path.
Add additional error check to block TMF
from entering during chip reset and along
the TMF path to cause it to bail out, skip
over abort of marker.
--- drivers/scsi/qla2xxx/qla_def.h | 4 ++ drivers/scsi/qla2xxx/qla_init.c | 60 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-)
drivers/scsi/qla2xxx/qla_def.h +4 -0
@@ -5516,4 +5516,8 @@ struct ql_vnd_tgt_stats_resp { _fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \ _fp->flags +#define TMF_NOT_READY (_fcport) \ + (!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \ + !_fcport->vha->hw->flags.fw_started) +#endif
drivers/scsi/qla2xxx/qla_init.c +57 -3
134 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 279/292 scsi: qla2xxx: Wait for io return on terminate rport
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit fc0cba0c7be8261a1625098bd1d695077ec621c9 upstream.
System crash due to use after free.
Current code allows terminate_rport_io to exit before making sure all IOs has returned. For FCP-2 device, IO's can hang on in HW because driver has not tear down the session in FW at first sign of cable pull. When dev_loss_tmo timer pops, terminate_rport_io is called and upper layer is about to free various resources. Terminate_rport_io trigger qla to do the final cleanup, but the cleanup might not be fast enough where it leave qla still holding on to the same resource.
Wait for IO's to return to upper layer before resources are freed.
--- drivers/scsi/qla2xxx/qla_attr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/scsi/qla2xxx/qla_attr.c +13 -0
@@ -2750,6 +2750,7 @@ static void qla2x00_terminate_rport_io(struct fc_rport *rport) {fc_port_t *fcport = *(fc_port_t **)rport->dd_data; +scsi_qla_host_t *vha;if (!fcport)return ;
@@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rpoif (test_bit (ABORT_ISP_ACTIVE , &fcport->vha->dpc_flags))return ; + vha = fcport->vha;if (unlikely (pci_channel_offline (fcport->vha->hw->pdev))) {qla2x00_abort_all_cmds (fcport->vha,DID_NO_CONNECT <<16 ); +qla2x00_eh_wait_for_pending_commands (fcport->vha, fcport->d_id.b24, +0 ,WAIT_TARGET );return ; }/*
@@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rpoqla2x00_port_logout (fcport->vha, fcport); } } + +/* check for any straggling io left behind */ +if (qla2x00_eh_wait_for_pending_commands (fcport->vha, fcport->d_id.b24,0 ,WAIT_TARGET )) { +ql_log (ql_log_warn, vha,0x300b , +"IO not return. Resetting. \n" ); +set_bit (ISP_ABORT_NEEDED , &vha->dpc_flags); +qla2xxx_wake_dpc (vha); +qla2x00_wait_for_chip_reset (vha); + } } static int
Greg Kroah-Hartman
maintainerPATCH 280/292 scsi: qla2xxx: Fix mem access after free
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit b843adde8d490934d042fbe9e3e46697cb3a64d2 upstream.
System crash, where driver is accessing scsi layer's memory (scsi_cmnd->device->host) to search for a well known internal pointer (vha). The scsi_cmnd was released back to upper layer which could be freed, but the driver is still accessing it.
7 [ffffa8e8d2c3f8d0] page_fault at ffffffff86c010fe
[exception RIP: __qla2x00_eh_wait_for_pending_commands+240]
RIP: ffffffffc0642350 RSP: ffffa8e8d2c3f988 RFLAGS: 00010286 RAX: 0000000000000165 RBX: 0000000000000002 RCX: 00000000000036d8 RDX: 0000000000000000 RSI: ffff9c5c56535188 RDI: 0000000000000286 RBP: ffff9c5bf7aa4a58 R8: ffff9c589aecdb70 R9: 00000000000003d1 R10: 0000000000000001 R11: 0000000000380000 R12: ffff9c5c5392bc78 R13: ffff9c57044ff5c0 R14: ffff9c56b5a3aa00 R15: 00000000000006db ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
8 [ffffa8e8d2c3f9c8] qla2x00_eh_wait_for_pending_commands at ffffffffc0646dd5 [qla2xxx] 9 [ffffa8e8d2c3fa00] __qla2x00_async_tm_cmd at ffffffffc0658094 [qla2xxx]
Remove access of freed memory. Currently the driver was checking to see if scsi_done was called by seeing if the sp->type has changed. Instead, check to see if the command has left the oustanding_cmds[] array as sign of scsi_done was called.
--- drivers/scsi/qla2xxx/qla_isr.c | 38 +++++++++-- drivers/scsi/qla2xxx/qla_os.c | 130 ++++++++++++++++++++--------------------- 2 files changed, 95 insertions(+), 73 deletions(-)
drivers/scsi/qla2xxx/qla_isr.c +31 -7
@@ -1862,9 +1862,9 @@ qla2x00_process_completed_request(struct } } -srb_t * -qla2x00_get_sp_from_handle (scsi_qla_host_t *vha,const char *func, -struct req_que *req,void *iocb) +static srb_t * +qla_get_sp_from_handle (scsi_qla_host_t *vha,const char *func, +struct req_que *req,void *iocb,u16 *ret_index) {struct qla_hw_data *ha = vha->hw;sts_entry_t *pkt = iocb;
@@ -1899,12 +1899,25 @@ qla2x00_get_sp_from_handle(scsi_qla_hostreturn NULL ; } - req->outstanding_cmds[index] =NULL ; - + *ret_index = index;qla_put_fw_resources (sp->qpair, &sp->iores);return sp; } +srb_t * +qla2x00_get_sp_from_handle (scsi_qla_host_t *vha,const char *func, +struct req_que *req,void *iocb) +{ +uint16_t index; +srb_t *sp; + + sp =qla_get_sp_from_handle (vha, func, req, iocb, &index); +if (sp) + req->outstanding_cmds[index] =NULL ; + +return sp; +} +static void qla2x00_mbx_iocb_entry (scsi_qla_host_t *vha,struct req_que *req,struct mbx_entry *mbx)
@@ -3237,13 +3250,13 @@ qla2x00_status_entry(scsi_qla_host_t *vhreturn ; } - req->outstanding_cmds[handle] =NULL ; cp =GET_CMD_SP (sp);if (cp ==NULL ) {ql_dbg (ql_dbg_io, vha,0x3018 ,"Command already returned (0x%x/%p).\n" , sts->handle, sp); + req->outstanding_cmds[handle] =NULL ;return ; }
@@ -3514,6 +3527,9 @@ out:if (rsp->status_srb ==NULL ) sp->done (sp, res); + +/* for io's, clearing of outstanding_cmds[handle] means scsi_done was called */ + req->outstanding_cmds[handle] =NULL ; }/**
@@ -3590,6 +3606,7 @@ qla2x00_error_entry(scsi_qla_host_t *vhauint16_t que =MSW (pkt->handle);struct req_que *req =NULL ;int res =DID_ERROR <<16 ; +u16 index; ql_dbg(ql_dbg_async, vha, 0x502a, "iocb type %xh with error status %xh, handle %xh, rspq id %d\n",
@@ -3608,7 +3625,6 @@ qla2x00_error_entry(scsi_qla_host_t *vhaswitch (pkt->entry_type) {case NOTIFY_ACK_TYPE : -case STATUS_TYPE :case STATUS_CONT_TYPE :case LOGINOUT_PORT_IOCB_TYPE :case CT_IOCB_TYPE :
@@ -3628,6 +3644,14 @@ qla2x00_error_entry(scsi_qla_host_t *vhacase CTIO_TYPE7 :case CTIO_CRC2 :return 1 ; +case STATUS_TYPE : + sp =qla_get_sp_from_handle (vha, func, req, pkt, &index); +if (sp) { + sp->done (sp, res); + req->outstanding_cmds[index] =NULL ; +return 0 ; + } +break ; } fatal: ql_log(ql_log_warn, vha, 0x5030,
drivers/scsi/qla2xxx/qla_os.c +64 -66
154 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 281/292 scsi: qla2xxx: Array index may go out of bound
In reply to Greg Kroah-HartmanFrom: Nilesh Javali <[email protected]>
commit d721b591b95cf3f290f8a7cbe90aa2ee0368388d upstream.
Klocwork reports array 'vha->host_str' of size 16 may use index value(s) 16..19. Use snprintf() instead of sprintf().
--- drivers/scsi/qla2xxx/qla_os.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_os.c +2 -1
@@ -5088,7 +5088,8 @@ struct scsi_qla_host *qla2x00_create_hos }INIT_DELAYED_WORK (&vha->scan.scan_work, qla_scan_work_fn); -sprintf (vha->host_str,"%s_%lu" ,QLA2XXX_DRIVER_NAME , vha->host_no); +snprintf (vha->host_str,sizeof (vha->host_str),"%s_%lu" , +QLA2XXX_DRIVER_NAME , vha->host_no); ql_dbg(ql_dbg_init, vha, 0x0041, "Allocated the host=%p hw=%p vha=%p dev_name=%s", vha->host, vha->hw, vha,
Greg Kroah-Hartman
maintainerPATCH 282/292 scsi: qla2xxx: Avoid fcport pointer dereference
In reply to Greg Kroah-HartmanFrom: Nilesh Javali <[email protected]>
commit 6b504d06976fe4a61cc05dedc68b84fadb397f77 upstream.
Klocwork reported warning of NULL pointer may be dereferenced. The routine exits when sa_ctl is NULL and fcport is allocated after the exit call thus causing NULL fcport pointer to dereference at the time of exit.
To avoid fcport pointer dereference, exit the routine when sa_ctl is NULL.
--- drivers/scsi/qla2xxx/qla_edif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/qla2xxx/qla_edif.c +2 -2
@@ -2361,8 +2361,8 @@ qla24xx_issue_sa_replace_iocb(scsi_qla_hif (!sa_ctl) {ql_dbg (ql_dbg_edif, vha,0x70e6 ,"sa_ctl allocation failed\n" ); - rval = -ENOMEM ; - goto done; + rval = -ENOMEM ; +return rval; } fcport = sa_ctl->fcport;
Greg Kroah-Hartman
maintainerPATCH 283/292 scsi: qla2xxx: Fix buffer overrun
In reply to Greg Kroah-HartmanFrom: Quinn Tran <[email protected]>
commit b68710a8094fdffe8dd4f7a82c82649f479bb453 upstream.
Klocwork warning: Buffer Overflow - Array Index Out of Bounds
Driver uses fc_els_flogi to calculate size of buffer. The actual buffer is nested inside of fc_els_flogi which is smaller.
Replace structure name to allow proper size calculation.
--- drivers/scsi/qla2xxx/qla_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_init.c +1 -1
@@ -5549,7 +5549,7 @@ static void qla_get_login_template(scsi___be32 *q;memset (ha->init_cb,0 , ha->init_cb_size); - sz =min_t (int,sizeof (struct fc_els_flogi ), ha->init_cb_size); + sz =min_t (int,sizeof (struct fc_els_csp ), ha->init_cb_size); rval =qla24xx_get_port_login_templ (vha, ha->init_cb_dma, ha->init_cb, sz);if (rval !=QLA_SUCCESS ) {