From: Greg Kroah-Hartman Date: Fri, 8 Nov 2019 16:29:48 +0000 (+0100) Subject: 5.3-stable patches X-Git-Tag: v4.4.200~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0f688e389816b42f5ec9818b8733f06e64beae26;p=thirdparty%2Fkernel%2Fstable-queue.git 5.3-stable patches 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 --- 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 index 00000000000..cdaba142d8d --- /dev/null +++ b/queue-5.3/arm64-dts-ti-k3-am65-main-fix-gic-its-node-unit-address.patch @@ -0,0 +1,34 @@ +From 389ce1a7c5279ebfb682fab220b4021b2bd49c8b Mon Sep 17 00:00:00 2001 +From: Suman Anna +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 + +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 +Signed-off-by: Suman Anna +Signed-off-by: Tero Kristo +Signed-off-by: Mathieu Poirier +Signed-off-by: Greg Kroah-Hartman + +--- + 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_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 index 00000000000..94b820cdbc3 --- /dev/null +++ b/queue-5.3/asoc-pcm3168a-the-codec-does-not-support-s32_le.patch @@ -0,0 +1,36 @@ +From 7b2db65b59c30d58c129d3c8b2101feca686155a Mon Sep 17 00:00:00 2001 +From: Peter Ujfalusi +Date: Thu, 19 Sep 2019 10:16:52 +0300 +Subject: ASoC: pcm3168a: The codec does not support S32_LE + +From: Peter Ujfalusi + +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 +Link: https://lore.kernel.org/r/20190919071652.31724-1-peter.ujfalusi@ti.com +Signed-off-by: Mark Brown +Signed-off-by: Mathieu Poirier +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..491756b9f11 --- /dev/null +++ b/queue-5.3/cifs-fix-retry-mid-list-corruption-on-reconnects.patch @@ -0,0 +1,187 @@ +From abe57073d08c13b95a46ccf48cc9dc957d5c6fdb Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Tue, 22 Oct 2019 08:41:42 -0700 +Subject: CIFS: Fix retry mid list corruption on reconnects + +From: Pavel Shilovsky + +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 +Reviewed-and-tested-by: David Wysochanski +Signed-off-by: Pavel Shilovsky +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..9405921b133 --- /dev/null +++ b/queue-5.3/selftests-powerpc-add-test-case-for-tlbie-vs-mtpidr-ordering-issue.patch @@ -0,0 +1,773 @@ +From 93cad5f789951eaa27c3392b15294b4e51253944 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +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 + +commit 93cad5f789951eaa27c3392b15294b4e51253944 upstream. + +Signed-off-by: Aneesh Kumar K.V +[mpe: Some minor fixes to make it build] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20190924035254.24612-4-aneesh.kumar@linux.ibm.com +Signed-off-by: Sandipan Das +Signed-off-by: Greg Kroah-Hartman + +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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, ¶m) == -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, ¶m) == -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 ] [-n ] [-l ] [-t ]\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 index 00000000000..5f2af58b130 --- /dev/null +++ b/queue-5.3/selftests-powerpc-fix-compile-error-on-tlbie_test-due-to-newer-gcc.patch @@ -0,0 +1,42 @@ +From 5b216ea1c40cf06eead15054c70e238c9bd4729e Mon Sep 17 00:00:00 2001 +From: "Desnes A. Nunes do Rosario" +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 + +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 +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20191003211010.9711-1-desnesn@linux.ibm.com +Signed-off-by: Sandipan Das +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-5.3/series b/queue-5.3/series index 15077382755..2a5d1a18284 100644 --- a/queue-5.3/series +++ b/queue-5.3/series @@ -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 index 00000000000..caff7d7f742 --- /dev/null +++ b/queue-5.3/usb-gadget-udc-core-fix-segfault-if-udc_bind_to_driver-for-pending-driver-fails.patch @@ -0,0 +1,97 @@ +From 163be6ff7739b12ff300d77897d340f661821da2 Mon Sep 17 00:00:00 2001 +From: Roger Quadros +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 + +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 +Signed-off-by: Roger Quadros +Signed-off-by: Felipe Balbi +Signed-off-by: Mathieu Poirier +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } +