summaryrefslogtreecommitdiff |
diff options
author | Johannes Thumshirn <jthumshirn@suse.de> | 2019-01-15 09:23:53 +0100 |
---|---|---|
committer | Johannes Thumshirn <jthumshirn@suse.de> | 2019-01-15 09:23:53 +0100 |
commit | 7e1735dd4735f4e903cf4d759749b58b54771b5e (patch) | |
tree | 0e81032134c42341a558336aca00dba92937627b | |
parent | e1e720a6f483bbdc65671b1bd793b098ce768e46 (diff) | |
parent | 34aaefb40b6e456f41072706174ba255da59c3b1 (diff) |
Merge remote-tracking branch 'origin/SLE15' into SLE12-SP4-merge
Conflicts:
series.conf
44 files changed, 4020 insertions, 23 deletions
diff --git a/blacklist.conf b/blacklist.conf index 648e1ed612..b9887b74ea 100644 --- a/blacklist.conf +++ b/blacklist.conf @@ -981,3 +981,8 @@ fb265c9cb49e2074ddcdd4de99728aefdd3b3592 # Intrusive patch, mostly cleanup, fixe 83bc0f5b432f60394466deef16fc753e27371d0b # Duplicate of 4c9613ce556fdeb671e779668b627ea3a2b61728 914a4fd8cd28016038ce749a818a836124a8d270 # Duplicate of d9a515867bdba59ebf196a6ade10faae8e8be36a 7aaf7727235870f497eb928f728f7773d6df3b40 # Minor fix but outside chance it breaks vmstat parsers +af27d9403f5b80685b79c88425086edccecaf711 # Warning applies to unsupported configuration +379b03b7fa05f7db521b7732a52692448a3c34fe # Affected code is reverted +613a5eb5677923fdaecfa582738c7bcf80abe186 # Problem affects debugging builds only and is harmless +d50d82faa0c964e31f7a946ba8aba7c715ca7ab0 # Problem affects SLUB which is not enabled in kconfig +8363dae23463df5d27aa3f3430ad64f5c8fcee3e # Not applicable for SLE15 diff --git a/config/arm64/default b/config/arm64/default index 338d2b2c80..12a2dc7204 100644 --- a/config/arm64/default +++ b/config/arm64/default @@ -3324,7 +3324,69 @@ CONFIG_TABLET_USB_HANWANG=m CONFIG_TABLET_USB_KBTAB=m CONFIG_TABLET_USB_PEGASUS=m CONFIG_TABLET_SERIAL_WACOM4=m -# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_IPROC is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +CONFIG_TOUCHSCREEN_RASPBERRYPI_FW=m +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_TI_AM335X_TSC is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_WM97XX is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_SUN4I is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set CONFIG_INPUT_MISC=y # CONFIG_INPUT_AD714X is not set CONFIG_INPUT_ATMEL_CAPTOUCH=m diff --git a/patches.arch/s390-dasd-simplify-locking-in-dasd_times_out.patch b/patches.arch/s390-dasd-simplify-locking-in-dasd_times_out.patch new file mode 100644 index 0000000000..963b9e77b6 --- /dev/null +++ b/patches.arch/s390-dasd-simplify-locking-in-dasd_times_out.patch @@ -0,0 +1,101 @@ +From: Sebastian Ott <sebott@linux.ibm.com> +Date: Wed, 16 May 2018 11:25:21 +0200 +Subject: [PATCH] s390/dasd: simplify locking in dasd_times_out +Git-commit: 1bcdb5354aee2c0abcd13d912be35ae39a4144b6 +Patch-mainline: v4.18-rc1 +References: bsc#1104967,FATE#325924 + +Provide __dasd_cancel_req that is called with the ccw device lock +held to simplify the locking in dasd_times_out. Also this removes +the following sparse warning: +context imbalance in 'dasd_times_out' - different lock contexts for basic block + +Note: with this change dasd_schedule_device_bh is now called (via +dasd_cancel_req) with the ccw device lock held. But is is already +the case for other codepaths. + +Signed-off-by: Sebastian Ott <sebott@linux.ibm.com> +Reviewed-by: Stefan Haberland <sth@linux.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +Acked-by: Hannes Reinecke <hare@suse.com> +--- + drivers/s390/block/dasd.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +--- a/drivers/s390/block/dasd.c ++++ b/drivers/s390/block/dasd.c +@@ -2553,14 +2553,11 @@ EXPORT_SYMBOL(dasd_sleep_on_immediatly); + * Cancellation of a request is an asynchronous operation! The calling + * function has to wait until the request is properly returned via callback. + */ +-int dasd_cancel_req(struct dasd_ccw_req *cqr) ++static int __dasd_cancel_req(struct dasd_ccw_req *cqr) + { + struct dasd_device *device = cqr->startdev; +- unsigned long flags; +- int rc; ++ int rc = 0; + +- rc = 0; +- spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + switch (cqr->status) { + case DASD_CQR_QUEUED: + /* request was not started - just set to cleared */ +@@ -2580,10 +2577,21 @@ int dasd_cancel_req(struct dasd_ccw_req + default: /* already finished or clear pending - do nothing */ + break; + } +- spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + dasd_schedule_device_bh(device); + return rc; + } ++ ++int dasd_cancel_req(struct dasd_ccw_req *cqr) ++{ ++ struct dasd_device *device = cqr->startdev; ++ unsigned long flags; ++ int rc; ++ ++ spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); ++ rc = __dasd_cancel_req(cqr); ++ spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); ++ return rc; ++} + EXPORT_SYMBOL(dasd_cancel_req); + + /* +@@ -3082,12 +3090,10 @@ enum blk_eh_timer_return dasd_times_out( + cqr->retries = -1; + cqr->intrc = -ETIMEDOUT; + if (cqr->status >= DASD_CQR_QUEUED) { +- spin_unlock(get_ccwdev_lock(device->cdev)); +- rc = dasd_cancel_req(cqr); ++ rc = __dasd_cancel_req(cqr); + } else if (cqr->status == DASD_CQR_FILLED || + cqr->status == DASD_CQR_NEED_ERP) { + cqr->status = DASD_CQR_TERMINATED; +- spin_unlock(get_ccwdev_lock(device->cdev)); + } else if (cqr->status == DASD_CQR_IN_ERP) { + struct dasd_ccw_req *searchcqr, *nextcqr, *tmpcqr; + +@@ -3102,9 +3108,7 @@ enum blk_eh_timer_return dasd_times_out( + searchcqr->retries = -1; + searchcqr->intrc = -ETIMEDOUT; + if (searchcqr->status >= DASD_CQR_QUEUED) { +- spin_unlock(get_ccwdev_lock(device->cdev)); +- rc = dasd_cancel_req(searchcqr); +- spin_lock(get_ccwdev_lock(device->cdev)); ++ rc = __dasd_cancel_req(searchcqr); + } else if ((searchcqr->status == DASD_CQR_FILLED) || + (searchcqr->status == DASD_CQR_NEED_ERP)) { + searchcqr->status = DASD_CQR_TERMINATED; +@@ -3118,8 +3122,8 @@ enum blk_eh_timer_return dasd_times_out( + } + break; + } +- spin_unlock(get_ccwdev_lock(device->cdev)); + } ++ spin_unlock(get_ccwdev_lock(device->cdev)); + dasd_schedule_block_bh(block); + spin_unlock(&block->queue_lock); + diff --git a/patches.arch/s390-scsi-zfcp-fix-posting-too-many-status-read-buffers.patch b/patches.arch/s390-scsi-zfcp-fix-posting-too-many-status-read-buffers.patch new file mode 100644 index 0000000000..2ebd17950b --- /dev/null +++ b/patches.arch/s390-scsi-zfcp-fix-posting-too-many-status-read-buffers.patch @@ -0,0 +1,93 @@ +From: Steffen Maier <maier@linux.ibm.com> +Date: Thu, 6 Dec 2018 17:31:20 +0100 +Subject: scsi: zfcp: fix posting too many status read buffers leading to + adapter shutdown +Git-commit: 60a161b7e5b2a252ff0d4c622266a7d8da1120ce +Patch-mainline: v4.20 or v4.20-rc7 (next release) +References: bsc#1121483, LTC#174588 + +Suppose adapter (open) recovery is between opened QDIO queues and before +(the end of) initial posting of status read buffers (SRBs). This time +window can be seconds long due to FSF_PROT_HOST_CONNECTION_INITIALIZING +causing by design looping with exponential increase sleeps in the function +performing exchange config data during recovery +[zfcp_erp_adapter_strat_fsf_xconf()]. Recovery triggered by local link up. + +Suppose an event occurs for which the FCP channel would send an unsolicited +notification to zfcp by means of a previously posted SRB. We saw it with +local cable pull (link down) in multi-initiator zoning with multiple +NPIV-enabled subchannels of the same shared FCP channel. + +As soon as zfcp_erp_adapter_strategy_open_fsf() starts posting the initial +status read buffers from within the adapter's ERP thread, the channel does +send an unsolicited notification. + +Since v2.6.27 commit d26ab06ede83 ("[SCSI] zfcp: receiving an unsolicted +status can lead to I/O stall"), zfcp_fsf_status_read_handler() schedules +adapter->stat_work to re-fill the just consumed SRB from a work item. + +Now the ERP thread and the work item post SRBs in parallel. Both contexts +call the helper function zfcp_status_read_refill(). The tracking of +missing (to be posted / re-filled) SRBs is not thread-safe due to separate +atomic_read() and atomic_dec(), in order to depend on posting +success. Hence, both contexts can see +atomic_read(&adapter->stat_miss) == 1. One of the two contexts posts +one too many SRB. Zfcp gets QDIO_ERROR_SLSB_STATE on the output queue +(trace tag "qdireq1") leading to zfcp_erp_adapter_shutdown() in +zfcp_qdio_handler_error(). + +An obvious and seemingly clean fix would be to schedule stat_work from the +ERP thread and wait for it to finish. This would serialize all SRB +re-fills. However, we already have another work item wait on the ERP +thread: adapter->scan_work runs zfcp_fc_scan_ports() which calls +zfcp_fc_eval_gpn_ft(). The latter calls zfcp_erp_wait() to wait for all the +open port recoveries during zfcp auto port scan, but in fact it waits for +any pending recovery including an adapter recovery. This approach leads to +a deadlock. [see also v3.19 commit 18f87a67e6d6 ("zfcp: auto port scan +resiliency"); v2.6.37 commit d3e1088d6873 +("[SCSI] zfcp: No ERP escalation on gpn_ft eval"); +v2.6.28 commit fca55b6fb587 +("[SCSI] zfcp: fix deadlock between wq triggered port scan and ERP") +fixing v2.6.27 commit c57a39a45a76 +("[SCSI] zfcp: wait until adapter is finished with ERP during auto-port"); +v2.6.27 commit cc8c282963bd +("[SCSI] zfcp: Automatically attach remote ports")] + +Instead make the accounting of missing SRBs atomic for parallel execution +in both the ERP thread and adapter->stat_work. + +Signed-off-by: Steffen Maier <maier@linux.ibm.com> +Fixes: d26ab06ede83 ("[SCSI] zfcp: receiving an unsolicted status can lead to I/O stall") +Cc: <stable@vger.kernel.org> #2.6.27+ +Reviewed-by: Jens Remus <jremus@linux.ibm.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Acked-by: Petr Tesarik <ptesarik@suse.com> +--- + drivers/s390/scsi/zfcp_aux.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c +index df10f4e07a4a..882789fff574 100644 +--- a/drivers/s390/scsi/zfcp_aux.c ++++ b/drivers/s390/scsi/zfcp_aux.c +@@ -271,16 +271,16 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) + */ + int zfcp_status_read_refill(struct zfcp_adapter *adapter) + { +- while (atomic_read(&adapter->stat_miss) > 0) ++ while (atomic_add_unless(&adapter->stat_miss, -1, 0)) + if (zfcp_fsf_status_read(adapter->qdio)) { ++ atomic_inc(&adapter->stat_miss); /* undo add -1 */ + if (atomic_read(&adapter->stat_miss) >= + adapter->stat_read_buf_num) { + zfcp_erp_adapter_reopen(adapter, 0, "axsref1"); + return 1; + } + break; +- } else +- atomic_dec(&adapter->stat_miss); ++ } + return 0; + } + + diff --git a/patches.arch/s390-sles15-17-01-01-s390-kdump-Fix-elfcorehdr-size-calculation.patch b/patches.arch/s390-sles15-17-01-01-s390-kdump-Fix-elfcorehdr-size-calculation.patch new file mode 100644 index 0000000000..8bd69bfd7f --- /dev/null +++ b/patches.arch/s390-sles15-17-01-01-s390-kdump-Fix-elfcorehdr-size-calculation.patch @@ -0,0 +1,199 @@ +From: Philipp Rudo <prudo@linux.ibm.com> +Subject: s390/kdump: Fix elfcorehdr size calculation +Patch-mainline: v4.19-rc1 +Git-commit: 8cce437fbb5c1f2af2f63834fa05082596beca5d +References: bsc#1117953, LTC#171112 + +Description: s390/kdump: Fix elfcorehdr size calculation +Symptom: BUG_ON triggeres kernel panic in crash kernel. +Problem: When the crash kernel allocates memory for the elfcorehdr, the + assumed per-cpu memory is too small. The mis-calculation is + usually countered by enough spare memory in the overhead + (Elf_Ehdr, vmcoreinfo, etc.). However, with a growing overhead + and/or huge cpu count the calculated size gets too small + triggering the BUG_ON. +Solution: Properly calculate the required size. +Reproduction: - + +Upstream-Description: + + s390/kdump: Fix elfcorehdr size calculation + + Before the memory for the elfcorehdr is allocated the required size is + estimated with + + alloc_size = 0x1000 + get_cpu_cnt() * 0x4a0 + + mem_chunk_cnt * sizeof(Elf64_Phdr); + + Where 0x4a0 is used as size for the ELF notes to store the register + contend. This size is 8 bytes too small. Usually this does not immediately + cause a problem because the page reserved for overhead (Elf_Ehdr, + vmcoreinfo, etc.) is pretty generous. So usually there is enough spare + memory to counter the mis-calculated per cpu size. However, with growing + overhead and/or a huge cpu count the allocated size gets too small for the + elfcorehdr. Ultimately a BUG_ON is triggered causing the crash kernel to + panic. + + Fix this by properly calculating the required size instead of relying on + magic numbers. + + Fixes: a62bc07392539 ("s390/kdump: add support for vector extension") + Signed-off-by: Philipp Rudo <prudo@linux.ibm.com> + Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> + + +Signed-off-by: Philipp Rudo <prudo@linux.ibm.com> +Acked-by: Petr Tesarik <ptesarik@suse.com> +--- + arch/s390/kernel/crash_dump.c | 104 +++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 98 insertions(+), 6 deletions(-) + +--- a/arch/s390/kernel/crash_dump.c ++++ b/arch/s390/kernel/crash_dump.c +@@ -305,6 +305,15 @@ static void *kzalloc_panic(int len) + return rc; + } + ++static const char *nt_name(Elf64_Word type) ++{ ++ const char *name = "LINUX"; ++ ++ if (type == NT_PRPSINFO || type == NT_PRSTATUS || type == NT_PRFPREG) ++ name = KEXEC_CORE_NOTE_NAME; ++ return name; ++} ++ + /* + * Initialize ELF note + */ +@@ -331,11 +340,26 @@ static void *nt_init_name(void *buf, Elf + + static inline void *nt_init(void *buf, Elf64_Word type, void *desc, int d_len) + { +- const char *note_name = "LINUX"; ++ return nt_init_name(buf, type, desc, d_len, nt_name(type)); ++} + +- if (type == NT_PRPSINFO || type == NT_PRSTATUS || type == NT_PRFPREG) +- note_name = KEXEC_CORE_NOTE_NAME; +- return nt_init_name(buf, type, desc, d_len, note_name); ++/* ++ * Calculate the size of ELF note ++ */ ++static size_t nt_size_name(int d_len, const char *name) ++{ ++ size_t size; ++ ++ size = sizeof(Elf64_Nhdr); ++ size += roundup(strlen(name) + 1, 4); ++ size += roundup(d_len, 4); ++ ++ return size; ++} ++ ++static inline size_t nt_size(Elf64_Word type, int d_len) ++{ ++ return nt_size_name(d_len, nt_name(type)); + } + + /* +@@ -374,6 +398,29 @@ static void *fill_cpu_elf_notes(void *pt + } + + /* ++ * Calculate size of ELF notes per cpu ++ */ ++static size_t get_cpu_elf_notes_size(void) ++{ ++ struct save_area *sa = NULL; ++ size_t size; ++ ++ size = nt_size(NT_PRSTATUS, sizeof(struct elf_prstatus)); ++ size += nt_size(NT_PRFPREG, sizeof(elf_fpregset_t)); ++ size += nt_size(NT_S390_TIMER, sizeof(sa->timer)); ++ size += nt_size(NT_S390_TODCMP, sizeof(sa->todcmp)); ++ size += nt_size(NT_S390_TODPREG, sizeof(sa->todpreg)); ++ size += nt_size(NT_S390_CTRS, sizeof(sa->ctrs)); ++ size += nt_size(NT_S390_PREFIX, sizeof(sa->prefix)); ++ if (MACHINE_HAS_VX) { ++ size += nt_size(NT_S390_VXRS_HIGH, sizeof(sa->vxrs_high)); ++ size += nt_size(NT_S390_VXRS_LOW, sizeof(sa->vxrs_low)); ++ } ++ ++ return size; ++} ++ ++/* + * Initialize prpsinfo note (new kernel) + */ + static void *nt_prpsinfo(void *ptr) +@@ -428,6 +475,30 @@ static void *nt_vmcoreinfo(void *ptr) + return nt_init_name(ptr, 0, vmcoreinfo, size, "VMCOREINFO"); + } + ++static size_t nt_vmcoreinfo_size(void) ++{ ++ const char *name = "VMCOREINFO"; ++ char nt_name[11]; ++ Elf64_Nhdr note; ++ void *addr; ++ ++ if (copy_oldmem_kernel(&addr, &S390_lowcore.vmcore_info, sizeof(addr))) ++ return 0; ++ ++ if (copy_oldmem_kernel(¬e, addr, sizeof(note))) ++ return 0; ++ ++ memset(nt_name, 0, sizeof(nt_name)); ++ if (copy_oldmem_kernel(nt_name, addr + sizeof(note), ++ sizeof(nt_name) - 1)) ++ return 0; ++ ++ if (strcmp(nt_name, name) != 0) ++ return 0; ++ ++ return nt_size_name(note.n_descsz, name); ++} ++ + /* + * Initialize final note (needed for /proc/vmcore code) + */ +@@ -538,6 +609,27 @@ static void *notes_init(Elf64_Phdr *phdr + return ptr; + } + ++static size_t get_elfcorehdr_size(int mem_chunk_cnt) ++{ ++ size_t size; ++ ++ size = sizeof(Elf64_Ehdr); ++ /* PT_NOTES */ ++ size += sizeof(Elf64_Phdr); ++ /* nt_prpsinfo */ ++ size += nt_size(NT_PRPSINFO, sizeof(struct elf_prpsinfo)); ++ /* regsets */ ++ size += get_cpu_cnt() * get_cpu_elf_notes_size(); ++ /* nt_vmcoreinfo */ ++ size += nt_vmcoreinfo_size(); ++ /* nt_final */ ++ size += sizeof(Elf64_Nhdr); ++ /* PT_LOADS */ ++ size += mem_chunk_cnt * sizeof(Elf64_Phdr); ++ ++ return size; ++} ++ + /* + * Create ELF core header (new kernel) + */ +@@ -565,8 +657,8 @@ int elfcorehdr_alloc(unsigned long long + + mem_chunk_cnt = get_mem_chunk_cnt(); + +- alloc_size = 0x1000 + get_cpu_cnt() * 0x4a0 + +- mem_chunk_cnt * sizeof(Elf64_Phdr); ++ alloc_size = get_elfcorehdr_size(mem_chunk_cnt); ++ + hdr = kzalloc_panic(alloc_size); + /* Init elf header */ + ptr = ehdr_init(hdr, mem_chunk_cnt); diff --git a/patches.arch/s390-sles15-17-01-02-s390-kdump-Make-elfcorehdr-size-calculation-ABI-comp.patch b/patches.arch/s390-sles15-17-01-02-s390-kdump-Make-elfcorehdr-size-calculation-ABI-comp.patch new file mode 100644 index 0000000000..371cb1290f --- /dev/null +++ b/patches.arch/s390-sles15-17-01-02-s390-kdump-Make-elfcorehdr-size-calculation-ABI-comp.patch @@ -0,0 +1,79 @@ +From: Philipp Rudo <prudo@linux.ibm.com> +Subject: s390/kdump: Make elfcorehdr size calculation ABI compliant +Patch-mainline: v4.19-rc1 +Git-commit: 263b0e480c9b0fda77a89f5d6375d8a39de5c166 +References: bsc#1117953, LTC#171112 + +Description: s390/kdump: Fix elfcorehdr size calculation +Symptom: BUG_ON triggeres kernel panic in crash kernel. +Problem: When the crash kernel allocates memory for the elfcorehdr, the + assumed per-cpu memory is too small. The mis-calculation is + usually countered by enough spare memory in the overhead + (Elf_Ehdr, vmcoreinfo, etc.). However, with a growing overhead + and/or huge cpu count the calculated size gets too small + triggering the BUG_ON. +Solution: Properly calculate the required size. +Reproduction: - + +Upstream-Description: + + s390/kdump: Make elfcorehdr size calculation ABI compliant + + There are two ways to pass the vmcoreinfo to the crash kernel 1) via the + os_info mechanism and 2) via the lowcore->vmcore_info field. In the Linux + kernel only the second way is used. However, the first way is ABI for + stand-alone kdump. So other OSes use it to pass additional debug info. Make + the elfcorehdr size calculation aware of both possible ways. + + Fixes: 8cce437fbb5c ("s390/kdump: Fix elfcorehdr size calculation") + Signed-off-by: Philipp Rudo <prudo@linux.ibm.com> + Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> + Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> + + +Signed-off-by: Philipp Rudo <prudo@linux.ibm.com> +Acked-by: Petr Tesarik <ptesarik@suse.com> +--- + arch/s390/kernel/crash_dump.c | 28 +++++++++++----------------- + 1 file changed, 11 insertions(+), 17 deletions(-) + +--- a/arch/s390/kernel/crash_dump.c ++++ b/arch/s390/kernel/crash_dump.c +@@ -477,26 +477,20 @@ static void *nt_vmcoreinfo(void *ptr) + + static size_t nt_vmcoreinfo_size(void) + { +- const char *name = "VMCOREINFO"; +- char nt_name[11]; +- Elf64_Nhdr note; +- void *addr; ++ const char *name = VMCOREINFO_NOTE_NAME; ++ unsigned long size; ++ void *vmcoreinfo; ++ ++ vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size); ++ if (vmcoreinfo) ++ return nt_size_name(size, name); + +- if (copy_oldmem_kernel(&addr, &S390_lowcore.vmcore_info, sizeof(addr))) ++ vmcoreinfo = get_vmcoreinfo_old(&size); ++ if (!vmcoreinfo) + return 0; + +- if (copy_oldmem_kernel(¬e, addr, sizeof(note))) +- return 0; +- +- memset(nt_name, 0, sizeof(nt_name)); +- if (copy_oldmem_kernel(nt_name, addr + sizeof(note), +- sizeof(nt_name) - 1)) +- return 0; +- +- if (strcmp(nt_name, name) != 0) +- return 0; +- +- return nt_size_name(note.n_descsz, name); ++ kfree(vmcoreinfo); ++ return nt_size_name(size, name); + } + + /* diff --git a/patches.arch/s390-sles15-17-02-01-s390-qeth-remove-outdated-portname-debug-msg.patch b/patches.arch/s390-sles15-17-02-01-s390-qeth-remove-outdated-portname-debug-msg.patch new file mode 100644 index 0000000000..fd377b8737 --- /dev/null +++ b/patches.arch/s390-sles15-17-02-01-s390-qeth-remove-outdated-portname-debug-msg.patch @@ -0,0 +1,48 @@ +From: Julian Wiedmann <jwi@linux.ibm.com> +Subject: s390/qeth: remove outdated portname debug msg +Patch-mainline: v4.17-rc1 +Git-commit: d857e11193a24d6623bb562e9b26cde582bd877f +References: bsc#1117953, LTC#172960 + +Description: qeth: sanitize strings in debug messages +Symptom: Use-after free when reading from s390 debug files. +Problem: Pointers in sprintf-formatted s390dbf debug files are + dereferenced whenever the trace file is read from. + If the referenced data has a shorter life-time than the trace + file, any read operation can result in a use-after-free. +Solution: Sanitize the debug entries, remove all usage of indirect data. +Reproduction: Workload that creates and removes many qeth-based network + interfaces, while reading from s390 debug files. + +Upstream-Description: + + s390/qeth: remove outdated portname debug msg + + The 'portname' attribute is deprecated and setting it has no effect. + + Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com> + Signed-off-by: David S. Miller <davem@davemloft.net> + + +Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> +Acked-by: Petr Tesarik <ptesarik@suse.com> +--- + drivers/s390/net/qeth_core_main.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -719,11 +719,8 @@ static int qeth_check_idx_response(struc + + QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN); + if ((buffer[2] & 0xc0) == 0xc0) { +- QETH_DBF_MESSAGE(2, "received an IDX TERMINATE " +- "with cause code 0x%02x%s\n", +- buffer[4], +- ((buffer[4] == 0x22) ? +- " -- try another portname" : "")); ++ QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#02x\n", ++ buffer[4]); + QETH_CARD_TEXT(card, 2, "ckidxres"); + QETH_CARD_TEXT(card, 2, " idxterm"); + QETH_CARD_TEXT_(card, 2, " rc%d", -EIO); diff --git a/patches.arch/s390-sles15-17-02-02-s390-qeth-sanitize-strings-in-debug-messages.patch b/patches.arch/s390-sles15-17-02-02-s390-qeth-sanitize-strings-in-debug-messages.patch new file mode 100644 index 0000000000..624f9b88bb --- /dev/null +++ b/patches.arch/s390-sles15-17-02-02-s390-qeth-sanitize-strings-in-debug-messages.patch @@ -0,0 +1,642 @@ +From: Julian Wiedmann <jwi@linux.ibm.com> +Subject: s390/qeth: sanitize strings in debug messages +Patch-mainline: v4.20-rc2 +Git-commit: e19e5be8b4cafa8b3f8b0cd1b1dfe20fa0145b83 +References: bsc#1117953, LTC#172960 + +Description: qeth: sanitize strings in debug messages +Symptom: Use-after free when reading from s390 debug files. +Problem: Pointers in sprintf-formatted s390dbf debug files are + dereferenced whenever the trace file is read from. + If the referenced data has a shorter life-time than the trace + file, any read operation can result in a use-after-free. +Solution: Sanitize the debug entries, remove all usage of indirect data. +Reproduction: Workload that creates and removes many qeth-based network + interfaces, while reading from s390 debug files. + +Upstream-Description: + + s390/qeth: sanitize strings in debug messages + + As Documentation/s390/s390dbf.txt states quite clearly, using any + pointer in sprinf-formatted s390dbf debug entries is dangerous. + The pointers are dereferenced whenever the trace file is read from. + So if the referenced data has a shorter life-time than the trace file, + any read operation can result in a use-after-free. + + So rip out all hazardous use of indirect data, and replace any usage of + dev_name() and such by the Bus ID number. + + Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> + Signed-off-by: David S. Miller <davem@davemloft.net> + + +Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> +Acked-by: Petr Tesarik <ptesarik@suse.com> +--- + drivers/s390/net/qeth_core.h | 15 ++++ + drivers/s390/net/qeth_core_main.c | 127 +++++++++++++++++--------------------- + drivers/s390/net/qeth_l2_main.c | 25 +++---- + drivers/s390/net/qeth_l3_main.c | 104 ++++++++++--------------------- + 4 files changed, 119 insertions(+), 152 deletions(-) + +--- a/drivers/s390/net/qeth_core.h ++++ b/drivers/s390/net/qeth_core.h +@@ -84,6 +84,18 @@ struct qeth_dbf_info { + #define SENSE_RESETTING_EVENT_BYTE 1 + #define SENSE_RESETTING_EVENT_FLAG 0x80 + ++static inline u32 qeth_get_device_id(struct ccw_device *cdev) ++{ ++ struct ccw_dev_id dev_id; ++ u32 id; ++ ++ ccw_device_get_id(cdev, &dev_id); ++ id = dev_id.devno; ++ id |= (u32) (dev_id.ssid << 16); ++ ++ return id; ++} ++ + /* + * Common IO related definitions + */ +@@ -94,7 +106,8 @@ struct qeth_dbf_info { + #define CARD_RDEV_ID(card) dev_name(&card->read.ccwdev->dev) + #define CARD_WDEV_ID(card) dev_name(&card->write.ccwdev->dev) + #define CARD_DDEV_ID(card) dev_name(&card->data.ccwdev->dev) +-#define CHANNEL_ID(channel) dev_name(&channel->ccwdev->dev) ++#define CCW_DEVID(cdev) (qeth_get_device_id(cdev)) ++#define CARD_DEVID(card) (CCW_DEVID(CARD_RDEV(card))) + + /** + * card stuff +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -545,8 +545,8 @@ static int __qeth_issue_next_read(struct + if (!iob) { + dev_warn(&card->gdev->dev, "The qeth device driver " + "failed to recover an error on the device\n"); +- QETH_DBF_MESSAGE(2, "%s issue_next_read failed: no iob " +- "available\n", dev_name(&card->gdev->dev)); ++ QETH_DBF_MESSAGE(2, "issue_next_read on device %x failed: no iob available\n", ++ CARD_DEVID(card)); + return -ENOMEM; + } + qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE); +@@ -554,8 +554,8 @@ static int __qeth_issue_next_read(struct + rc = ccw_device_start(card->read.ccwdev, &card->read.ccw, + (addr_t) iob, 0, 0); + if (rc) { +- QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! " +- "rc=%i\n", dev_name(&card->gdev->dev), rc); ++ QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n", ++ rc, CARD_DEVID(card)); + atomic_set(&card->read.irq_pending, 0); + card->read_or_write_problem = 1; + qeth_schedule_recovery(card); +@@ -607,16 +607,14 @@ static void qeth_issue_ipa_msg(struct qe + const char *ipa_name; + int com = cmd->hdr.command; + ipa_name = qeth_get_ipa_cmd_name(com); ++ + if (rc) +- QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s/%s returned " +- "x%X \"%s\"\n", +- ipa_name, com, dev_name(&card->gdev->dev), +- QETH_CARD_IFNAME(card), rc, +- qeth_get_ipa_msg(rc)); ++ QETH_DBF_MESSAGE(2, "IPA: %s(%#x) for device %x returned %#x \"%s\"\n", ++ ipa_name, com, CARD_DEVID(card), rc, ++ qeth_get_ipa_msg(rc)); + else +- QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s/%s succeeded\n", +- ipa_name, com, dev_name(&card->gdev->dev), +- QETH_CARD_IFNAME(card)); ++ QETH_DBF_MESSAGE(5, "IPA: %s(%#x) for device %x succeeded\n", ++ ipa_name, com, CARD_DEVID(card)); + } + + static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, +@@ -726,7 +724,7 @@ static int qeth_check_idx_response(struc + + QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN); + if ((buffer[2] & 0xc0) == 0xc0) { +- QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#02x\n", ++ QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#04x\n", + buffer[4]); + QETH_CARD_TEXT(card, 2, "ckidxres"); + QETH_CARD_TEXT(card, 2, " idxterm"); +@@ -1033,8 +1031,8 @@ static int qeth_get_problem(struct ccw_d + QETH_CARD_TEXT(card, 2, "CGENCHK"); + dev_warn(&cdev->dev, "The qeth device driver " + "failed to recover an error on the device\n"); +- QETH_DBF_MESSAGE(2, "%s check on device dstat=x%x, cstat=x%x\n", +- dev_name(&cdev->dev), dstat, cstat); ++ QETH_DBF_MESSAGE(2, "check on channel %x with dstat=%#x, cstat=%#x\n", ++ CCW_DEVID(cdev), dstat, cstat); + print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET, + 16, 1, irb, 64, 1); + return 1; +@@ -1077,8 +1075,8 @@ static long __qeth_check_irb_error(struc + + switch (PTR_ERR(irb)) { + case -EIO: +- QETH_DBF_MESSAGE(2, "%s i/o-error on device\n", +- dev_name(&cdev->dev)); ++ QETH_DBF_MESSAGE(2, "i/o-error on channel %x\n", ++ CCW_DEVID(cdev)); + QETH_CARD_TEXT(card, 2, "ckirberr"); + QETH_CARD_TEXT_(card, 2, " rc%d", -EIO); + break; +@@ -1095,8 +1093,8 @@ static long __qeth_check_irb_error(struc + } + break; + default: +- QETH_DBF_MESSAGE(2, "%s unknown error %ld on device\n", +- dev_name(&cdev->dev), PTR_ERR(irb)); ++ QETH_DBF_MESSAGE(2, "unknown error %ld on channel %x\n", ++ PTR_ERR(irb), CCW_DEVID(cdev)); + QETH_CARD_TEXT(card, 2, "ckirberr"); + QETH_CARD_TEXT(card, 2, " rc???"); + } +@@ -1165,9 +1163,9 @@ static void qeth_irq(struct ccw_device * + dev_warn(&channel->ccwdev->dev, + "The qeth device driver failed to recover " + "an error on the device\n"); +- QETH_DBF_MESSAGE(2, "%s sense data available. cstat " +- "0x%X dstat 0x%X\n", +- dev_name(&channel->ccwdev->dev), cstat, dstat); ++ QETH_DBF_MESSAGE(2, "sense data available on channel %x: cstat %#X dstat %#X\n", ++ CCW_DEVID(channel->ccwdev), cstat, ++ dstat); + print_hex_dump(KERN_WARNING, "qeth: irb ", + DUMP_PREFIX_OFFSET, 16, 1, irb, 32, 1); + print_hex_dump(KERN_WARNING, "qeth: sense data ", +@@ -1921,8 +1919,8 @@ static int qeth_idx_activate_channel(str + if (channel->state != CH_STATE_ACTIVATING) { + dev_warn(&channel->ccwdev->dev, "The qeth device driver" + " failed to recover an error on the device\n"); +- QETH_DBF_MESSAGE(2, "%s IDX activate timed out\n", +- dev_name(&channel->ccwdev->dev)); ++ QETH_DBF_MESSAGE(2, "IDX activate timed out on channel %x\n", ++ CCW_DEVID(channel->ccwdev)); + QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME); + qeth_clear_cmd_buffers(channel); + return -ETIME; +@@ -1959,17 +1957,15 @@ static void qeth_idx_write_cb(struct qet + "The adapter is used exclusively by another " + "host\n"); + else +- QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on write channel:" +- " negative reply\n", +- dev_name(&card->write.ccwdev->dev)); ++ QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: negative reply\n", ++ CCW_DEVID(channel->ccwdev)); + goto out; + } + memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2); + if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) { +- QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on write channel: " +- "function level mismatch (sent: 0x%x, received: " +- "0x%x)\n", dev_name(&card->write.ccwdev->dev), +- card->info.func_level, temp); ++ QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: function level mismatch (sent: %#x, received: %#x)\n", ++ CCW_DEVID(channel->ccwdev), ++ card->info.func_level, temp); + goto out; + } + channel->state = CH_STATE_UP; +@@ -2007,9 +2003,8 @@ static void qeth_idx_read_cb(struct qeth + "insufficient authorization\n"); + break; + default: +- QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel:" +- " negative reply\n", +- dev_name(&card->read.ccwdev->dev)); ++ QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: negative reply\n", ++ CCW_DEVID(channel->ccwdev)); + } + QETH_CARD_TEXT_(card, 2, "idxread%c", + QETH_IDX_ACT_CAUSE_CODE(iob->data)); +@@ -2018,10 +2013,9 @@ static void qeth_idx_read_cb(struct qeth + + memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2); + if (temp != qeth_peer_func_level(card->info.func_level)) { +- QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel: function " +- "level mismatch (sent: 0x%x, received: 0x%x)\n", +- dev_name(&card->read.ccwdev->dev), +- card->info.func_level, temp); ++ QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: function level mismatch (sent: %#x, received: %#x)\n", ++ CCW_DEVID(channel->ccwdev), ++ card->info.func_level, temp); + goto out; + } + memcpy(&card->token.issuer_rm_r, +@@ -2129,9 +2123,8 @@ int qeth_send_control_data(struct qeth_c + (addr_t) iob, 0, 0); + spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags); + if (rc) { +- QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: " +- "ccw_device_start rc = %i\n", +- dev_name(&card->write.ccwdev->dev), rc); ++ QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n", ++ CARD_DEVID(card), rc); + QETH_CARD_TEXT_(card, 2, " err%d", rc); + spin_lock_irqsave(&card->lock, flags); + list_del_init(&reply->list); +@@ -2936,8 +2929,8 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_ + } else { + dev_warn(&card->gdev->dev, + "The qeth driver ran out of channel command buffers\n"); +- QETH_DBF_MESSAGE(1, "%s The qeth driver ran out of channel command buffers", +- dev_name(&card->gdev->dev)); ++ QETH_DBF_MESSAGE(1, "device %x ran out of channel command buffers", ++ CARD_DEVID(card)); + } + + return iob; +@@ -3081,10 +3074,9 @@ static int qeth_query_ipassists_cb(struc + return -0; + default: + if (cmd->hdr.return_code) { +- QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled " +- "rc=%d\n", +- dev_name(&card->gdev->dev), +- cmd->hdr.return_code); ++ QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n", ++ CARD_DEVID(card), ++ cmd->hdr.return_code); + return 0; + } + } +@@ -3096,8 +3088,8 @@ static int qeth_query_ipassists_cb(struc + card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; + card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; + } else +- QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected" +- "\n", dev_name(&card->gdev->dev)); ++ QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Flawed LIC detected\n", ++ CARD_DEVID(card)); + return 0; + } + +@@ -4320,10 +4312,9 @@ static int qeth_setadpparms_set_access_c + cmd->data.setadapterparms.hdr.return_code); + if (cmd->data.setadapterparms.hdr.return_code != + SET_ACCESS_CTRL_RC_SUCCESS) +- QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n", +- card->gdev->dev.kobj.name, +- access_ctrl_req->subcmd_code, +- cmd->data.setadapterparms.hdr.return_code); ++ QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%#x) on device %x: %#x\n", ++ access_ctrl_req->subcmd_code, CARD_DEVID(card), ++ cmd->data.setadapterparms.hdr.return_code); + switch (cmd->data.setadapterparms.hdr.return_code) { + case SET_ACCESS_CTRL_RC_SUCCESS: + if (card->options.isolation == ISOLATION_MODE_NONE) { +@@ -4335,14 +4326,14 @@ static int qeth_setadpparms_set_access_c + } + break; + case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED: +- QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already " +- "deactivated\n", dev_name(&card->gdev->dev)); ++ QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already deactivated\n", ++ CARD_DEVID(card)); + if (fallback) + card->options.isolation = card->options.prev_isolation; + break; + case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED: +- QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already" +- " activated\n", dev_name(&card->gdev->dev)); ++ QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already activated\n", ++ CARD_DEVID(card)); + if (fallback) + card->options.isolation = card->options.prev_isolation; + break; +@@ -4428,10 +4419,8 @@ int qeth_set_access_ctrl_online(struct q + rc = qeth_setadpparms_set_access_ctrl(card, + card->options.isolation, fallback); + if (rc) { +- QETH_DBF_MESSAGE(3, +- "IPA(SET_ACCESS_CTRL,%s,%d) sent failed\n", +- card->gdev->dev.kobj.name, +- rc); ++ QETH_DBF_MESSAGE(3, "IPA(SET_ACCESS_CTRL(%d) on device %x: sent failed\n", ++ rc, CARD_DEVID(card)); + rc = -EOPNOTSUPP; + } + } else if (card->options.isolation != ISOLATION_MODE_NONE) { +@@ -4657,8 +4646,8 @@ static int qeth_snmp_command(struct qeth + rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len, + qeth_snmp_command_cb, (void *)&qinfo); + if (rc) +- QETH_DBF_MESSAGE(2, "SNMP command failed on %s: (0x%x)\n", +- QETH_CARD_IFNAME(card), rc); ++ QETH_DBF_MESSAGE(2, "SNMP command failed on device %x: (%#x)\n", ++ CARD_DEVID(card), rc); + else { + if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) + rc = -EFAULT; +@@ -4892,8 +4881,8 @@ static void qeth_determine_capabilities( + + rc = qeth_read_conf_data(card, (void **) &prcd, &length); + if (rc) { +- QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", +- dev_name(&card->gdev->dev), rc); ++ QETH_DBF_MESSAGE(2, "qeth_read_conf_data on device %x returned %i\n", ++ CARD_DEVID(card), rc); + QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); + goto out_offline; + } +@@ -5118,8 +5107,8 @@ int qeth_core_hardsetup_card(struct qeth + qeth_update_from_chp_desc(card); + retry: + if (retries < 3) +- QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", +- dev_name(&card->gdev->dev)); ++ QETH_DBF_MESSAGE(2, "Retrying to do IDX activates on device %x.\n", ++ CARD_DEVID(card)); + rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD); + ccw_device_set_offline(CARD_DDEV(card)); + ccw_device_set_offline(CARD_WDEV(card)); +@@ -5217,8 +5206,8 @@ retriable: + out: + dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " + "an error on the device\n"); +- QETH_DBF_MESSAGE(2, "%s Initialization in hardsetup failed! rc=%d\n", +- dev_name(&card->gdev->dev), rc); ++ QETH_DBF_MESSAGE(2, "Initialization for device %x failed in hardsetup! rc=%d\n", ++ CARD_DEVID(card), rc); + return rc; + } + EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card); +--- a/drivers/s390/net/qeth_l2_main.c ++++ b/drivers/s390/net/qeth_l2_main.c +@@ -164,11 +164,11 @@ static int qeth_l2_send_setgroupmac(stru + QETH_CARD_TEXT(card, 2, "L2Sgmac"); + rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETGMAC); + if (rc == -EEXIST) +- QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s\n", +- mac, QETH_CARD_IFNAME(card)); ++ QETH_DBF_MESSAGE(2, "MAC already registered on device %x\n", ++ CARD_DEVID(card)); + else if (rc) +- QETH_DBF_MESSAGE(2, "Could not set group MAC %pM on %s: %d\n", +- mac, QETH_CARD_IFNAME(card), rc); ++ QETH_DBF_MESSAGE(2, "Failed to register MAC on device %x: %d\n", ++ CARD_DEVID(card), rc); + return rc; + } + +@@ -179,9 +179,8 @@ static int qeth_l2_send_delgroupmac(stru + QETH_CARD_TEXT(card, 2, "L2Dgmac"); + rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELGMAC); + if (rc) +- QETH_DBF_MESSAGE(2, +- "Could not delete group MAC %pM on %s: %d\n", +- mac, QETH_CARD_IFNAME(card), rc); ++ QETH_DBF_MESSAGE(2, "Failed to delete MAC on device %u: %d\n", ++ CARD_DEVID(card), rc); + return rc; + } + +@@ -304,9 +303,9 @@ static int qeth_l2_send_setdelvlan_cb(st + + QETH_CARD_TEXT(card, 2, "L2sdvcb"); + if (cmd->hdr.return_code) { +- QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x.\n", ++ QETH_DBF_MESSAGE(2, "Error in processing VLAN %u on device %x: %#x.\n", + cmd->data.setdelvlan.vlan_id, +- QETH_CARD_IFNAME(card), cmd->hdr.return_code); ++ CARD_DEVID(card), cmd->hdr.return_code); + QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command); + QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code); + } +@@ -518,8 +517,8 @@ static int qeth_l2_request_initial_mac(s + rc = qeth_vm_request_mac(card); + if (!rc) + goto out; +- QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %s: x%x\n", +- CARD_BUS_ID(card), rc); ++ QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %x: %#x\n", ++ CARD_DEVID(card), rc); + QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc); + /* fall back to alternative mechanism: */ + } +@@ -530,8 +529,8 @@ static int qeth_l2_request_initial_mac(s + card->info.guestlan) { + rc = qeth_setadpparms_change_macaddr(card); + if (rc) { +- QETH_DBF_MESSAGE(2, "couldn't get MAC address on " +- "device %s: x%x\n", CARD_BUS_ID(card), rc); ++ QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n", ++ CARD_DEVID(card), rc); + QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc); + return rc; + } +--- a/drivers/s390/net/qeth_l3_main.c ++++ b/drivers/s390/net/qeth_l3_main.c +@@ -560,9 +560,8 @@ int qeth_l3_setrouting_v4(struct qeth_ca + QETH_PROT_IPV4); + if (rc) { + card->options.route4.type = NO_ROUTER; +- QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" +- " on %s. Type set to 'no router'.\n", rc, +- QETH_CARD_IFNAME(card)); ++ QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n", ++ rc, CARD_DEVID(card)); + } + return rc; + } +@@ -585,9 +584,8 @@ int qeth_l3_setrouting_v6(struct qeth_ca + QETH_PROT_IPV6); + if (rc) { + card->options.route6.type = NO_ROUTER; +- QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" +- " on %s. Type set to 'no router'.\n", rc, +- QETH_CARD_IFNAME(card)); ++ QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n", ++ rc, CARD_DEVID(card)); + } + #endif + return rc; +@@ -1290,8 +1288,8 @@ qeth_diags_trace_cb(struct qeth_card *ca + } + break; + default: +- QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n", +- cmd->data.diagass.action, QETH_CARD_IFNAME(card)); ++ QETH_DBF_MESSAGE(2, "Unknown sniffer action (%#06x) on device %x\n", ++ cmd->data.diagass.action, CARD_DEVID(card)); + } + + return 0; +@@ -1973,32 +1971,25 @@ static void qeth_l3_set_multicast_list(s + qeth_l3_handle_promisc_mode(card); + } + +-static const char *qeth_l3_arp_get_error_cause(int *rc) ++static int qeth_l3_arp_makerc(int rc) + { +- switch (*rc) { +- case QETH_IPA_ARP_RC_FAILED: +- *rc = -EIO; +- return "operation failed"; ++ switch (rc) { ++ case IPA_RC_SUCCESS: ++ return 0; + case QETH_IPA_ARP_RC_NOTSUPP: +- *rc = -EOPNOTSUPP; +- return "operation not supported"; +- case QETH_IPA_ARP_RC_OUT_OF_RANGE: +- *rc = -EINVAL; +- return "argument out of range"; + case QETH_IPA_ARP_RC_Q_NOTSUPP: +- *rc = -EOPNOTSUPP; +- return "query operation not supported"; ++ return -EOPNOTSUPP; ++ case QETH_IPA_ARP_RC_OUT_OF_RANGE: ++ return -EINVAL; + case QETH_IPA_ARP_RC_Q_NO_DATA: +- *rc = -ENOENT; +- return "no query data available"; ++ return -ENOENT; + default: +- return "unknown error"; ++ return -EIO; + } + } + + static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) + { +- int tmp; + int rc; + + QETH_CARD_TEXT(card, 3, "arpstnoe"); +@@ -2016,13 +2007,10 @@ static int qeth_l3_arp_set_no_entries(st + rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_SET_NO_ENTRIES, + no_entries); +- if (rc) { +- tmp = rc; +- QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on " +- "%s: %s (0x%x/%d)\n", QETH_CARD_IFNAME(card), +- qeth_l3_arp_get_error_cause(&rc), tmp, tmp); +- } +- return rc; ++ if (rc) ++ QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on device %x: %#x\n", ++ CARD_DEVID(card), rc); ++ return qeth_l3_arp_makerc(rc); + } + + static __u32 get_arp_entry_size(struct qeth_card *card, +@@ -2172,7 +2160,6 @@ static int qeth_l3_query_arp_cache_info( + { + struct qeth_cmd_buffer *iob; + struct qeth_ipa_cmd *cmd; +- int tmp; + int rc; + + QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot); +@@ -2191,15 +2178,10 @@ static int qeth_l3_query_arp_cache_info( + rc = qeth_l3_send_ipa_arp_cmd(card, iob, + QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN, + qeth_l3_arp_query_cb, (void *)qinfo); +- if (rc) { +- tmp = rc; +- QETH_DBF_MESSAGE(2, +- "Error while querying ARP cache on %s: %s " +- "(0x%x/%d)\n", QETH_CARD_IFNAME(card), +- qeth_l3_arp_get_error_cause(&rc), tmp, tmp); +- } +- +- return rc; ++ if (rc) ++ QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n", ++ CARD_DEVID(card), rc); ++ return qeth_l3_arp_makerc(rc); + } + + static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) +@@ -2255,8 +2237,6 @@ static int qeth_l3_arp_add_entry(struct + struct qeth_arp_cache_entry *entry) + { + struct qeth_cmd_buffer *iob; +- char buf[16]; +- int tmp; + int rc; + + QETH_CARD_TEXT(card, 3, "arpadent"); +@@ -2282,14 +2262,10 @@ static int qeth_l3_arp_add_entry(struct + sizeof(struct qeth_arp_cache_entry), + (unsigned long) entry, + qeth_setassparms_cb, NULL); +- if (rc) { +- tmp = rc; +- qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); +- QETH_DBF_MESSAGE(2, "Could not add ARP entry for address %s " +- "on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), +- qeth_l3_arp_get_error_cause(&rc), tmp, tmp); +- } +- return rc; ++ if (rc) ++ QETH_DBF_MESSAGE(2, "Could not add ARP entry on device %x: %#x\n", ++ CARD_DEVID(card), rc); ++ return qeth_l3_arp_makerc(rc); + } + + static int qeth_l3_arp_remove_entry(struct qeth_card *card, +@@ -2297,7 +2273,6 @@ static int qeth_l3_arp_remove_entry(stru + { + struct qeth_cmd_buffer *iob; + char buf[16] = {0, }; +- int tmp; + int rc; + + QETH_CARD_TEXT(card, 3, "arprment"); +@@ -2322,21 +2297,15 @@ static int qeth_l3_arp_remove_entry(stru + rc = qeth_send_setassparms(card, iob, + 12, (unsigned long)buf, + qeth_setassparms_cb, NULL); +- if (rc) { +- tmp = rc; +- memset(buf, 0, 16); +- qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); +- QETH_DBF_MESSAGE(2, "Could not delete ARP entry for address %s" +- " on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), +- qeth_l3_arp_get_error_cause(&rc), tmp, tmp); +- } +- return rc; ++ if (rc) ++ QETH_DBF_MESSAGE(2, "Could not delete ARP entry on device %x: %#x\n", ++ CARD_DEVID(card), rc); ++ return qeth_l3_arp_makerc(rc); + } + + static int qeth_l3_arp_flush_cache(struct qeth_card *card) + { + int rc; +- int tmp; + + QETH_CARD_TEXT(card, 3, "arpflush"); + +@@ -2352,13 +2321,10 @@ static int qeth_l3_arp_flush_cache(struc + } + rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_FLUSH_CACHE, 0); +- if (rc) { +- tmp = rc; +- QETH_DBF_MESSAGE(2, "Could not flush ARP cache on %s: %s " +- "(0x%x/%d)\n", QETH_CARD_IFNAME(card), +- qeth_l3_arp_get_error_cause(&rc), tmp, tmp); +- } +- return rc; ++ if (rc) ++ QETH_DBF_MESSAGE(2, "Could not flush ARP cache on device %x: %#x\n", ++ CARD_DEVID(card), rc); ++ return qeth_l3_arp_makerc(rc); + } + + static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) diff --git a/patches.arch/s390-sles15-17-03-s390-qeth-fix-length-check-in-SNMP-processing.patch b/patches.arch/s390-sles15-17-03-s390-qeth-fix-length-check-in-SNMP-processing.patch new file mode 100644 index 0000000000..7504033828 --- /dev/null +++ b/patches.arch/s390-sles15-17-03-s390-qeth-fix-length-check-in-SNMP-processing.patch @@ -0,0 +1,107 @@ +From: Julian Wiedmann <jwi@linux.ibm.com> +Subject: s390/qeth: fix length check in SNMP processing +Patch-mainline: v4.20-rc5 +Git-commit: 9a764c1e59684c0358e16ccaafd870629f2cfe67 +References: bsc#1117953, LTC#173657 + +Description: qeth: fix length check in SNMP processing +Symptom: Undefined behaviour. +Problem: The response for a SNMP request can consist of multiple parts, + which the cmd callback stages into a kernel buffer until all + parts have been received. If the callback detects that the + staging buffer provides insufficient space, it bails out with + error. + This processing is buggy for the first part of the response - + while it initially checks for a length of 'data_len', it later + copies an additional amount of + 'offsetof(struct qeth_snmp_cmd, data)' bytes. +Solution: Fix the calculation of 'data_len' for the first part of the + response. +Reproduction: - + +Upstream-Description: + + s390/qeth: fix length check in SNMP processing + + The response for a SNMP request can consist of multiple parts, which + the cmd callback stages into a kernel buffer until all parts have been + received. If the callback detects that the staging buffer provides + insufficient space, it bails out with error. + This processing is buggy for the first part of the response - while it + initially checks for a length of 'data_len', it later copies an + additional amount of 'offsetof(struct qeth_snmp_cmd, data)' bytes. + + Fix the calculation of 'data_len' for the first part of the response. + This also nicely cleans up the memcpy code. + + Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") + Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> + Reviewed-by: Ursula Braun <ubraun@linux.ibm.com> + Signed-off-by: David S. Miller <davem@davemloft.net> + + +Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> +Acked-by: Petr Tesarik <ptesarik@suse.com> +--- + drivers/s390/net/qeth_core_main.c | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -4541,8 +4541,8 @@ static int qeth_snmp_command_cb(struct q + { + struct qeth_ipa_cmd *cmd; + struct qeth_arp_query_info *qinfo; +- struct qeth_snmp_cmd *snmp; + unsigned char *data; ++ void *snmp_data; + __u16 data_len; + + QETH_CARD_TEXT(card, 3, "snpcmdcb"); +@@ -4550,7 +4550,6 @@ static int qeth_snmp_command_cb(struct q + cmd = (struct qeth_ipa_cmd *) sdata; + data = (unsigned char *)((char *)cmd - reply->offset); + qinfo = (struct qeth_arp_query_info *) reply->param; +- snmp = &cmd->data.setadapterparms.data.snmp; + + if (cmd->hdr.return_code) { + QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code); +@@ -4563,10 +4562,15 @@ static int qeth_snmp_command_cb(struct q + return 0; + } + data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data)); +- if (cmd->data.setadapterparms.hdr.seq_no == 1) +- data_len -= (__u16)((char *)&snmp->data - (char *)cmd); +- else +- data_len -= (__u16)((char *)&snmp->request - (char *)cmd); ++ if (cmd->data.setadapterparms.hdr.seq_no == 1) { ++ snmp_data = &cmd->data.setadapterparms.data.snmp; ++ data_len -= offsetof(struct qeth_ipa_cmd, ++ data.setadapterparms.data.snmp); ++ } else { ++ snmp_data = &cmd->data.setadapterparms.data.snmp.request; ++ data_len -= offsetof(struct qeth_ipa_cmd, ++ data.setadapterparms.data.snmp.request); ++ } + + /* check if there is enough room in userspace */ + if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { +@@ -4579,16 +4583,9 @@ static int qeth_snmp_command_cb(struct q + QETH_CARD_TEXT_(card, 4, "sseqn%i", + cmd->data.setadapterparms.hdr.seq_no); + /*copy entries to user buffer*/ +- if (cmd->data.setadapterparms.hdr.seq_no == 1) { +- memcpy(qinfo->udata + qinfo->udata_offset, +- (char *)snmp, +- data_len + offsetof(struct qeth_snmp_cmd, data)); +- qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data); +- } else { +- memcpy(qinfo->udata + qinfo->udata_offset, +- (char *)&snmp->request, data_len); +- } ++ memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len); + qinfo->udata_offset += data_len; ++ + /* check if all replies received ... */ + QETH_CARD_TEXT_(card, 4, "srtot%i", + cmd->data.setadapterparms.hdr.used_total); diff --git a/patches.arch/s390-sles15-dasd-fix-deadlock-in-dasd_times_out.patch b/patches.arch/s390-sles15-dasd-fix-deadlock-in-dasd_times_out.patch new file mode 100644 index 0000000000..6f812bb09f --- /dev/null +++ b/patches.arch/s390-sles15-dasd-fix-deadlock-in-dasd_times_out.patch @@ -0,0 +1,62 @@ +From: Stefan Haberland <sth@linux.ibm.com> +Subject: dasd: fix deadlock in dasd_times_out +Patch-mainline: never, fixed differently +References: bsc#1121477, LTC#174111 + +Description: dasd: fix deadlock in dasd_times_out +Symptom: System does not respond after disk timeout. +Problem: The dasd_times_out function processes requests that have an + internal timeout as well as an external timeout called through + dasd_ioctl_abortio(). + For the latter type of requests the CQR may be already in a final + state. The if-else path in dasd_times_out does not handle CQRs in + the final states DASD_CQR_DONE, DASD_CQR_FAILED and + DASD_CQR_TERMINATED and therefore the ccw device lock is never + freed. +Solution: Provide __dasd_cancel_req that is called with the ccw device lock + held to simplify the locking in dasd_times_out and fix the + deadlock issue. Also ensure that interrupts are disabled. The + function may get called with interrupts enabled or already + disabled. +Reproduction: Run IO on disks that do not respond to IO requests in a given + amount of time for example due to hardware failure or reserved + disk state. + + +Signed-off-by: Stefan Haberland <sth@linux.ibm.com> +[ ptesarik: Commit 1bcdb5354aee2c0abcd13d912be35ae39a4144b6 is backported + separately. The interrupt disable issue is fixed in mainline by commit + e443343e509aac82e7281020f25bf8fa0dd46ab7; not backported to SLE15. ] +Acked-by: Petr Tesarik <ptesarik@suse.com> +--- + drivers/s390/block/dasd.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/s390/block/dasd.c ++++ b/drivers/s390/block/dasd.c +@@ -3072,6 +3072,7 @@ enum blk_eh_timer_return dasd_times_out( + struct dasd_ccw_req *cqr = req->completion_data; + struct dasd_block *block = req->q->queuedata; + struct dasd_device *device; ++ unsigned long flags; + int rc = 0; + + if (!cqr) +@@ -3084,7 +3085,7 @@ enum blk_eh_timer_return dasd_times_out( + " dasd_times_out cqr %p status %x", + cqr, cqr->status); + +- spin_lock(&block->queue_lock); ++ spin_lock_irqsave(&block->queue_lock, flags); + spin_lock(get_ccwdev_lock(device->cdev)); + cqr->retries = -1; + cqr->intrc = -ETIMEDOUT; +@@ -3124,7 +3125,7 @@ enum blk_eh_timer_return dasd_times_out( + } + spin_unlock(get_ccwdev_lock(device->cdev)); + dasd_schedule_block_bh(block); +- spin_unlock(&block->queue_lock); ++ spin_unlock_irqrestore(&block->queue_lock, flags); + + return rc ? BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; + } diff --git a/patches.drivers/ALSA-cs46xx-Potential-NULL-dereference-in-probe.patch b/patches.drivers/ALSA-cs46xx-Potential-NULL-dereference-in-probe.patch new file mode 100644 index 0000000000..9666bb581c --- /dev/null +++ b/patches.drivers/ALSA-cs46xx-Potential-NULL-dereference-in-probe.patch @@ -0,0 +1,37 @@ +From 1524f4e47f90b27a3ac84efbdd94c63172246a6f Mon Sep 17 00:00:00 2001 +From: Dan Carpenter <dan.carpenter@oracle.com> +Date: Tue, 8 Jan 2019 10:43:30 +0300 +Subject: [PATCH 6/9] ALSA: cs46xx: Potential NULL dereference in probe +Git-commit: 1524f4e47f90b27a3ac84efbdd94c63172246a6f +Patch-mainline: v5.0-rc2 +References: bsc#1051510 + +The "chip->dsp_spos_instance" can be NULL on some of the ealier error +paths in snd_cs46xx_create(). + +Reported-by: "Yavuz, Tuba" <tuba@ece.ufl.edu> +Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> + +--- + sound/pci/cs46xx/dsp_spos.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c +index 598d140bb7cb..5fc497c6d738 100644 +--- a/sound/pci/cs46xx/dsp_spos.c ++++ b/sound/pci/cs46xx/dsp_spos.c +@@ -903,6 +903,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) + struct dsp_spos_instance * ins = chip->dsp_spos_instance; + int i; + ++ if (!ins) ++ return 0; ++ + snd_info_free_entry(ins->proc_sym_info_entry); + ins->proc_sym_info_entry = NULL; + +-- +2.20.1 + diff --git a/patches.drivers/ALSA-hda-realtek-Add-unplug-function-into-unplug-sta.patch b/patches.drivers/ALSA-hda-realtek-Add-unplug-function-into-unplug-sta.patch new file mode 100644 index 0000000000..8138859726 --- /dev/null +++ b/patches.drivers/ALSA-hda-realtek-Add-unplug-function-into-unplug-sta.patch @@ -0,0 +1,34 @@ +From 4d4b0c52bde470c379f5d168d5c139ad866cb808 Mon Sep 17 00:00:00 2001 +From: Kailang Yang <kailang@realtek.com> +Date: Wed, 9 Jan 2019 16:23:37 +0800 +Subject: [PATCH 8/9] ALSA: hda/realtek - Add unplug function into unplug state of Headset Mode for ALC225 +Git-commit: 4d4b0c52bde470c379f5d168d5c139ad866cb808 +Patch-mainline: v5.0-rc2 +References: bsc#1051510 + +Forgot to add unplug function to unplug state of headset mode +for ALC225. + +Signed-off-by: Kailang Yang <kailang@realtek.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> + +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 396ec43a2a54..2c5c8ad84783 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -4102,6 +4102,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) + case 0x10ec0295: + case 0x10ec0289: + case 0x10ec0299: ++ alc_process_coef_fw(codec, alc225_pre_hsmode); + alc_process_coef_fw(codec, coef0225); + break; + case 0x10ec0867: +-- +2.20.1 + diff --git a/patches.drivers/ALSA-hda-realtek-Disable-headset-Mic-VREF-for-headse.patch b/patches.drivers/ALSA-hda-realtek-Disable-headset-Mic-VREF-for-headse.patch new file mode 100644 index 0000000000..3790d397a3 --- /dev/null +++ b/patches.drivers/ALSA-hda-realtek-Disable-headset-Mic-VREF-for-headse.patch @@ -0,0 +1,67 @@ +From d1dd42110d2727e81b9265841a62bc84c454c3a2 Mon Sep 17 00:00:00 2001 +From: Kailang Yang <kailang@realtek.com> +Date: Wed, 9 Jan 2019 17:05:24 +0800 +Subject: [PATCH 9/9] ALSA: hda/realtek - Disable headset Mic VREF for headset mode of ALC225 +Git-commit: d1dd42110d2727e81b9265841a62bc84c454c3a2 +Patch-mainline: v5.0-rc2 +References: bsc#1051510 + +Disable Headset Mic VREF for headset mode of ALC225. +This will be controlled by coef bits of headset mode functions. + +[ Fixed a compile warning and code simplification -- tiwai ] + +Signed-off-by: Kailang Yang <kailang@realtek.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> + +--- + sound/pci/hda/patch_realtek.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -5460,6 +5460,13 @@ static void alc285_fixup_invalidate_dacs + snd_hda_override_wcaps(codec, 0x03, 0); + } + ++static void alc_fixup_disable_mic_vref(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ if (action == HDA_FIXUP_ACT_PRE_PROBE) ++ snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ); ++} ++ + /* for hda_fixup_thinkpad_acpi() */ + #include "thinkpad_helper.c" + +@@ -5572,6 +5579,7 @@ enum { + ALC293_FIXUP_LENOVO_SPK_NOISE, + ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, + ALC255_FIXUP_DELL_SPK_NOISE, ++ ALC225_FIXUP_DISABLE_MIC_VREF, + ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, + ALC295_FIXUP_DISABLE_DAC3, + ALC280_FIXUP_HP_HEADSET_MIC, +@@ -6293,6 +6301,12 @@ static const struct hda_fixup alc269_fix + .chained = true, + .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE + }, ++ [ALC225_FIXUP_DISABLE_MIC_VREF] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc_fixup_disable_mic_vref, ++ .chained = true, ++ .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE ++ }, + [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { +@@ -6302,7 +6316,7 @@ static const struct hda_fixup alc269_fix + {} + }, + .chained = true, +- .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE ++ .chain_id = ALC225_FIXUP_DISABLE_MIC_VREF + }, + [ALC280_FIXUP_HP_HEADSET_MIC] = { + .type = HDA_FIXUP_FUNC, diff --git a/patches.drivers/ALSA-hda-realtek-Support-Dell-headset-mode-for-New-A.patch b/patches.drivers/ALSA-hda-realtek-Support-Dell-headset-mode-for-New-A.patch new file mode 100644 index 0000000000..7a24572096 --- /dev/null +++ b/patches.drivers/ALSA-hda-realtek-Support-Dell-headset-mode-for-New-A.patch @@ -0,0 +1,34 @@ +From c2a7c55a04065c3b0c32d23b099db7ea1dbf6250 Mon Sep 17 00:00:00 2001 +From: Kailang Yang <kailang@realtek.com> +Date: Thu, 3 Jan 2019 15:53:39 +0800 +Subject: [PATCH 5/9] ALSA: hda/realtek - Support Dell headset mode for New AIO platform +Git-commit: c2a7c55a04065c3b0c32d23b099db7ea1dbf6250 +Patch-mainline: v5.0-rc2 +References: bsc#1051510 + +Dell has new platform for ALC274. +This will support to enable headset mode. + +Signed-off-by: Kailang Yang <kailang@realtek.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> + +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index aee4cbd29d53..396ec43a2a54 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -6584,6 +6584,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), + SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), + SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB), ++ SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), + SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), +-- +2.20.1 + diff --git a/patches.drivers/ALSA-usb-audio-Avoid-access-before-bLength-check-in-.patch b/patches.drivers/ALSA-usb-audio-Avoid-access-before-bLength-check-in-.patch new file mode 100644 index 0000000000..d0e3a70c51 --- /dev/null +++ b/patches.drivers/ALSA-usb-audio-Avoid-access-before-bLength-check-in-.patch @@ -0,0 +1,51 @@ +From f4351a199cc120ff9d59e06d02e8657d08e6cc46 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai <tiwai@suse.de> +Date: Wed, 19 Dec 2018 12:36:27 +0100 +Subject: [PATCH 1/9] ALSA: usb-audio: Avoid access before bLength check in build_audio_procunit() +Git-commit: f4351a199cc120ff9d59e06d02e8657d08e6cc46 +Patch-mainline: v5.0-rc2 +References: bsc#1051510 + +The parser for the processing unit reads bNrInPins field before the +bLength sanity check, which may lead to an out-of-bound access when a +malformed descriptor is given. Fix it by assignment after the bLength +check. + +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> + +--- + sound/usb/mixer.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c +index c63c84b54969..0131de348cf6 100644 +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -2314,7 +2314,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, + char *name) + { + struct uac_processing_unit_descriptor *desc = raw_desc; +- int num_ins = desc->bNrInPins; ++ int num_ins; + struct usb_mixer_elem_info *cval; + struct snd_kcontrol *kctl; + int i, err, nameid, type, len; +@@ -2329,7 +2329,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, + 0, NULL, default_value_info + }; + +- if (desc->bLength < 13 || desc->bLength < 13 + num_ins || ++ if (desc->bLength < 13) { ++ usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); ++ return -EINVAL; ++ } ++ ++ num_ins = desc->bNrInPins; ++ if (desc->bLength < 13 + num_ins || + desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) { + usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid); + return -EINVAL; +-- +2.20.1 + diff --git a/patches.drivers/ALSA-usb-audio-Fix-an-out-of-bound-read-in-create_co.patch b/patches.drivers/ALSA-usb-audio-Fix-an-out-of-bound-read-in-create_co.patch new file mode 100644 index 0000000000..710a45a0a7 --- /dev/null +++ b/patches.drivers/ALSA-usb-audio-Fix-an-out-of-bound-read-in-create_co.patch @@ -0,0 +1,58 @@ +From cbb2ebf70daf7f7d97d3811a2ff8e39655b8c184 Mon Sep 17 00:00:00 2001 +From: Hui Peng <benquike@163.com> +Date: Tue, 25 Dec 2018 18:11:52 -0500 +Subject: [PATCH 4/9] ALSA: usb-audio: Fix an out-of-bound read in create_composite_quirks +Git-commit: cbb2ebf70daf7f7d97d3811a2ff8e39655b8c184 +Patch-mainline: v5.0-rc2 +References: bsc#1051510 + +In `create_composite_quirk`, the terminating condition of for loops is +`quirk->ifnum < 0`. So any composite quirks should end with `struct +snd_usb_audio_quirk` object with ifnum < 0. + + for (quirk = quirk_comp->data; quirk->ifnum >= 0; ++quirk) { + + ..... + } + +the data field of Bower's & Wilkins PX headphones usb device device quirks +do not end with {.ifnum = -1}, wihch may result in out-of-bound read. + +This Patch fix the bug by adding an ending quirk object. + +Fixes: 240a8af929c7 ("ALSA: usb-audio: Add a quirck for B&W PX headphones") +Signed-off-by: Hui Peng <benquike@163.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Takashi Iwai <tiwai@suse.de> + +--- + sound/usb/quirks-table.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index 37fc0447c071..b345beb447bd 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -3326,6 +3326,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + } + } + }, ++ { ++ .ifnum = -1 ++ }, + } + } + }, +@@ -3369,6 +3372,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), + } + } + }, ++ { ++ .ifnum = -1 ++ }, + } + } + }, +-- +2.20.1 + diff --git a/patches.drivers/ARM-bcm2835-Add-GET_THROTTLED-firmware-property.patch b/patches.drivers/ARM-bcm2835-Add-GET_THROTTLED-firmware-property.patch index 45e0337b22..e361855286 100644 --- a/patches.drivers/ARM-bcm2835-Add-GET_THROTTLED-firmware-property.patch +++ b/patches.drivers/ARM-bcm2835-Add-GET_THROTTLED-firmware-property.patch @@ -30,9 +30,9 @@ Signed-off-by: Matthias Brugger <mbrugger@suse.com> --- a/include/soc/bcm2835/raspberrypi-firmware.h +++ b/include/soc/bcm2835/raspberrypi-firmware.h -@@ -73,6 +73,7 @@ enum rpi_firmware_property_tag { - RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, +@@ -75,6 +75,7 @@ enum rpi_firmware_property_tag { RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, + RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, + RPI_FIRMWARE_GET_THROTTLED = 0x00030046, RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, diff --git a/patches.drivers/input-add-official-raspberry-pi-s-touchscreen-driver.patch b/patches.drivers/input-add-official-raspberry-pi-s-touchscreen-driver.patch new file mode 100644 index 0000000000..d46fc31f92 --- /dev/null +++ b/patches.drivers/input-add-official-raspberry-pi-s-touchscreen-driver.patch @@ -0,0 +1,322 @@ +From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> +Date: Fri, 21 Dec 2018 00:47:40 -0800 +Subject: Input: add official Raspberry Pi's touchscreen driver +Git-commit: 0b9f28fed3f70ff9a0380fe308739dd72a30a6f6 +Patch-mainline: v5.0-rc1 +References: FATE#326921 + +Add's support to Raspberry Pi's 7" Touch device. Instead of using a +conventional bus all information is copied into a memory mapped area by +RPi's firmware. + +Based on the driver found in RPi's kernel repository. + +Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> +Reviewed-by: Rob Herring <robh@kernel.org> +Acked-by: Eric Anholt <eric@anholt.net> +Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> +--- + .../input/touchscreen/raspberrypi,firmware-ts.txt | 26 +++ + drivers/input/touchscreen/Kconfig | 12 ++ + drivers/input/touchscreen/Makefile | 1 + + drivers/input/touchscreen/raspberrypi-ts.c | 227 +++++++++++++++++++++ + 4 files changed, 266 insertions(+) + +diff --git a/Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt +new file mode 100644 +index 000000000000..2a1af240ccc3 +--- /dev/null ++++ b/Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt +@@ -0,0 +1,26 @@ ++Raspberry Pi firmware based 7" touchscreen ++===================================== ++ ++Required properties: ++ - compatible: "raspberrypi,firmware-ts" ++ ++Optional properties: ++ - firmware: Reference to RPi's firmware device node ++ - touchscreen-size-x: See touchscreen.txt ++ - touchscreen-size-y: See touchscreen.txt ++ - touchscreen-inverted-x: See touchscreen.txt ++ - touchscreen-inverted-y: See touchscreen.txt ++ - touchscreen-swapped-x-y: See touchscreen.txt ++ ++Example: ++ ++firmware: firmware-rpi { ++ compatible = "raspberrypi,bcm2835-firmware"; ++ mboxes = <&mailbox>; ++ ++ ts: touchscreen { ++ compatible = "raspberrypi,firmware-ts"; ++ touchscreen-size-x = <800>; ++ touchscreen-size-y = <480>; ++ }; ++}; +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index 5374bd573e66..a391eacf8cf6 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -683,6 +683,18 @@ config TOUCHSCREEN_EDT_FT5X06 + To compile this driver as a module, choose M here: the + module will be called edt-ft5x06. + ++config TOUCHSCREEN_RASPBERRYPI_FW ++ tristate "Raspberry Pi's firmware base touch screen support" ++ depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST ++ help ++ Say Y here if you have the official Raspberry Pi 7 inch screen on ++ your system. ++ ++ If unsure, say N. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called raspberrypi-ts. ++ + config TOUCHSCREEN_MIGOR + tristate "Renesas MIGO-R touchscreen" + depends on (SH_MIGOR || COMPILE_TEST) && I2C +diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +index c2175163152d..aca7cb04910b 100644 +--- a/drivers/input/touchscreen/Makefile ++++ b/drivers/input/touchscreen/Makefile +@@ -108,3 +108,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZET6223) += zet6223.o + obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o + obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o + obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o ++obj-$(CONFIG_TOUCHSCREEN_RASPBERRYPI_FW) += raspberrypi-ts.o +diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c +new file mode 100644 +index 000000000000..f456c1125bd6 +--- /dev/null ++++ b/drivers/input/touchscreen/raspberrypi-ts.c +@@ -0,0 +1,227 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Raspberry Pi firmware based touchscreen driver ++ * ++ * Copyright (C) 2015, 2017 Raspberry Pi ++ * Copyright (C) 2018 Nicolas Saenz Julienne <nsaenzjulienne@suse.de> ++ */ ++ ++#include <linux/io.h> ++#include <linux/of.h> ++#include <linux/slab.h> ++#include <linux/device.h> ++#include <linux/module.h> ++#include <linux/bitops.h> ++#include <linux/dma-mapping.h> ++#include <linux/platform_device.h> ++#include <linux/input.h> ++#include <linux/input/mt.h> ++#include <linux/input-polldev.h> ++#include <linux/input/touchscreen.h> ++#include <soc/bcm2835/raspberrypi-firmware.h> ++ ++#define RPI_TS_DEFAULT_WIDTH 800 ++#define RPI_TS_DEFAULT_HEIGHT 480 ++ ++#define RPI_TS_MAX_SUPPORTED_POINTS 10 ++ ++#define RPI_TS_FTS_TOUCH_DOWN 0 ++#define RPI_TS_FTS_TOUCH_CONTACT 2 ++ ++#define RPI_TS_POLL_INTERVAL 17 /* 60fps */ ++ ++#define RPI_TS_NPOINTS_REG_INVALIDATE 99 ++ ++struct rpi_ts { ++ struct platform_device *pdev; ++ struct input_polled_dev *poll_dev; ++ struct touchscreen_properties prop; ++ ++ void __iomem *fw_regs_va; ++ dma_addr_t fw_regs_phys; ++ ++ int known_ids; ++}; ++ ++struct rpi_ts_regs { ++ u8 device_mode; ++ u8 gesture_id; ++ u8 num_points; ++ struct rpi_ts_touch { ++ u8 xh; ++ u8 xl; ++ u8 yh; ++ u8 yl; ++ u8 pressure; /* Not supported */ ++ u8 area; /* Not supported */ ++ } point[RPI_TS_MAX_SUPPORTED_POINTS]; ++}; ++ ++static void rpi_ts_poll(struct input_polled_dev *dev) ++{ ++ struct input_dev *input = dev->input; ++ struct rpi_ts *ts = dev->private; ++ struct rpi_ts_regs regs; ++ int modified_ids = 0; ++ long released_ids; ++ int event_type; ++ int touchid; ++ int x, y; ++ int i; ++ ++ memcpy_fromio(®s, ts->fw_regs_va, sizeof(regs)); ++ /* ++ * We poll the memory based register copy of the touchscreen chip using ++ * the number of points register to know whether the copy has been ++ * updated (we write 99 to the memory copy, the GPU will write between ++ * 0 - 10 points) ++ */ ++ iowrite8(RPI_TS_NPOINTS_REG_INVALIDATE, ++ ts->fw_regs_va + offsetof(struct rpi_ts_regs, num_points)); ++ ++ if (regs.num_points == RPI_TS_NPOINTS_REG_INVALIDATE || ++ (regs.num_points == 0 && ts->known_ids == 0)) ++ return; ++ ++ for (i = 0; i < regs.num_points; i++) { ++ x = (((int)regs.point[i].xh & 0xf) << 8) + regs.point[i].xl; ++ y = (((int)regs.point[i].yh & 0xf) << 8) + regs.point[i].yl; ++ touchid = (regs.point[i].yh >> 4) & 0xf; ++ event_type = (regs.point[i].xh >> 6) & 0x03; ++ ++ modified_ids |= BIT(touchid); ++ ++ if (event_type == RPI_TS_FTS_TOUCH_DOWN || ++ event_type == RPI_TS_FTS_TOUCH_CONTACT) { ++ input_mt_slot(input, touchid); ++ input_mt_report_slot_state(input, MT_TOOL_FINGER, 1); ++ touchscreen_report_pos(input, &ts->prop, x, y, true); ++ } ++ } ++ ++ released_ids = ts->known_ids & ~modified_ids; ++ for_each_set_bit(i, &released_ids, RPI_TS_MAX_SUPPORTED_POINTS) { ++ input_mt_slot(input, i); ++ input_mt_report_slot_state(input, MT_TOOL_FINGER, 0); ++ modified_ids &= ~(BIT(i)); ++ } ++ ts->known_ids = modified_ids; ++ ++ input_mt_sync_frame(input); ++ input_sync(input); ++} ++ ++static void rpi_ts_dma_cleanup(void *data) ++{ ++ struct rpi_ts *ts = data; ++ struct device *dev = &ts->pdev->dev; ++ ++ dma_free_coherent(dev, PAGE_SIZE, ts->fw_regs_va, ts->fw_regs_phys); ++} ++ ++static int rpi_ts_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct input_polled_dev *poll_dev; ++ struct device_node *fw_node; ++ struct rpi_firmware *fw; ++ struct input_dev *input; ++ struct rpi_ts *ts; ++ u32 touchbuf; ++ int error; ++ ++ fw_node = of_get_parent(np); ++ if (!fw_node) { ++ dev_err(dev, "Missing firmware node\n"); ++ return -ENOENT; ++ } ++ ++ fw = rpi_firmware_get(fw_node); ++ of_node_put(fw_node); ++ if (!fw) ++ return -EPROBE_DEFER; ++ ++ ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); ++ if (!ts) ++ return -ENOMEM; ++ ts->pdev = pdev; ++ ++ ts->fw_regs_va = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys, ++ GFP_KERNEL); ++ if (!ts->fw_regs_va) { ++ dev_err(dev, "failed to dma_alloc_coherent\n"); ++ return -ENOMEM; ++ } ++ ++ error = devm_add_action_or_reset(dev, rpi_ts_dma_cleanup, ts); ++ if (error) { ++ dev_err(dev, "failed to devm_add_action_or_reset, %d\n", error); ++ return error; ++ } ++ ++ ++ touchbuf = (u32)ts->fw_regs_phys; ++ error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, ++ &touchbuf, sizeof(touchbuf)); ++ ++ if (error || touchbuf != 0) { ++ dev_warn(dev, "Failed to set touchbuf, %d\n", error); ++ return error; ++ } ++ ++ poll_dev = devm_input_allocate_polled_device(dev); ++ if (!poll_dev) { ++ dev_err(dev, "Failed to allocate input device\n"); ++ return -ENOMEM; ++ } ++ ts->poll_dev = poll_dev; ++ input = poll_dev->input; ++ ++ input->name = "raspberrypi-ts"; ++ input->id.bustype = BUS_HOST; ++ poll_dev->poll_interval = RPI_TS_POLL_INTERVAL; ++ poll_dev->poll = rpi_ts_poll; ++ poll_dev->private = ts; ++ ++ input_set_abs_params(input, ABS_MT_POSITION_X, 0, ++ RPI_TS_DEFAULT_WIDTH, 0, 0); ++ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ++ RPI_TS_DEFAULT_HEIGHT, 0, 0); ++ touchscreen_parse_properties(input, true, &ts->prop); ++ ++ error = input_mt_init_slots(input, RPI_TS_MAX_SUPPORTED_POINTS, ++ INPUT_MT_DIRECT); ++ if (error) { ++ dev_err(dev, "could not init mt slots, %d\n", error); ++ return error; ++ } ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ dev_err(dev, "could not register input device, %d\n", error); ++ return error; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id rpi_ts_match[] = { ++ { .compatible = "raspberrypi,firmware-ts", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rpi_ts_match); ++ ++static struct platform_driver rpi_ts_driver = { ++ .driver = { ++ .name = "raspberrypi-ts", ++ .of_match_table = rpi_ts_match, ++ }, ++ .probe = rpi_ts_probe, ++}; ++module_platform_driver(rpi_ts_driver); ++ ++MODULE_AUTHOR("Gordon Hollingworth"); ++MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>"); ++MODULE_DESCRIPTION("Raspberry Pi firmware based touchscreen driver"); ++MODULE_LICENSE("GPL v2"); + diff --git a/patches.drivers/soc-bcm2835-sync-firmware-properties-with-downstream.patch b/patches.drivers/soc-bcm2835-sync-firmware-properties-with-downstream.patch new file mode 100644 index 0000000000..944b8f2f7a --- /dev/null +++ b/patches.drivers/soc-bcm2835-sync-firmware-properties-with-downstream.patch @@ -0,0 +1,83 @@ +From: Baruch Siach <baruch@tkos.co.il> +Date: Tue, 20 Feb 2018 14:19:31 +0200 +Subject: soc: bcm2835: sync firmware properties with downstream +Git-commit: 08af112e79cab22f318ca0ad1a48187eee5ac2f0 +Patch-mainline: v4.17-rc1 +References: FATE#326921 + +Add latest firmware property tags from the latest Raspberry Pi downstream +kernel. This is needed for the GPIO tags, so we can control the GPIO +multiplexor lines. + +Acked-by: Stefan Wahren <stefan.wahren@i2se.com> +Signed-off-by: Baruch Siach <baruch@tkos.co.il> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Acked-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> +--- + include/soc/bcm2835/raspberrypi-firmware.h | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h +index cb979ad90401..50df5b28d2c9 100644 +--- a/include/soc/bcm2835/raspberrypi-firmware.h ++++ b/include/soc/bcm2835/raspberrypi-firmware.h +@@ -63,6 +63,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008, + RPI_FIRMWARE_GET_TURBO = 0x00030009, + RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a, ++ RPI_FIRMWARE_GET_STC = 0x0003000b, + RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c, + RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d, + RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e, +@@ -72,12 +73,22 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012, + RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, ++ RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, + RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, + RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, + RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, + RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, + RPI_FIRMWARE_SET_TURBO = 0x00038009, ++ RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021, + RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030, ++ RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041, ++ RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041, ++ RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042, ++ RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043, ++ RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, ++ RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045, ++ RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045, ++ + + /* Dispmanx TAGS */ + RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, +@@ -91,6 +102,8 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, ++ RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001, + RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, +@@ -100,6 +113,7 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, ++ RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005, +@@ -108,6 +122,10 @@ enum rpi_firmware_property_tag { + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, ++ RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, + + diff --git a/patches.drm/drm-bridge-sii8620-Fix-display-of-packed-pixel-modes b/patches.drm/Revert-drm-bridge-sii8620-fix-display-of-packed-pixel index 668cdac282..668cdac282 100644 --- a/patches.drm/drm-bridge-sii8620-Fix-display-of-packed-pixel-modes +++ b/patches.drm/Revert-drm-bridge-sii8620-fix-display-of-packed-pixel diff --git a/patches.fixes/0001-md-fix-raid10-hang-issue-caused-by-barrier.patch b/patches.fixes/0001-md-fix-raid10-hang-issue-caused-by-barrier.patch new file mode 100644 index 0000000000..6779126bc7 --- /dev/null +++ b/patches.fixes/0001-md-fix-raid10-hang-issue-caused-by-barrier.patch @@ -0,0 +1,127 @@ +From 77f860c698b87b4ec41342c61e99b42fe91b1f79 Mon Sep 17 00:00:00 2001 +From: Guoqing Jiang <gqjiang@suse.com> +Date: Mon, 14 Jan 2019 15:30:15 +0800 +Subject: [PATCH] md: fix raid10 hang issue caused by barrier +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Git-commit: e820d55cb99dd93ac2dc949cf486bb187e5cd70d +Patch-mainline: v5.0-rc1 +References: git-fixes + +When both regular IO and resync IO happen at the same time, +and if we also need to split regular. Then we can see tasks +hang due to barrier. + +1. resync thread +[ 1463.757205] INFO: task md1_resync:5215 blocked for more than 480 seconds. +[ 1463.757207] Not tainted 4.19.5-1-default #1 +[ 1463.757209] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 1463.757212] md1_resync D 0 5215 2 0x80000000 +[ 1463.757216] Call Trace: +[ 1463.757223] ? __schedule+0x29a/0x880 +[ 1463.757231] ? raise_barrier+0x8d/0x140 [raid10] +[ 1463.757236] schedule+0x78/0x110 +[ 1463.757243] raise_barrier+0x8d/0x140 [raid10] +[ 1463.757248] ? wait_woken+0x80/0x80 +[ 1463.757257] raid10_sync_request+0x1f6/0x1e30 [raid10] +[ 1463.757265] ? _raw_spin_unlock_irq+0x22/0x40 +[ 1463.757284] ? is_mddev_idle+0x125/0x137 [md_mod] +[ 1463.757302] md_do_sync.cold.78+0x404/0x969 [md_mod] +[ 1463.757311] ? wait_woken+0x80/0x80 +[ 1463.757336] ? md_rdev_init+0xb0/0xb0 [md_mod] +[ 1463.757351] md_thread+0xe9/0x140 [md_mod] +[ 1463.757358] ? _raw_spin_unlock_irqrestore+0x2e/0x60 +[ 1463.757364] ? __kthread_parkme+0x4c/0x70 +[ 1463.757369] kthread+0x112/0x130 +[ 1463.757374] ? kthread_create_worker_on_cpu+0x40/0x40 +[ 1463.757380] ret_from_fork+0x3a/0x50 + +2. regular IO +[ 1463.760679] INFO: task kworker/0:8:5367 blocked for more than 480 seconds. +[ 1463.760683] Not tainted 4.19.5-1-default #1 +[ 1463.760684] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 1463.760687] kworker/0:8 D 0 5367 2 0x80000000 +[ 1463.760718] Workqueue: md submit_flushes [md_mod] +[ 1463.760721] Call Trace: +[ 1463.760731] ? __schedule+0x29a/0x880 +[ 1463.760741] ? wait_barrier+0xdd/0x170 [raid10] +[ 1463.760746] schedule+0x78/0x110 +[ 1463.760753] wait_barrier+0xdd/0x170 [raid10] +[ 1463.760761] ? wait_woken+0x80/0x80 +[ 1463.760768] raid10_write_request+0xf2/0x900 [raid10] +[ 1463.760774] ? wait_woken+0x80/0x80 +[ 1463.760778] ? mempool_alloc+0x55/0x160 +[ 1463.760795] ? md_write_start+0xa9/0x270 [md_mod] +[ 1463.760801] ? try_to_wake_up+0x44/0x470 +[ 1463.760810] raid10_make_request+0xc1/0x120 [raid10] +[ 1463.760816] ? wait_woken+0x80/0x80 +[ 1463.760831] md_handle_request+0x121/0x190 [md_mod] +[ 1463.760851] md_make_request+0x78/0x190 [md_mod] +[ 1463.760860] generic_make_request+0x1c6/0x470 +[ 1463.760870] raid10_write_request+0x77a/0x900 [raid10] +[ 1463.760875] ? wait_woken+0x80/0x80 +[ 1463.760879] ? mempool_alloc+0x55/0x160 +[ 1463.760895] ? md_write_start+0xa9/0x270 [md_mod] +[ 1463.760904] raid10_make_request+0xc1/0x120 [raid10] +[ 1463.760910] ? wait_woken+0x80/0x80 +[ 1463.760926] md_handle_request+0x121/0x190 [md_mod] +[ 1463.760931] ? _raw_spin_unlock_irq+0x22/0x40 +[ 1463.760936] ? finish_task_switch+0x74/0x260 +[ 1463.760954] submit_flushes+0x21/0x40 [md_mod] + +So resync io is waiting for regular write io to complete to +decrease nr_pending (conf->barrier++ is called before waiting). +The regular write io splits another bio after call wait_barrier +which call nr_pending++, then the splitted bio would continue +with raid10_write_request -> wait_barrier, so the splitted bio +has to wait for barrier to be zero, then deadlock happens as +follows. + + resync io regular io + + raise_barrier + wait_barrier + generic_make_request + wait_barrier + +To resolve the issue, we need to call allow_barrier to decrease +nr_pending before generic_make_request since regular IO is not +issued to underlying devices, and wait_barrier is called again +to ensure no internal IO happening. + +Fixes: fc9977dd069e ("md/raid10: simplify the splitting of requests.") +Reported-and-tested-by: SiniÅ¡a Bandin <sinisa@4net.rs> +Signed-off-by: Guoqing Jiang <gqjiang@suse.com> +Signed-off-by: Shaohua Li <shli@fb.com> +--- + drivers/md/raid10.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index de10caf0e685..7acf3b424a31 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1220,7 +1220,9 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, + struct bio *split = bio_split(bio, max_sectors, + gfp, conf->bio_split); + bio_chain(split, bio); ++ allow_barrier(conf); + generic_make_request(bio); ++ wait_barrier(conf); + bio = split; + r10_bio->master_bio = bio; + r10_bio->sectors = max_sectors; +@@ -1525,7 +1527,9 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio, + struct bio *split = bio_split(bio, r10_bio->sectors, + GFP_NOIO, conf->bio_split); + bio_chain(split, bio); ++ allow_barrier(conf); + generic_make_request(bio); ++ wait_barrier(conf); + bio = split; + r10_bio->master_bio = bio; + } +-- +2.12.3 + diff --git a/patches.fixes/0001-mm-only-report-isolation-failures-when-offlining-mem.patch b/patches.fixes/0001-mm-only-report-isolation-failures-when-offlining-mem.patch new file mode 100644 index 0000000000..b7e7242169 --- /dev/null +++ b/patches.fixes/0001-mm-only-report-isolation-failures-when-offlining-mem.patch @@ -0,0 +1,187 @@ +From d381c54760dcfad23743da40516e7e003d73952a Mon Sep 17 00:00:00 2001 +From: Michal Hocko <mhocko@suse.com> +Date: Fri, 28 Dec 2018 00:33:56 -0800 +Subject: [PATCH] mm: only report isolation failures when offlining memory +Git-commit: d381c54760dcfad23743da40516e7e003d73952a +Patch-mainline: v5.0-rc1 +References: generic hotplug debugability + +Heiko has complained that his log is swamped by warnings from +has_unmovable_pages + +[ 20.536664] page dumped because: has_unmovable_pages +[ 20.536792] page:000003d081ff4080 count:1 mapcount:0 mapping:000000008ff88600 index:0x0 compound_mapcount: 0 +[ 20.536794] flags: 0x3fffe0000010200(slab|head) +[ 20.536795] raw: 03fffe0000010200 0000000000000100 0000000000000200 000000008ff88600 +[ 20.536796] raw: 0000000000000000 0020004100000000 ffffffff00000001 0000000000000000 +[ 20.536797] page dumped because: has_unmovable_pages +[ 20.536814] page:000003d0823b0000 count:1 mapcount:0 mapping:0000000000000000 index:0x0 +[ 20.536815] flags: 0x7fffe0000000000() +[ 20.536817] raw: 07fffe0000000000 0000000000000100 0000000000000200 0000000000000000 +[ 20.536818] raw: 0000000000000000 0000000000000000 ffffffff00000001 0000000000000000 + +which are not triggered by the memory hotplug but rather CMA allocator. +The original idea behind dumping the page state for all call paths was +that these messages will be helpful debugging failures. From the above it +seems that this is not the case for the CMA path because we are lacking +much more context. E.g the second reported page might be a CMA allocated +page. It is still interesting to see a slab page in the CMA area but it +is hard to tell whether this is bug from the above output alone. + +Address this issue by dumping the page state only on request. Both +start_isolate_page_range and has_unmovable_pages already have an argument +to ignore hwpoison pages so make this argument more generic and turn it +into flags and allow callers to combine non-default modes into a mask. +While we are at it, has_unmovable_pages call from +is_pageblock_removable_nolock (sysfs removable file) is questionable to +report the failure so drop it from there as well. + +Link: http://lkml.kernel.org/r/20181218092802.31429-1-mhocko@kernel.org +Signed-off-by: Michal Hocko <mhocko@suse.com> +Reported-by: Heiko Carstens <heiko.carstens@de.ibm.com> +Reviewed-by: Oscar Salvador <osalvador@suse.de> +Cc: Anshuman Khandual <anshuman.khandual@arm.com> +Cc: Stephen Rothwell <sfr@canb.auug.org.au> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> + +--- + include/linux/page-isolation.h | 11 +++++++++-- + mm/memory_hotplug.c | 3 ++- + mm/page_alloc.c | 13 ++++++------- + mm/page_isolation.c | 10 ++++------ + 4 files changed, 21 insertions(+), 16 deletions(-) + +--- a/include/linux/page-isolation.h ++++ b/include/linux/page-isolation.h +@@ -29,8 +29,11 @@ static inline bool is_migrate_isolate(in + } + #endif + ++#define SKIP_HWPOISON 0x1 ++#define REPORT_FAILURE 0x2 ++ + bool has_unmovable_pages(struct zone *zone, struct page *page, int count, +- int migratetype, bool skip_hwpoisoned_pages); ++ int migratetype, int flags); + void set_pageblock_migratetype(struct page *page, int migratetype); + int move_freepages_block(struct zone *zone, struct page *page, + int migratetype, int *num_movable); +@@ -43,10 +46,14 @@ int move_freepages_block(struct zone *zo + * For isolating all pages in the range finally, the caller have to + * free all pages in the range. test_page_isolated() can be used for + * test it. ++ * ++ * The following flags are allowed (they can be combined in a bit mask) ++ * SKIP_HWPOISON - ignore hwpoison pages ++ * REPORT_FAILURE - report details about the failure to isolate the range + */ + int + start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, +- unsigned migratetype, bool skip_hwpoisoned_pages); ++ unsigned migratetype, int flags); + + /* + * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE. +--- a/mm/memory_hotplug.c ++++ b/mm/memory_hotplug.c +@@ -1769,7 +1769,8 @@ static int __ref __offline_pages(unsigne + + /* set above range as isolated */ + ret = start_isolate_page_range(start_pfn, end_pfn, +- MIGRATE_MOVABLE, true); ++ MIGRATE_MOVABLE, ++ SKIP_HWPOISON | REPORT_FAILURE); + if (ret) { + reason = "failure to isolate range"; + goto failed_removal; +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -7383,8 +7383,7 @@ void *__init alloc_large_system_hash(con + * race condition. So you can't expect this function should be exact. + */ + bool has_unmovable_pages(struct zone *zone, struct page *page, int count, +- int migratetype, +- bool skip_hwpoisoned_pages) ++ int migratetype, int flags) + { + unsigned long pfn, iter, found; + +@@ -7446,7 +7445,7 @@ bool has_unmovable_pages(struct zone *zo + * The HWPoisoned page may be not in buddy system, and + * page_count() is not 0. + */ +- if (skip_hwpoisoned_pages && PageHWPoison(page)) ++ if ((flags & SKIP_HWPOISON) && PageHWPoison(page)) + continue; + + if (__PageMovable(page)) +@@ -7472,7 +7471,8 @@ bool has_unmovable_pages(struct zone *zo + } + return false; + unmovable: +- dump_page(pfn_to_page(pfn+iter), "unmovable page"); ++ if (flags & REPORT_FAILURE) ++ dump_page(pfn_to_page(pfn+iter), "unmovable page"); + return true; + } + +@@ -7496,7 +7496,7 @@ bool is_pageblock_removable_nolock(struc + if (!zone_spans_pfn(zone, pfn)) + return false; + +- return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE, true); ++ return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE, SKIP_HWPOISON); + } + + #if (defined(CONFIG_MEMORY_ISOLATION) && defined(CONFIG_COMPACTION)) || defined(CONFIG_CMA) +@@ -7621,8 +7621,7 @@ int alloc_contig_range(unsigned long sta + */ + + ret = start_isolate_page_range(pfn_max_align_down(start), +- pfn_max_align_up(end), migratetype, +- false); ++ pfn_max_align_up(end), migratetype, 0); + if (ret) + return ret; + +--- a/mm/page_isolation.c ++++ b/mm/page_isolation.c +@@ -14,8 +14,7 @@ + #define CREATE_TRACE_POINTS + #include <trace/events/page_isolation.h> + +-static int set_migratetype_isolate(struct page *page, int migratetype, +- bool skip_hwpoisoned_pages) ++static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags) + { + struct zone *zone; + unsigned long flags, pfn; +@@ -51,8 +50,7 @@ static int set_migratetype_isolate(struc + * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. + * We just check MOVABLE pages. + */ +- if (!has_unmovable_pages(zone, page, arg.pages_found, migratetype, +- skip_hwpoisoned_pages)) ++ if (!has_unmovable_pages(zone, page, arg.pages_found, migratetype, flags)) + ret = 0; + + /* +@@ -168,7 +166,7 @@ __first_valid_page(unsigned long pfn, un + * Returns 0 on success and -EBUSY if any part of range cannot be isolated. + */ + int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn, +- unsigned migratetype, bool skip_hwpoisoned_pages) ++ unsigned migratetype, int flags) + { + unsigned long pfn; + unsigned long undo_pfn; +@@ -182,7 +180,7 @@ int start_isolate_page_range(unsigned lo + pfn += pageblock_nr_pages) { + page = __first_valid_page(pfn, pageblock_nr_pages); + if (page && +- set_migratetype_isolate(page, migratetype, skip_hwpoisoned_pages)) { ++ set_migratetype_isolate(page, migratetype, flags)) { + undo_pfn = pfn; + goto undo; + } diff --git a/patches.fixes/ceph-don-t-update-importing-cap-s-mseq-when-handing-cap-export.patch b/patches.fixes/ceph-don-t-update-importing-cap-s-mseq-when-handing-cap-export.patch new file mode 100644 index 0000000000..5e2d37c048 --- /dev/null +++ b/patches.fixes/ceph-don-t-update-importing-cap-s-mseq-when-handing-cap-export.patch @@ -0,0 +1,35 @@ +From: "Yan, Zheng" <zyan@redhat.com> +Date: Thu, 29 Nov 2018 11:22:50 +0800 +Subject: ceph: don't update importing cap's mseq when handing cap export +Git-commit: 3c1392d4c49962a31874af14ae9ff289cb2b3851 +Patch-mainline: v5.0-rc1 +References: bsc#1121273 + +Updating mseq makes client think importer mds has accepted all prior +cap messages and importer mds knows what caps client wants. Actually +some cap messages may have been dropped because of mseq mismatch. + +If mseq is left untouched, importing cap's mds_wanted later will get +reset by cap import message. + +Cc: stable@vger.kernel.org +Signed-off-by: "Yan, Zheng" <zyan@redhat.com> +Signed-off-by: Ilya Dryomov <idryomov@gmail.com> +Acked-by: Luis Henriques <lhenriques@suse.com> +--- + fs/ceph/caps.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c +index f3496db4bb3e..a58666a3f8dd 100644 +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -3569,7 +3569,6 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, + tcap->cap_id = t_cap_id; + tcap->seq = t_seq - 1; + tcap->issue_seq = t_seq - 1; +- tcap->mseq = t_mseq; + tcap->issued |= issued; + tcap->implemented |= issued; + if (cap == ci->i_auth_cap) + diff --git a/patches.fixes/mm-huge_memory-c-reorder-operations-in-_split_huge_page_tail.patch b/patches.fixes/mm-huge_memory-c-reorder-operations-in-_split_huge_page_tail.patch new file mode 100644 index 0000000000..d36ded2dd5 --- /dev/null +++ b/patches.fixes/mm-huge_memory-c-reorder-operations-in-_split_huge_page_tail.patch @@ -0,0 +1,100 @@ +From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Date: Thu, 5 Apr 2018 16:23:28 -0700 +Subject: mm/huge_memory.c: reorder operations in __split_huge_page_tail() +Git-commit: 605ca5ede7643a01f4c4a15913f9714ac297f8a6 +Patch-mainline: v4.17-rc1 +References: VM Functionality bsc#1119962 + +THP split makes non-atomic change of tail page flags. This is almost ok +because tail pages are locked and isolated but this breaks recent +changes in page locking: non-atomic operation could clear bit +PG_waiters. + +As a result concurrent sequence get_page_unless_zero() -> lock_page() +might block forever. Especially if this page was truncated later. + +Fix is trivial: clone flags before unfreezing page reference counter. + +This race exists since commit 62906027091f ("mm: add PageWaiters +indicating tasks are waiting for a page bit") while unsave unfreeze +itself was added in commit 8df651c7059e ("thp: cleanup +split_huge_page()"). + +clear_compound_head() also must be called before unfreezing page +reference because after successful get_page_unless_zero() might follow +put_page() which needs correct compound_head(). + +And replace page_ref_inc()/page_ref_add() with page_ref_unfreeze() which +is made especially for that and has semantic of smp_store_release(). + +Link: http://lkml.kernel.org/r/151844393341.210639.13162088407980624477.stgit@buzz +Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Nicholas Piggin <npiggin@gmail.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/huge_memory.c | 36 +++++++++++++++--------------------- + 1 file changed, 15 insertions(+), 21 deletions(-) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2212,26 +2212,13 @@ static void __split_huge_page_tail(struc + struct page *page_tail = head + tail; + + VM_BUG_ON_PAGE(atomic_read(&page_tail->_mapcount) != -1, page_tail); +- VM_BUG_ON_PAGE(page_ref_count(page_tail) != 0, page_tail); + + /* +- * tail_page->_refcount is zero and not changing from under us. But +- * get_page_unless_zero() may be running from under us on the +- * tail_page. If we used atomic_set() below instead of atomic_inc() or +- * atomic_add(), we would then run atomic_set() concurrently with +- * get_page_unless_zero(), and atomic_set() is implemented in C not +- * using locked ops. spin_unlock on x86 sometime uses locked ops +- * because of PPro errata 66, 92, so unless somebody can guarantee +- * atomic_set() here would be safe on all archs (and not only on x86), +- * it's safer to use atomic_inc()/atomic_add(). ++ * Clone page flags before unfreezing refcount. ++ * ++ * After successful get_page_unless_zero() might follow flags change, ++ * for exmaple lock_page() which set PG_waiters. + */ +- if (PageAnon(head)) { +- page_ref_inc(page_tail); +- } else { +- /* Additional pin to radix tree */ +- page_ref_add(page_tail, 2); +- } +- + page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP; + page_tail->flags |= (head->flags & + ((1L << PG_referenced) | +@@ -2243,14 +2230,21 @@ static void __split_huge_page_tail(struc + (1L << PG_unevictable) | + (1L << PG_dirty))); + +- /* +- * After clearing PageTail the gup refcount can be released. +- * Page flags also must be visible before we make the page non-compound. +- */ ++ /* Page flags must be visible before we make the page non-compound. */ + smp_wmb(); + ++ /* ++ * Clear PageTail before unfreezing page refcount. ++ * ++ * After successful get_page_unless_zero() might follow put_page() ++ * which needs correct compound_head(). ++ */ + clear_compound_head(page_tail); + ++ /* Finally unfreeze refcount. Additional reference from page cache. */ ++ page_ref_unfreeze(page_tail, 1 + (!PageAnon(head) || ++ PageSwapCache(head))); ++ + if (page_is_young(head)) + set_page_young(page_tail); + if (page_is_idle(head)) diff --git a/patches.fixes/mm-huge_memory-fix-lockdep-complaint-on-32-bit-i_size_read.patch b/patches.fixes/mm-huge_memory-fix-lockdep-complaint-on-32-bit-i_size_read.patch new file mode 100644 index 0000000000..b6dfab4f10 --- /dev/null +++ b/patches.fixes/mm-huge_memory-fix-lockdep-complaint-on-32-bit-i_size_read.patch @@ -0,0 +1,99 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:21 -0800 +Subject: mm/huge_memory: fix lockdep complaint on 32-bit i_size_read() +Git-commit: 006d3ff27e884f80bd7d306b041afc415f63598f +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +Huge tmpfs testing, on 32-bit kernel with lockdep enabled, showed that +__split_huge_page() was using i_size_read() while holding the irq-safe +lru_lock and page tree lock, but the 32-bit i_size_read() uses an +irq-unsafe seqlock which should not be nested inside them. + +Instead, read the i_size earlier in split_huge_page_to_list(), and pass +the end offset down to __split_huge_page(): all while holding head page +lock, which is enough to prevent truncation of that extent before the +page tree lock has been taken. + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261520070.2275@eggly.anvils +Fixes: baa355fd33142 ("thp: file pages support for split_huge_page()") +Signed-off-by: Hugh Dickins <hughd@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/huge_memory.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2260,12 +2260,11 @@ static void __split_huge_page_tail(struc + } + + static void __split_huge_page(struct page *page, struct list_head *list, +- unsigned long flags) ++ pgoff_t end, unsigned long flags) + { + struct page *head = compound_head(page); + struct zone *zone = page_zone(head); + struct lruvec *lruvec; +- pgoff_t end = -1; + int i; + + lruvec = mem_cgroup_page_lruvec(head, zone->zone_pgdat); +@@ -2273,9 +2272,6 @@ static void __split_huge_page(struct pag + /* complete memcg works before add pages to LRU */ + mem_cgroup_split_huge_fixup(head); + +- if (!PageAnon(page)) +- end = DIV_ROUND_UP(i_size_read(head->mapping->host), PAGE_SIZE); +- + for (i = HPAGE_PMD_NR - 1; i >= 1; i--) { + __split_huge_page_tail(head, i, lruvec, list); + /* Some pages can be beyond i_size: drop them from page cache */ +@@ -2428,6 +2424,7 @@ int split_huge_page_to_list(struct page + int count, mapcount, extra_pins, ret; + bool mlocked; + unsigned long flags; ++ pgoff_t end; + + VM_BUG_ON_PAGE(is_huge_zero_page(page), page); + VM_BUG_ON_PAGE(!PageLocked(page), page); +@@ -2448,6 +2445,7 @@ int split_huge_page_to_list(struct page + goto out; + } + extra_pins = 0; ++ end = -1; + mapping = NULL; + anon_vma_lock_write(anon_vma); + } else { +@@ -2463,6 +2461,15 @@ int split_huge_page_to_list(struct page + extra_pins = HPAGE_PMD_NR; + anon_vma = NULL; + i_mmap_lock_read(mapping); ++ ++ /* ++ *__split_huge_page() may need to trim off pages beyond EOF: ++ * but on 32-bit, i_size_read() takes an irq-unsafe seqlock, ++ * which cannot be nested inside the page tree lock. So note ++ * end now: i_size itself may be changed at any moment, but ++ * head page lock is good enough to serialize the trimming. ++ */ ++ end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE); + } + + /* +@@ -2512,7 +2519,7 @@ int split_huge_page_to_list(struct page + if (mapping) + __dec_node_page_state(page, NR_SHMEM_THPS); + spin_unlock(&pgdata->split_queue_lock); +- __split_huge_page(page, list, flags); ++ __split_huge_page(page, list, end, flags); + ret = 0; + } else { + if (IS_ENABLED(CONFIG_DEBUG_VM) && mapcount) { diff --git a/patches.fixes/mm-huge_memory-rename-freeze_page-to-unmap_page.patch b/patches.fixes/mm-huge_memory-rename-freeze_page-to-unmap_page.patch new file mode 100644 index 0000000000..9106bc3635 --- /dev/null +++ b/patches.fixes/mm-huge_memory-rename-freeze_page-to-unmap_page.patch @@ -0,0 +1,87 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:13 -0800 +Subject: mm/huge_memory: rename freeze_page() to unmap_page() +Git-commit: 906f9cdfc2a0800f13683f9e4ebdfd08c12ee81b +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +The term "freeze" is used in several ways in the kernel, and in mm it +has the particular meaning of forcing page refcount temporarily to 0. +freeze_page() is just too confusing a name for a function that unmaps a +page: rename it unmap_page(), and rename unfreeze_page() remap_page(). + +Went to change the mention of freeze_page() added later in mm/rmap.c, +but found it to be incorrect: ordinary page reclaim reaches there too; +but the substance of the comment still seems correct, so edit it down. + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261514080.2275@eggly.anvils +Fixes: e9b61f19858a5 ("thp: reintroduce split_huge_page()") +Signed-off-by: Hugh Dickins <hughd@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/huge_memory.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2179,7 +2179,7 @@ void vma_adjust_trans_huge(struct vm_are + } + } + +-static void freeze_page(struct page *page) ++static void unmap_page(struct page *page) + { + enum ttu_flags ttu_flags = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS | + TTU_RMAP_LOCKED | TTU_SPLIT_HUGE_PMD; +@@ -2194,7 +2194,7 @@ static void freeze_page(struct page *pag + VM_BUG_ON_PAGE(!unmap_success, page); + } + +-static void unfreeze_page(struct page *page) ++static void remap_page(struct page *page) + { + int i; + if (PageTransHuge(page)) { +@@ -2300,7 +2300,7 @@ static void __split_huge_page(struct pag + + spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags); + +- unfreeze_page(head); ++ remap_page(head); + + for (i = 0; i < HPAGE_PMD_NR; i++) { + struct page *subpage = head + i; +@@ -2466,7 +2466,7 @@ int split_huge_page_to_list(struct page + } + + /* +- * Racy check if we can split the page, before freeze_page() will ++ * Racy check if we can split the page, before unmap_page() will + * split PMDs + */ + if (total_mapcount(head) != page_count(head) - extra_pins - 1) { +@@ -2475,7 +2475,7 @@ int split_huge_page_to_list(struct page + } + + mlocked = PageMlocked(page); +- freeze_page(head); ++ unmap_page(head); + VM_BUG_ON_PAGE(compound_mapcount(head), head); + + /* Make sure the page is not on per-CPU pagevec as it takes pin */ +@@ -2527,7 +2527,7 @@ int split_huge_page_to_list(struct page + fail: if (mapping) + spin_unlock(&mapping->tree_lock); + spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags); +- unfreeze_page(head); ++ remap_page(head); + ret = -EBUSY; + } + diff --git a/patches.fixes/mm-huge_memory-splitting-set-mapping-index-before-unfreeze.patch b/patches.fixes/mm-huge_memory-splitting-set-mapping-index-before-unfreeze.patch new file mode 100644 index 0000000000..acd1c39b60 --- /dev/null +++ b/patches.fixes/mm-huge_memory-splitting-set-mapping-index-before-unfreeze.patch @@ -0,0 +1,66 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:16 -0800 +Subject: mm/huge_memory: splitting set mapping+index before unfreeze +Git-commit: 173d9d9fd3ddae84c110fea8aedf1f26af6be9ec +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +Huge tmpfs stress testing has occasionally hit shmem_undo_range()'s +VM_BUG_ON_PAGE(page_to_pgoff(page) != index, page). + +Move the setting of mapping and index up before the page_ref_unfreeze() +in __split_huge_page_tail() to fix this: so that a page cache lookup +cannot get a reference while the tail's mapping and index are unstable. + +In fact, might as well move them up before the smp_wmb(): I don't see an +actual need for that, but if I'm missing something, this way round is +safer than the other, and no less efficient. + +You might argue that VM_BUG_ON_PAGE(page_to_pgoff(page) != index, page) is +misplaced, and should be left until after the trylock_page(); but left as +is has not crashed since, and gives more stringent assurance. + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261516380.2275@eggly.anvils +Fixes: e9b61f19858a5 ("thp: reintroduce split_huge_page()") +Requires: 605ca5ede764 ("mm/huge_memory.c: reorder operations in __split_huge_page_tail()") +Signed-off-by: Hugh Dickins <hughd@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/huge_memory.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/mm/huge_memory.c ++++ b/mm/huge_memory.c +@@ -2229,6 +2229,12 @@ static void __split_huge_page_tail(struc + (1L << PG_unevictable) | + (1L << PG_dirty))); + ++ /* ->mapping in first tail page is compound_mapcount */ ++ VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING, ++ page_tail); ++ page_tail->mapping = head->mapping; ++ page_tail->index = head->index + tail; ++ + /* Page flags must be visible before we make the page non-compound. */ + smp_wmb(); + +@@ -2249,12 +2255,6 @@ static void __split_huge_page_tail(struc + if (page_is_idle(head)) + set_page_idle(page_tail); + +- /* ->mapping in first tail page is compound_mapcount */ +- VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING, +- page_tail); +- page_tail->mapping = head->mapping; +- +- page_tail->index = head->index + tail; + page_cpupid_xchg_last(page_tail, page_cpupid_last(head)); + lru_add_page_tail(head, page_tail, lruvec, list); + } diff --git a/patches.fixes/mm-khugepaged-collapse_shmem-do-not-crash-on-compound.patch b/patches.fixes/mm-khugepaged-collapse_shmem-do-not-crash-on-compound.patch new file mode 100644 index 0000000000..58d8996e22 --- /dev/null +++ b/patches.fixes/mm-khugepaged-collapse_shmem-do-not-crash-on-compound.patch @@ -0,0 +1,48 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:47 -0800 +Subject: mm/khugepaged: collapse_shmem() do not crash on Compound +Git-commit: 06a5e1268a5fb9c2b346a3da6b97e85f2eba0f07 +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +collapse_shmem()'s VM_BUG_ON_PAGE(PageTransCompound) was unsafe: before +it holds page lock of the first page, racing truncation then extension +might conceivably have inserted a hugepage there already. Fail with the +SCAN_PAGE_COMPOUND result, instead of crashing (CONFIG_DEBUG_VM=y) or +otherwise mishandling the unexpected hugepage - though later we might +code up a more constructive way of handling it, with SCAN_SUCCESS. + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261529310.2275@eggly.anvils +Fixes: f3f0e1d2150b2 ("khugepaged: add support of collapse for tmpfs/shmem pages") +Signed-off-by: Hugh Dickins <hughd@google.com> +Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/khugepaged.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1396,7 +1396,15 @@ static void collapse_shmem(struct mm_str + */ + VM_BUG_ON_PAGE(!PageLocked(page), page); + VM_BUG_ON_PAGE(!PageUptodate(page), page); +- VM_BUG_ON_PAGE(PageTransCompound(page), page); ++ ++ /* ++ * If file was truncated then extended, or hole-punched, before ++ * we locked the first page, then a THP might be there already. ++ */ ++ if (PageTransCompound(page)) { ++ result = SCAN_PAGE_COMPOUND; ++ goto out_unlock; ++ } + + if (page_mapping(page) != mapping) { + result = SCAN_TRUNCATED; diff --git a/patches.fixes/mm-khugepaged-collapse_shmem-remember-to-clear-holes.patch b/patches.fixes/mm-khugepaged-collapse_shmem-remember-to-clear-holes.patch new file mode 100644 index 0000000000..9651bc93ce --- /dev/null +++ b/patches.fixes/mm-khugepaged-collapse_shmem-remember-to-clear-holes.patch @@ -0,0 +1,59 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:35 -0800 +Subject: mm/khugepaged: collapse_shmem() remember to clear holes +Git-commit: 2af8ff291848cc4b1cce24b6c943394eb2c761e8 +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +Huge tmpfs testing reminds us that there is no __GFP_ZERO in the gfp +flags khugepaged uses to allocate a huge page - in all common cases it +would just be a waste of effort - so collapse_shmem() must remember to +clear out any holes that it instantiates. + +The obvious place to do so, where they are put into the page cache tree, +is not a good choice: because interrupts are disabled there. Leave it +until further down, once success is assured, where the other pages are +copied (before setting PageUptodate). + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261525080.2275@eggly.anvils +Fixes: f3f0e1d2150b2 ("khugepaged: add support of collapse for tmpfs/shmem pages") +Signed-off-by: Hugh Dickins <hughd@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/khugepaged.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1497,7 +1497,12 @@ tree_unlocked: + * Replacing old pages with new one has succeed, now we need to + * copy the content and free old pages. + */ ++ index = start; + list_for_each_entry_safe(page, tmp, &pagelist, lru) { ++ while (index < page->index) { ++ clear_highpage(new_page + (index % HPAGE_PMD_NR)); ++ index++; ++ } + copy_highpage(new_page + (page->index % HPAGE_PMD_NR), + page); + list_del(&page->lru); +@@ -1507,6 +1512,11 @@ tree_unlocked: + ClearPageActive(page); + ClearPageUnevictable(page); + put_page(page); ++ index++; ++ } ++ while (index < end) { ++ clear_highpage(new_page + (index % HPAGE_PMD_NR)); ++ index++; + } + + local_irq_save(flags); diff --git a/patches.fixes/mm-khugepaged-collapse_shmem-stop-if-punched-or-truncated.patch b/patches.fixes/mm-khugepaged-collapse_shmem-stop-if-punched-or-truncated.patch new file mode 100644 index 0000000000..c746dde23f --- /dev/null +++ b/patches.fixes/mm-khugepaged-collapse_shmem-stop-if-punched-or-truncated.patch @@ -0,0 +1,60 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:25 -0800 +Subject: mm/khugepaged: collapse_shmem() stop if punched or truncated +Git-commit: 701270fa193aadf00bdcf607738f64997275d4c7 +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +[ vbabka@suse.cz: use the 4.14 pre-xarray stable backport ] + +Huge tmpfs testing showed that although collapse_shmem() recognizes a +concurrently truncated or hole-punched page correctly, its handling of +holes was liable to refill an emptied extent. Add check to stop that. + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261522040.2275@eggly.anvils +Fixes: f3f0e1d2150b2 ("khugepaged: add support of collapse for tmpfs/shmem pages") +Signed-off-by: Hugh Dickins <hughd@google.com> +Reviewed-by: Matthew Wilcox <willy@infradead.org> +Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/khugepaged.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1348,6 +1348,16 @@ static void collapse_shmem(struct mm_str + int n = min(iter.index, end) - index; + + /* ++ * Stop if extent has been hole-punched, and is now completely ++ * empty (the more obvious i_size_read() check would take an ++ * irq-unsafe seqlock on 32-bit). ++ */ ++ if (n >= HPAGE_PMD_NR) { ++ result = SCAN_TRUNCATED; ++ goto tree_locked; ++ } ++ ++ /* + * Handle holes in the radix tree: charge it from shmem and + * insert relevant subpage of new_page into the radix-tree. + */ +@@ -1458,6 +1468,11 @@ out_unlock: + if (result == SCAN_SUCCEED && index < end) { + int n = end - index; + ++ /* Stop if extent has been truncated, and is now empty */ ++ if (n >= HPAGE_PMD_NR) { ++ result = SCAN_TRUNCATED; ++ goto tree_locked; ++ } + if (!shmem_charge(mapping->host, n)) { + result = SCAN_FAIL; + goto tree_locked; diff --git a/patches.fixes/mm-khugepaged-collapse_shmem-without-freezing-new_page.patch b/patches.fixes/mm-khugepaged-collapse_shmem-without-freezing-new_page.patch new file mode 100644 index 0000000000..e6c560bc7d --- /dev/null +++ b/patches.fixes/mm-khugepaged-collapse_shmem-without-freezing-new_page.patch @@ -0,0 +1,115 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:43 -0800 +Subject: mm/khugepaged: collapse_shmem() without freezing new_page +Git-commit: 87c460a0bded56195b5eb497d44709777ef7b415 +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +[ vbabka@suse.cz: use stable 4.14 pre-xarray backport ] + +khugepaged's collapse_shmem() does almost all of its work, to assemble +the huge new_page from 512 scattered old pages, with the new_page's +refcount frozen to 0 (and refcounts of all old pages so far also frozen +to 0). Including shmem_getpage() to read in any which were out on swap, +memory reclaim if necessary to allocate their intermediate pages, and +copying over all the data from old to new. + +Imagine the frozen refcount as a spinlock held, but without any lock +debugging to highlight the abuse: it's not good, and under serious load +heads into lockups - speculative getters of the page are not expecting +to spin while khugepaged is rescheduled. + +One can get a little further under load by hacking around elsewhere; but +fortunately, freezing the new_page turns out to have been entirely +unnecessary, with no hacks needed elsewhere. + +The huge new_page lock is already held throughout, and guards all its +subpages as they are brought one by one into the page cache tree; and +anything reading the data in that page, without the lock, before it has +been marked PageUptodate, would already be in the wrong. So simply +eliminate the freezing of the new_page. + +Each of the old pages remains frozen with refcount 0 after it has been +replaced by a new_page subpage in the page cache tree, until they are +all unfrozen on success or failure: just as before. They could be +unfrozen sooner, but cause no problem once no longer visible to +find_get_entry(), filemap_map_pages() and other speculative lookups. + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261527570.2275@eggly.anvils +Fixes: f3f0e1d2150b2 ("khugepaged: add support of collapse for tmpfs/shmem pages") +Signed-off-by: Hugh Dickins <hughd@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/khugepaged.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1285,7 +1285,7 @@ static void retract_page_tables(struct a + * collapse_shmem - collapse small tmpfs/shmem pages into huge one. + * + * Basic scheme is simple, details are more complex: +- * - allocate and freeze a new huge page; ++ * - allocate and lock a new huge page; + * - scan over radix tree replacing old pages the new one + * + swap in pages if necessary; + * + fill in gaps; +@@ -1293,11 +1293,11 @@ static void retract_page_tables(struct a + * - if replacing succeed: + * + copy data over; + * + free old pages; +- * + unfreeze huge page; ++ * + unlock huge page; + * - if replacing failed; + * + put all pages back and unfreeze them; + * + restore gaps in the radix-tree; +- * + free huge page; ++ * + unlock and free huge page; + */ + static void collapse_shmem(struct mm_struct *mm, + struct address_space *mapping, pgoff_t start, +@@ -1332,13 +1332,11 @@ static void collapse_shmem(struct mm_str + __SetPageSwapBacked(new_page); + new_page->index = start; + new_page->mapping = mapping; +- BUG_ON(!page_ref_freeze(new_page, 1)); + + /* +- * At this point the new_page is 'frozen' (page_count() is zero), locked +- * and not up-to-date. It's safe to insert it into radix tree, because +- * nobody would be able to map it or use it in other way until we +- * unfreeze it. ++ * At this point the new_page is locked and not up-to-date. ++ * It's safe to insert it into the page cache, because nobody would ++ * be able to map it or use it in another way until we unlock it. + */ + + index = start; +@@ -1516,9 +1514,8 @@ tree_unlocked: + index++; + } + +- /* Everything is ready, let's unfreeze the new_page */ + SetPageUptodate(new_page); +- page_ref_unfreeze(new_page, HPAGE_PMD_NR); ++ page_ref_add(new_page, HPAGE_PMD_NR - 1); + set_page_dirty(new_page); + mem_cgroup_commit_charge(new_page, memcg, false, true); + lru_cache_add_anon(new_page); +@@ -1566,8 +1563,6 @@ tree_unlocked: + VM_BUG_ON(nr_none); + spin_unlock_irq(&mapping->tree_lock); + +- /* Unfreeze new_page, caller would take care about freeing it */ +- page_ref_unfreeze(new_page, 1); + mem_cgroup_cancel_charge(new_page, memcg, true); + new_page->mapping = NULL; + } diff --git a/patches.fixes/mm-khugepaged-fix-crashes-due-to-misaccounted-holes.patch b/patches.fixes/mm-khugepaged-fix-crashes-due-to-misaccounted-holes.patch new file mode 100644 index 0000000000..99c0a49393 --- /dev/null +++ b/patches.fixes/mm-khugepaged-fix-crashes-due-to-misaccounted-holes.patch @@ -0,0 +1,88 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:29 -0800 +Subject: mm/khugepaged: fix crashes due to misaccounted holes +Git-commit: aaa52e340073b7f4593b3c4ddafcafa70cf838b5 +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +[ vbabka@suse.cz: use 4.14 pre-xarray stable backport ] + +Huge tmpfs testing on a shortish file mapped into a pmd-rounded extent +hit shmem_evict_inode()'s WARN_ON(inode->i_blocks) followed by +clear_inode()'s BUG_ON(inode->i_data.nrpages) when the file was later +closed and unlinked. + +khugepaged's collapse_shmem() was forgetting to update mapping->nrpages +on the rollback path, after it had added but then needs to undo some +holes. + +There is indeed an irritating asymmetry between shmem_charge(), whose +callers want it to increment nrpages after successfully accounting +blocks, and shmem_uncharge(), when __delete_from_page_cache() already +decremented nrpages itself: oh well, just add a comment on that to them +both. + +And shmem_recalc_inode() is supposed to be called when the accounting is +expected to be in balance (so it can deduce from imbalance that reclaim +discarded some pages): so change shmem_charge() to update nrpages +earlier (though it's rare for the difference to matter at all). + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261523450.2275@eggly.anvils +Fixes: 800d8c63b2e98 ("shmem: add huge pages support") +Fixes: f3f0e1d2150b2 ("khugepaged: add support of collapse for tmpfs/shmem pages") +Signed-off-by: Hugh Dickins <hughd@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/khugepaged.c | 4 +++- + mm/shmem.c | 6 +++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1534,8 +1534,10 @@ tree_unlocked: + *hpage = NULL; + } else { + /* Something went wrong: rollback changes to the radix-tree */ +- shmem_uncharge(mapping->host, nr_none); + spin_lock_irq(&mapping->tree_lock); ++ mapping->nrpages -= nr_none; ++ shmem_uncharge(mapping->host, nr_none); ++ + radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, + start) { + if (iter.index >= end) +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -294,12 +294,14 @@ bool shmem_charge(struct inode *inode, l + if (!shmem_inode_acct_block(inode, pages)) + return false; + ++ /* nrpages adjustment first, then shmem_recalc_inode() when balanced */ ++ inode->i_mapping->nrpages += pages; ++ + spin_lock_irqsave(&info->lock, flags); + info->alloced += pages; + inode->i_blocks += pages * BLOCKS_PER_PAGE; + shmem_recalc_inode(inode); + spin_unlock_irqrestore(&info->lock, flags); +- inode->i_mapping->nrpages += pages; + + return true; + } +@@ -309,6 +311,8 @@ void shmem_uncharge(struct inode *inode, + struct shmem_inode_info *info = SHMEM_I(inode); + unsigned long flags; + ++ /* nrpages adjustment done by __delete_from_page_cache() or caller */ ++ + spin_lock_irqsave(&info->lock, flags); + info->alloced -= pages; + inode->i_blocks -= pages * BLOCKS_PER_PAGE; diff --git a/patches.fixes/mm-khugepaged-minor-reorderings-in-collapse_shmem.patch b/patches.fixes/mm-khugepaged-minor-reorderings-in-collapse_shmem.patch new file mode 100644 index 0000000000..f4c0d7ca23 --- /dev/null +++ b/patches.fixes/mm-khugepaged-minor-reorderings-in-collapse_shmem.patch @@ -0,0 +1,232 @@ +From: Hugh Dickins <hughd@google.com> +Date: Fri, 30 Nov 2018 14:10:39 -0800 +Subject: mm/khugepaged: minor reorderings in collapse_shmem() +Git-commit: 042a30824871fa3149b0127009074b75cc25863c +Patch-mainline: v4.20-rc5 +References: VM Functionality, bsc#1121599 + +[ vbabka@suse.cz: use stable 4.14 pre-xarray backport ] + +Several cleanups in collapse_shmem(): most of which probably do not +really matter, beyond doing things in a more familiar and reassuring +order. Simplify the failure gotos in the main loop, and on success +update stats while interrupts still disabled from the last iteration. + +Link: http://lkml.kernel.org/r/alpine.LSU.2.11.1811261526400.2275@eggly.anvils +Fixes: f3f0e1d2150b2 ("khugepaged: add support of collapse for tmpfs/shmem pages") +Signed-off-by: Hugh Dickins <hughd@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Cc: Jerome Glisse <jglisse@redhat.com> +Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: <stable@vger.kernel.org> [4.8+] +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Sasha Levin <sashal@kernel.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/khugepaged.c | 73 +++++++++++++++++++++++--------------------------------- + 1 file changed, 30 insertions(+), 43 deletions(-) + +--- a/mm/khugepaged.c ++++ b/mm/khugepaged.c +@@ -1328,13 +1328,12 @@ static void collapse_shmem(struct mm_str + goto out; + } + ++ __SetPageLocked(new_page); ++ __SetPageSwapBacked(new_page); + new_page->index = start; + new_page->mapping = mapping; +- __SetPageSwapBacked(new_page); +- __SetPageLocked(new_page); + BUG_ON(!page_ref_freeze(new_page, 1)); + +- + /* + * At this point the new_page is 'frozen' (page_count() is zero), locked + * and not up-to-date. It's safe to insert it into radix tree, because +@@ -1363,13 +1362,13 @@ static void collapse_shmem(struct mm_str + */ + if (n && !shmem_charge(mapping->host, n)) { + result = SCAN_FAIL; +- break; ++ goto tree_locked; + } +- nr_none += n; + for (; index < min(iter.index, end); index++) { + radix_tree_insert(&mapping->page_tree, index, + new_page + (index % HPAGE_PMD_NR)); + } ++ nr_none += n; + + /* We are done. */ + if (index >= end) +@@ -1385,12 +1384,12 @@ static void collapse_shmem(struct mm_str + result = SCAN_FAIL; + goto tree_unlocked; + } +- spin_lock_irq(&mapping->tree_lock); + } else if (trylock_page(page)) { + get_page(page); ++ spin_unlock_irq(&mapping->tree_lock); + } else { + result = SCAN_PAGE_LOCK; +- break; ++ goto tree_locked; + } + + /* +@@ -1405,11 +1404,10 @@ static void collapse_shmem(struct mm_str + result = SCAN_TRUNCATED; + goto out_unlock; + } +- spin_unlock_irq(&mapping->tree_lock); + + if (isolate_lru_page(page)) { + result = SCAN_DEL_PAGE_LRU; +- goto out_isolate_failed; ++ goto out_unlock; + } + + if (page_mapped(page)) +@@ -1431,7 +1429,9 @@ static void collapse_shmem(struct mm_str + */ + if (!page_ref_freeze(page, 3)) { + result = SCAN_PAGE_COUNT; +- goto out_lru; ++ spin_unlock_irq(&mapping->tree_lock); ++ putback_lru_page(page); ++ goto out_unlock; + } + + /* +@@ -1447,17 +1447,10 @@ static void collapse_shmem(struct mm_str + slot = radix_tree_iter_resume(slot, &iter); + index++; + continue; +-out_lru: +- spin_unlock_irq(&mapping->tree_lock); +- putback_lru_page(page); +-out_isolate_failed: +- unlock_page(page); +- put_page(page); +- goto tree_unlocked; + out_unlock: + unlock_page(page); + put_page(page); +- break; ++ goto tree_unlocked; + } + + /* +@@ -1465,7 +1458,7 @@ out_unlock: + * This code only triggers if there's nothing in radix tree + * beyond 'end'. + */ +- if (result == SCAN_SUCCEED && index < end) { ++ if (index < end) { + int n = end - index; + + /* Stop if extent has been truncated, and is now empty */ +@@ -1477,7 +1470,6 @@ out_unlock: + result = SCAN_FAIL; + goto tree_locked; + } +- + for (; index < end; index++) { + radix_tree_insert(&mapping->page_tree, index, + new_page + (index % HPAGE_PMD_NR)); +@@ -1485,14 +1477,19 @@ out_unlock: + nr_none += n; + } + ++ __inc_node_page_state(new_page, NR_SHMEM_THPS); ++ if (nr_none) { ++ struct zone *zone = page_zone(new_page); ++ ++ __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none); ++ __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none); ++ } ++ + tree_locked: + spin_unlock_irq(&mapping->tree_lock); + tree_unlocked: + + if (result == SCAN_SUCCEED) { +- unsigned long flags; +- struct zone *zone = page_zone(new_page); +- + /* + * Replacing old pages with new one has succeed, now we need to + * copy the content and free old pages. +@@ -1506,11 +1503,11 @@ tree_unlocked: + copy_highpage(new_page + (page->index % HPAGE_PMD_NR), + page); + list_del(&page->lru); +- unlock_page(page); +- page_ref_unfreeze(page, 1); + page->mapping = NULL; ++ page_ref_unfreeze(page, 1); + ClearPageActive(page); + ClearPageUnevictable(page); ++ unlock_page(page); + put_page(page); + index++; + } +@@ -1519,28 +1516,17 @@ tree_unlocked: + index++; + } + +- local_irq_save(flags); +- __inc_node_page_state(new_page, NR_SHMEM_THPS); +- if (nr_none) { +- __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none); +- __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none); +- } +- local_irq_restore(flags); +- +- /* +- * Remove pte page tables, so we can re-faulti +- * the page as huge. +- */ +- retract_page_tables(mapping, start); +- + /* Everything is ready, let's unfreeze the new_page */ +- set_page_dirty(new_page); + SetPageUptodate(new_page); + page_ref_unfreeze(new_page, HPAGE_PMD_NR); ++ set_page_dirty(new_page); + mem_cgroup_commit_charge(new_page, memcg, false, true); + lru_cache_add_anon(new_page); +- unlock_page(new_page); + ++ /* ++ * Remove pte page tables, so we can re-fault the page as huge. ++ */ ++ retract_page_tables(mapping, start); + *hpage = NULL; + } else { + /* Something went wrong: rollback changes to the radix-tree */ +@@ -1573,8 +1559,8 @@ tree_unlocked: + slot, page); + slot = radix_tree_iter_resume(slot, &iter); + spin_unlock_irq(&mapping->tree_lock); +- putback_lru_page(page); + unlock_page(page); ++ putback_lru_page(page); + spin_lock_irq(&mapping->tree_lock); + } + VM_BUG_ON(nr_none); +@@ -1583,9 +1569,10 @@ tree_unlocked: + /* Unfreeze new_page, caller would take care about freeing it */ + page_ref_unfreeze(new_page, 1); + mem_cgroup_cancel_charge(new_page, memcg, true); +- unlock_page(new_page); + new_page->mapping = NULL; + } ++ ++ unlock_page(new_page); + out: + VM_BUG_ON(!list_empty(&pagelist)); + /* TODO: tracepoints */ diff --git a/patches.fixes/shmem-introduce-shmem_inode_acct_block.patch b/patches.fixes/shmem-introduce-shmem_inode_acct_block.patch new file mode 100644 index 0000000000..1363e6117a --- /dev/null +++ b/patches.fixes/shmem-introduce-shmem_inode_acct_block.patch @@ -0,0 +1,247 @@ +From: Mike Rapoport <rppt@linux.vnet.ibm.com> +Date: Wed, 6 Sep 2017 16:22:59 -0700 +Subject: shmem: introduce shmem_inode_acct_block +Git-commit: 0f0796945614b7523987f7eea32407421af4b1ee +Patch-mainline: v4.14-rc1 +References: VM Functionality, bsc#1121599 + +The shmem_acct_block and the update of used_blocks are following one +another in all the places they are used. Combine these two into a +helper function. + +Link: http://lkml.kernel.org/r/1497939652-16528-3-git-send-email-rppt@linux.vnet.ibm.com +Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com> +Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> +Cc: Andrea Arcangeli <aarcange@redhat.com> +Cc: Hillf Danton <hillf.zj@alibaba-inc.com> +Cc: Hugh Dickins <hughd@google.com> +Cc: Pavel Emelyanov <xemul@virtuozzo.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/shmem.c | 102 +++++++++++++++++++++++++++---------------------------------- + 1 file changed, 46 insertions(+), 56 deletions(-) + +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -187,6 +187,38 @@ static inline void shmem_unacct_blocks(u + vm_unacct_memory(pages * VM_ACCT(PAGE_SIZE)); + } + ++static inline bool shmem_inode_acct_block(struct inode *inode, long pages) ++{ ++ struct shmem_inode_info *info = SHMEM_I(inode); ++ struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); ++ ++ if (shmem_acct_block(info->flags, pages)) ++ return false; ++ ++ if (sbinfo->max_blocks) { ++ if (percpu_counter_compare(&sbinfo->used_blocks, ++ sbinfo->max_blocks - pages) > 0) ++ goto unacct; ++ percpu_counter_add(&sbinfo->used_blocks, pages); ++ } ++ ++ return true; ++ ++unacct: ++ shmem_unacct_blocks(info->flags, pages); ++ return false; ++} ++ ++static inline void shmem_inode_unacct_blocks(struct inode *inode, long pages) ++{ ++ struct shmem_inode_info *info = SHMEM_I(inode); ++ struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); ++ ++ if (sbinfo->max_blocks) ++ percpu_counter_sub(&sbinfo->used_blocks, pages); ++ shmem_unacct_blocks(info->flags, pages); ++} ++ + static const struct super_operations shmem_ops; + static const struct address_space_operations shmem_aops; + static const struct file_operations shmem_file_operations; +@@ -248,31 +280,20 @@ static void shmem_recalc_inode(struct in + + freed = info->alloced - info->swapped - inode->i_mapping->nrpages; + if (freed > 0) { +- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); +- if (sbinfo->max_blocks) +- percpu_counter_add(&sbinfo->used_blocks, -freed); + info->alloced -= freed; + inode->i_blocks -= freed * BLOCKS_PER_PAGE; +- shmem_unacct_blocks(info->flags, freed); ++ shmem_inode_unacct_blocks(inode, freed); + } + } + + bool shmem_charge(struct inode *inode, long pages) + { + struct shmem_inode_info *info = SHMEM_I(inode); +- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + unsigned long flags; + +- if (shmem_acct_block(info->flags, pages)) ++ if (!shmem_inode_acct_block(inode, pages)) + return false; + +- if (sbinfo->max_blocks) { +- if (percpu_counter_compare(&sbinfo->used_blocks, +- sbinfo->max_blocks - pages) > 0) +- goto unacct; +- percpu_counter_add(&sbinfo->used_blocks, pages); +- } +- + spin_lock_irqsave(&info->lock, flags); + info->alloced += pages; + inode->i_blocks += pages * BLOCKS_PER_PAGE; +@@ -281,16 +302,11 @@ bool shmem_charge(struct inode *inode, l + inode->i_mapping->nrpages += pages; + + return true; +- +-unacct: +- shmem_unacct_blocks(info->flags, pages); +- return false; + } + + void shmem_uncharge(struct inode *inode, long pages) + { + struct shmem_inode_info *info = SHMEM_I(inode); +- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + unsigned long flags; + + spin_lock_irqsave(&info->lock, flags); +@@ -299,9 +315,7 @@ void shmem_uncharge(struct inode *inode, + shmem_recalc_inode(inode); + spin_unlock_irqrestore(&info->lock, flags); + +- if (sbinfo->max_blocks) +- percpu_counter_sub(&sbinfo->used_blocks, pages); +- shmem_unacct_blocks(info->flags, pages); ++ shmem_inode_unacct_blocks(inode, pages); + } + + /* +@@ -1450,9 +1464,10 @@ static struct page *shmem_alloc_page(gfp + } + + static struct page *shmem_alloc_and_acct_page(gfp_t gfp, +- struct shmem_inode_info *info, struct shmem_sb_info *sbinfo, ++ struct inode *inode, + pgoff_t index, bool huge) + { ++ struct shmem_inode_info *info = SHMEM_I(inode); + struct page *page; + int nr; + int err = -ENOSPC; +@@ -1461,14 +1476,8 @@ static struct page *shmem_alloc_and_acct + huge = false; + nr = huge ? HPAGE_PMD_NR : 1; + +- if (shmem_acct_block(info->flags, nr)) ++ if (!shmem_inode_acct_block(inode, nr)) + goto failed; +- if (sbinfo->max_blocks) { +- if (percpu_counter_compare(&sbinfo->used_blocks, +- sbinfo->max_blocks - nr) > 0) +- goto unacct; +- percpu_counter_add(&sbinfo->used_blocks, nr); +- } + + if (huge) + page = shmem_alloc_hugepage(gfp, info, index); +@@ -1481,10 +1490,7 @@ static struct page *shmem_alloc_and_acct + } + + err = -ENOMEM; +- if (sbinfo->max_blocks) +- percpu_counter_add(&sbinfo->used_blocks, -nr); +-unacct: +- shmem_unacct_blocks(info->flags, nr); ++ shmem_inode_unacct_blocks(inode, nr); + failed: + return ERR_PTR(err); + } +@@ -1750,10 +1756,9 @@ repeat: + } + + alloc_huge: +- page = shmem_alloc_and_acct_page(gfp, info, sbinfo, +- index, true); ++ page = shmem_alloc_and_acct_page(gfp, inode, index, true); + if (IS_ERR(page)) { +-alloc_nohuge: page = shmem_alloc_and_acct_page(gfp, info, sbinfo, ++alloc_nohuge: page = shmem_alloc_and_acct_page(gfp, inode, + index, false); + } + if (IS_ERR(page)) { +@@ -1875,10 +1880,7 @@ clear: + * Error recovery. + */ + unacct: +- if (sbinfo->max_blocks) +- percpu_counter_sub(&sbinfo->used_blocks, +- 1 << compound_order(page)); +- shmem_unacct_blocks(info->flags, 1 << compound_order(page)); ++ shmem_inode_unacct_blocks(inode, 1 << compound_order(page)); + + if (PageTransHuge(page)) { + unlock_page(page); +@@ -2214,7 +2216,6 @@ int shmem_mcopy_atomic_pte(struct mm_str + { + struct inode *inode = file_inode(dst_vma->vm_file); + struct shmem_inode_info *info = SHMEM_I(inode); +- struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + struct address_space *mapping = inode->i_mapping; + gfp_t gfp = mapping_gfp_mask(mapping); + pgoff_t pgoff = linear_page_index(dst_vma, dst_addr); +@@ -2226,19 +2227,13 @@ int shmem_mcopy_atomic_pte(struct mm_str + int ret; + + ret = -ENOMEM; +- if (shmem_acct_block(info->flags, 1)) ++ if (!shmem_inode_acct_block(inode, 1)) + goto out; +- if (sbinfo->max_blocks) { +- if (percpu_counter_compare(&sbinfo->used_blocks, +- sbinfo->max_blocks) >= 0) +- goto out_unacct_blocks; +- percpu_counter_inc(&sbinfo->used_blocks); +- } + + if (!*pagep) { + page = shmem_alloc_page(gfp, info, pgoff); + if (!page) +- goto out_dec_used_blocks; ++ goto out_unacct_blocks; + + page_kaddr = kmap_atomic(page); + ret = copy_from_user(page_kaddr, (const void __user *)src_addr, +@@ -2248,9 +2243,7 @@ int shmem_mcopy_atomic_pte(struct mm_str + /* fallback to copy_from_user outside mmap_sem */ + if (unlikely(ret)) { + *pagep = page; +- if (sbinfo->max_blocks) +- percpu_counter_add(&sbinfo->used_blocks, -1); +- shmem_unacct_blocks(info->flags, 1); ++ shmem_inode_unacct_blocks(inode, 1); + /* don't free the page */ + return -EFAULT; + } +@@ -2313,11 +2306,8 @@ out_release_uncharge: + out_release: + unlock_page(page); + put_page(page); +-out_dec_used_blocks: +- if (sbinfo->max_blocks) +- percpu_counter_add(&sbinfo->used_blocks, -1); + out_unacct_blocks: +- shmem_unacct_blocks(info->flags, 1); ++ shmem_inode_unacct_blocks(inode, 1); + goto out; + } + diff --git a/patches.fixes/shmem-shmem_charge-verify-max_block-is-not-exceeded-before-inode-update.patch b/patches.fixes/shmem-shmem_charge-verify-max_block-is-not-exceeded-before-inode-update.patch new file mode 100644 index 0000000000..ea08c966ec --- /dev/null +++ b/patches.fixes/shmem-shmem_charge-verify-max_block-is-not-exceeded-before-inode-update.patch @@ -0,0 +1,78 @@ +From: Mike Rapoport <rppt@linux.vnet.ibm.com> +Date: Wed, 6 Sep 2017 16:22:56 -0700 +Subject: shmem: shmem_charge: verify max_block is not exceeded before inode + update +Git-commit: b1cc94ab2f2ba31fcb2c59df0b9cf03f6d720553 +Patch-mainline: v4.14-rc1 +References: VM Functionality, bsc#1121599 + +Patch series "userfaultfd: enable zeropage support for shmem". + +These patches enable support for UFFDIO_ZEROPAGE for shared memory. + +The first two patches are not strictly related to userfaultfd, they are +just minor refactoring to reduce amount of code duplication. + +This patch (of 7): + +Currently we update inode and shmem_inode_info before verifying that +used_blocks will not exceed max_blocks. In case it will, we undo the +update. Let's switch the order and move the verification of the blocks +count before the inode and shmem_inode_info update. + +Link: http://lkml.kernel.org/r/1497939652-16528-2-git-send-email-rppt@linux.vnet.ibm.com +Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com> +Cc: Andrea Arcangeli <aarcange@redhat.com> +Cc: Hugh Dickins <hughd@google.com> +Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> +Cc: Hillf Danton <hillf.zj@alibaba-inc.com> +Cc: Pavel Emelyanov <xemul@virtuozzo.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Vlastimil Babka <vbabka@suse.cz> +--- + mm/shmem.c | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -265,6 +265,14 @@ bool shmem_charge(struct inode *inode, l + + if (shmem_acct_block(info->flags, pages)) + return false; ++ ++ if (sbinfo->max_blocks) { ++ if (percpu_counter_compare(&sbinfo->used_blocks, ++ sbinfo->max_blocks - pages) > 0) ++ goto unacct; ++ percpu_counter_add(&sbinfo->used_blocks, pages); ++ } ++ + spin_lock_irqsave(&info->lock, flags); + info->alloced += pages; + inode->i_blocks += pages * BLOCKS_PER_PAGE; +@@ -272,20 +280,11 @@ bool shmem_charge(struct inode *inode, l + spin_unlock_irqrestore(&info->lock, flags); + inode->i_mapping->nrpages += pages; + +- if (!sbinfo->max_blocks) +- return true; +- if (percpu_counter_compare(&sbinfo->used_blocks, +- sbinfo->max_blocks - pages) > 0) { +- inode->i_mapping->nrpages -= pages; +- spin_lock_irqsave(&info->lock, flags); +- info->alloced -= pages; +- shmem_recalc_inode(inode); +- spin_unlock_irqrestore(&info->lock, flags); +- shmem_unacct_blocks(info->flags, pages); +- return false; +- } +- percpu_counter_add(&sbinfo->used_blocks, pages); + return true; ++ ++unacct: ++ shmem_unacct_blocks(info->flags, pages); ++ return false; + } + + void shmem_uncharge(struct inode *inode, long pages) diff --git a/patches.fixes/userfaultfd-shmem-add-i_size-checks.patch b/patches.fixes/userfaultfd-shmem-add-i_size-checks.patch index 7d3d9d2bc0..698ad77370 100644 --- a/patches.fixes/userfaultfd-shmem-add-i_size-checks.patch +++ b/patches.fixes/userfaultfd-shmem-add-i_size-checks.patch @@ -44,8 +44,8 @@ Signed-off-by: Vlastimil Babka <vbabka@suse.cz> + pgoff_t offset, max_off; ret = -ENOMEM; - if (shmem_acct_block(info->flags, 1)) -@@ -2274,6 +2275,12 @@ int shmem_mcopy_atomic_pte(struct mm_str + if (!shmem_inode_acct_block(inode, 1)) +@@ -2266,6 +2267,12 @@ int shmem_mcopy_atomic_pte(struct mm_str __SetPageSwapBacked(page); __SetPageUptodate(page); @@ -58,7 +58,7 @@ Signed-off-by: Vlastimil Babka <vbabka@suse.cz> ret = mem_cgroup_try_charge(page, dst_mm, gfp, &memcg, false); if (ret) goto out_release; -@@ -2292,8 +2299,14 @@ int shmem_mcopy_atomic_pte(struct mm_str +@@ -2284,8 +2291,14 @@ int shmem_mcopy_atomic_pte(struct mm_str if (dst_vma->vm_flags & VM_WRITE) _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte)); @@ -74,7 +74,7 @@ Signed-off-by: Vlastimil Babka <vbabka@suse.cz> if (!pte_none(*dst_pte)) goto out_release_uncharge_unlock; -@@ -2311,13 +2324,14 @@ int shmem_mcopy_atomic_pte(struct mm_str +@@ -2303,13 +2316,14 @@ int shmem_mcopy_atomic_pte(struct mm_str /* No need to invalidate - it was non-present before */ update_mmu_cache(dst_vma, dst_addr, dst_pte); diff --git a/patches.fixes/xfs-fix-quotacheck-dquot-id-overflow-infinite-loop.patch b/patches.fixes/xfs-fix-quotacheck-dquot-id-overflow-infinite-loop.patch new file mode 100644 index 0000000000..123d01f63f --- /dev/null +++ b/patches.fixes/xfs-fix-quotacheck-dquot-id-overflow-infinite-loop.patch @@ -0,0 +1,42 @@ +From cfaf2d034360166e569a4929dd83ae9698bed856 Mon Sep 17 00:00:00 2001 +From: Brian Foster <bfoster@redhat.com> +Date: Mon, 24 Jul 2017 08:33:25 -0700 +Subject: [PATCH] xfs: fix quotacheck dquot id overflow infinite loop +Git-commit: cfaf2d034360166e569a4929dd83ae9698bed856 +Patch-mainline: v4.13-rc3 +References: bsc#1121621 + +If a dquot has an id of U32_MAX, the next lookup index increment +overflows the uint32_t back to 0. This starts the lookup sequence +over from the beginning, repeats indefinitely and results in a +livelock. + +Update xfs_qm_dquot_walk() to explicitly check for the lookup +overflow and exit the loop. + +Signed-off-by: Brian Foster <bfoster@redhat.com> +Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> +Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> +Acked-by: Anthony Iliopoulos <ailiopoulos@suse.com> + +--- + fs/xfs/xfs_qm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c +index 6ce948c436d5..15751dc2a27d 100644 +--- a/fs/xfs/xfs_qm.c ++++ b/fs/xfs/xfs_qm.c +@@ -111,6 +111,9 @@ xfs_qm_dquot_walk( + skipped = 0; + break; + } ++ /* we're done if id overflows back to zero */ ++ if (!next_index) ++ break; + } + + if (skipped) { +-- +2.16.4 + diff --git a/patches.suse/0003-modsign-log-module-name-in-the-event-of-an-error.patch b/patches.suse/0003-modsign-log-module-name-in-the-event-of-an-error.patch index 811ace7253..645d989f9b 100644 --- a/patches.suse/0003-modsign-log-module-name-in-the-event-of-an-error.patch +++ b/patches.suse/0003-modsign-log-module-name-in-the-event-of-an-error.patch @@ -17,8 +17,8 @@ Acked-by: Jessica Yu <jeyu@suse.de> --- kernel/module-internal.h | 24 +++++++++++++++++++++++- kernel/module.c | 21 +-------------------- - kernel/module_signing.c | 12 +++++++----- - 3 files changed, 31 insertions(+), 26 deletions(-) + kernel/module_signing.c | 13 ++++++++----- + 3 files changed, 32 insertions(+), 26 deletions(-) --- a/kernel/module-internal.h +++ b/kernel/module-internal.h @@ -89,7 +89,15 @@ Acked-by: Jessica Yu <jeyu@suse.de> if (!err) { --- a/kernel/module_signing.c +++ b/kernel/module_signing.c -@@ -45,10 +45,10 @@ struct module_signature { +@@ -13,6 +13,7 @@ + #include <linux/errno.h> + #include <linux/string.h> + #include <linux/verification.h> ++#include <linux/module.h> + #include <crypto/public_key.h> + #include "module-internal.h" + +@@ -45,10 +46,10 @@ struct module_signature { /* * Verify the signature on a module. */ @@ -102,7 +110,7 @@ Acked-by: Jessica Yu <jeyu@suse.de> pr_devel("==>%s(,%zu)\n", __func__, modlen); -@@ -62,10 +62,11 @@ int mod_verify_sig(const void *mod, unsi +@@ -62,10 +63,11 @@ int mod_verify_sig(const void *mod, unsi if (sig_len >= modlen) return -EBADMSG; modlen -= sig_len; @@ -116,7 +124,7 @@ Acked-by: Jessica Yu <jeyu@suse.de> return -ENOPKG; } -@@ -76,7 +77,8 @@ int mod_verify_sig(const void *mod, unsi +@@ -76,7 +78,8 @@ int mod_verify_sig(const void *mod, unsi ms.__pad[0] != 0 || ms.__pad[1] != 0 || ms.__pad[2] != 0) { diff --git a/patches.suse/0004-MODSIGN-checking-the-blacklisted-hash-before-loading.patch b/patches.suse/0004-MODSIGN-checking-the-blacklisted-hash-before-loading.patch index cd34d50955..68837d050e 100644 --- a/patches.suse/0004-MODSIGN-checking-the-blacklisted-hash-before-loading.patch +++ b/patches.suse/0004-MODSIGN-checking-the-blacklisted-hash-before-loading.patch @@ -19,25 +19,21 @@ compared by kernel. Signed-off-by: Lee, Chun-Yi <jlee@suse.com> --- - kernel/module_signing.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 60 insertions(+), 2 deletions(-) + kernel/module_signing.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 59 insertions(+), 2 deletions(-) --- a/kernel/module_signing.c +++ b/kernel/module_signing.c -@@ -11,9 +11,12 @@ - - #include <linux/kernel.h> - #include <linux/errno.h> -+#include <linux/module.h> - #include <linux/string.h> +@@ -15,6 +15,8 @@ #include <linux/verification.h> + #include <linux/module.h> #include <crypto/public_key.h> +#include <crypto/hash.h> +#include <keys/system_keyring.h> #include "module-internal.h" enum pkey_id_type { -@@ -42,19 +45,67 @@ struct module_signature { +@@ -43,19 +45,67 @@ struct module_signature { __be32 sig_len; /* Length of signature data */ }; @@ -106,7 +102,7 @@ Signed-off-by: Lee, Chun-Yi <jlee@suse.com> memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); modlen -= sizeof(ms); -@@ -82,7 +133,14 @@ int mod_verify_sig(const void *mod, stru +@@ -83,7 +133,14 @@ int mod_verify_sig(const void *mod, stru return -EBADMSG; } diff --git a/patches.suse/ath10k-QCA9377-firmware-limit.patch b/patches.suse/ath10k-QCA9377-firmware-limit.patch new file mode 100644 index 0000000000..5633067c2f --- /dev/null +++ b/patches.suse/ath10k-QCA9377-firmware-limit.patch @@ -0,0 +1,40 @@ +From: Takashi Iwai <tiwai@suse.de> +Subject: Limit max FW API version for QCA9377 +Patch-mainline: Never, SLE15-SP0 only (not for SP1!) +References: bsc#1121714, bsc#1121715 + +QCA9377 got a new firmware API 6 from upstream, but this is broken for +SLE15 / Leap 15.0 ath10k driver code. As a workaround, introduce the +API version limit per board model, and define for QCA9377 and QCA6174. + +Signed-off-by: Takashi Iwai <tiwai@suse.de> + +--- + drivers/net/wireless/ath/ath10k/core.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -1411,12 +1411,21 @@ static void ath10k_core_get_fw_name(stru + static int ath10k_core_fetch_firmware_files(struct ath10k *ar) + { + int ret, i; ++ int api_max; + char fw_name[100]; + + /* calibration file is optional, don't check for any errors */ + ath10k_fetch_cal_file(ar); + +- for (i = ATH10K_FW_API_MAX; i >= ATH10K_FW_API_MIN; i--) { ++ api_max = ATH10K_FW_API_MAX; ++ /* XXX: SLE15/Leap-15.0 version of ath10k doesn't work with the latest ++ * FW API for some chips. ++ */ ++ if (ar->hw_params.dev_id == QCA9377_1_0_DEVICE_ID || ++ ar->hw_params.dev_id == QCA6174_2_1_DEVICE_ID) ++ api_max = 5; ++ ++ for (i = api_max; i >= ATH10K_FW_API_MIN; i--) { + ar->fw_api = i; + ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", + ar->fw_api); diff --git a/patches.suse/mm-don-t-warn-about-large-allocations-for-slab.patch b/patches.suse/mm-don-t-warn-about-large-allocations-for-slab.patch new file mode 100644 index 0000000000..3258a9c3c7 --- /dev/null +++ b/patches.suse/mm-don-t-warn-about-large-allocations-for-slab.patch @@ -0,0 +1,110 @@ +From a06fa0d0d6beb579294eecb3b07e639b0dfbf922 Mon Sep 17 00:00:00 2001 +From: Dmitry Vyukov <dvyukov@google.com> +Date: Fri, 26 Oct 2018 15:03:12 -0700 +Subject: [PATCH] mm: don't warn about large allocations for slab + +References: git fixes (slab) +Patch-mainline: v4.20 +Git-commit: 61448479a9f2c954cde0cfe778cb6bec5d0a748d + +Slub does not call kmalloc_slab() for sizes > KMALLOC_MAX_CACHE_SIZE, +instead it falls back to kmalloc_large(). + +For slab KMALLOC_MAX_CACHE_SIZE == KMALLOC_MAX_SIZE and it calls +kmalloc_slab() for all allocations relying on NULL return value for +over-sized allocations. + +This inconsistency leads to unwanted warnings from kmalloc_slab() for +over-sized allocations for slab. Returning NULL for failed allocations is +the expected behavior. + +Make slub and slab code consistent by checking size > +KMALLOC_MAX_CACHE_SIZE in slab before calling kmalloc_slab(). + +While we are here also fix the check in kmalloc_slab(). We should check +against KMALLOC_MAX_CACHE_SIZE rather than KMALLOC_MAX_SIZE. It all kinda +worked because for slab the constants are the same, and slub always checks +the size against KMALLOC_MAX_CACHE_SIZE before kmalloc_slab(). But if we +get there with size > KMALLOC_MAX_CACHE_SIZE anyhow bad things will +happen. For example, in case of a newly introduced bug in slub code. + +Also move the check in kmalloc_slab() from function entry to the size > +192 case. This partially compensates for the additional check in slab +code and makes slub code a bit faster (at least theoretically). + +Also drop __GFP_NOWARN in the warning check. This warning means a bug in +slab code itself, user-passed flags have nothing to do with it. + +Nothing of this affects slob. + +Link: http://lkml.kernel.org/r/20180927171502.226522-1-dvyukov@gmail.com +Signed-off-by: Dmitry Vyukov <dvyukov@google.com> +Reported-by: syzbot+87829a10073277282ad1@syzkaller.appspotmail.com +Reported-by: syzbot+ef4e8fc3a06e9019bb40@syzkaller.appspotmail.com +Reported-by: syzbot+6e438f4036df52cbb863@syzkaller.appspotmail.com +Reported-by: syzbot+8574471d8734457d98aa@syzkaller.appspotmail.com +Reported-by: syzbot+af1504df0807a083dbd9@syzkaller.appspotmail.com +Acked-by: Christoph Lameter <cl@linux.com> +Acked-by: Vlastimil Babka <vbabka@suse.cz> +Cc: Pekka Enberg <penberg@kernel.org> +Cc: David Rientjes <rientjes@google.com> +Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Mel Gorman <mgorman@suse.de> +--- + mm/slab.c | 4 ++++ + mm/slab_common.c | 12 ++++++------ + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/mm/slab.c b/mm/slab.c +index 6ee5a1d8dc82..d19f551d5279 100644 +--- a/mm/slab.c ++++ b/mm/slab.c +@@ -3690,6 +3690,8 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller) + struct kmem_cache *cachep; + void *ret; + ++ if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) ++ return NULL; + cachep = kmalloc_slab(size, flags); + if (unlikely(ZERO_OR_NULL_PTR(cachep))) + return cachep; +@@ -3725,6 +3727,8 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, + struct kmem_cache *cachep; + void *ret; + ++ if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) ++ return NULL; + cachep = kmalloc_slab(size, flags); + if (unlikely(ZERO_OR_NULL_PTR(cachep))) + return cachep; +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 01a0fe2eb332..1469d6a77ed4 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -959,18 +959,18 @@ struct kmem_cache *kmalloc_slab(size_t size, gfp_t flags) + { + int index; + +- if (unlikely(size > KMALLOC_MAX_SIZE)) { +- WARN_ON_ONCE(!(flags & __GFP_NOWARN)); +- return NULL; +- } +- + if (size <= 192) { + if (!size) + return ZERO_SIZE_PTR; + + index = size_index[size_index_elem(size)]; +- } else ++ } else { ++ if (unlikely(size > KMALLOC_MAX_CACHE_SIZE)) { ++ WARN_ON(1); ++ return NULL; ++ } + index = fls(size - 1); ++ } + + #ifdef CONFIG_ZONE_DMA + if (unlikely((flags & GFP_DMA))) diff --git a/patches.suse/mm-hugetlb-yield-when-prepping-struct-pages.patch b/patches.suse/mm-hugetlb-yield-when-prepping-struct-pages.patch new file mode 100644 index 0000000000..eac8722b01 --- /dev/null +++ b/patches.suse/mm-hugetlb-yield-when-prepping-struct-pages.patch @@ -0,0 +1,53 @@ +From 2048e98e9f9d4a8c374248ac520dca679d052896 Mon Sep 17 00:00:00 2001 +From: Cannon Matthews <cannonmatthews@google.com> +Date: Tue, 3 Jul 2018 17:02:43 -0700 +Subject: [PATCH] mm: hugetlb: yield when prepping struct pages + +References: git fixes (memory initialisation) +Patch-mainline: v4.18 +Git-commit: 520495fe96d74e05db585fc748351e0504d8f40d + +When booting with very large numbers of gigantic (i.e. 1G) pages, the +operations in the loop of gather_bootmem_prealloc, and specifically +prep_compound_gigantic_page, takes a very long time, and can cause a +softlockup if enough pages are requested at boot. + +For example booting with 3844 1G pages requires prepping +(set_compound_head, init the count) over 1 billion 4K tail pages, which +takes considerable time. + +Add a cond_resched() to the outer loop in gather_bootmem_prealloc() to +prevent this lockup. + +Tested: Booted with softlockup_panic=1 hugepagesz=1G hugepages=3844 and +no softlockup is reported, and the hugepages are reported as +successfully setup. + +Link: http://lkml.kernel.org/r/20180627214447.260804-1-cannonmatthews@google.com +Signed-off-by: Cannon Matthews <cannonmatthews@google.com> +Reviewed-by: Andrew Morton <akpm@linux-foundation.org> +Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com> +Acked-by: Michal Hocko <mhocko@suse.com> +Cc: Andres Lagar-Cavilla <andreslc@google.com> +Cc: Peter Feiner <pfeiner@google.com> +Cc: Greg Thelen <gthelen@google.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Mel Gorman <mgorman@suse.de> +--- + mm/hugetlb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 8cda1b4af19f..10f27bdee1a4 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -2204,6 +2204,7 @@ static void __init gather_bootmem_prealloc(void) + */ + if (hstate_is_gigantic(h)) + adjust_managed_page_count(page, 1 << h->order); ++ cond_resched(); + } + } + diff --git a/series.conf b/series.conf index a023d5abd5..137e74db8c 100644 --- a/series.conf +++ b/series.conf @@ -4053,6 +4053,7 @@ patches.suse/KVM-nVMX-Fix-loss-of-L2-s-NMI-blocking-state.patch patches.suse/KVM-s390-take-srcu-lock-when-getting-setting-storage.patch patches.suse/KVM-LAPIC-Fix-reentrancy-issues-with-preempt-notifie.patch + patches.fixes/xfs-fix-quotacheck-dquot-id-overflow-infinite-loop.patch patches.fixes/0001-NFS-Optimize-fallocate-by-refreshing-mapping-when-ne.patch patches.fixes/perf-x86-intel-uncore-fix-skylake-upi-pmu-event-masks.patch patches.fixes/perf-x86-intel-uncore-fix-skylake-server-pcu-pmu-event-format.patch @@ -6077,6 +6078,8 @@ patches.fixes/dax-explain-how-read-2-write-2-addresses-are-validat.patch patches.fixes/dax-use-PG_PMD_COLOUR-instead-of-open-coding.patch patches.fixes/dax-initialize-variable-pfn-before-using-it.patch + patches.fixes/shmem-shmem_charge-verify-max_block-is-not-exceeded-before-inode-update.patch + patches.fixes/shmem-introduce-shmem_inode_acct_block.patch patches.fixes/userfaultfd-mcopy_atomic-introduce-mfill_atomic_pte-helper.patch patches.fixes/mm-hugetlb-do-not-allocate-non-migrateable-gigantic-pages-from-movable-zones.patch patches.drivers/mm-devm_memremap_pages-use-multi-order-radix-for-ZON.patch @@ -14554,6 +14557,7 @@ patches.drivers/net-hns3-refactor-the-coalesce-related-struct.patch patches.drivers/net-hns3-fix-for-coal-configuation-lost-when-setting.patch patches.drivers/cxgb4-increase-max-tx-rate-limit-to-100-Gbps.patch + patches.arch/s390-sles15-17-02-01-s390-qeth-remove-outdated-portname-debug-msg.patch patches.drivers/net-hns3-add-existence-check-when-remove-old-uc-mac-.patch patches.drivers/net-hns3-fix-for-netdev-not-running-problem-after-ca.patch patches.drivers/net-hns3-fix-for-ipv6-address-loss-problem-after-set.patch @@ -14887,6 +14891,7 @@ patches.suse/dev-mem-Avoid-overwriting-err-in-read_mem.patch patches.suse/msft-hv-1645-Drivers-hv-vmbus-do-not-mark-HV_PCIE-as-perf_device.patch patches.drivers/intel_th-Use-correct-method-of-finding-hub + patches.drivers/soc-bcm2835-sync-firmware-properties-with-downstream.patch patches.drivers/ALSA-emu10k1-remove-reserved_page patches.drivers/ALSA-emu10k1-use-dma_set_mask_and_coherent patches.drivers/ALSA-emu10k1-add-optional-debug-printouts-with-DMA-a @@ -15073,6 +15078,7 @@ patches.suse/0217-dm-raid-fix-parse_raid_params-variable-range-issue.patch patches.fixes/ocfs2-dlm-wait-for-dlm-recovery-done-when-migrating-.patch patches.arch/x86-mm-memory_hotplug-determine-block-size-based-on-the-end-of-boot-memory + patches.fixes/mm-huge_memory-c-reorder-operations-in-_split_huge_page_tail.patch patches.suse/mm-free_pcppages_bulk-update-pcp-count-inside.patch patches.suse/mm-free_pcppages_bulk-do-not-hold-lock-when-picking-pages-to-free.patch patches.suse/mm-free_pcppages_bulk-prefetch-buddy-while-not-holding-lock.patch @@ -16279,6 +16285,7 @@ patches.arch/s390-cpum_sf-add-data-entry-sizes-to-sampling-trailer-entry.patch patches.drivers/s390-cio-add-helper-to-query-utility-strings-per-given-ccw-device.patch patches.drivers/s390-cio-add-test-for-ccwgroup-device.patch + patches.arch/s390-dasd-simplify-locking-in-dasd_times_out.patch patches.drivers/s390-net-add-pnetid-support.patch patches.arch/s390-archrandom-rework-arch-random-implementation.patch patches.arch/s390-zcrypt-fix-cca-and-ep11-cprb-processing-failure-memory-leak.patch @@ -17406,11 +17413,12 @@ patches.fixes/md-raid10-fix-that-replacement-cannot-complete-recov.patch patches.drivers/net-smc-fix-up-merge-error-with-poll-changes.patch patches.suse/userfaultfd-hugetlbfs-fix-userfaultfd_huge_must_wait-pte-access.patch + patches.suse/mm-hugetlb-yield-when-prepping-struct-pages.patch patches.fixes/Fix-up-non-directory-creation-in-SGID-directories.patch patches.fixes/tracing-Fix-missing-return-symbol-in-function_graph-.patch patches.drm/0001-drm-udl-fix-display-corruption-of-the-last-line.patch patches.drm/0001-drm-Use-kvzalloc-for-allocating-blob-property-memory.patch - patches.drm/drm-bridge-sii8620-Fix-display-of-packed-pixel-modes + patches.drm/Revert-drm-bridge-sii8620-fix-display-of-packed-pixel patches.drm/drm-i915-Try-GGTT-mmapping-whole-object-as-partial patches.drm/drm-amdgpu-fix-swapped-emit_ib_size-in-vce3 patches.drm/drm-exynos-gsc-Fix-support-for-NV16-61-YUV420-YVU420 @@ -17800,6 +17808,7 @@ patches.arch/s390-mm-correct-allocate_pgste-proc_handler-callback.patch patches.arch/s390-sles15-16-01-kvm-fix-deadlock-when-killed-by-oom.patch patches.arch/s390-detect-etoken-facility.patch + patches.arch/s390-sles15-17-01-01-s390-kdump-Fix-elfcorehdr-size-calculation.patch patches.arch/s390-lib-use-expoline-for-all-bcr-instructions.patch patches.arch/s390-fix-br_r1_trampoline-for-machines-without-exrl.patch patches.fixes/binfmt_elf-Respect-error-return-from-regset-active.patch @@ -18501,6 +18510,7 @@ patches.fixes/sys-don-t-hold-uts_sem-while-accessing-userspace-mem.patch patches.fixes/getxattr-use-correct-xattr-length.patch patches.arch/s390-sles15-15-01-pci-fix-out-of-bounds-access-during-irq-setup.patch + patches.arch/s390-sles15-17-01-02-s390-kdump-Make-elfcorehdr-size-calculation-ABI-comp.patch patches.arch/powerpc-fadump-cleanup-crash-memory-ranges-support.patch patches.arch/powerpc-powernv-pci-Work-around-races-in-PCI-bridge-.patch patches.arch/powerpc-topology-Get-topology-for-shared-processors-.patch @@ -19317,6 +19327,7 @@ patches.suse/ipv6-ndisc-Preserve-IPv6-control-buffer-if-protocol-.patch patches.suse/bridge-do-not-add-port-to-router-list-when-receives-.patch patches.fixes/include-linux-pfn_t.h-force-to-be-parsed-as-an-unary.patch + patches.suse/mm-don-t-warn-about-large-allocations-for-slab.patch patches.fixes/0001-mm-rework-memcg-kernel-stack-accounting.patch patches.fixes/0001-mm-don-t-miss-the-last-page-because-of-round-off-err.patch patches.drivers/Input-synaptics-avoid-using-uninitialized-variable-w.patch @@ -19430,6 +19441,7 @@ patches.drivers/usbnet-smsc95xx-disable-carrier-check-while-suspendi.patch patches.suse/net-bcmgenet-protect-stop-from-timeout.patch patches.suse/net-systemport-Protect-stop-from-timeout.patch + patches.arch/s390-sles15-17-02-02-s390-qeth-sanitize-strings-in-debug-messages.patch patches.arch/s390-sles15-16-04-s390-qeth-fix-HiperSockets-sniffer.patch patches.arch/s390-sles15-16-05-s390-qeth-report-25Gbit-link-speed.patch patches.drivers/net-hns3-Fix-for-out-of-bounds-access-when-setting-p.patch @@ -19578,6 +19590,7 @@ patches.suse/btrfs-always-try-all-copies-when-reading-extent-buffers.patch patches.suse/0003-Btrfs-send-fix-infinite-loop-due-to-directory-rename.patch patches.fixes/bpf-fix-check-of-allowed-specifiers-in-bpf_trace_pri.patch + patches.arch/s390-sles15-17-03-s390-qeth-fix-length-check-in-SNMP-processing.patch patches.fixes/udf-Allow-mounting-volumes-with-incorrect-identifica.patch patches.fixes/ext2-fix-potential-use-after-free.patch patches.drivers/ALSA-ac97-Fix-incorrect-bit-shift-at-AC97-SPSA-contr.patch @@ -19635,6 +19648,15 @@ patches.fixes/userfaultfd-shmem-hugetlbfs-only-allow-to-register-vm_maywrite-vmas.patch patches.fixes/userfaultfd-shmem-add-i_size-checks.patch patches.fixes/userfaultfd-shmem-uffdio_copy-set-the-page-dirty-if-vm_write-is-not-set.patch + patches.fixes/mm-huge_memory-rename-freeze_page-to-unmap_page.patch + patches.fixes/mm-huge_memory-splitting-set-mapping-index-before-unfreeze.patch + patches.fixes/mm-huge_memory-fix-lockdep-complaint-on-32-bit-i_size_read.patch + patches.fixes/mm-khugepaged-collapse_shmem-stop-if-punched-or-truncated.patch + patches.fixes/mm-khugepaged-fix-crashes-due-to-misaccounted-holes.patch + patches.fixes/mm-khugepaged-collapse_shmem-remember-to-clear-holes.patch + patches.fixes/mm-khugepaged-minor-reorderings-in-collapse_shmem.patch + patches.fixes/mm-khugepaged-collapse_shmem-without-freezing-new_page.patch + patches.fixes/mm-khugepaged-collapse_shmem-do-not-crash-on-compound.patch patches.drivers/pci-imx6-fix-link-training-status-detection-in-link-up-check patches.fixes/fs-fix-lost-error-code-in-dio_complete.patch patches.fixes/nvme-free-ctrl-device-name-on-init-failure.patch @@ -19821,6 +19843,7 @@ patches.drivers/scsi-lpfc-update-driver-version-to-12.0.0.8.patch patches.fixes/scsi-target-add-emulate_pr-backstore-attr-to-toggle-.patch patches.fixes/scsi-target-drop-unused-pi_prot_format-attribute-sto.patch + patches.arch/s390-scsi-zfcp-fix-posting-too-many-status-read-buffers.patch patches.drivers/scsi-lpfc-Fix-panic-when-FW-log-buffsize-is-not-init.patch patches.drivers/scsi-lpfc-update-manufacturer-attribute-to-reflect-B.patch patches.drivers/scsi-lpfc-refactor-mailbox-structure-context-fields.patch @@ -19844,6 +19867,7 @@ patches.fixes/0003-mm-memory_hotplug-drop-pointless-block-alignment-che.patch patches.fixes/0004-mm-memory_hotplug-print-reason-for-the-offlining-fai.patch patches.fixes/0005-mm-memory_hotplug-be-more-verbose-for-memory-offline.patch + patches.fixes/0001-mm-only-report-isolation-failures-when-offlining-mem.patch patches.fixes/mm-put_and_wait_on_page_locked-while-page-is-migrated.patch patches.fixes/0001-hwpoison-memory_hotplug-allow-hwpoisoned-pages-to-be.patch patches.drivers/gpiolib-Fix-return-value-of-gpio_to_desc-stub-if-GPI.patch @@ -19867,12 +19891,21 @@ patches.fixes/sunrpc-use-SVC_NET-in-svcauth_gss_-functions.patch patches.fixes/sunrpc-use-after-free-in-svc_process_common.patch patches.drivers/Input-nomadik-ske-keypad-fix-a-loop-timeout-test.patch + patches.drivers/input-add-official-raspberry-pi-s-touchscreen-driver.patch patches.drivers/ALSA-hda-realtek-Enable-the-headset-mic-auto-detecti.patch patches.drivers/ALSA-hda-tegra-clear-pending-irq-handlers.patch + patches.fixes/ceph-don-t-update-importing-cap-s-mseq-when-handing-cap-export.patch patches.fixes/xfs-xfs_buf-drop-useless-LIST_HEAD.patch patches.drivers/thermal-bcm2835-enable-hwmon-explicitly.patch patches.fixes/0001-fbdev-fbmem-behave-better-with-small-rotated-display.patch patches.fixes/0001-fbdev-fbcon-Fix-unregister-crash-when-more-than-one-.patch + patches.fixes/0001-md-fix-raid10-hang-issue-caused-by-barrier.patch + patches.drivers/ALSA-usb-audio-Avoid-access-before-bLength-check-in-.patch + patches.drivers/ALSA-usb-audio-Fix-an-out-of-bound-read-in-create_co.patch + patches.drivers/ALSA-hda-realtek-Support-Dell-headset-mode-for-New-A.patch + patches.drivers/ALSA-cs46xx-Potential-NULL-dereference-in-probe.patch + patches.drivers/ALSA-hda-realtek-Add-unplug-function-into-unplug-sta.patch + patches.drivers/ALSA-hda-realtek-Disable-headset-Mic-VREF-for-headse.patch # dhowells/linux-fs keys-uefi patches.suse/0001-KEYS-Allow-unrestricted-boot-time-addition-of-keys-t.patch @@ -19995,6 +20028,7 @@ patches.arch/s390-sles15-05-01-gmb.patch patches.arch/s390-sles15-bpf-indirect-call.patch + patches.arch/s390-sles15-dasd-fix-deadlock-in-dasd_times_out.patch ######################################################## # aarch64 @@ -20267,6 +20301,7 @@ ######################################################## patches.suse/b43-missing-firmware-info.patch patches.suse/iwlwifi-expose-default-fallback-ucode-api + patches.suse/ath10k-QCA9377-firmware-limit.patch ######################################################## # ISDN diff --git a/supported.conf b/supported.conf index f6ced40d69..1a4eafa1a6 100644 --- a/supported.conf +++ b/supported.conf @@ -898,6 +898,7 @@ - drivers/input/touchscreen/wdt87xx_i2c drivers/input/touchscreen/wm97xx-ts - drivers/input/touchscreen/zforce_ts + drivers/input/touchscreen/raspberrypi-ts drivers/iommu/amd_iommu_v2 # AMD IOMMU v2 driver - drivers/ipack/carriers/tpci200 - drivers/ipack/devices/ipoctal |