]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.3-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Nov 2019 16:29:48 +0000 (17:29 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 8 Nov 2019 16:29:48 +0000 (17:29 +0100)
added patches:
arm64-dts-ti-k3-am65-main-fix-gic-its-node-unit-address.patch
asoc-pcm3168a-the-codec-does-not-support-s32_le.patch
cifs-fix-retry-mid-list-corruption-on-reconnects.patch
selftests-powerpc-add-test-case-for-tlbie-vs-mtpidr-ordering-issue.patch
selftests-powerpc-fix-compile-error-on-tlbie_test-due-to-newer-gcc.patch
usb-gadget-udc-core-fix-segfault-if-udc_bind_to_driver-for-pending-driver-fails.patch

queue-5.3/arm64-dts-ti-k3-am65-main-fix-gic-its-node-unit-address.patch [new file with mode: 0644]
queue-5.3/asoc-pcm3168a-the-codec-does-not-support-s32_le.patch [new file with mode: 0644]
queue-5.3/cifs-fix-retry-mid-list-corruption-on-reconnects.patch [new file with mode: 0644]
queue-5.3/selftests-powerpc-add-test-case-for-tlbie-vs-mtpidr-ordering-issue.patch [new file with mode: 0644]
queue-5.3/selftests-powerpc-fix-compile-error-on-tlbie_test-due-to-newer-gcc.patch [new file with mode: 0644]
queue-5.3/series
queue-5.3/usb-gadget-udc-core-fix-segfault-if-udc_bind_to_driver-for-pending-driver-fails.patch [new file with mode: 0644]

diff --git a/queue-5.3/arm64-dts-ti-k3-am65-main-fix-gic-its-node-unit-address.patch b/queue-5.3/arm64-dts-ti-k3-am65-main-fix-gic-its-node-unit-address.patch
new file mode 100644 (file)
index 0000000..cdaba14
--- /dev/null
@@ -0,0 +1,34 @@
+From 389ce1a7c5279ebfb682fab220b4021b2bd49c8b Mon Sep 17 00:00:00 2001
+From: Suman Anna <s-anna@ti.com>
+Date: Thu, 8 Aug 2019 09:39:28 -0500
+Subject: arm64: dts: ti: k3-am65-main: Fix gic-its node unit-address
+
+From: Suman Anna <s-anna@ti.com>
+
+commit 389ce1a7c5279ebfb682fab220b4021b2bd49c8b upstream.
+
+The gic-its node unit-address has an additional zero compared
+to the actual reg value. Fix it.
+
+Fixes: ea47eed33a3f ("arm64: dts: ti: Add Support for AM654 SoC")
+Reported-by: Robert Tivy <rtivy@ti.com>
+Signed-off-by: Suman Anna <s-anna@ti.com>
+Signed-off-by: Tero Kristo <t-kristo@ti.com>
+Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/boot/dts/ti/k3-am65-main.dtsi |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+@@ -42,7 +42,7 @@
+                */
+               interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+-              gic_its: gic-its@18200000 {
++              gic_its: gic-its@1820000 {
+                       compatible = "arm,gic-v3-its";
+                       reg = <0x00 0x01820000 0x00 0x10000>;
+                       socionext,synquacer-pre-its = <0x1000000 0x400000>;
diff --git a/queue-5.3/asoc-pcm3168a-the-codec-does-not-support-s32_le.patch b/queue-5.3/asoc-pcm3168a-the-codec-does-not-support-s32_le.patch
new file mode 100644 (file)
index 0000000..94b820c
--- /dev/null
@@ -0,0 +1,36 @@
+From 7b2db65b59c30d58c129d3c8b2101feca686155a Mon Sep 17 00:00:00 2001
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Date: Thu, 19 Sep 2019 10:16:52 +0300
+Subject: ASoC: pcm3168a: The codec does not support S32_LE
+
+From: Peter Ujfalusi <peter.ujfalusi@ti.com>
+
+commit 7b2db65b59c30d58c129d3c8b2101feca686155a upstream.
+
+24 bits is supported in all modes and 16 bit only when the codec is slave
+and the DAI is set to RIGHT_J.
+
+Remove the unsupported sample format.
+
+Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
+Link: https://lore.kernel.org/r/20190919071652.31724-1-peter.ujfalusi@ti.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/codecs/pcm3168a.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/sound/soc/codecs/pcm3168a.c
++++ b/sound/soc/codecs/pcm3168a.c
+@@ -21,8 +21,7 @@
+ #define PCM3168A_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+                        SNDRV_PCM_FMTBIT_S24_3LE | \
+-                       SNDRV_PCM_FMTBIT_S24_LE | \
+-                       SNDRV_PCM_FMTBIT_S32_LE)
++                       SNDRV_PCM_FMTBIT_S24_LE)
+ #define PCM3168A_FMT_I2S              0x0
+ #define PCM3168A_FMT_LEFT_J           0x1
diff --git a/queue-5.3/cifs-fix-retry-mid-list-corruption-on-reconnects.patch b/queue-5.3/cifs-fix-retry-mid-list-corruption-on-reconnects.patch
new file mode 100644 (file)
index 0000000..491756b
--- /dev/null
@@ -0,0 +1,187 @@
+From abe57073d08c13b95a46ccf48cc9dc957d5c6fdb Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Tue, 22 Oct 2019 08:41:42 -0700
+Subject: CIFS: Fix retry mid list corruption on reconnects
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit abe57073d08c13b95a46ccf48cc9dc957d5c6fdb upstream.
+
+When the client hits reconnect it iterates over the mid
+pending queue marking entries for retry and moving them
+to a temporary list to issue callbacks later without holding
+GlobalMid_Lock. In the same time there is no guarantee that
+mids can't be removed from the temporary list or even
+freed completely by another thread. It may cause a temporary
+list corruption:
+
+[  430.454897] list_del corruption. prev->next should be ffff98d3a8f316c0, but was 2e885cb266355469
+[  430.464668] ------------[ cut here ]------------
+[  430.466569] kernel BUG at lib/list_debug.c:51!
+[  430.468476] invalid opcode: 0000 [#1] SMP PTI
+[  430.470286] CPU: 0 PID: 13267 Comm: cifsd Kdump: loaded Not tainted 5.4.0-rc3+ #19
+[  430.473472] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
+[  430.475872] RIP: 0010:__list_del_entry_valid.cold+0x31/0x55
+...
+[  430.510426] Call Trace:
+[  430.511500]  cifs_reconnect+0x25e/0x610 [cifs]
+[  430.513350]  cifs_readv_from_socket+0x220/0x250 [cifs]
+[  430.515464]  cifs_read_from_socket+0x4a/0x70 [cifs]
+[  430.517452]  ? try_to_wake_up+0x212/0x650
+[  430.519122]  ? cifs_small_buf_get+0x16/0x30 [cifs]
+[  430.521086]  ? allocate_buffers+0x66/0x120 [cifs]
+[  430.523019]  cifs_demultiplex_thread+0xdc/0xc30 [cifs]
+[  430.525116]  kthread+0xfb/0x130
+[  430.526421]  ? cifs_handle_standard+0x190/0x190 [cifs]
+[  430.528514]  ? kthread_park+0x90/0x90
+[  430.530019]  ret_from_fork+0x35/0x40
+
+Fix this by obtaining extra references for mids being retried
+and marking them as MID_DELETED which indicates that such a mid
+has been dequeued from the pending list.
+
+Also move mid cleanup logic from DeleteMidQEntry to
+_cifs_mid_q_entry_release which is called when the last reference
+to a particular mid is put. This allows to avoid any use-after-free
+of response buffers.
+
+The patch needs to be backported to stable kernels. A stable tag
+is not mentioned below because the patch doesn't apply cleanly
+to any actively maintained stable kernel.
+
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Reviewed-and-tested-by: David Wysochanski <dwysocha@redhat.com>
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/connect.c   |   10 +++++++++-
+ fs/cifs/transport.c |   42 +++++++++++++++++++++++-------------------
+ 2 files changed, 32 insertions(+), 20 deletions(-)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -556,9 +556,11 @@ cifs_reconnect(struct TCP_Server_Info *s
+       spin_lock(&GlobalMid_Lock);
+       list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
+               mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
++              kref_get(&mid_entry->refcount);
+               if (mid_entry->mid_state == MID_REQUEST_SUBMITTED)
+                       mid_entry->mid_state = MID_RETRY_NEEDED;
+               list_move(&mid_entry->qhead, &retry_list);
++              mid_entry->mid_flags |= MID_DELETED;
+       }
+       spin_unlock(&GlobalMid_Lock);
+       mutex_unlock(&server->srv_mutex);
+@@ -568,6 +570,7 @@ cifs_reconnect(struct TCP_Server_Info *s
+               mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+               list_del_init(&mid_entry->qhead);
+               mid_entry->callback(mid_entry);
++              cifs_mid_q_entry_release(mid_entry);
+       }
+       if (cifs_rdma_enabled(server)) {
+@@ -887,8 +890,10 @@ dequeue_mid(struct mid_q_entry *mid, boo
+       if (mid->mid_flags & MID_DELETED)
+               printk_once(KERN_WARNING
+                           "trying to dequeue a deleted mid\n");
+-      else
++      else {
+               list_del_init(&mid->qhead);
++              mid->mid_flags |= MID_DELETED;
++      }
+       spin_unlock(&GlobalMid_Lock);
+ }
+@@ -958,8 +963,10 @@ static void clean_demultiplex_info(struc
+               list_for_each_safe(tmp, tmp2, &server->pending_mid_q) {
+                       mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+                       cifs_dbg(FYI, "Clearing mid 0x%llx\n", mid_entry->mid);
++                      kref_get(&mid_entry->refcount);
+                       mid_entry->mid_state = MID_SHUTDOWN;
+                       list_move(&mid_entry->qhead, &dispose_list);
++                      mid_entry->mid_flags |= MID_DELETED;
+               }
+               spin_unlock(&GlobalMid_Lock);
+@@ -969,6 +976,7 @@ static void clean_demultiplex_info(struc
+                       cifs_dbg(FYI, "Callback mid 0x%llx\n", mid_entry->mid);
+                       list_del_init(&mid_entry->qhead);
+                       mid_entry->callback(mid_entry);
++                      cifs_mid_q_entry_release(mid_entry);
+               }
+               /* 1/8th of sec is more than enough time for them to exit */
+               msleep(125);
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -86,22 +86,8 @@ AllocMidQEntry(const struct smb_hdr *smb
+ static void _cifs_mid_q_entry_release(struct kref *refcount)
+ {
+-      struct mid_q_entry *mid = container_of(refcount, struct mid_q_entry,
+-                                             refcount);
+-
+-      mempool_free(mid, cifs_mid_poolp);
+-}
+-
+-void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
+-{
+-      spin_lock(&GlobalMid_Lock);
+-      kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
+-      spin_unlock(&GlobalMid_Lock);
+-}
+-
+-void
+-DeleteMidQEntry(struct mid_q_entry *midEntry)
+-{
++      struct mid_q_entry *midEntry =
++                      container_of(refcount, struct mid_q_entry, refcount);
+ #ifdef CONFIG_CIFS_STATS2
+       __le16 command = midEntry->server->vals->lock_cmd;
+       __u16 smb_cmd = le16_to_cpu(midEntry->command);
+@@ -166,6 +152,19 @@ DeleteMidQEntry(struct mid_q_entry *midE
+               }
+       }
+ #endif
++
++      mempool_free(midEntry, cifs_mid_poolp);
++}
++
++void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
++{
++      spin_lock(&GlobalMid_Lock);
++      kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
++      spin_unlock(&GlobalMid_Lock);
++}
++
++void DeleteMidQEntry(struct mid_q_entry *midEntry)
++{
+       cifs_mid_q_entry_release(midEntry);
+ }
+@@ -173,8 +172,10 @@ void
+ cifs_delete_mid(struct mid_q_entry *mid)
+ {
+       spin_lock(&GlobalMid_Lock);
+-      list_del_init(&mid->qhead);
+-      mid->mid_flags |= MID_DELETED;
++      if (!(mid->mid_flags & MID_DELETED)) {
++              list_del_init(&mid->qhead);
++              mid->mid_flags |= MID_DELETED;
++      }
+       spin_unlock(&GlobalMid_Lock);
+       DeleteMidQEntry(mid);
+@@ -868,7 +869,10 @@ cifs_sync_mid_result(struct mid_q_entry
+               rc = -EHOSTDOWN;
+               break;
+       default:
+-              list_del_init(&mid->qhead);
++              if (!(mid->mid_flags & MID_DELETED)) {
++                      list_del_init(&mid->qhead);
++                      mid->mid_flags |= MID_DELETED;
++              }
+               cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
+                        __func__, mid->mid, mid->mid_state);
+               rc = -EIO;
diff --git a/queue-5.3/selftests-powerpc-add-test-case-for-tlbie-vs-mtpidr-ordering-issue.patch b/queue-5.3/selftests-powerpc-add-test-case-for-tlbie-vs-mtpidr-ordering-issue.patch
new file mode 100644 (file)
index 0000000..9405921
--- /dev/null
@@ -0,0 +1,773 @@
+From 93cad5f789951eaa27c3392b15294b4e51253944 Mon Sep 17 00:00:00 2001
+From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
+Date: Tue, 24 Sep 2019 09:22:54 +0530
+Subject: selftests/powerpc: Add test case for tlbie vs mtpidr ordering issue
+
+From: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+
+commit 93cad5f789951eaa27c3392b15294b4e51253944 upstream.
+
+Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+[mpe: Some minor fixes to make it build]
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20190924035254.24612-4-aneesh.kumar@linux.ibm.com
+Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/testing/selftests/powerpc/mm/Makefile     |    2 
+ tools/testing/selftests/powerpc/mm/tlbie_test.c |  734 ++++++++++++++++++++++++
+ 2 files changed, 736 insertions(+)
+
+--- a/tools/testing/selftests/powerpc/mm/Makefile
++++ b/tools/testing/selftests/powerpc/mm/Makefile
+@@ -4,6 +4,7 @@ noarg:
+ TEST_GEN_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao segv_errors wild_bctr \
+                 large_vm_fork_separation
++TEST_GEN_PROGS_EXTENDED := tlbie_test
+ TEST_GEN_FILES := tempfile
+ top_srcdir = ../../../../..
+@@ -19,3 +20,4 @@ $(OUTPUT)/large_vm_fork_separation: CFLA
+ $(OUTPUT)/tempfile:
+       dd if=/dev/zero of=$@ bs=64k count=1
++$(OUTPUT)/tlbie_test: LDLIBS += -lpthread
+--- /dev/null
++++ b/tools/testing/selftests/powerpc/mm/tlbie_test.c
+@@ -0,0 +1,734 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/*
++ * Copyright 2019, Nick Piggin, Gautham R. Shenoy, Aneesh Kumar K.V, IBM Corp.
++ */
++
++/*
++ *
++ * Test tlbie/mtpidr race. We have 4 threads doing flush/load/compare/store
++ * sequence in a loop. The same threads also rung a context switch task
++ * that does sched_yield() in loop.
++ *
++ * The snapshot thread mark the mmap area PROT_READ in between, make a copy
++ * and copy it back to the original area. This helps us to detect if any
++ * store continued to happen after we marked the memory PROT_READ.
++ */
++
++#define _GNU_SOURCE
++#include <stdio.h>
++#include <sys/mman.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <sys/ipc.h>
++#include <sys/shm.h>
++#include <sys/stat.h>
++#include <sys/time.h>
++#include <linux/futex.h>
++#include <unistd.h>
++#include <asm/unistd.h>
++#include <string.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <sched.h>
++#include <time.h>
++#include <stdarg.h>
++#include <sched.h>
++#include <pthread.h>
++#include <signal.h>
++#include <sys/prctl.h>
++
++static inline void dcbf(volatile unsigned int *addr)
++{
++      __asm__ __volatile__ ("dcbf %y0; sync" : : "Z"(*(unsigned char *)addr) : "memory");
++}
++
++static void err_msg(char *msg)
++{
++
++      time_t now;
++      time(&now);
++      printf("=================================\n");
++      printf("    Error: %s\n", msg);
++      printf("    %s", ctime(&now));
++      printf("=================================\n");
++      exit(1);
++}
++
++static char *map1;
++static char *map2;
++static pid_t rim_process_pid;
++
++/*
++ * A "rim-sequence" is defined to be the sequence of the following
++ * operations performed on a memory word:
++ *    1) FLUSH the contents of that word.
++ *    2) LOAD the contents of that word.
++ *    3) COMPARE the contents of that word with the content that was
++ *               previously stored at that word
++ *    4) STORE new content into that word.
++ *
++ * The threads in this test that perform the rim-sequence are termed
++ * as rim_threads.
++ */
++
++/*
++ * A "corruption" is defined to be the failed COMPARE operation in a
++ * rim-sequence.
++ *
++ * A rim_thread that detects a corruption informs about it to all the
++ * other rim_threads, and the mem_snapshot thread.
++ */
++static volatile unsigned int corruption_found;
++
++/*
++ * This defines the maximum number of rim_threads in this test.
++ *
++ * The THREAD_ID_BITS denote the number of bits required
++ * to represent the thread_ids [0..MAX_THREADS - 1].
++ * We are being a bit paranoid here and set it to 8 bits,
++ * though 6 bits suffice.
++ *
++ */
++#define MAX_THREADS           64
++#define THREAD_ID_BITS                8
++#define THREAD_ID_MASK                ((1 << THREAD_ID_BITS) - 1)
++static unsigned int rim_thread_ids[MAX_THREADS];
++static pthread_t rim_threads[MAX_THREADS];
++
++
++/*
++ * Each rim_thread works on an exclusive "chunk" of size
++ * RIM_CHUNK_SIZE.
++ *
++ * The ith rim_thread works on the ith chunk.
++ *
++ * The ith chunk begins at
++ * map1 + (i * RIM_CHUNK_SIZE)
++ */
++#define RIM_CHUNK_SIZE        1024
++#define BITS_PER_BYTE                 8
++#define WORD_SIZE                     (sizeof(unsigned int))
++#define WORD_BITS             (WORD_SIZE * BITS_PER_BYTE)
++#define WORDS_PER_CHUNK               (RIM_CHUNK_SIZE/WORD_SIZE)
++
++static inline char *compute_chunk_start_addr(unsigned int thread_id)
++{
++      char *chunk_start;
++
++      chunk_start = (char *)((unsigned long)map1 +
++                             (thread_id * RIM_CHUNK_SIZE));
++
++      return chunk_start;
++}
++
++/*
++ * The "word-offset" of a word-aligned address inside a chunk, is
++ * defined to be the number of words that precede the address in that
++ * chunk.
++ *
++ * WORD_OFFSET_BITS denote the number of bits required to represent
++ * the word-offsets of all the word-aligned addresses of a chunk.
++ */
++#define WORD_OFFSET_BITS      (__builtin_ctz(WORDS_PER_CHUNK))
++#define WORD_OFFSET_MASK      ((1 << WORD_OFFSET_BITS) - 1)
++
++static inline unsigned int compute_word_offset(char *start, unsigned int *addr)
++{
++      unsigned int delta_bytes, ret;
++      delta_bytes = (unsigned long)addr - (unsigned long)start;
++
++      ret = delta_bytes/WORD_SIZE;
++
++      return ret;
++}
++
++/*
++ * A "sweep" is defined to be the sequential execution of the
++ * rim-sequence by a rim_thread on its chunk one word at a time,
++ * starting from the first word of its chunk and ending with the last
++ * word of its chunk.
++ *
++ * Each sweep of a rim_thread is uniquely identified by a sweep_id.
++ * SWEEP_ID_BITS denote the number of bits required to represent
++ * the sweep_ids of rim_threads.
++ *
++ * As to why SWEEP_ID_BITS are computed as a function of THREAD_ID_BITS,
++ * WORD_OFFSET_BITS, and WORD_BITS, see the "store-pattern" below.
++ */
++#define SWEEP_ID_BITS         (WORD_BITS - (THREAD_ID_BITS + WORD_OFFSET_BITS))
++#define SWEEP_ID_MASK         ((1 << SWEEP_ID_BITS) - 1)
++
++/*
++ * A "store-pattern" is the word-pattern that is stored into a word
++ * location in the 4)STORE step of the rim-sequence.
++ *
++ * In the store-pattern, we shall encode:
++ *
++ *      - The thread-id of the rim_thread performing the store
++ *        (The most significant THREAD_ID_BITS)
++ *
++ *      - The word-offset of the address into which the store is being
++ *        performed (The next WORD_OFFSET_BITS)
++ *
++ *      - The sweep_id of the current sweep in which the store is
++ *        being performed. (The lower SWEEP_ID_BITS)
++ *
++ * Store Pattern: 32 bits
++ * |------------------|--------------------|---------------------------------|
++ * |    Thread id     |  Word offset       |         sweep_id                |
++ * |------------------|--------------------|---------------------------------|
++ *    THREAD_ID_BITS     WORD_OFFSET_BITS          SWEEP_ID_BITS
++ *
++ * In the store pattern, the (Thread-id + Word-offset) uniquely identify the
++ * address to which the store is being performed i.e,
++ *    address == map1 +
++ *              (Thread-id * RIM_CHUNK_SIZE) + (Word-offset * WORD_SIZE)
++ *
++ * And the sweep_id in the store pattern identifies the time when the
++ * store was performed by the rim_thread.
++ *
++ * We shall use this property in the 3)COMPARE step of the
++ * rim-sequence.
++ */
++#define SWEEP_ID_SHIFT        0
++#define WORD_OFFSET_SHIFT     (SWEEP_ID_BITS)
++#define THREAD_ID_SHIFT               (WORD_OFFSET_BITS + SWEEP_ID_BITS)
++
++/*
++ * Compute the store pattern for a given thread with id @tid, at
++ * location @addr in the sweep identified by @sweep_id
++ */
++static inline unsigned int compute_store_pattern(unsigned int tid,
++                                               unsigned int *addr,
++                                               unsigned int sweep_id)
++{
++      unsigned int ret = 0;
++      char *start = compute_chunk_start_addr(tid);
++      unsigned int word_offset = compute_word_offset(start, addr);
++
++      ret += (tid & THREAD_ID_MASK) << THREAD_ID_SHIFT;
++      ret += (word_offset & WORD_OFFSET_MASK) << WORD_OFFSET_SHIFT;
++      ret += (sweep_id & SWEEP_ID_MASK) << SWEEP_ID_SHIFT;
++      return ret;
++}
++
++/* Extract the thread-id from the given store-pattern */
++static inline unsigned int extract_tid(unsigned int pattern)
++{
++      unsigned int ret;
++
++      ret = (pattern >> THREAD_ID_SHIFT) & THREAD_ID_MASK;
++      return ret;
++}
++
++/* Extract the word-offset from the given store-pattern */
++static inline unsigned int extract_word_offset(unsigned int pattern)
++{
++      unsigned int ret;
++
++      ret = (pattern >> WORD_OFFSET_SHIFT) & WORD_OFFSET_MASK;
++
++      return ret;
++}
++
++/* Extract the sweep-id from the given store-pattern */
++static inline unsigned int extract_sweep_id(unsigned int pattern)
++
++{
++      unsigned int ret;
++
++      ret = (pattern >> SWEEP_ID_SHIFT) & SWEEP_ID_MASK;
++
++      return ret;
++}
++
++/************************************************************
++ *                                                          *
++ *          Logging the output of the verification          *
++ *                                                          *
++ ************************************************************/
++#define LOGDIR_NAME_SIZE 100
++static char logdir[LOGDIR_NAME_SIZE];
++
++static FILE *fp[MAX_THREADS];
++static const char logfilename[] ="Thread-%02d-Chunk";
++
++static inline void start_verification_log(unsigned int tid,
++                                        unsigned int *addr,
++                                        unsigned int cur_sweep_id,
++                                        unsigned int prev_sweep_id)
++{
++      FILE *f;
++      char logfile[30];
++      char path[LOGDIR_NAME_SIZE + 30];
++      char separator[2] = "/";
++      char *chunk_start = compute_chunk_start_addr(tid);
++      unsigned int size = RIM_CHUNK_SIZE;
++
++      sprintf(logfile, logfilename, tid);
++      strcpy(path, logdir);
++      strcat(path, separator);
++      strcat(path, logfile);
++      f = fopen(path, "w");
++
++      if (!f) {
++              err_msg("Unable to create logfile\n");
++      }
++
++      fp[tid] = f;
++
++      fprintf(f, "----------------------------------------------------------\n");
++      fprintf(f, "PID                = %d\n", rim_process_pid);
++      fprintf(f, "Thread id          = %02d\n", tid);
++      fprintf(f, "Chunk Start Addr   = 0x%016lx\n", (unsigned long)chunk_start);
++      fprintf(f, "Chunk Size         = %d\n", size);
++      fprintf(f, "Next Store Addr    = 0x%016lx\n", (unsigned long)addr);
++      fprintf(f, "Current sweep-id   = 0x%08x\n", cur_sweep_id);
++      fprintf(f, "Previous sweep-id  = 0x%08x\n", prev_sweep_id);
++      fprintf(f, "----------------------------------------------------------\n");
++}
++
++static inline void log_anamoly(unsigned int tid, unsigned int *addr,
++                             unsigned int expected, unsigned int observed)
++{
++      FILE *f = fp[tid];
++
++      fprintf(f, "Thread %02d: Addr 0x%lx: Expected 0x%x, Observed 0x%x\n",
++              tid, (unsigned long)addr, expected, observed);
++      fprintf(f, "Thread %02d: Expected Thread id   = %02d\n", tid, extract_tid(expected));
++      fprintf(f, "Thread %02d: Observed Thread id   = %02d\n", tid, extract_tid(observed));
++      fprintf(f, "Thread %02d: Expected Word offset = %03d\n", tid, extract_word_offset(expected));
++      fprintf(f, "Thread %02d: Observed Word offset = %03d\n", tid, extract_word_offset(observed));
++      fprintf(f, "Thread %02d: Expected sweep-id    = 0x%x\n", tid, extract_sweep_id(expected));
++      fprintf(f, "Thread %02d: Observed sweep-id    = 0x%x\n", tid, extract_sweep_id(observed));
++      fprintf(f, "----------------------------------------------------------\n");
++}
++
++static inline void end_verification_log(unsigned int tid, unsigned nr_anamolies)
++{
++      FILE *f = fp[tid];
++      char logfile[30];
++      char path[LOGDIR_NAME_SIZE + 30];
++      char separator[] = "/";
++
++      fclose(f);
++
++      if (nr_anamolies == 0) {
++              remove(path);
++              return;
++      }
++
++      sprintf(logfile, logfilename, tid);
++      strcpy(path, logdir);
++      strcat(path, separator);
++      strcat(path, logfile);
++
++      printf("Thread %02d chunk has %d corrupted words. For details check %s\n",
++              tid, nr_anamolies, path);
++}
++
++/*
++ * When a COMPARE step of a rim-sequence fails, the rim_thread informs
++ * everyone else via the shared_memory pointed to by
++ * corruption_found variable. On seeing this, every thread verifies the
++ * content of its chunk as follows.
++ *
++ * Suppose a thread identified with @tid was about to store (but not
++ * yet stored) to @next_store_addr in its current sweep identified
++ * @cur_sweep_id. Let @prev_sweep_id indicate the previous sweep_id.
++ *
++ * This implies that for all the addresses @addr < @next_store_addr,
++ * Thread @tid has already performed a store as part of its current
++ * sweep. Hence we expect the content of such @addr to be:
++ *    |-------------------------------------------------|
++ *    | tid   | word_offset(addr) |    cur_sweep_id     |
++ *    |-------------------------------------------------|
++ *
++ * Since Thread @tid is yet to perform stores on address
++ * @next_store_addr and above, we expect the content of such an
++ * address @addr to be:
++ *    |-------------------------------------------------|
++ *    | tid   | word_offset(addr) |    prev_sweep_id    |
++ *    |-------------------------------------------------|
++ *
++ * The verifier function @verify_chunk does this verification and logs
++ * any anamolies that it finds.
++ */
++static void verify_chunk(unsigned int tid, unsigned int *next_store_addr,
++                unsigned int cur_sweep_id,
++                unsigned int prev_sweep_id)
++{
++      unsigned int *iter_ptr;
++      unsigned int size = RIM_CHUNK_SIZE;
++      unsigned int expected;
++      unsigned int observed;
++      char *chunk_start = compute_chunk_start_addr(tid);
++
++      int nr_anamolies = 0;
++
++      start_verification_log(tid, next_store_addr,
++                             cur_sweep_id, prev_sweep_id);
++
++      for (iter_ptr = (unsigned int *)chunk_start;
++           (unsigned long)iter_ptr < (unsigned long)chunk_start + size;
++           iter_ptr++) {
++              unsigned int expected_sweep_id;
++
++              if (iter_ptr < next_store_addr) {
++                      expected_sweep_id = cur_sweep_id;
++              } else {
++                      expected_sweep_id = prev_sweep_id;
++              }
++
++              expected = compute_store_pattern(tid, iter_ptr, expected_sweep_id);
++
++              dcbf((volatile unsigned int*)iter_ptr); //Flush before reading
++              observed = *iter_ptr;
++
++              if (observed != expected) {
++                      nr_anamolies++;
++                      log_anamoly(tid, iter_ptr, expected, observed);
++              }
++      }
++
++      end_verification_log(tid, nr_anamolies);
++}
++
++static void set_pthread_cpu(pthread_t th, int cpu)
++{
++      cpu_set_t run_cpu_mask;
++      struct sched_param param;
++
++      CPU_ZERO(&run_cpu_mask);
++      CPU_SET(cpu, &run_cpu_mask);
++      pthread_setaffinity_np(th, sizeof(cpu_set_t), &run_cpu_mask);
++
++      param.sched_priority = 1;
++      if (0 && sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
++              /* haven't reproduced with this setting, it kills random preemption which may be a factor */
++              fprintf(stderr, "could not set SCHED_FIFO, run as root?\n");
++      }
++}
++
++static void set_mycpu(int cpu)
++{
++      cpu_set_t run_cpu_mask;
++      struct sched_param param;
++
++      CPU_ZERO(&run_cpu_mask);
++      CPU_SET(cpu, &run_cpu_mask);
++      sched_setaffinity(0, sizeof(cpu_set_t), &run_cpu_mask);
++
++      param.sched_priority = 1;
++      if (0 && sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
++              fprintf(stderr, "could not set SCHED_FIFO, run as root?\n");
++      }
++}
++
++static volatile int segv_wait;
++
++static void segv_handler(int signo, siginfo_t *info, void *extra)
++{
++      while (segv_wait) {
++              sched_yield();
++      }
++
++}
++
++static void set_segv_handler(void)
++{
++      struct sigaction sa;
++
++      sa.sa_flags = SA_SIGINFO;
++      sa.sa_sigaction = segv_handler;
++
++      if (sigaction(SIGSEGV, &sa, NULL) == -1) {
++              perror("sigaction");
++              exit(EXIT_FAILURE);
++      }
++}
++
++int timeout = 0;
++/*
++ * This function is executed by every rim_thread.
++ *
++ * This function performs sweeps over the exclusive chunks of the
++ * rim_threads executing the rim-sequence one word at a time.
++ */
++static void *rim_fn(void *arg)
++{
++      unsigned int tid = *((unsigned int *)arg);
++
++      int size = RIM_CHUNK_SIZE;
++      char *chunk_start = compute_chunk_start_addr(tid);
++
++      unsigned int prev_sweep_id;
++      unsigned int cur_sweep_id = 0;
++
++      /* word access */
++      unsigned int pattern = cur_sweep_id;
++      unsigned int *pattern_ptr = &pattern;
++      unsigned int *w_ptr, read_data;
++
++      set_segv_handler();
++
++      /*
++       * Let us initialize the chunk:
++       *
++       * Each word-aligned address addr in the chunk,
++       * is initialized to :
++       *    |-------------------------------------------------|
++       *    | tid   | word_offset(addr) |         0           |
++       *    |-------------------------------------------------|
++       */
++      for (w_ptr = (unsigned int *)chunk_start;
++           (unsigned long)w_ptr < (unsigned long)(chunk_start) + size;
++           w_ptr++) {
++
++              *pattern_ptr = compute_store_pattern(tid, w_ptr, cur_sweep_id);
++              *w_ptr = *pattern_ptr;
++      }
++
++      while (!corruption_found && !timeout) {
++              prev_sweep_id = cur_sweep_id;
++              cur_sweep_id = cur_sweep_id + 1;
++
++              for (w_ptr = (unsigned int *)chunk_start;
++                   (unsigned long)w_ptr < (unsigned long)(chunk_start) + size;
++                   w_ptr++)  {
++                      unsigned int old_pattern;
++
++                      /*
++                       * Compute the pattern that we would have
++                       * stored at this location in the previous
++                       * sweep.
++                       */
++                      old_pattern = compute_store_pattern(tid, w_ptr, prev_sweep_id);
++
++                      /*
++                       * FLUSH:Ensure that we flush the contents of
++                       *       the cache before loading
++                       */
++                      dcbf((volatile unsigned int*)w_ptr); //Flush
++
++                      /* LOAD: Read the value */
++                      read_data = *w_ptr; //Load
++
++                      /*
++                       * COMPARE: Is it the same as what we had stored
++                       *          in the previous sweep ? It better be!
++                       */
++                      if (read_data != old_pattern) {
++                              /* No it isn't! Tell everyone */
++                              corruption_found = 1;
++                      }
++
++                      /*
++                       * Before performing a store, let us check if
++                       * any rim_thread has found a corruption.
++                       */
++                      if (corruption_found || timeout) {
++                              /*
++                               * Yes. Someone (including us!) has found
++                               * a corruption :(
++                               *
++                               * Let us verify that our chunk is
++                               * correct.
++                               */
++                              /* But first, let us allow the dust to settle down! */
++                              verify_chunk(tid, w_ptr, cur_sweep_id, prev_sweep_id);
++
++                              return 0;
++                      }
++
++                      /*
++                       * Compute the new pattern that we are going
++                       * to write to this location
++                       */
++                      *pattern_ptr = compute_store_pattern(tid, w_ptr, cur_sweep_id);
++
++                      /*
++                       * STORE: Now let us write this pattern into
++                       *        the location
++                       */
++                      *w_ptr = *pattern_ptr;
++              }
++      }
++
++      return NULL;
++}
++
++
++static unsigned long start_cpu = 0;
++static unsigned long nrthreads = 4;
++
++static pthread_t mem_snapshot_thread;
++
++static void *mem_snapshot_fn(void *arg)
++{
++      int page_size = getpagesize();
++      size_t size = page_size;
++      void *tmp = malloc(size);
++
++      while (!corruption_found && !timeout) {
++              /* Stop memory migration once corruption is found */
++              segv_wait = 1;
++
++              mprotect(map1, size, PROT_READ);
++
++              /*
++               * Load from the working alias (map1). Loading from map2
++               * also fails.
++               */
++              memcpy(tmp, map1, size);
++
++              /*
++               * Stores must go via map2 which has write permissions, but
++               * the corrupted data tends to be seen in the snapshot buffer,
++               * so corruption does not appear to be introduced at the
++               * copy-back via map2 alias here.
++               */
++              memcpy(map2, tmp, size);
++              /*
++               * Before releasing other threads, must ensure the copy
++               * back to
++               */
++              asm volatile("sync" ::: "memory");
++              mprotect(map1, size, PROT_READ|PROT_WRITE);
++              asm volatile("sync" ::: "memory");
++              segv_wait = 0;
++
++              usleep(1); /* This value makes a big difference */
++      }
++
++      return 0;
++}
++
++void alrm_sighandler(int sig)
++{
++      timeout = 1;
++}
++
++int main(int argc, char *argv[])
++{
++      int c;
++      int page_size = getpagesize();
++      time_t now;
++      int i, dir_error;
++      pthread_attr_t attr;
++      key_t shm_key = (key_t) getpid();
++      int shmid, run_time = 20 * 60;
++      struct sigaction sa_alrm;
++
++      snprintf(logdir, LOGDIR_NAME_SIZE,
++               "/tmp/logdir-%u", (unsigned int)getpid());
++      while ((c = getopt(argc, argv, "r:hn:l:t:")) != -1) {
++              switch(c) {
++              case 'r':
++                      start_cpu = strtoul(optarg, NULL, 10);
++                      break;
++              case 'h':
++                      printf("%s [-r <start_cpu>] [-n <nrthreads>] [-l <logdir>] [-t <timeout>]\n", argv[0]);
++                      exit(0);
++                      break;
++              case 'n':
++                      nrthreads = strtoul(optarg, NULL, 10);
++                      break;
++              case 'l':
++                      strncpy(logdir, optarg, LOGDIR_NAME_SIZE);
++                      break;
++              case 't':
++                      run_time = strtoul(optarg, NULL, 10);
++                      break;
++              default:
++                      printf("invalid option\n");
++                      exit(0);
++                      break;
++              }
++      }
++
++      if (nrthreads > MAX_THREADS)
++              nrthreads = MAX_THREADS;
++
++      shmid = shmget(shm_key, page_size, IPC_CREAT|0666);
++      if (shmid < 0) {
++              err_msg("Failed shmget\n");
++      }
++
++      map1 = shmat(shmid, NULL, 0);
++      if (map1 == (void *) -1) {
++              err_msg("Failed shmat");
++      }
++
++      map2 = shmat(shmid, NULL, 0);
++      if (map2 == (void *) -1) {
++              err_msg("Failed shmat");
++      }
++
++      dir_error = mkdir(logdir, 0755);
++
++      if (dir_error) {
++              err_msg("Failed mkdir");
++      }
++
++      printf("start_cpu list:%lu\n", start_cpu);
++      printf("number of worker threads:%lu + 1 snapshot thread\n", nrthreads);
++      printf("Allocated address:0x%016lx + secondary map:0x%016lx\n", (unsigned long)map1, (unsigned long)map2);
++      printf("logdir at : %s\n", logdir);
++      printf("Timeout: %d seconds\n", run_time);
++
++      time(&now);
++      printf("=================================\n");
++      printf("     Starting Test\n");
++      printf("     %s", ctime(&now));
++      printf("=================================\n");
++
++      for (i = 0; i < nrthreads; i++) {
++              if (1 && !fork()) {
++                      prctl(PR_SET_PDEATHSIG, SIGKILL);
++                      set_mycpu(start_cpu + i);
++                      for (;;)
++                              sched_yield();
++                      exit(0);
++              }
++      }
++
++
++      sa_alrm.sa_handler = &alrm_sighandler;
++      sigemptyset(&sa_alrm.sa_mask);
++      sa_alrm.sa_flags = 0;
++
++      if (sigaction(SIGALRM, &sa_alrm, 0) == -1) {
++              err_msg("Failed signal handler registration\n");
++      }
++
++      alarm(run_time);
++
++      pthread_attr_init(&attr);
++      for (i = 0; i < nrthreads; i++) {
++              rim_thread_ids[i] = i;
++              pthread_create(&rim_threads[i], &attr, rim_fn, &rim_thread_ids[i]);
++              set_pthread_cpu(rim_threads[i], start_cpu + i);
++      }
++
++      pthread_create(&mem_snapshot_thread, &attr, mem_snapshot_fn, map1);
++      set_pthread_cpu(mem_snapshot_thread, start_cpu + i);
++
++
++      pthread_join(mem_snapshot_thread, NULL);
++      for (i = 0; i < nrthreads; i++) {
++              pthread_join(rim_threads[i], NULL);
++      }
++
++      if (!timeout) {
++              time(&now);
++              printf("=================================\n");
++              printf("      Data Corruption Detected\n");
++              printf("      %s", ctime(&now));
++              printf("      See logfiles in %s\n", logdir);
++              printf("=================================\n");
++              return 1;
++      }
++      return 0;
++}
diff --git a/queue-5.3/selftests-powerpc-fix-compile-error-on-tlbie_test-due-to-newer-gcc.patch b/queue-5.3/selftests-powerpc-fix-compile-error-on-tlbie_test-due-to-newer-gcc.patch
new file mode 100644 (file)
index 0000000..5f2af58
--- /dev/null
@@ -0,0 +1,42 @@
+From 5b216ea1c40cf06eead15054c70e238c9bd4729e Mon Sep 17 00:00:00 2001
+From: "Desnes A. Nunes do Rosario" <desnesn@linux.ibm.com>
+Date: Thu, 3 Oct 2019 18:10:10 -0300
+Subject: selftests/powerpc: Fix compile error on tlbie_test due to newer gcc
+
+From: Desnes A. Nunes do Rosario <desnesn@linux.ibm.com>
+
+commit 5b216ea1c40cf06eead15054c70e238c9bd4729e upstream.
+
+Newer versions of GCC (>= 9) demand that the size of the string to be
+copied must be explicitly smaller than the size of the destination.
+Thus, the NULL char has to be taken into account on strncpy.
+
+This will avoid the following compiling error:
+
+  tlbie_test.c: In function 'main':
+  tlbie_test.c:639:4: error: 'strncpy' specified bound 100 equals destination size
+      strncpy(logdir, optarg, LOGDIR_NAME_SIZE);
+      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  cc1: all warnings being treated as errors
+
+Signed-off-by: Desnes A. Nunes do Rosario <desnesn@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20191003211010.9711-1-desnesn@linux.ibm.com
+Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/testing/selftests/powerpc/mm/tlbie_test.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/tools/testing/selftests/powerpc/mm/tlbie_test.c
++++ b/tools/testing/selftests/powerpc/mm/tlbie_test.c
+@@ -636,7 +636,7 @@ int main(int argc, char *argv[])
+                       nrthreads = strtoul(optarg, NULL, 10);
+                       break;
+               case 'l':
+-                      strncpy(logdir, optarg, LOGDIR_NAME_SIZE);
++                      strncpy(logdir, optarg, LOGDIR_NAME_SIZE - 1);
+                       break;
+               case 't':
+                       run_time = strtoul(optarg, NULL, 10);
index 15077382755260730a332e9a9f9083dce2a436e8..2a5d1a182842dfcf30eff08368d55b37db0cd9fc 100644 (file)
@@ -132,3 +132,9 @@ net-phy-bcm7xxx-define-soft_reset-for-40nm-ephy.patch
 net-bcmgenet-reset-40nm-ephy-on-energy-detect.patch
 net-flow_dissector-switch-to-siphash.patch
 platform-x86-pmc_atom-add-siemens-simatic-ipc227e-to-critclk_systems-dmi-table.patch
+cifs-fix-retry-mid-list-corruption-on-reconnects.patch
+selftests-powerpc-add-test-case-for-tlbie-vs-mtpidr-ordering-issue.patch
+selftests-powerpc-fix-compile-error-on-tlbie_test-due-to-newer-gcc.patch
+asoc-pcm3168a-the-codec-does-not-support-s32_le.patch
+arm64-dts-ti-k3-am65-main-fix-gic-its-node-unit-address.patch
+usb-gadget-udc-core-fix-segfault-if-udc_bind_to_driver-for-pending-driver-fails.patch
diff --git a/queue-5.3/usb-gadget-udc-core-fix-segfault-if-udc_bind_to_driver-for-pending-driver-fails.patch b/queue-5.3/usb-gadget-udc-core-fix-segfault-if-udc_bind_to_driver-for-pending-driver-fails.patch
new file mode 100644 (file)
index 0000000..caff7d7
--- /dev/null
@@ -0,0 +1,97 @@
+From 163be6ff7739b12ff300d77897d340f661821da2 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Thu, 22 Aug 2019 16:40:28 +0300
+Subject: usb: gadget: udc: core: Fix segfault if udc_bind_to_driver() for pending driver fails
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit 163be6ff7739b12ff300d77897d340f661821da2 upstream.
+
+If a gadget driver is in the pending drivers list, a UDC
+becomes available and udc_bind_to_driver() fails, then it
+gets deleted from the pending list.
+i.e. list_del(&driver->pending) in check_pending_gadget_drivers().
+
+Then if that gadget driver is unregistered,
+usb_gadget_unregister_driver() does a list_del(&driver->pending)
+again thus causing a page fault as that list entry has been poisoned
+by the previous list_del().
+
+Fix this by using list_del_init() instead of list_del() in
+check_pending_gadget_drivers().
+
+Test case:
+
+- Make sure no UDC is available
+- modprobe g_mass_storage file=wrongfile
+- Load UDC driver so it becomes available
+       lun0: unable to open backing file: wrongfile
+- modprobe -r g_mass_storage
+
+[   60.900431] Unable to handle kernel paging request at virtual address dead000000000108
+[   60.908346] Mem abort info:
+[   60.911145]   ESR = 0x96000044
+[   60.914227]   Exception class = DABT (current EL), IL = 32 bits
+[   60.920162]   SET = 0, FnV = 0
+[   60.923217]   EA = 0, S1PTW = 0
+[   60.926354] Data abort info:
+[   60.929228]   ISV = 0, ISS = 0x00000044
+[   60.933058]   CM = 0, WnR = 1
+[   60.936011] [dead000000000108] address between user and kernel address ranges
+[   60.943136] Internal error: Oops: 96000044 [#1] PREEMPT SMP
+[   60.948691] Modules linked in: g_mass_storage(-) usb_f_mass_storage libcomposite xhci_plat_hcd xhci_hcd usbcore ti_am335x_adc kfifo_buf omap_rng cdns3 rng_core udc_core crc32_ce xfrm_user crct10dif_ce snd_so6
+[   60.993995] Process modprobe (pid: 834, stack limit = 0x00000000c2aebc69)
+[   61.000765] CPU: 0 PID: 834 Comm: modprobe Not tainted 4.19.59-01963-g065f42a60499 #92
+[   61.008658] Hardware name: Texas Instruments SoC (DT)
+[   61.014472] pstate: 60000005 (nZCv daif -PAN -UAO)
+[   61.019253] pc : usb_gadget_unregister_driver+0x7c/0x108 [udc_core]
+[   61.025503] lr : usb_gadget_unregister_driver+0x30/0x108 [udc_core]
+[   61.031750] sp : ffff00001338fda0
+[   61.035049] x29: ffff00001338fda0 x28: ffff800846d40000
+[   61.040346] x27: 0000000000000000 x26: 0000000000000000
+[   61.045642] x25: 0000000056000000 x24: 0000000000000800
+[   61.050938] x23: ffff000008d7b0d0 x22: ffff0000088b07c8
+[   61.056234] x21: ffff000001100000 x20: ffff000002020260
+[   61.061530] x19: ffff0000010ffd28 x18: 0000000000000000
+[   61.066825] x17: 0000000000000000 x16: 0000000000000000
+[   61.072121] x15: 0000000000000000 x14: 0000000000000000
+[   61.077417] x13: ffff000000000000 x12: ffffffffffffffff
+[   61.082712] x11: 0000000000000030 x10: 7f7f7f7f7f7f7f7f
+[   61.088008] x9 : fefefefefefefeff x8 : 0000000000000000
+[   61.093304] x7 : ffffffffffffffff x6 : 000000000000ffff
+[   61.098599] x5 : 8080000000000000 x4 : 0000000000000000
+[   61.103895] x3 : ffff000001100020 x2 : ffff800846d40000
+[   61.109190] x1 : dead000000000100 x0 : dead000000000200
+[   61.114486] Call trace:
+[   61.116922]  usb_gadget_unregister_driver+0x7c/0x108 [udc_core]
+[   61.122828]  usb_composite_unregister+0x10/0x18 [libcomposite]
+[   61.128643]  msg_cleanup+0x18/0xfce0 [g_mass_storage]
+[   61.133682]  __arm64_sys_delete_module+0x17c/0x1f0
+[   61.138458]  el0_svc_common+0x90/0x158
+[   61.142192]  el0_svc_handler+0x2c/0x80
+[   61.145926]  el0_svc+0x8/0xc
+[   61.148794] Code: eb03003f d10be033 54ffff21 a94d0281 (f9000420)
+[   61.154869] ---[ end trace afb22e9b637bd9a7 ]---
+Segmentation fault
+
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/udc/core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -1154,7 +1154,7 @@ static int check_pending_gadget_drivers(
+                                               dev_name(&udc->dev)) == 0) {
+                       ret = udc_bind_to_driver(udc, driver);
+                       if (ret != -EPROBE_DEFER)
+-                              list_del(&driver->pending);
++                              list_del_init(&driver->pending);
+                       break;
+               }